Amazon Web Services ブログ

AWS Distro for OpenTelemetry Collector を使用したクロスアカウントの Amazon ECS メトリクス収集

この記事は、Using AWS Distro for OpenTelemetry Collector for cross-account metrics collection on Amazon ECS を翻訳したものです。

2020 年 11 月、AWS は AWS Distro for OpenTelemetry (ADOT) による OpenTelemetry のサポートを発表しました。これは AWS がサポートする Cloud Native Computing Foundation (CNCF) OpenTelemetry プロジェクトのセキュアかつプロダクションレディなディストリビューションです。ADOT を使用すると、相関性のあるアプリケーションメトリクスやトレースを Amazon Managed Service for Prometheus (AMP) やパートナーの監視ソリューションなど複数の AWS ソリューションに送信し、計測できます。

多くのお客様はアプリケーションを別々の AWS アカウントや別々の AWS リージョンで実行しつつ、アプリケーションの可観測性を一箇所で管理したいと考えています。以前の記事では、Amazon Elastic Kubernetes Service (Amazon EKS) を使用して複数アカウントにまたがってメトリクスを収集する方法を紹介しました。シナリオは似ていますが、今回は ADOT エージェントを使用して、AWS ネイティブなコンテナオーケストレーションプラットフォームである Amazon Elastic Container Service (Amazon ECS) で実行されているワークロードのアプリケーションおよびプラットフォームのメトリクスを AMP ワークスペースに収集します。

セットアップの概要

課題を解決するために次のような構成にします。

ワークロードを実行するアカウント(以下、ワークロードアカウント):

  • Amazon ECS のタスクで使用する IAM ロールを作成

モニタリングを実行するセントラルのアカウント(以下、モニタリングアカウント):

  • AMP ワークスペースを作成
  • AMP へのクロスアカウントアクセスを許可する IAM ロールの作成

ワークロードアカウント:

  • クロスアカウントの IAM ロールを引き受けるための Amazon ECS のタスクロールの作成
  • アプリケーションと AWS Distro for OpenTelemetry エージェントのセットアップ
  • Amazon ECS クラスターの作成とアプリケーションの実行

モニタリングアカウント:

全体のアーキテクチャは以下のようになります。

ワークロードアカウント: ECS のロールのセットアップ

ワークロードアカウントにログインし、のちに Amazon ECS のタスクで使用する IAM ロールを作成します。このロールはモニタリングを実行するモニタリングアカウントで信頼され、assume-role の権限を与えられます。

cat > task-assume-role.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
aws iam create-role --role-name ecs-xaccount-task-role \
  --assume-role-policy-document file://task-assume-role.json \
  --region eu-west-1

モニタリングアカウントのセットアップ

ワークロードアカウントにログインし、AWS CLI を使用した以下のコマンドで AMP ワークスペースを作成します。

aws amp create-workspace --alias ecs-xaccount-metrics-demo --region eu-west-1

もしくは AWS コンソールを使って AMP サービスに移動することもできます。

以下のコマンドで AMP ワークスペースへの書き込み権限を持つ IAM ロールを作成できます。複数のアカウントに権限を付与するには “AWS” 配列に適切な IAM ロールの ARN を入力します。

# ワークロードアカウントの ID を設定
WORKLOAD_ACCOUNT_ID=

cat > policy.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::$WORKLOAD_ACCOUNT_ID:role/ecs-xaccount-task-role"
        ]
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
EOF
# 注意: ワークロードアカウントに ecs-xaccount-task-role が存在しない場合に
# エラーが発生することがあります。
aws iam create-role \
  --role-name ECS-AMP-Central-Role \
  --assume-role-policy-document file://policy.json \
  --query 'Role.RoleName' \
  --output text
aws iam attach-role-policy --role-name ECS-AMP-Central-Role \
    --policy-arn arn:aws:iam::aws:policy/AmazonPrometheusRemoteWriteAccess

ワークロードアカウント

注:このセクションの説明は、必要な数のワークロードアカウントに対して繰り返します。
ワークロードアカウントにログインして、先に作成したロールに assumeRole 権限を付与します。

# モニタリングアカウントの ID を設定
CENTRAL_ACCOUNT_ID=

cat > policy.json <<EOF
{
   "Version":"2012-10-17",
   "Statement":[
      {
         "Effect":"Allow",
         "Action":[
            "sts:AssumeRole"
         ],
         "Resource":"arn:aws:iam::${CENTRAL_ACCOUNT_ID}:role/ECS-AMP-Central-Role"
      }
   ]
}
EOF
POLICY_ARN=$(aws iam create-policy --policy-name xaccount-amp-write \
    --policy-document file://policy.json | jq -r '.Policy.Arn')
aws iam attach-role-policy --role-name ecs-xaccount-task-role \
    --policy-arn $POLICY_ARN 

ワークロードの設定

次に、Prometheus のメトリクスを公開するサンプルアプリケーションを設定します。

  • アプリケーションと ECS のメトリクスをスクレイピングするため aws-otel-collectorを設定します。
  • Docker イメージをビルドし、Amazon Elastic Container Registry (Amazon ECR) 上でホストします。
  • ecs-cliを使用して、Amazon ECS クラスターの設定、作成、実行などを行います。

レイアウトは以下のように構成します。

├── aws-otel-collector
│   ├── Dockerfile
│   └── config.yaml
├── demo-app
│   ├── Dockerfile
│   └── main.go
├── docker-compose.yml
└── ecs-params.yml

Amazon ECS をセットアップするには、要件として Dockerecs-cli が必要です。Linux の場合、ecs-cliは以下のようにインストールできます。

sudo curl -Lo /usr/local/bin/ecs-cli https://amazon-ecs-cli.s3.amazonaws.com/ecs-cli-linux-amd64-latest

それでは、/metricsの Prometheus エンドポイント を公開するサンプルアプリケーションを作成してみましょう。

mkdir demo-app
cd demo-app/

cat > main.go <<EOF
package main
import (
    "github.com/prometheus/client_golang/prometheus/promhttp"
    "net/http"
)
func main() {
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8000", nil)
}
EOF

アプリケーション用の Dockerfile を作成します。

cat > Dockerfile <<EOF
FROM golang:1.15 as builder
WORKDIR /go/src/app
COPY . .
RUN go get .
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .

FROM alpine:latest
WORKDIR /app
RUN apk --no-cache add ca-certificates
COPY --from=builder /go/src/app/app .
EXPOSE 8000
CMD ["./app"]
EOF

最後に、以下のスクリプトで ECR リポジトリを作成し、アプリケーションのコンテナイメージをビルドして Amazon ECR にプッシュします。

APP_REPOSITORY=$(aws ecr create-repository --repository demo-app --query repository.repositoryUri --output text)
docker build . -t app
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin $APP_REPOSITORY
docker tag demo-app:latest $APP_REPOSITORY
docker push $APP_REPOSITORY
cd -

それでは、AWS Distro for OpenTelemetry Collector の設定を行っていきます。ここでは Pipeline と呼ばれるデータ収集のためのカスタム設定を作成します。Pipeline ではデータの受信から始まり、処理や修正、最後にエクスポーターを経由して Collector を出るまでの、データが Collector 内でたどる経路を定義します。

ここでは、/metrics エンドポイントを持つアプリケーションからデータを収集し、ecs-metrics-receiverを使用して ECS タスクメタデータエンドポイントから様々な ECS タスクメタデータをスクレイピングします。ecs-metrics-receiver やその他の設定オプションの詳細についてはドキュメントをご覧ください。

awsprometheusremotewrite exporters の設定を使用して、監視用のアカウントで作成された AMP ワークスペースに、収集したメトリクスをエクスポートします。AMP の remote_write エンドポイントと、ロールを引き受けるための IAM ロール (ここでは ECS-AMP-Central-Role) の両方を用意します。

変数の WORKSPACE_ID および CENTRAL_ACCOUNT_ID を編集し、以下のスクリプトを実行してパイプラインを作成します。

WORKSPACE_ID=
CENTRAL_ACCOUNT_ID=

mkdir aws-otel-collector
cd aws-otel-collector

cat > config.yaml <<EOF
receivers:
  prometheus:
    config:
      global:
        scrape_interval: 15s
        scrape_timeout: 10s
      scrape_configs:
      - job_name: "prometheus-demo-app"
        static_configs:
        - targets: [ 0.0.0.0:8000 ]
  awsecscontainermetrics:
    collection_interval: 20s

processors:
  filter:
    metrics:
      include:
        match_type: strict
        metric_names:
          - ecs.task.memory.utilized
          - ecs.task.memory.reserved
          - ecs.task.cpu.utilized
          - ecs.task.cpu.reserved
          - ecs.task.network.rate.rx
          - ecs.task.network.rate.tx
          - ecs.task.storage.read_bytes
          - ecs.task.storage.write_bytes

exporters:
  awsprometheusremotewrite:
    endpoint: https://aps-workspaces.eu-west-1.amazonaws.com/workspaces/$WORKSPACE_ID/api/v1/remote_write
    aws_auth:
      region: eu-west-1
      service: "aps"
      role_arn: arn:aws:iam::$CENTRAL_ACCOUNT_ID:role/ECS-AMP-Central-Role
  logging:
    loglevel: debug

service:
  pipelines:
    metrics:
      receivers: [prometheus]
      exporters: [logging, awsprometheusremotewrite]
    metrics/ecs:
      receivers: [awsecscontainermetrics]
      processors: [filter]
      exporters: [logging, awsprometheusremotewrite]
EOF

aws-otel-collector の最新バージョンを使用して、カスタムの設定を持つコンテナイメージを Amazon ECR に作成します。

cat > Dockerfile <<EOF
FROM public.ecr.aws/aws-observability/aws-otel-collector:latest
COPY config.yaml /etc/ecs/otel-config.yaml
CMD ["--config=/etc/ecs/otel-config.yaml"]
EOF

最後に、コンテナイメージをビルドしてプッシュします。

COLLECTOR_REPOSITORY=$(aws ecr create-repository --repository aws-otel-collector --query repository.repositoryUri --output text)
docker build . -t aws-otel-collector
aws ecr get-login-password --region eu-west-1 | docker login --username AWS --password-stdin $COLLECTOR_REPOSITORY
docker tag aws-otel-collector:latest $COLLECTOR_REPOSITORY
docker push $COLLECTOR_REPOSITORY
cd -

アプリケーションの実行: Amazon ECS のセットアップ

Amazon ECS はタスクを実行するための権限セットであるタスク実行ロールを必要とします。以下のスクリプトを実行して作成します。

cat > task-execution-assume-role.json <<EOF
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "",
      "Effect": "Allow",
      "Principal": {
        "Service": "ecs-tasks.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
EOF
aws iam create-role --role-name ecs-xaccount-task-execution-role \
    --assume-role-policy-document file://task-execution-assume-role.json \
    --region eu-west-1
aws iam --region eu-west-1 attach-role-policy --role-name ecs-xaccount-task-execution-role \
    --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy

WORKLOAD_ACCOUNT_ID 変数を設定し、以下のスクリプトを実行して docker-compose ファイルを作成します。

WORKLOAD_ACCOUNT_ID=

cat > docker-compose.yml <<EOF
version: "3"
services:
  aws-otel-collector:
    image: $WORKLOAD_ACCOUNT_ID.dkr.ecr.eu-west-1.amazonaws.com/aws-otel-collector:latest
    environment:
      - AWS_REGION=eu-west-1
    logging:
      driver: awslogs
      options: 
        awslogs-group: ecs-xaccount-metrics-demo
        awslogs-region: eu-west-1
        awslogs-stream-prefix: aws-otel-collector

  prometheus-demo-app:
    image: $WORKLOAD_ACCOUNT_ID.dkr.ecr.eu-west-1.amazonaws.com/demo-app
    ports:
      - "8000:8000"
    depends_on:
      - aws-otel-collector
    logging:
      driver: awslogs
      options: 
        awslogs-group: ecs-xaccount-metrics-demo
        awslogs-region: eu-west-1
        awslogs-stream-prefix: demo-app
EOF

ecs-cli を使って Amazon ECS クラスターを作成します。

ecs-cli configure --cluster ecs-xaccount-metrics-demo \
    --default-launch-type FARGATE \
    --config-name ecs-xaccount-metrics-demo \
    --region eu-west-1
ecs-cli up --cluster-config ecs-xaccount-metrics-demo

数分後、必要な関連リソースをすべて備えた ECS クラスターが作成されます。前述のコマンドから VPC_ID を設定し、その VPC に関連付けられたデフォルトのセキュリティグループを取得します。

VPC_ID=

aws ec2 describe-security-groups --filters Name=vpc-id,Values=$VPC_ID \
  --region eu-west-1 \
  --query SecurityGroups[0].GroupId \
  --output text

ecs-cli が必要とする ecs-params.yml ファイルを編集し、前のコマンドで出力されたサブネット ID とセキュリティグループに置き換えます。

version: 1
task_definition:
  ecs_network_mode: awsvpc
  task_role_arn: ecs-xaccount-task-role
  task_execution_role:  ecs-xaccount-task-execution-role
  task_size:
    mem_limit: 0.5GB
    cpu_limit: 256
run_params:
  network_configuration:
    awsvpc_configuration:
      subnets:
        - "subnet-"
        - "subnet-"
      security_groups:
        - "sg-"
      assign_public_ip: ENABLED

最後に、以下のスクリプトを実行してアプリケーションをデプロイします。

ecs-cli compose --project-name ecs-xaccount-metrics-demo \
  service up \
  --cluster-config ecs-xaccount-metrics-demo \
  --create-log-groups

数分後、Amazon ECS サービスが起動して実行されるはずです。Amazon CloudWatch Logs コンソールで aws-otel-collector のログを、ロググループ ecs-xaccount-metrics-demo で確認できます。

モニタリングアカウント: メトリクスの可視化

モニタリングアカウントに戻って、Amazon Managed Service for Grafana (AMG) のワークスペースを使ってメトリクスを可視化してみましょう。AMG の設定についてはドキュメントを参照してください。

アプリケーションのエンドポイントからのメトリクスを見ることができます。

Amazon ECS クラスターのメトリクス:

後片付け

ワークロードアカウント

WORKLOAD_ACCOUNT_ID=

# ECS サービスの停止と削除
ecs-cli compose --project-name ecs-xaccount-metrics-demo service down --cluster-config ecs-xaccount-metrics-demo

# ECS クラスターの削除
ecs-cli down --cluster-config ecs-xaccount-metrics-demo

# タスクロールの削除
aws iam detach-role-policy --role-name ecs-xaccount-task-role --policy-arn arn:aws:iam::$WORKLOAD_ACCOUNT_ID:policy/xaccount-amp-write
aws iam delete-policy --policy-arn arn:aws:iam::$WORKLOAD_ACCOUNT_ID:policy/xaccount-amp-write
aws iam delete-role --role-name ecs-xaccount-task-role

# タスク実行ロールの削除
aws iam detach-role-policy --role-name ecs-xaccount-task-execution-role --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
aws iam delete-role --role-name ecs-xaccount-task-execution-role

モニタリングアカウント

WORKSPACE_ID=

# IAM ロールの削除
aws iam detach-role-policy --role-name ECS-AMP-Central-Role --policy-arn arn:aws:iam::aws:policy/AmazonPrometheusRemoteWriteAccess
aws iam delete-role --role-name ECS-AMP-Central-Role
# ワークスペースの削除
aws amp delete-workspace --workspace-id $WORKSPACE_ID

まとめ

この記事では、AWS Distro for OpenTelemetry (ADOT) エージェントを使用して、Amazon ECS 上で動作するワークロードのアプリケーションおよびプラットフォームのメトリクスを収集する方法を説明しました。

ADOT は Amazon EKS、Amazon Elastic Compute Cloud (Amazon EC2)、またはオンプレミスなどの他のプラットフォームでも使用できます。さらに ADOT を使用して分散型トレース情報を収集し、複数の異なるワークロードアカウントがメトリクスを AMP や他のプラットフォームに一元的に送信することができます。また必要に応じて VPC エンドポイントや VPC ピアリングによるプライベート接続を設定することも可能です。
詳しくは ADOTAMPAMGのサイトをご覧ください。

翻訳はソリューションアーキテクト加治が担当しました。原文はこちらです。