AWS CloudWatch エージェントでPrometheus エクスポーターのメトリクスを取得する

ざつくり本記事について説明するとcloudwatchとPrometheusエクスポータの連携についてです。

AWS ECSを監視する際にCloudWatch エージェントを使うことが多いと思うが、

CloudWatch エージェントで取得できるメトリクスは限られている。

CloudWatchエージェントで取得できるメトリクスはこちら

そこで、Prometheusのエクスポーターを使ってCloudWatchにメトリクスを送ることにより、CloudWatchエージェントでは取得できないメトリクスについて取得・監視することが可能となる。

以下のような挙動になります。

  1. CloudWatchエージェントが監視対象のサーバを検出
  2. CloudWatchエージェントが監視対象サーバのメトリクスを取得
    • 監視されるサーバにはPromethusエクスポーターを入れておく必要あり
  3. CloudWatchエージェントが取得したメトリクスをCloudWatchに送る

Prometheusとは??という方は以下の記事をご参照ください

Prometheusとはーシステム監視で利用できるPrometheusについてざっくり理解する

スポンサーリンク

どんなAWSサービスを使うの?

  • ECS-Fargate
  • Cloud watch

Prometheus エクスポーターを使うとどんな感じになるの?

前準備:ECS-FargateにCloudWatchエージェントとPrometheusのエクスポータを入れておく

実際の動作:CloudWatchエージェントがPrometheusのエクスポータを叩き、結果をCloudWatchへ送る

Amazon ECS クラスターで Prometheus メトリクスコレクションをセットアップおよび設定する - Amazon CloudWatch
Amazon ECS で Prometheus メトリクスを収集するために CloudWatch Container Insights をセットアップする方法について説明します。

ここら辺の話。

文字だけだとわかりづらいので、試しにapacheエクスポーターを使って実際の動作を確かめてみます。

apacheエクスポーターを使って実際に動作を確認

Dokerイメージの作成

以下のものをコンテナにインストールしてapacheエクスポーターの動きを見ていきます。

  • apache
  • CloudWatch agent
  • Supervisord
  • Prometheus exporter(apache exporter)

supervisordの設定ファイルの作成

「supervisord.conf」というファイル名で以下の内容のファイルを作成します

[supervisord]
user = root
nodaemon=true

[program:apachectl]
command=/usr/sbin/apache2ctl -DFOREGROUND

[program:amazon-cloudwatch-agent]
command=/opt/aws/amazon-cloudwatch-agent/bin/start-amazon-cloudwatch-agent

[program:prometheus-apache-exporter]
command=/usr/local/apache_exporter-0.7.0/apache_exporter

Dockerfileでインストールするものを起動するような設定となっています。

CloudWatchエージェントの設定ファイルの作成

「amazon-cloudwatch-agent.json」というファイル名で以下の内容のファイルを作成します

{
  "logs": {
	"metrics_collected": {
	  "prometheus": {
		"prometheus_config_path": "/opt/aws/amazon-cloudwatch-agent/bin/prometheus.yaml",
		"ecs_service_discovery": {
			"sd_frequency": "1m",
			"sd_result_file": "/tmp/cwagent_ecs_auto_sd.yaml",
			"task_definition_list": [
			  {
				"sd_metrics_ports": "9117",
				"sd_task_definition_arn_pattern": ".*:task-definition/.*prometheus.*",
				"sd_metrics_path": "/metrics"
			  }
			]
		},
		"emf_processor": {
		  "metric_declaration": [
			{
			  "source_labels": ["container_name"],
			  "label_matcher": "^cloudwatch-agent-prometheus$",
			  "dimensions": [["ClusterName"]],
			  "metric_selectors": [
				"^apache_accesses_total$"
			  ]
			}
		  ]
		}
	  }
	},
	"force_flush_interval": 5
  }

}

task_definition_list内の条件に合致するメトリクス取得対象を自動検出して「/tmp/cwagent_ecs_auto_sd.yaml」に吐き出す。

metric_declaration内の条件でCloudWatchにメトリクスを送る

Prometheusの設定

「prometheus.yaml」というファイル名で以下の内容のファイルを作成します

global:
 scrape_interval:     15s
 evaluation_interval: 15s 
scrape_configs:
  - job_name: cwagent-ecs-file-sd-config
    sample_limit: 10000
    file_sd_configs:
      - files: [ "/tmp/cwagent_ecs_auto_sd.yaml" ]

「/tmp/cwagent_ecs_auto_sd.yaml」内の情報で15秒間隔でメトリクスを取得するよってこと

Dockerfileの中身

「Dockerfile」というファイル名で以下の内容のファイルを作成します

FROM ubuntu

ENV DEBIAN_FRONTEND noninteractive

# curlインストール
RUN apt-get update \
&& apt-get install -y curl

# Apacheインストール
RUN apt-get install -y apache2

# CloudWatchエージェントインストール
RUN curl -Lo amazon-cloudwatch-agent.deb https://s3.amazonaws.com/amazoncloudwatch-agent/ubuntu/amd64/latest/amazon-cloudwatch-agent.deb
RUN dpkg -i -E ./amazon-cloudwatch-agent.deb
COPY amazon-cloudwatch-agent.json /opt/aws/amazon-cloudwatch-agent/bin/default_linux_config.json
ENV RUN_IN_CONTAINER=True

# Supervisorインストール
RUN apt-get install -y supervisor 
COPY ./supervisord.conf /etc/

#prometheus関連
COPY ./prometheus.yaml /opt/aws/amazon-cloudwatch-agent/bin/prometheus.yaml
RUN curl -Lo apache_exporter-0.7.0.linux-amd64.tar.gz  https://github.com/Lusitaniae/apache_exporter/releases/download/v0.7.0/apache_exporter-0.7.0.linux-amd64.tar.gz
RUN tar zxvf apache_exporter-0.7.0.linux-amd64.tar.gz
RUN mv -i apache_exporter-0.7.0.linux-amd64 /usr/local/apache_exporter-0.7.0
WORKDIR /usr/local/
RUN ln -s apache_exporter-0.7.0 apache_exporter

EXPOSE 80 9117

# 起動
CMD /usr/bin/supervisord -c /etc/supervisord.conf

「RUN_IN_CONTAINER=True」を記載しないとコンテナでCloudWatchエージェントが動かないので要注意です。

Dockerイメージのビルド

Dockerイメージを以下のコマンドでビルドします。

docker build -t prometheustest/prometheustest:latest .

Amazon Elastic Container Registryへイメージをプッシュ

作成したイメージはAmazon Elastic Container Registryへイメージをプッシュしておきます

コンテナの起動

ロールの作成

以下のポリシーを持ったロールを作成する

 
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "ecs:DescribeTasks",
                "ecs:ListTasks",
                "ecs:DescribeContainerInstances"
            ],
            "Resource": "*",
            "Effect": "Allow"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:PutMetricData",
                "ec2:DescribeVolumes",
                "ec2:DescribeTags",
                "logs:PutLogEvents",
                "logs:DescribeLogStreams",
                "logs:DescribeLogGroups",
                "logs:CreateLogStream",
                "logs:CreateLogGroup"
            ],
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "ssm:GetParameter"
            ],
            "Resource": "arn:aws:ssm:*:*:parameter/AmazonCloudWatch-*"
        }
    ]
}

コンテナ起動

  1.  ECSコンソール画面から「クラスターの作成」ボタンを押下してクラスターを作成する。設定値は以下を参照。
    • クラスター名:prometheus-test
    • 上記以外はデフォルトのまま
  2. ECSコンソール画面からタスク定義を選択後に「新しいタスク定義の作成」ボタンを押下してタスク定義を作成する。設定値は以下を参照。
    • タスク定義ファミリー:ecs-prometheus-test
    • コンテナ:イメージURIにElastic Container RegistryのURIを設定
    • タスクロール:先ほど「ロール作成」で作成したロールを指定
    • タスク実行ロール:先ほど「ロール作成」で作成したロールを指定
    • 上記以外はデフォルトのまま
  3. ECSコンソール画面から作成したクラスターを選択し、タスクタブを選択し、「新しいタスクの実行」ボタンを押下して、コンテナを起動する
    • タスク定義:先ほど作成したタスク定義
    • 必要なタスク:1
    • セキュリティグループ:ポート「9117」を許可
    • 上記以外はデフォルトのまま

Prometheus エクスポーターでCloudWatchにメトリクスを送った結果

Prometheus エクスポーターでCloudWatchにメトリクスを送った結果

複数のコンテナが立ち上がってる場合、「/tmp/cwagent_ecs_auto_sd.yaml」に複数コンテナの情報が書き込まれ、立ち上がってる分だけのコンテナの情報を収集するので、CloudWatchエージェント用のコンテナを立てるのが普通?

 

ちなみに、、自身のコンテナの情報だけをCloudWatchへ送る方法もある。この場合、CloudWatchエージェント用のコンテナは不要。やり方は↓↓↓↓↓↓↓↓↓↓↓

Prometheus エクスポーターでコンテナローカルのメトリクス 取得ver.

コンテナローカルのメトリクス 取得ver.

コンテナの自動検出機能を使わないと↓こんな感じ↓になる

amazon-cloudwatch-agent.json(コンテナローカルのメトリクス 取得ver.)

{  
  "logs": {
	"metrics_collected": {
	  "prometheus": {
		"prometheus_config_path": "/opt/aws/amazon-cloudwatch-agent/bin/prometheus.yaml",
		"emf_processor": {
		  "metric_declaration": [
			{
			  "source_labels": ["ClusterName"],
			  "label_matcher": "*",
			  "dimensions": [["ClusterName","job"]],
			  "metric_selectors": [
				"^apache_accesses_total$"
			  ]
			}
		  ]
		}
	  }
	},
	"force_flush_interval": 5
  }
}

prometheus.yaml(コンテナローカルのメトリクス 取得ver.)

global:
 scrape_interval:     15s
 evaluation_interval: 15s 
scrape_configs:
  - job_name: 'apache'
    static_configs:
      - targets: ['localhost:9117']