ADOT で OpenTelemetry に入門する (Metrics | EC2 on EKS)
AWS Distro for OpenTelemetry を使用して EC2 on EKS 環境のメトリクスを収集する
この記事は OpenTelemetry に入門してみるシリーズの第一回です。今後数回の記事に分けて、OpenTelemetry に入門していきます。
第一回となる本記事では、AWS Distro for OpenTelemetry (以降 ADOT) を使用して EC2 on EKS 環境のメトリクスを収集します。
事前準備
以降の節では、ADOT Operator がクラスターで利用可能となっていることを前提としています。
今回の記事の執筆環境は、以下のように ADOT Operator を導入しています。
- ADOT Operator は ADOT アドオンとして導入済み (ガイド)
- cert-manager を導入済み (ADOT アドオンの利用に必要となるため)
ADOT アドオンが利用可能である場合は、以下の様なポッドや API リソースが確認できます。
$ kubectl get po -n opentelemetry-operator-system
NAME READY STATUS RESTARTS AGE
opentelemetry-operator-b7dbbdf7c-f74jx 2/2 Running 0 2m39s
$ kubectl api-resources | grep opentelemetry
instrumentations otelinst,otelinsts opentelemetry.io/v1alpha1 true Instrumentation
opampbridges opentelemetry.io/v1alpha1 true OpAMPBridge
opentelemetrycollectors otelcol,otelcols opentelemetry.io/v1beta1 true OpenTelemetryCollector
留意点
執筆時点では、ADOT アドオンは EKS バージョン 1.31 をサポートしていませんでした。(Issue | #2435 [EKS] [request]: No available versions of ADOT add-on for EKS 1.31)
そのため、本記事の執筆環境の EKS はバージョン 1.30 を利用しています。過去にも、ADOT アドオンがサポートする EKS バージョンとして、利用可能な最新の EKS バージョンが含まれない期間があったようなので、組織で EKS のバージョン管理ポリシーを定めている場合は、アドオンの利用は慎重に検討しても良いかもしれません。
メトリクスを収集する
Kubernetes のメトリクスを収集する方法はいくつかあると思いますが、本記事では Container Insights EKS Infrastructure Metrics のチュートリアルを参考に AWS Container Insigths Reciever を使用して、ノードやポッドのメトリクスを収集します。
まずは、以下の内容で adot.yaml
を作成します。
このマニフェストは、ADOT Collector を DaemonSet モードで起動させ、AWS Container Insigths Reciever により収集されたメトリクスを、Logging Exporter によりコンソールに出力するパイプラインを動かすものです。
apiVersion: v1
kind: Namespace
metadata:
name: aws-otel-eks
labels:
name: aws-otel-eks
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: otel-collector
namespace: aws-otel-eks
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: otel-collector-role
rules:
- apiGroups: [""]
resources: ["pods", "nodes", "endpoints"]
verbs: ["list", "watch", "get"]
- apiGroups: ["apps"]
resources: ["replicasets"]
verbs: ["list", "watch", "get"]
- apiGroups: ["batch"]
resources: ["jobs"]
verbs: ["list", "watch"]
- apiGroups: [""]
resources: ["nodes/proxy"]
verbs: ["get"]
- apiGroups: [""]
resources: ["nodes/stats", "configmaps", "events"]
verbs: ["create", "get"]
- apiGroups: [""]
resources: ["configmaps"]
resourceNames: ["otel-container-insight-clusterleader"]
verbs: ["get","update"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
verbs: ["create","get", "update"]
- apiGroups: ["coordination.k8s.io"]
resources: ["leases"]
resourceNames: ["otel-container-insight-clusterleader"]
verbs: ["get","update", "create"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: otel-collector-role-binding
subjects:
- kind: ServiceAccount
name: otel-collector
namespace: aws-otel-eks
roleRef:
kind: ClusterRole
name: otel-collector-role
apiGroup: rbac.authorization.k8s.io
---
apiVersion: opentelemetry.io/v1beta1
kind: OpenTelemetryCollector
metadata:
name: otel-collector
namespace: aws-otel-eks
spec:
managementState: managed
mode: daemonset
serviceAccount: otel-collector
# https://github.com/aws-observability/aws-otel-collector/issues/2317
securityContext:
runAsUser: 0
runAsGroup: 0
env:
- name: K8S_NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: HOST_IP
valueFrom:
fieldRef:
fieldPath: status.hostIP
- name: HOST_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: K8S_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
volumes:
- name: rootfs
hostPath:
path: /
# https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/ContainerInsights-troubleshooting.html
- name: dockersock
hostPath:
path: /var/run/docker.sock
- name: varlibdocker
hostPath:
path: /var/lib/docker
- name: varlibcontainerd
hostPath:
path: /var/lib/containerd/
- name: containerdsock
hostPath:
# path: /run/containerd/containerd.sock
# bottlerocket does not mount containerd sock at normal place
# https://github.com/bottlerocket-os/bottlerocket/commit/91810c85b83ff4c3660b496e243ef8b55df0973b
path: /run/dockershim.sock
- name: sys
hostPath:
path: /sys
- name: devdisk
hostPath:
path: /dev/disk/
volumeMounts:
- name: rootfs
mountPath: /rootfs
readOnly: true
# https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/ContainerInsights-troubleshooting.html
- name: dockersock
mountPath: /var/run/docker.sock
readOnly: true
- name: varlibdocker
mountPath: /var/lib/docker
readOnly: true
- name: varlibcontainerd
mountPath: /var/lib/containerd
readOnly: true
- name: containerdsock # NEW mount
mountPath: /run/containerd/containerd.sock
readOnly: true
- name: sys
mountPath: /sys
readOnly: true
- name: devdisk
mountPath: /dev/disk
readOnly: true
resources:
limits:
cpu: 200m
memory: 200Mi
requests:
cpu: 200m
memory: 200Mi
config:
receivers:
awscontainerinsightreceiver:
collection_interval: 60s
container_orchestrator: eks
add_service_as_attribute: true
prefer_full_pod_name: false
add_full_pod_name_metric_label: false
exporters:
logging:
verbosity: detailed
sampling_initial: 100
sampling_thereafter: 1
processors:
batch:
timeout: 10s
service:
pipelines:
metrics/101:
receivers: [awscontainerinsightreceiver]
processors: [batch]
exporters: [logging]
次に、作成した adot.yaml
を適用します。
$ kubectl apply -f adot.yaml
適用後、ポッドが起動したことが確認できます。
$ kubectl get po -n aws-otel-eks
NAME READY STATUS RESTARTS AGE
otel-collector-collector-2rv6g 1/1 Running 0 25s
otel-collector-collector-mzttn 1/1 Running 0 24s
起動されたいずれかのポッドのログを確認することで、ADOT Collector により、メトリクスが収集されていることが確認できます。
$ kubectl logs otel-collector-collector-2rv6g -n aws-otel-eks
Descriptor:
-> Name: namespace_number_of_running_pods
-> Description:
-> Unit: Count
-> DataType: Gauge
Descriptor:
-> Name: node_memory_rss
-> Description:
-> Unit: Bytes
-> DataType: Gauge
Descriptor:
-> Name: pod_memory_max_usage
-> Description:
-> Unit: Bytes
-> DataType: Gauge
おわりに
本記事では、ADOT を使用して EC2 on EKS 環境のメトリクスを収集してみました。
本記事の内容では、収集したメトリクスを Logging Exporter でコンソールに出力しているだけですが、バックエンドサービスへ連携するエクスポーターへ差し替えることで、バックエンドサービスにメトリクスを連携できるようになります。
なお、本記事の構成で ADOT Collector を動作させる場合は、Fargate ノードで動作するポッドのメトリクスは収集できません。次回は Fargate ノード上のポッドのメトリクスを収集する方法について触れてみたいと思います。