注目イベント!
アドベントカレンダー2024開催します(12/1~12/25)!
一年を締めくくる特別なイベント、アドベントカレンダーを今年も開催します!
初心者からベテランまで楽しめる内容で、毎日新しい技術トピックをお届けします。
詳細はこちらから!
event banner

メトリクス収集・可視化 - OpenTelemetry / CloudWatch

| 21 min read
Author: noboru-kudo noboru-kudoの画像

前回はPrometheusとGrafanaを利用して、Kubernetesおよびアプリケーションに関するメトリクスの収集・可視化を行いました。
今回はOpenTelemetryCloudWatchを使って同じことをしてみましょう。

OpenTelemetryとは?

#

OpenTelemetryは、メトリクス、トレース、ログ等のテレメトリー[1]情報のやりとりに関するインターフェースを規定する仕様です(現状ログはまだドラフトです)。
OpenTelemetryには言語非依存のAPIに加えて、各言語に特化したSDK、プロトコル(OTLP:OpenTelemetry Line Protocol)が含まれています。

詳細な仕様や現在のステータスについては、公式ドキュメントを確認してください。

また、必須ではありませんがOpenTelemetryのテレメトリー情報収集には、ベンダー中立のCollectorと呼ばれる仕組みを利用することが推奨されています。
CollectorはReceiver / Processor / Exporterの3つのコンポーネントで構成されます。

以下は、OpenTelemetry公式サイトに掲載されているCollectorのパイプラインイメージです。
OpenTelemetry Collector Pipeline
引用元:https://opentelemetry.io/docs/collector/

  1. Receiver: OTLPの他、PrometheusやJaeger等の任意フォーマットのテレメトリー情報を取り込む
  2. Processor: データのフィルタリングや変換等を行う(任意)
  3. Exporter: Prometheus、Datadog等のバックエンドにテレメトリー情報を送信する

これらはプラグイン形式となっており、利用環境にあったものを組み合わせてパイプラインを構成できます。

また、OpenTelemetryエコシステムでは、知名度のあるフレームワークやツールに対応したReceiver/Exporterや自動構成ライブラリ(auto-instrumentation)等が提供されてます。
OpenTelemetry導入を検討する際は、まず以下を参照して、対応しているものがあるかを確認すると良いでしょう。

ベンダーサポート状況は以下より確認できます。主要なクラウド・SaaSベンダーがOpenTelemetryをサポートしていることが分かります。

AWS Distro for OpenTelemetry(ADOT)の紹介

#

AWSでは、AWS環境での利用に特化したOpenTelemetryのディストリビューションとしてAWS Distro for OpenTelemetry(以下ADOT)を無償提供しています。
ADOTの実態は、AWS環境に必要な設定やコンポーネントをセットアップしたOpenTelemetry Collectorのカスタマイズバージョンです。
これを利用することで、EKS、ECSからLambda、EC2までの各種メトリクスを、様々なバックエンドサービス(CloudWatch、AWS X-Ray、Prometheus等)に送信できます。

ADOTに組み込まれているコンポーネントは、GitHubリポジトリのREADMEファイルより確認できます。

それでは、ADOTを使ってメトリクスを収集・可視化してみましょう。
なお、今回はメトリクス収集・可視化のバックエンドサービスには、AWSのマネージドサービスであるCloudWatchを使います。

事前準備

#

前回の続きになります。必要な環境(EKS/アプリ等)については以下を参照してください。

今回はバックエンドサービスとしてPrometheusは利用しませんので、以下のコマンドでPrometheusとGrafanaはアンインストールしておきましょう。

helm uninstall kube-prometheus-stack -n prometheus

アクセス許可ポリシー作成(Kubernetesメトリクス向け)

#

まずは、Kubernetesメトリクスを収集する設定をします。
これには、ADOTがメトリクス収集のためにKubernetesのNodeであるEC2や、メトリクス送信先であるCloudWatchにアクセスできる必要があります。
必要なIAMポリシーは、AWSのマネージドポリシーであるCloudWatchAgentServerPolicyが用意されていますので、改めて作成する必要はありません。

Terraform設定ファイルのapp/terraform/main.tfに以下を追記します。

module "adot_collector" {
  source                        = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
  version                       = "~> 4.0"
  create_role                   = true
  role_name                     = "ADOTCollector"
  provider_url                  = var.oidc_provider_url
  role_policy_arns              = ["arn:aws:iam::aws:policy/CloudWatchAgentServerPolicy"] # AWS managed policy
  oidc_fully_qualified_subjects = ["system:serviceaccount:amzn-cloudwatch-metrics:adot-collector"]
}

IAMロール(ADOTCollector)を作成し、これにAWSマネージドポリシーのCloudWatchAgentServerPolicyを紐付けています。

これをTerraformでAWS環境に反映(terraform apply)しておきましょう。反映の仕方は以下を参照しくてださい。

ADOT DaemonSetのセットアップ

#

それではまず、ADOTはKubernetesのメトリクス収集用のために、ADOTのDaemonSetをセットアップしましょう。
AWSからADOTのHelmチャートが公開されていますので、こちらを利用します。
まずは、いつものようにHelmチャートのリポジトリを追加します。

helm repo add aws-otel https://aws-observability.github.io/aws-otel-helm-charts
helm repo update

helmコマンドでインストールします。ここでは0.2.0のHelmチャートのバージョンを指定しました。

# <aws-account-id>の部分は利用しているAWS環境のアカウントIDに置き換えてください
helm upgrade aws-otel-ds aws-otel/adot-exporter-for-eks-on-ec2 \
    --install --version 0.2.0 \
    --namespace kube-system \
    --set adotCollector.daemonSet.serviceAccount.name=adot-collector \
    --set adotCollector.daemonSet.serviceAccount.annotations."eks\.amazonaws\.com/role-arn"=arn:aws:iam::<aws-account-id>:role/ADOTCollector \
    --set clusterName=mz-k8s \
    --set awsRegion=ap-northeast-1 \
    --set fluentbit.enabled=false \
    --wait

clusterName/awsRegionの各パラメータは、自身の環境に合ったものを指定してください。

Helmチャートで作成されるServiceAccountのannotationsには、先程Terraformで作成したIAMロールのARNを指定します。
また、今回ログ収集はスコープ外としていますので、FluentBitは無効にしています(fluentbit.enabled=false)。

インストールが終わったら、Podの状態を確認しましょう。

kubectl get pod -n amzn-cloudwatch-metrics
NAME                             READY   STATUS    RESTARTS   AGE
adot-collector-daemonset-47qfb   1/1     Running   0          1h12m
adot-collector-daemonset-mdd9d   1/1     Running   0          1h12m

ここでは、ADOT CollectorをDaemonSetとして導入していますので、クラスタのノード数と同じ数のPodが起動していることを確認します(上記は2ノード構成のため2レプリカとなっています)。

また、Podのログも確認し(kubectl logs)、エラーがないことも確認しておきましょう。

Information

ここではEC2上に構築したEKSを対象としていますが、2022/2/17よりFargateサポートが追加されています。
Fargateを使ってEKSを構築している場合は、以下を参照してください。

Kubernetesメトリクス可視化

#

これでDaemonSetとしてデプロイしたADOT CollectorがKubernetesクラスタのメトリクスの収集を開始しているはずです。
しばらく時間を置いてから、AWSマネジメントコンソールを確認してみましょう。
サービスとしてCloudWatchを選択し、サイドメニューよりインサイト -> Container Insightsと進みます。

container-insights resources

Kubernetesリソースの一覧が表示され、コンテナの平均CPUや平均メモリ使用率が確認できます。
任意のリソースを選択すると、以下のように各メトリクスがグラフ表示されます。

これらはPod単位だけでなく、ServiceやNode単位でも参照できます。
また、プルダウンメニューからコンテナマップを選択すると、以下のようにリソース間の関連性を可視化できます。

これで満たせない場合は、カスタムクエリを使うことで様々な角度からメトリクスを分析できます。
この場合は、サイドメニューよりログ -> ログのインサイトへ進み、ロググループaws/containerinsights/<cluster-name>/performanceを選択して、任意のクエリを記述します。
以下は1時間ごとのNodeのCPU使用率を表示する例です。

cloudwatch log insights

クエリのシンタックスや利用可能なメトリクスは、以下のAWS公式ドキュメントを参照してください。

なお、クエリ作成の際は、実際のログ出力内容からメトリクス(JSONフォーマット)を見ながら作成すると効率的です。

Information

現時点ではプレビュー版(2021/11/29公開)ですが、CloudWatchのメトリクスインサイトでもクエリを作成できます。

この場合は、多くの人に馴染みのあるSQL構文に準じたクエリ言語を記述します。
詳細は公式ドキュメントを参照してください。

このように、Grafanaと比較すると見た目は劣りますが、CloudWatchでも十分に実用的と言えるレベルになっていることが分かります。

アクセス許可ポリシー作成(アプリケーションメトリクス向け)

#

ここまででインフラレイヤーのメトリクス収集と可視化を実践してきました。ここからはアプリケーションレイヤーについても対応していきましょう。

アプリケーションメトリクスの収集についても、先程のDaemonSetを利用可能です。
しかし、ADOTの公式ドキュメントによると、DaemonSetではなく、フル機能をサポートするサイドカーコンテナによるデプロイが推奨されています。

これに従い、別途アプリケーションPodのサイドカーコンテナとしてADOTを導入しましょう。

まず、サイドカーコンテナ用に別途アクセス許可を設定する必要があります。
今回はNode(EC2)へのアクセスは不要で、CloudWatchへのメトリクス送信のみがあれば問題ありません。必要なポリシーファイルはGitHubのこちらに用意しました。
このファイルをapp/terraformに配置してください(otel-collector-policy.jsonとしました)。

curl -o otel-collector-policy.json \
  https://raw.githubusercontent.com/mamezou-tech/k8s-tutorial/main/ops/otel/otel-collector-policy.json

次に、先程同様にapp/terraform/main.tfを修正します。

# サイドカーコンテナ用のポリシー作成
resource "aws_iam_policy" "eks_aodt_collector" {
  name   = "EKSADOTCollector"
  policy = file("${path.module}/otel-collector-policy.json")
}

# 以下は修正(role_policy_arnsに上記ポリシーを追加)
module "task_service" {
  source                        = "terraform-aws-modules/iam/aws//modules/iam-assumable-role-with-oidc"
  version                       = "~> 4.0"
  create_role                   = true
  role_path                     = "/app/"
  role_name                     = "TaskService"
  provider_url                  = var.oidc_provider_url
  role_policy_arns              = [aws_iam_policy.app_task_table.arn, aws_iam_policy.eks_aodt_collector.arn]
  oidc_fully_qualified_subjects = ["system:serviceaccount:${var.env}:task-service"]
}

ここでは、前回同様task-servicePodのみに適用します。
既にtask-serviceのロールは作成済みですので、それに対してADOT Collectorのポリシーを紐付けるだけです(role_policy_arns)。

これを先程同様にAWS環境に反映(terraform apply)しましょう。
これで、サイドカーコンテナ(ADOT)からCloudWatchへのメトリクス送信ができるようになります。

ADOT サイドカーコンテナのセットアップ

#

これで準備が整いました。ADOTのサイドカーコンテナをアプリケーションに組み込んでいきましょう。

前回は、アプリケーションに対してPrometheusクライアントライブラリ(prometheus-api-metrics/prom-client)を導入しました。
これにより、アプリケーション内でメトリクス自動収集と/metricsエンドポイント公開が行われ、ここからPrometheusがメトリクスを取得(PULL)していました。

prometheus-architecture

しかし、ADOTデフォルトではOpenTelemetryプロトコル(OTLP)でメトリクスが送信されてくることを待っています(PUSH型)。
このため、単純に置き換えるだけではPrometheus用のエンドポイントからメトリクスが収集されません。

prom-adot-mismatch

アプリケーションをOTLPに対応すること自体は可能ですが、現時点ではprometheus-api-metricsのようにNode.jsのメトリクスを自動収集するライブラリは存在しません(トレーシングのみ)。
このため、アプリケーション内でNode.jsやExpressに関するメトリクス収集機能を実装する必要がありますが、これを正確に行うのはかなりハードルが高いと言えます。
これに対する解決策としては、ADOTつまりOpenTelemetry Collectorの設定をカスタマイズすることです。
前述の通り、OpenTelemetry Collectorはプラグイン形式で組み替えることが可能です。今回利用しているOpenTelemetryディストリビューションのADOTでも、ReceiverコンポーネントとしてPrometheusをサポートしています。
今回は、アプリケーションは前回と同じくPrometheus用のエンドポイントを公開し、ADOT側でこのエンドポイントからメトリクスを収集(PULL)するようにチューニングを行うこととします。

prom-adot-adapt

Information

OpenTelemetryはNode.jsの自動構成(auto-instrumentation)ライブラリがないのは執筆時点の状況です。
Node.jsはメジャーなランタイム環境ですので、そう遠くない未来にprometheus-api-metricsのような自動構成ライブラリが提供されると想像できます。
実際に利用する際には、最新の状況を確認するようにしてください。

では、アプリケーションのKubernetesのマニフェストを修正してサイドカーコンテナを組み込みましょう。
ここでは、app/k8s/otelディレクトリを作成し、アプリケーション開発編で作成したapp/k8s/v3の内容をコピーします。
ここに対してOpenTelemetryの修正を加えていきます[2]

まず、OpenTelemetryの設定ファイルを用意します。app/k8s/otel/patches/task-service配下にotel-config.yamlを作成します。
内容は以下のようになります。

extensions:
  health_check:

receivers:
  prometheus:
    config:
      global:
        evaluation_interval: 30s
      scrape_configs:
        - job_name: prod/task-service
          static_configs:
            - targets: ['localhost:3000']
          scrape_interval: 30s
          metrics_path: /metrics

processors:
  batch/metrics:
    timeout: 60s

exporters:
  # AWS Embedded metric format
  # AWS Doc: https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/CloudWatch_Embedded_Metric_Format_Specification.html
  # Exporter Doc: https://github.com/open-telemetry/opentelemetry-collector-contrib/tree/main/exporter/awsemfexporter
  awsemf:

service:
  pipelines:
    metrics:
      receivers: [prometheus]
      processors: [batch/metrics]
      exporters: [awsemf]

ポイントはreceiversの部分です。ここでADOTに組み込まれているprometheusを使うよう指定します。

そして、conifig配下にPrometheusの設定を記述します。この部分はPrometheusの設定ファイルと同一フォーマットとなります。
ここでは、メトリクス収集のエンドポイントは固定設定(static_configs)とし、アクセス先であるtargetsは、ローカルアクセスのlocalhost:3000とします[3]
これは、ADOTはサイドカーコンテナで、アプリケーションと同じPod内での実行(ネットワーク共有)となるためです。

なお、この設定ファイルの詳細については、OpenTelemetryの公式ドキュメントを参照してください。

Caution

OpenTelemetryのReceiverコンポーネントのPrometheusは、現時点ではまだ開発中ステータスです。
実際に利用する際はGitHubリポジトリを参照し、最新の状態を確認してください。

この設定ファイルをKustomizeのConfigMapジェネレータに追加しましょう。app/k8s/otel/overlays/prod/kustomization.yamlを修正します。
以下追加部分を抜粋します。

configMapGenerator:
  - name: task-service-config
    behavior: merge
    envs:
      - patches/task-service/.env
  - name: task-reporter-config
    behavior: merge
    envs:
      - patches/task-reporter/.env
  # 以下を追加
  - name: otel-config
    files:
      - patches/task-service/otel-config.yaml

OpenTelemetryの設定ファイルを、otel-configという名前のConfigMapリソースとして作成するよう指定しました(デプロイ時はプレフィックスprod-がつきます)。

最後にサイドカーコンテナの設定です。
task-serviceのDeploymentリソースに対応するKustomizeパッチファイルが、app/k8s/otel/overlays/prod/patches/task-service/deployment.patch.yamlにあるはずです。
ここにサイドカーコンテナの定義を追加しましょう。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: task-service
spec:
  replicas: 3
  template:
    spec:
      # IRSA
      serviceAccountName: task-service
      containers:
        - name: task-service
          imagePullPolicy: IfNotPresent
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 300m
              memory: 512Mi
        # ここから追加
        - name: aws-otel-collector
          image: amazon/aws-otel-collector:latest
          command: [ "/awscollector" ]
          args: [ "--config", "/config/otel-config.yaml" ]
          volumeMounts:
            - mountPath: /config
              name: otel-config-vol
              readOnly: true
          env:
            # 東京リージョン。別リージョンに配置している場合は変更してください。
            - name: AWS_REGION
              value: ap-northeast-1
          resources:
            limits:
              cpu: 256m
              memory: 512Mi
            requests:
              cpu: 32m
              memory: 24Mi
      volumes:
        - name: otel-config-vol
          configMap:
            name: otel-config

今まではcontainers配下はアプリケーション用のコンテナ1つでしたが、ADOTのサイドカーコンテナを追加しています。

また、volumesとして先程作成したConfigMapをボリュームとして作成し、volumeMountsでそのボリュームをサイドカーコンテナ側の/configにマウントします。
ADOT実行時には、マウントしたConfigMap内の設定ファイルを引数(args)に渡すよう指定しています。
これを実施することで、ADOTはカスタムの設定ファイル(Prometheus Receiver)を認識します。

最終的にapp/k8s/otel/overlays/prodは以下のような構成となります。

app/otel/overlays/prod/
├── kustomization.yaml <- OpenTelemetryの設定ファイルをConfigMap化
├── lets-encrypt-issuer.yaml
├── patches
│ ├── ingress
│ │ └── ingress.patch.yaml
│ ├── task-reporter
│ │ └── cronjob.patch.yaml
│ └── task-service
│     ├── deployment.patch.yaml <- サイドカーコンテナを追加し、ConfigMapをマウント
│     └── otel-config.yaml <- OpenTelemetry設定ファイル配置
└── task-web
├── deployment.yaml
└── service.yaml

これで準備完了です。後はこれをKubernetesに反映しましょう。
デプロイはいつもと同じ手順です。

kubectl apply -k app/k8s/otel/overlays/prod

デプロイが完了したらPodの状態を確認してみましょう。

kubectl get pod -n prod -l app=task-service
NAME                                READY   STATUS    RESTARTS   AGE
prod-task-service-ddcc79d8f-f7hjn   2/2     Running   0          92s
prod-task-service-ddcc79d8f-jj6vx   2/2     Running   0          92s
prod-task-service-ddcc79d8f-wd264   2/2     Running   0          92s

READYの部分が2/2になっていることが確認できます。
今まではアプリケーションコンテナの1つのみでしたが、今回はサイドカーコンテナとしてADOTを指定していますので、2つのコンテナが起動します。
サイドカーコンテナのログも見てみましょう。サイドカーコンテナのログを見るには-cオプションでコンテナ名を指定します。

POD_NAME=$(kubectl get pod -l app=task-service -n prod -o jsonpath='{.items[0].metadata.name}')
kubectl logs ${POD_NAME} -c aws-otel-collector -n prod
2022-03-21T05:04:15.099Z        info    builder/exporters_builder.go:255        Exporter was built.     {"kind": "exporter", "name": "awsemf"}
2022-03-21T05:04:15.099Z        info    builder/pipelines_builder.go:223        Pipeline was built.     {"name": "pipeline", "name": "metrics"}
2022-03-21T05:04:15.099Z        info    builder/receivers_builder.go:226        Receiver was built.     {"kind": "receiver", "name": "prometheus", "datatype": "metrics"}
2022-03-21T05:04:15.099Z        info    service/service.go:82   Starting extensions...
2022-03-21T05:04:15.099Z        info    service/service.go:87   Starting exporters...
2022-03-21T05:04:15.099Z        info    builder/exporters_builder.go:40 Exporter is starting... {"kind": "exporter", "name": "awsemf"}
2022-03-21T05:04:15.099Z        info    builder/exporters_builder.go:48 Exporter started.       {"kind": "exporter", "name": "awsemf"}
2022-03-21T05:04:15.099Z        info    service/service.go:92   Starting processors...
2022-03-21T05:04:15.100Z        info    builder/pipelines_builder.go:54 Pipeline is starting... {"name": "pipeline", "name": "metrics"}
2022-03-21T05:04:15.100Z        info    builder/pipelines_builder.go:65 Pipeline is started.    {"name": "pipeline", "name": "metrics"}
2022-03-21T05:04:15.100Z        info    service/service.go:97   Starting receivers...
2022-03-21T05:04:15.100Z        info    builder/receivers_builder.go:68 Receiver is starting... {"kind": "receiver", "name": "prometheus"}
2022-03-21T05:04:15.100Z        info    builder/receivers_builder.go:73 Receiver started.       {"kind": "receiver", "name": "prometheus"}
2022-03-21T05:04:15.100Z        info    service/telemetry.go:95 Setting up own telemetry...
2022-03-21T05:04:15.183Z        info    service/telemetry.go:115        Serving Prometheus metrics      {"address": ":8888", "level": "basic", "service.instance.id": "2bbe44cc-25e0-4fb1-9f06-36aa7341702e", "service.version": "latest"}
2022-03-21T05:04:15.183Z        info    service/collector.go:229        Starting aws-otel-collector...  {"Version": "v0.17.0", "NumCPU": 2}
2022-03-21T05:04:15.183Z        info    service/collector.go:124        Everything is ready. Begin running and processing data.
2022-03-21T05:05:15.100Z        info    awsemfexporter@v0.45.1/emf_exporter.go:133      Start processing resource metrics       {"kind": "exporter", "name": "awsemf", "labels": {"instance":"0.0.0.0:3000","job":"prod/task-service","port":"3000","scheme":"http","service.name":"prod/task-service"}}
2022-03-21T05:05:15.429Z        info    cwlogs@v0.45.1/pusher.go:298    logpusher: publish log events successfully.     {"kind": "exporter", "name": "awsemf", "NumOfLogEvents": 38, "LogEventsSize": 18.6669921875, "Time": 31}
2022-03-21T05:05:15.598Z        info    awsemfexporter@v0.45.1/emf_exporter.go:185      Finish processing resource metrics      {"kind": "exporter", "name": "awsemf", "labels": {"instance":"0.0.0.0:3000","job":"prod/task-service","port":"3000","scheme":"http","service.name":"prod/task-service"}}

PrometheusのReceiverが構成され、アプリケーションメトリクスの収集が始まっていることが分かります。

エラーが発生して、メトリクスが収集できない場合は、以下の観点で確認してください。

  • IAMロール(TaskService)にアクセス許可(ADOTCollectorポリシー)が追加設定されているか
  • サイドカーコンテナのパッチファイルが正しいか(特にボリュームマウント周辺)
  • OpenTelemetryの設定ファイル(otel-config.yaml)のシンタックスが正しいか
OpenTelemetry Operatorで自動的にサイドカーコンテナを注入する

今回はPodに直接サイドカーコンテナを設定しましたが、OpenTelemetryで用意しているOpenTelemetry Operatorを使うとPod作成時にサイドカーコンテナを自動的に追加可能です。
こちらのアプローチでサイドカーコンテナを注入する方が、マニフェストファイルをクリーンに保つことができます。
ただし、この場合は利用するimageにADOTのイメージを設定する必要がありますので注意してください。

OpenTelemetry Operatorでサイドカーコンテナを使う方法は以下を参照してください。

AWS X-Rayを使ったトレース情報の収集ではこちらのアプローチを利用していますので、参考にしてください。

アプリケーションメトリクス可視化

#

最後に、アプリケーションのメトリクスをCloudWatchで可視化してみましょう。

AWSマネジメントコンソールのCloudWatchメニューよりメトリクス -> すべのメトリクスを選択します。

cloudwatch metrics namespaces

上記のCustom namespacesのprod/task-service[4]から、サイドカーコンテナのADOTで収集されたメトリクスが確認できます。

例えば、アプリケーションのメモリ使用量をグラフ化してみましょう。

  1. ディメンションからspaceを選択
  2. メトリクスフィールドでused_bytesを入力してフィルタリング
  3. 表示されたメトリクスのチェックをON

以下のように、時系列グラフとして各領域のメモリの使用量が確認できます。

app memory graph

もちろんCloudWatchでも、Grafanaのようにダッシュボード機能があります。
しかし、事前に使えるものは一部のマネージドサービスのものだけで、prometheus-api-metricsのように綺麗なダッシュボードテンプレートがありませんので、自前で作成する必要があります。

ここでやり方を説明するよりも、実際に公式ドキュメントを参照し、自分で任意のダッシュボードを作成してみましょう。

サンプルとして以下のようなものが作成できます(表示をナイトモードに切り替えてGrafanaのUIに近くしています)。

複雑なグラフには個別にクエリ(メトリクスインサイト)記述もできますし、見た目のチューニングもある程度対応できることが分かります。

クリーンアップ

#

DaemonSetとしてインストールしたADOTは、helmコマンドでアンインストールしてください。

helm uninstall aws-otel-ds -n kube-system

それ以外のリリース削除については、以下を参照してください。

サイドカーコンテナとしてインストールしたADOTもアプリケーションと共に削除されます。

まとめ

#

OpenTelemetryという標準プロトコルを利用し、任意のバックエンドサービスに対してメトリクスの収集・可視化を行いました。
今回はCloudWatchをバックエンドサービスとして利用しましたが、OpenTelemetryはベンダー非依存のプロトコルですので、サポートされているプロダクトであれば設定変更で簡単に切り替えることができます。
モニタリングサービスは数多くありますので、自分の組織にあったものを採用する上でOpenTelemetryを抑えておくことは、今後重要になってくるでしょう。
ただし、現時点でOpenTelemetryやそのエコシステムはアクティブに開発中ですので、採用する場合は最新の状況をキャッチアップするようにしてください。

なお、今回のようにCloudWatch等のマネージドサービスをバックエンドサービスとして利用すると、簡単にスケーラビリティ獲得やツール自体の運用から開放されますが、課金条件に注意が必要です。
カスタムメトリクスは、意外にコストが高い印象ですので、各サービスの課金体系は事前にチェックしておきましょう。
最初は全量取得するとしても、その後の運用を通して不要なメトリクスをそぎ落としていく等の工夫が必要となることも多いと思います。

また、ここでは触れませんでしたが、CloudWatchでは、ADOTを使わずともPrometheusに蓄積したメトリクスの収集が可能になっています。

現在既にメトリクスの収集にPrometheusを使っていて、可視化部分を簡単にCloudWatchに移行したい場合は、こちらを検討するのも良いかと思います。


参照資料


更新情報

  • 2022-04-07: ADOTのHelmチャート(aws-otel/adot-exporter-for-eks-on-ec2)のバージョンアップ(0.1.0 -> 0.2.0)を反映(不具合パッチ記述を削除)

  1. OpenTelemetryの仕様では収集対象のメトリクスやトレース、ログのことをSignalsと呼んでいますが、ここではOpenTelemetryの名前からテレメトリーと訳します。 ↩︎

  2. 完成イメージを見たい場合は、こちらを参照してください。 ↩︎

  3. 通常のPrometheusの場合は、static_configsではなくkubernetes_sd_configs(サービスディスカバリ)を利用し、relabel_configsでフィルタリングすることが多いでしょう。 ↩︎

  4. Prometheusの設定(otel-config.yaml)で指定したjob_nameの値です。また、ContainerInsightsnamespaceがDaemonSetのADOTで収集したKubernetesメトリクスです。 ↩︎

豆蔵では共に高め合う仲間を募集しています!

recruit

具体的な採用情報はこちらからご覧いただけます。