Amazon Web Services ブログ

Amazon ECS と Amazon EKS での AWS Distro for Open Telemetry と CloudWatch Container Insights の Prometheus サポートのご紹介

この記事は Introducing CloudWatch Container Insights Prometheus Support with AWS Distro for OpenTelemetry on Amazon ECS and Amazon EKS (記事公開日: 2021 年 8 月 24 日) を翻訳したものです。

CloudWatch Container Insights を使用して、コンテナ化されたアプリケーションやマイクロサービスを監視、トラブルシューティング、アラームすることができます。Amazon CloudWatch は、CPU、メモリ、ディスク、ネットワークデータなどのコンピュート使用率情報を収集、集約、要約します。また、コンテナの再起動失敗などの診断情報を提供することで、問題を切り分け、迅速に解決するのにも役立ちます。Container Insights は、Amazon Elastic Container Service (Amazon ECS)Amazon Elastic Kubernetes Service (Amazon EKS)AWS Fargate、スタンドアロンの Kubernetes などの、コンテナ管理サービスからのインサイトを提供します。

AWS は、Cloud Native Computing Foundation (CNCF) の OpenTelemetry コミュニティのメンバーとして、分散トレースやメトリクスを収集するためのオープンスタンダードの定義に取り組んでいます。2020 年 10 月には、AWS Distro for OpenTelemetry (ADOT) のプレビューを開始しました。ADOT は、OpenTelemetry 仕様で定義された API 、ライブラリ、エージェント、コレクターの、安全でサポートされているディストリビューションです。

ADOT コレクターは、お客様の環境内で動作します。Amazon EKS と Amazon ECS での一般的な使用方法では、ADOT コレクターを次のように起動することをお勧めします。

  • Amazon EKS では、サイドカーや DaemonSet として
  • Amazon ECS では、サイドカーとして
  • Amazon Elastic Compute Cloud (Amazon EC2) 上のエージェントデーモンサービスとして

なお、ADOT コレクターは、StatefulSet などの他のモードでも起動できます。収集したいメトリクスやトレースを設定し、どの AWS サービスに転送するかを設定できます。さらに、サンプリングレート (生データの何パーセントを転送し、最終的に保存するか) を制御することもできます。

デフォルト設定では、ADOT は Container Insights により収集されるメトリクスのドキュメントで定義されているメトリクスの完全なセットを収集します。ADOT に特定のメトリクスを CloudWatch にストリームさせることで、CloudWatch に Container Insights のメトリクスを取り込むための AWS のコストを削減することが可能です。

Prometheus のバックグラウンド

Prometheus は人気のあるオープンソースのモニタリングツールで、Graduated という成熟度に分類されている CNCF のプロジェクトであり、大規模で活発なユーザーのコミュニティを持ちます。Container Insights は、コンテナ化されたアプリケーションからの Prometheus メトリクスの検出と収集を自動化します。AWS App Mesh、NGINX、Java/JMX、Memcached、HAProxy などの一般的なワークロードについて、カスタム CloudWatch メトリクスを自動的に収集、フィルタリング、集約し、ダッシュボードで可視化を行います。デフォルトでは、事前に選択されたサービスがスクレイピングされ、事前に集約され、クラスター名や Pod 名などのメタデータが自動的に追加されます。

Prometheus メトリクスの検出は、Amazon ECS、Amazon EKS、および Amazon EC2 インスタンス上で実行されている Kubernetes クラスターでサポートされています。Prometheus のカウンター、ゲージ、およびサマリーのメトリクスタイプが収集されます。Amazon ECS と Amazon EKS のクラスターでは、EC2 と Fargate の両方の起動タイプがサポートされています。Container Insights は自動的に一部のワークロードからメトリクスを収集しますが、任意のワークロードからメトリクスを収集するように構成することもできます。

CloudWatch にカスタムメトリクスを取り込むためのオープンソースかつオープンスタンダードな手法として、Prometheus を採用することができます。CloudWatch の Container Insights の Prometheus メトリクスのモニタリングは、Prometheus メトリクスの CloudWatch への送信と、すぐに使える視覚化をサポートしています。これまでは、CloudWatch エージェントのみが、Prometheus メトリクスの収集と、Container Insights のパフォーマンスダッシュボードで使用される CloudWatch のログ/メトリクス形式への変換をサポートしていました。最新リリースの ADOT コレクター (0.11) では、CloudWatch エージェントと同じ機能に加えて、改良された EMF エクスポーターと新しい ecsobserver 拡張機能が追加されています。

デザインと実装

Prometheus を CloudWatch の Container Insights の Prometheus メトリクスのモニタリングと統合するためには、解決すべき 2 つの課題があります。1 つ目は、さまざまな AWS コンテナ環境で Prometheus からメトリクスを取得することです。2 つ目は、適切なメタデータのセットを使用して CloudWatch 固有の形式でメトリクスを公開することです。

Prometheus は Pull ベースのメトリクス収集システムなので、コレクターは基盤となるコンテナ環境から API を使用して Prometheus のスクレイピングターゲットを検出する必要があります。コンテナオーケストレーションシステムの API から変更を監視することにより、コレクターは、新しいコンテナが起動したときに収集を開始し、古いコンテナがなくなったときに停止することができます。さらに、これらの API は、サービス名やコンテナ名などの追加のメタデータを提供します。これらのメタデータは、アプリケーション自体によっては公開されませんが、多数のサービスを監視するためには不可欠です。これらのメタデータがなければ、さまざまなディメンションに基づいてフィルタリングしたり、機能フラグ A を有効にしているすべての Java アプリケーションのヒープ使用量を取得するようなクエリを実行することはできません。Amazon EKS の場合、Prometheus には組み込みの Kubernetes のディスカバリーサポートがあるため、それを直接利用することができます。しかし、Amazon ECS の場合は、独自に作成する必要があります。CloudWatch エージェントではすでに実装していたので、それを OpenTelemetry コレクターに ecsobserver という新しい拡張機能として移植しました。

CloudWatch とその自動生成された Container Insights の Prometheus メトリクスのモニタリングのパフォーマンスダッシュボードをサポートするために、Prometheus の組み込みの relabel config と EMF エクスポーターの metrics_declaration を使って、特定のディメンションでメトリクスをエクスポートします。しかしながら、Container Insights のすべての機能を必要とせず、コストを削減したい場合は、設定ファイルを更新するだけで、メトリクスやディメンションの数を減らすことができます。すべての metrics_declaration ルールを削除したとしても、コンテナのメトリクスはすべて取得されます。メトリクスは常に構造化された JSON ログとしてエクスポートされ、CloudWatch Logs Insights を使って分析することができます。構造化されたログに含まれる情報が多すぎると思われる場合は、プロセッサーを使用してコレクターレベルでメトリクスをフィルタリングすることで、さらに減らすことができます。これは、コスト削減のためのノブが限られていて柔軟性がない CloudWatch エージェントとは異なります。

AWS が提供する他の OpenTelemetry コンポーネントと同様に、すべての実装は GitHub 上のコミュニティが管理するリポジトリで行われ、ADOT に含まれています。既存の CloudWatch EMF エクスポーターを Prometheus のメトリクスを認識できるように改良しprom_metric_type などの属性を追加しました。CloudWatch エージェントにはすでに実装されていた機能を、OpenTelemetry コレクターに ecsobserver という新しい拡張機能として移植しました。ecsobserver 拡張機能は新しいコンポーネントであり、既存の Prometheus のファイルベースのディスカバリーを再利用します。検出された Amazon ECS ターゲットを YAML ファイルとしてエクスポートするため、Prometheus レシーバーはコードを変更することなく file_sd を使ってそれを使用することができます。

さまざまな環境に対して、さまざまなコンポーネントのセットを選択するためのさまざまなパイプラインがあります。パイプラインは、デフォルトの config-all.yaml のような設定ファイルで定義されます。パイプラインは、OpenTelemetry コレクターのデータフローを定義し、メトリクスの受信、処理、エクスポート、およびトレースデータを含みます。各ステージには複数のコンポーネントが存在し、それらはシリアル (プロセッサー) またはパラレル (レシーバー、エクスポーター) に実行できます。内部的には、すべてのコンポーネントは OpenTelemetry の統一されたデータモデルを使用して通信するため、さまさまなベンダーのコンポーネントが連携できます。レシーバーはソースシステムからデータを収集し、内部モデルに変換します。プロセッサーはメトリクスのフィルタリングや修正を行います。エクスポーターは、データを他のスキーマに変換し、(リモートの) ターゲットシステムに送信します。拡張機能はさまざまなコンポーネントと連携し、さまざまなステージに適合することができます。詳細については、OpenTelemetry Collector Architecture を参照してください。

以下のグラフでは、CloudWatch Container Insights のシナリオをサポートするために ECS/EKS パイプラインで定義した主要なコンポーネントを示しています。2 つのパイプラインの唯一の違いは、Prometheus メトリクスのデータソースです。Amazon EKS と Amazon ECS では異なるディスカバリープラグインを使用しています。Amazon ECS パイプラインでは、ecsobserver 拡張機能が ECS API にクエリを実行し、Prometheus レシーバーが使用できるように結果をローカルファイルに書き込みます。Amazon EKS パイプラインでは、Prometheus 組み込みの Kubernetes ディスカバリーが Kubernetes API サーバーにクエリを実行するため、そのまま使用できます。パイプラインの残りの部分では、EMF エクスポーターを使用してメトリクスを変換し、CloudWatch に送信します。

Amazon ECS pipeline

Amazon ECS では、コレクターは ecsobserver 拡張機能を使ってスクレイピングターゲットを検出します。続いて、Prometheus レシーバーを使用してメトリクスを収集し、EMF エクスポーターを使用して CloudWatch に送信します。

Amazon EKS pipeline

Amazon EKS では、コレクターは Kubernetes API を監視する組み込みプラグインを使ってスクレイピングターゲットを検出します。続いて、Prometheus レシーバーを使用してメトリクスを収集し、EMF エクスポーターを使用して CloudWatch に送信します。

始めてみよう

クイックスタートとして、以下のコマンドを実行して、オールインワンの otel-container-insights-prometheus.yaml を既存の EKS クラスターにデプロイします。その他のワークロードやステップバイステップの手順については、公式ドキュメントを参照してください。(訳注: Amazon EKS でのステップバイステップの手順はこちらです。適切な IAM ポリシーをワーカーノードまたは IAM Roles for Service Accounts を使用して Pod にアタッチする必要があります。)

export CLUSTER_NAME=<eks-cluster-name>
export AWS_REGION=<aws-region>
wget https://raw.githubusercontent.com/aws-observability/aws-otel-collector/main/deployment-template/eks/otel-container-insights-prometheus.yaml
cat otel-container-insights-prometheus.yaml |sed "s/{{region}}/$AWS_REGION/g" | sed "s/{{cluster_name}}/$CLUSTER_NAME/g" | kubectl apply -f - 

上記のコマンドは、otel-container-insights-prometheus.yaml 内のクラスター名を置き換え、kubectl を使用してデプロイします。このシングルレプリカのデプロイメントでは、Docker イメージのビルド時にコンテナに含めたバンドルされた config-all.yaml を使用してコレクターを実行します。本番環境にデプロイするためには、Amazon EKS では ConfigMap を、Amazon ECS では SSM パラメータを使用することができます。

# https://github.com/aws-observability/aws-otel-collector/blob/main/config/eks/prometheus/config-all.yaml
    spec:
      serviceAccountName: aws-otel-collector
      containers:
        - name: aws-otel-collector
          image: amazon/aws-otel-collector:latest
          command: [ "/awscollector" ]
          args: [ "--config", "/etc/eks/prometheus/config-all.yaml" ]

設定の中では、receivers > prometheus > config > scrape_configs > kubernetes_sd_configs を使って、Prometheus レシーバーが組み込みの Kubernetesディスカバリーを使って Pod を検出するように設定しています。Prometheus スクレーパーが Kubernetes のメタデータを Prometheus のラベルに変換するための relabel_configs の長いリストがあります。これらのラベルは Prometheus レシーバーによって OpenTelemetry のラベルに変換され、最終的には CloudWatch ディメンションや EMF エクスポーターの構造化されたログのフィールドになります。例えば、__meta_kubernetes_namespace は、Prometheus レシーバーで Namespace にリネームされた Kubernetes Pod のメタデータです。EMF エクスポーターでは、metrics_decalarations > dimensions: [ [ ClusterName, Namespace ] ] を使ってディメンションとして抽出されます。一方、__meta_kubernetes_pod_namepod_name になりますが、ラベル名がディメンションのリストと一致しないため、構造化されたログに表示されるのみです。

# https://github.com/aws-observability/aws-otel-collector/blob/main/config/eks/prometheus/config-jmx.yaml
receivers:
  prometheus:
    config:
      global:
        scrape_interval: 1m
        scrape_timeout: 10s
      scrape_configs:
        - job_name: 'kubernetes-pod-jmx'
          sample_limit: 10000
          metrics_path: /metrics
          kubernetes_sd_configs:
            - role: pod
          relabel_configs:
            - action: replace
              source_labels:
                - __meta_kubernetes_namespace
              target_label: Namespace 
            - source_labels: [ __meta_kubernetes_pod_name ]
              action: replace
              target_label: pod_name
....

exporters:
  awsemf:
    namespace: ContainerInsights/Prometheus
    log_group_name: "/aws/containerinsights/{ClusterName}/prometheus"
    log_stream_name: "{TaskId}"
    resource_to_telemetry_conversion:
      enabled: true
    dimension_rollup_option: NoDimensionRollup
    metric_declarations:
      - dimensions: [ [ ClusterName, Namespace ] ]
        metric_name_selectors:
          - "^jvm_threads_(current|daemon)$"
          - "^jvm_classes_loaded$"
        label_matchers:
          - label_names:
              - service.name
            regex: ^kubernetes-pod-jmx$

コレクターを稼働させた後、JMX などのワークロードをデプロイして、事前に構築されたダッシュボードを試すことができます。デプロイ後、CloudWatch コンソール > Container Insights > Performance monitoring > EKS/ECS Prometheus で、事前に構築されたダッシュボードを確認できます。これらのダッシュボードは、サポートされているワークロードとクラスターごとに自動生成されます。サポートされているワークロードの完全なリストはドキュメントで確認できます。(訳注: Container Insights の Prometheus メトリクスのモニタリングのセットアップだけではダッシュボードにクラスターが表示されない場合、コンテナのメトリクスを収集する Container Insights をセットアップして下さい。)

Pre-built dashboard in console

CloudWatch コンソールのパフォーマンスダッシュボードに、App Mesh の 1 秒あたりのリクエスト数、合計ヒープ使用量などの Prometheus メトリクスが表示されます。

メトリクスは EMF ログとしてエクスポートされるため、対応するロググループで見つけることができます。一部のログは、EMF エクスポーターの metric_declarations の設定に基づいて、メトリクスのメタデータを持たない場合があります。(注: Amazon EKS と Amazon ECS のロググループは異なります。次の画面キャプチャは、Amazon ECS での例を示しています。)

Amazon EKS の場合、ロググループは /aws/containerinsights/my-eks-cluster-name/prometheus となります。_aws 以下の JSON フィールドには、ログから抽出されたメトリクスのメタデータが含まれます。これらは、コレクターの EMF エクスポーターでの設定と一致する必要があります。

ECSS SD view log

CloudWatch Logs コンソールに、メトリクスの名前空間とディメンションのために埋め込まれたメトリクスメタデータを含む JSON ログエントリが表示されます。

まとめ

このブログ記事では、ADOT を使用して、CloudWatch Container Insights で Amazon ECS と Amazon EKS の Prometheus メトリクスをモニタリングする方法を説明しました。Prometheus メトリクスに対する ADOT サポートのプレビューが利用可能であり、今日から使用を開始できます。Amazon CloudWatch と AWS X-Ray における AWS のオブザーバビリティ機能の詳細については、One Observability Demo ワークショップをご覧ください (訳注: 日本語も選択可能です) 。

AWS はアップストリームリポジトリを追跡し、ツールキットの新しいバージョンを毎月リリースする予定です。このブログで紹介したコンポーネントの使いやすさの向上に常に取り組んでいます。 例えば、クラスター名の自動検出や、オブザーバー作成フレームワークのパフォーマンス向上などがあります。これはオープンソースプロジェクトであり、皆様からのプルリクエストやコミュニティへの貢献をお待ちしています。AWS 関連のコンポーネントについてフィードバックやレビューが必要な場合は、GitHub の PR/Issue にタグ付けしてください。“ (多すぎる) 例で混乱している” などの質問がある場合は、ADOT リポジトリで Issue を開くこともできます。

著者について

  • Pinglei Guo は、Amazon CloudWatch の SDE です。彼は OpenTelemetry コレクターと CloudWatch Agent に貢献しています。余暇には、アニメを見たり、友人とビデオゲーム (モンスターハンターなど) をしたりしています。
  • Mengyi Zhou は、Amazon CloudWatch の SDE です。OpenTelemetry コミュニティのオブザーバビリティとモニタリングのプロジェクトに貢献しています。彼女はまた、Kubernetes に熱心であり、コンテナ化されたアプリケーション用の大規模な PaaS プラットフォームを構築しています。
  • Javier Martin は、シアトルを拠点とする Amazon CloudWatch のシニアプロダクトマネージャーです。AWS で顧客のシステムやアプリケーションの監視を支援する製品を作るのが大好きです。

翻訳はプロフェッショナルサービスの杉田が担当しました。原文はこちらです。