使用AWS Distro for OpenTelemetry将EKS的度量数据导入CloudWatch
首先
在Kubernetes上管理应用程序的指标的方法有很多选择,其中包括Prometheus + Grafana和ELK堆栈。然而,在AWS的Elastic Kubernetes Service(EKS)中,许多人可能更倾向于使用AWS的托管监控服务CloudWatch。
只要使用AWS Distro for OpenTelemetry,就能轻松将EKS上应用的指标发送至CloudWatch!包括Pod的CPU和RAM使用率,当然也支持Prometheus格式的指标。
AWS Distro for OpenTelemetry (ADOT) 是什么?
ADOT 是 AWS 官方维护的 OpenTelemetry Collector 的发行版本。由于名称太长,以下简称为 ADOT。
一开始,OpenTelemetry Collector是什么?
该收集代理程序统一处理应用程序的日志、度量和跟踪,并支持多种输入和输出。GitHub上的这个代理程序相当受欢迎,因为它可以被普遍使用而不依赖于特定的云厂商。
如果您熟悉Fluent Bit(简单来说),您可能会认为OpenTelemetry Collector是类似的。OpenTelemetry Collector主要有3种组件(如下图):Receiver / Processor / Exporter,这与Fluent Bit的Input / Filter / Output的3个元素相似。
Fluent Bit的输入包括statsd、Tail、HTTP等,输出包括CloudWatch、Stackdriver等,支持多种用例。此外,您还可以通过设置过滤器/解析器来灵活地配置收集。这同样适用于OpenTelemetry Collector。接收器列表、导出器列表
如果要列举与Fluent Bit的区别,那么可以说,Fluent Bit更多地被视为主要用于日志收集的用例。因此,在指标收集方面,使用者较少,而且支持还相对薄弱。
根据我了解,OpenTelemetry Collector在度量收集方面支持非常好。例如,使用AWS Container Insights Receiver组件,您可以一次获取EKS的Pod/Node度量数据,并且可以直接在CloudWatch控制台上进行可视化展示。
ADOT的目的是什么?
ADOT是一个预先安装了许多在EKS上使用的方便组件的OpenTelemetry Collector分发版本。因此,可以非常容易地开始使用,并集成到AWS服务中。预先安装的组件列表可以在这里找到。
如果将这里与 Fluent Bit 类比,那么就类似于 AWS for Fluent Bit,它在原始的 Fluent Bit 基础上提供了一些预装的插件。因此,如果想在 EKS 上使用 OpenTelemetry Collector,使用 ADOT 是最方便快捷的选择。
除了官方的 OpenTelemetry 发行版之外,据看来 EKS 中似乎包含了明显不需要的组件。如果要在 EKS 上使用,ADOT 似乎是一个恰到好处的选择,既满足需求又足够。
此外,ADOT自身不仅考虑了在EKS上的运行,还考虑了在ECS和EC2上的运行,但本文将专注于在EKS上使用的话题。
安装步骤
安装ADOT到EKS有几种方法可以选择。
使用YAML进行安装
通过在kubectl上运行`kubectl apply`命令,可以安装此YAML文件。
有关详细步骤,请参考此处。
如果您需要追求灵活性,我们建议您使用YAML进行安装,因为它可以完全定制配置。
使用Helm进行安装。
Helm的安装也得到了AWS官方的支持。请参考此处以获得详细步骤。
由于此Helm图表中包含了用于日志收集的Fluent Bit,因此它很方便地用于在EKS上快速设置日志/指标收集功能。
然而,如果无法从图表外部进行必要的配置,那么它可能不适合需要完全自定义性的情况。
另外,无论选择使用yaml/helm的哪种操作步骤,都需要单独创建一个适用于ADOT所使用的服务账号的IAM角色。请参考以下详细说明。
基本上,只需创建一个能够由ADOT所使用的服务账号通过OIDC进行Assume的IAM角色(并附加CloudWatchAgentServerPolicy策略)就可以了。
构成方式
如果这样还不够,您可以更改ADOT的设置,以便根据您的用例进行定制。
ADOT的配置
如果通过YAML方式安装ADOT,则在YAML文件中有一个名为”otel-agent-config”的配置项。
您可以通过编辑该部分来自定义ADOT的配置。
如果使用Helm进行安装,可以根据values.yaml文件设置一些条目。然而,在编写Helm图表时可能需要阅读并理解其内容。在这一点上,使用yaml进行安装可能更容易理解。
请参考此处以获取ADOT配置的编写方式。
使用 Prometheus 的指標数据
让我们思考一个常见的用例,即将Prometheus格式的指标发送到CloudWatch。
首先,您可以使用Prometheus接收器作为接收器。以下是一个简单的配置示例。
receivers:
prometheus:
config:
# https://prometheus.io/docs/prometheus/latest/configuration/configuration/
scrape_configs:
- job_name: 'otel-collector'
scrape_interval: 60s
kubernetes_sd_configs:
- role: pod
relabel_configs:
# PodのAnnotationからPrometheus metricsエンドポイントを検出する
# https://github.com/prometheus/prometheus/blob/v2.33.4/documentation/examples/prometheus-kubernetes.yml#L157-L178
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $$1:$$2
target_label: __address__
# awscontainerinsightreceiverと同一のLabel (Attribute) を付与する
- source_labels: [__meta_kubernetes_namespace]
action: replace
target_label: Namespace
- source_labels: [__meta_kubernetes_pod_node_name]
action: replace
target_label: NodeName
- source_labels: [__meta_kubernetes_pod_name]
action: replace
target_label: PodName
# cluster名は既存の __meta labelから取得できないので、外から渡す
# https://albersdevelopment.net/2019/08/28/prometheus-adding-a-label-to-a-target/
- source_labels: [__address__]
target_label: ClusterName
replacement: "sample-cluster"
# Service名は既存のlabelから取得できない とりあえずコンテナ名を代替にする
- source_labels: [__meta_kubernetes_pod_container_name]
action: replace
target_label: Service
在 Prometheus 接收器(Prometheus receiver)的设置中,可以直接在配置文件(config)中编写 Prometheus 的配置(scrape_configs)。在这个例子中,我们使用 kubernetes_sd_configs 来收集 pod 的度量数据。
在接下来的relabel_configs中,首先会查看Pod的annotation,然后进行自动发现目标Pod的指标获取。这并不直接与ADOT相关,而是Prometheus中众所周知的一种技巧。
通过这种方式,拥有这些设置的Pod将自动成为ADOT的指标收集目标。
接下来,我们设置了一些标签,如Namespace / NodeName / PodName / Service / ClusterName。我们确保标签名称与AWS Container Insights Receiver中设置的标签相同。
这些标签是通过awsemf配置的Exporter来引用的。请注意下面的dimensions部分。
exporters:
awsemf:
namespace: ContainerInsights
log_group_name: '/aws/containerinsights/{ClusterName}/performance'
log_stream_name: '{NodeName}'
metric_declarations:
# labelはこのDimensionで指定する!
- dimensions: [[NodeName, ClusterName]]
metric_name_selectors:
- node_cpu_utilization
- node_memory_utilization
awsemf是AWS CloudWatch EMF Exporter的配置。
设定在此维度上的标签将会使得CloudWatch上的指标进行分组和聚合。同时,在这里设置的标签不存在的指标将会被忽略并不会发送到CloudWatch。
为了在CloudWatch上进行指标分组,需要适当地为Prometheus指标设置标签。
您可以自由地设置标签,维度的选项也是可选的,因此根据您的用例进行自定义会更好。
我们在这里介绍了以Prometheus格式收集指标的例子,但还有许多其他的接收器也被支持。
支持的组件列表
这些组件同样可以通过编写配置文件进行使用,请根据需要进行尝试。
节约成本
默认设置下,会发送一般情况下所需的各种度量指标。
通过根据使用情况选择度量指标,可以节省成本。
请参阅这篇文章以获取详细信息。
简而言之,通过使用ADOT的Processor功能,可以进行指标过滤和删除不需要的字段等操作。
processors:
# 特定のフィールドをEMFのログから削除する例
resource:
attributes:
- key: Sources
action: delete
- key: kubernetes
action: delete
# 特定の名前をもつメトリクスを処理対象から除外する例
filter/exclude:
metrics:
exclude:
match_type: regexp
metric_names:
- container_.*
- go_.*
- redis_.*
顺便提一下,费用主要来源是CloudWatch Logs的导入费用和按CloudWatch Metrics每个指标计费。可能会有人问为什么需要日志,但在ADOT中,我们以EMF格式将指标作为日志发送,所以日志的导入费用也是计费对象。因为积少成多,所以积极地排除不需要监视的指标似乎是个不错的选择。参考:CloudWatch使用费用
我了解指标,但日志和追踪呢?
观测性的三种工具是日志/指标/追踪,ADOT是否都支持?
OpenTelemetry Collector目前具有将日志导出到CloudWatch的插件,即AWS CloudWatch Logs Exporter。然而,该插件目前仍处于实验阶段,并尚未包含在ADOT中。因此,目前最好的选择是使用Fluent Bit等工具将日志发送到CloudWatch。
关于追踪,ADOT包含了一个将追踪导出到AWS X-Ray的插件。使用AWS X-Ray跟踪导出器适配器,您应该能够处理追踪。(但我还没有使用过,所以期待您的使用报告!)
总结
通过使用AWS Distro for OpenTelemetry(ADOT),您可以轻松地将EKS的指标收集到CloudWatch中。
它由AWS官方维护,并且目前正在积极开发中,因此是一种有前景的方法。
如果您已经在CloudWatch中收集日志,或者苦于无法收集指标,请务必尝试一下!
参考资料
- OpenTelemetry Collector