ラベル付きメトリックのチュートリアル
このチュートリアルでは AWS の ECS 上で稼働している Nginx を対象に、ゼロからラベル付きメトリックを収集して Mackerel のダッシュボード上でグラフを表示するところまでをゴールとします。
なお、Mackerel のラベル付きメトリック機能は本記事執筆時点(2023 年 9月)でベータ版となっています。そのため、Mackerel のウェブコンソール上の画面は実際のものと異なる場合があります。
現在、「ラベル付きメトリック機能」ベータ版テストの参加者を募集しています。下記のフォームよりベータ版テストへの参加お申し込みをいただけます。
OpenTelemetry コレクターを設定する
OpenTelemetry コレクターは、テレメトリーデータの受信・処理・エクスポートについてベンダーに依存しない実装を提供します。テレメトリーデータをバックエンドから直接エクスポートするのではなく、コレクターを経由することには、以下のようなメリットがあります。
- バックエンドからはエクスポート先を意識せずにテレメトリーデータを送信できる
- データを加工したり、複数のエクスポーター(Mackerel, Jaeger, Prometheus)へ送信したりできる
- パフォーマンスを最適化できる
OpenTelemetry コレクターは YAML ファイルで設定を記述することで、どこから来たデータをどのように加工して送信するかを定義します。 設定は以下の 4 つのコンポーネントから構成されています。
- Receivers: テレメトリーデータをコレクターに取り込む方法
- Processors: テレメトリーデータを加工する
- Exporters: テレメトリーデータをバックエンドにエクスポートする
- Connectors: 2 つのパイプラインを接続する(今回のチュートリアルでは使用しません)
これらのコンポーネントは service セクション内の pipelines で定義しない限り、有効となりません。今回は、以下のような設定を記述します。
receivers: nginx: endpoint: "http://localhost:80/status" collection_interval: 10s processors: batch: timeout: 1m exporters: otlp/mackerel: endpoint: otlp.mackerelio.com:4317 compression: gzip headers: Mackerel-Api-Key: ${env:MACKEREL_APIKEY} service: pipelines: metrics: receivers: [nginx] processors: [batch] exporters: [otlp/mackerel]
それぞれのセクションについて詳しく見ていきましょう。
receivers
receivers はデータをコレクターに取り込む方法です。多くのレシーバーにはデフォルトの設定が付属しているので、レシーバー名を指定するだけで利用できます。
ここでは Nginx からデータを収集するため、Nginx Receiver をレシーバーとして指定しています。このレシーバーは、Nginx の ngx_http_stub_status_module
で提供される status
エンドポイントからメトリックを取得します。
receivers: nginx: endpoint: "http://localhost:80/status" collection_interval: 10s
Nginx Receiver は以下のオプションを必ず指定する必要があります。
endpoint
: Nginx のstatus
エンドポイントの URL。Nginx 側の設定に応じて、適宜変更が必要。
任意で以下の 2 つの設定を行えます。
collection_interval
: データを収集する間隔。デフォルトは 10 秒。initial_delay
:データを収集する前に待機する時間。デフォルトは 1 秒。
Nginx Receiver がメトリックを取得できるよう、Nginx 側で ngx_http_stub_status_module を有効にする必要があります。これには Nginx の設定の server
または location
ディレクティブに以下のように追加します。location
に指定するパス名 /status
は、 endpoint
で指定した URL と一致していなければなりません。
location /status { stub_status; }
processors
processors はテレメトリーデータを加工するもので、データを受信してからエクスポートされるまでの間に実行されます。デフォルトでは有効となっているプロセッサーはありませんが、データソースによって推奨されるプロセッサーがあります。
今回の例では batch プロセッサーを指定しています。batch プロセッサーは、指定した時間ごとにデータをバッチ処理してエクスポートするプロセッサーです。バッチ処理により、データがより適切に圧縮され、データの送信に必要な発信接続の数が削減されます。batch プロセッサーはすべてのコレクターで有効にすることを強く推奨します。
ここでは timeout
セクションに 1m
を設定して、1 分ごとにデータをバッチ処理しています。
processors: batch: timeout: 1m
exporters
exporters は複数のバックエンド/デスティネーションにデータを送信する方法を定義します。例えば、Mackerel, Prometheus, Jaeger などのシステムに対して設定を記述し service セクションのパイプラインで指定することで、1 つのコレクターから複数のバックエンドにデータを送信できます。多くの場合、エクスポーターにはエンドポイントと認証情報の設定を記述することになります。
今回は Mackerel にデータを送信するために、otlp/mackerel
を指定します。ここで指定するキー名は、後ほど service セクションの pipeline で指定するために使用するものです。/
以降の文字は、ユニークな名前であれば任意の名前を指定できます。
endpoint
はデータの送信先です。この設定は Mackerel を利用する際は固定の値で otlp.mackerelio.com:4317
となります。Mackerel では認証方式として API キーを使用するため、headers.Mackerel-Api-Key
に API キーを設定しています。ここでは API キーは環境変数から取得するようにしています。
exporters: otlp/mackerel: endpoint: otlp.mackerelio.com:4317 compression: gzip headers: Mackerel-Api-Key: ${env:MACKEREL_APIKEY}
ここでは、MACKEREL_APIKEY
という名前で環境変数を設定することを想定しています(環境変数は後ほど設定します)。
service
service セクションは定義されたコンポーネントの中でどれを有効にするかを定義します。service セクション内で使用されていないコンポーネントは有効となりません。
service セクションには pipelines
セクションがあり、ここでレシーバー、プロセッサー、エクスポーターのセットを構成します。pipelines
セクションには、トレース(trace
)、メトリック(mtrics
)、ログ(logs
)のデータを処理するパイプラインのセクションをそれぞれ定義します。
今回はメトリックのみを処理するので metrics
のみを使い、service セクションの外側でこれまで定義してきたレシーバー、プロセッサー、エクスポーターのセットのセットを指定します。
service: pipelines: metrics: receivers: [nginx] processors: [batch] exporters: [otlp/mackerel]
この設定では、Nginx Receiver で収集したデータを batch プロセッサーでバッチ処理し、otlp/mackerel エクスポーターで Mackerel にデータを送信する、というパイプラインを定義しています。
OpenTelemetry コレクターを起動する
OpenTelemetry コレクターを実行するには、テレメトリーデータを収集する対象のアプリケーションと同じホストにインストールする必要があります。今回は、Docker を使用して先ほどの設定ファイルを読み込んだイメージを作成し、そのイメージをもとにコンテナを起動します。
Docker イメージを作成する
まずはイメージを作成するために、以下の Dockerfile を作成します。Docker Hub で OpenTelemetry より公開されている otel/opentelemetry-collector-contrib イメージをベースとして、先ほどの設定ファイルをコンテナ内にコピーします。
opentelemetry-collector-contrib は、多くのコンポーネントがあらかじめ含まれているイメージです。さまざまな構成を試すために、このイメージをベースにするのは妥当な選択です。しかし、本番環境では、環境に必要なコンポーネントのみを含めたイメージを作成することが以下の理由から推奨されます。
- コレクターのサイズを縮小し、コレクターのデプロイメント時間を短縮する
- 利用可能な攻撃対象領域を減らすことで、コレクターのセキュリティを向上させる
OpenTelemetry Collector Contrib Distro - Recommendation
本番環境では otel/opentelemetry-collector をベースイメージとして必要なプラグインのみを含めてビルドすることをお勧めします。
設定ファイルの名前は otel-collector-config.yaml
とし、Dockerfile と同じディレクトリに配置します。設定ファイルは起動時の引数で指定するため、CMD
で設定ファイルのパスを指定しています。
FROM otel/opentelemetry-collector-contrib:latest COPY otel-collector-config.yaml /etc/otel-collector-config.yaml CMD ["--config=/etc/otel-collector-config.yaml"]
次に、Dockerfile と同じディレクトリで以下のコマンドを実行してイメージを作成します。このチュートリアルでは ECS を amd64
アーキテクチャで使用するため、--platform linux/amd64
を明示しています。
docker build -t otel-collector --platform linux/amd64 .
作成したイメージを ECS から利用できるようにするために、ECR にリポジトリを用意し、イメージをプッシュします。まずは ECR のリポジトリを作りましょう。AWS コンソールから直接作成してもよいのですが、ここでは Terraform を使用して作成することにします。以下のような main.tf
を作成します。
resource "aws_ecr_repository" "repo" { name = "nginx-opentelemetry-collector" image_tag_mutability = "MUTABLE" }
terraform init
で初期化し、terraform apply
でリポジトリを作成します。
terraform init terraform apply
これで、nginx-opentelemetry-collector
という名前の ECR リポジトリが作成されました。次に、イメージをプッシュします。ECR にイメージをプッシュするためのコマンドは、AWS コンソールの「AmazonECR」>「リポジトリ」>「nginx-opentelemetry-collector(作成したリポジトリ名)」>「プッシュコマンドの表示」から確認できます。基本的には、表示されるコマンドに沿って実行すれば問題ありません。
正常にコマンドの実行が完了していれば、ECR にイメージがプッシュされているはずです。ECR のコンソールから確認してみましょう。
ECS に OpenTelemetry コレクターをデプロイ
ECR にイメージをプッシュできたので、このイメージを ECS にデプロイして OpenTelemetry コレクターを実行できるようにしましょう。
ECS タスク定義 に、先ほど ECR にプッシュした OpenTelemetry コレクターのイメージをタスクの情報として JSON 形式で記述します。
{ "containerDefinitions": [ { "cpu": 0, "essential": false, "image": "{ECR の URL}/nginx-opentelmetry-collector:latest", "logConfiguration": { "logDriver": "awslogs", "options": { "awslogs-group": "/aws/ecs/nginx", "awslogs-region": "ap-northeast-1", "awslogs-stream-prefix": "otel-collector" } }, "memory": 64, "name": "otel-collector", "secrets": [ { "name": "MACKEREL_APIKEY", "valueFrom": "{AWS Parameter Store のパラメータ名}" } ] } ], }
コンテナの定義は containerDefinitions
の配列の要素として記述します。image
には ECR リポジトリの名前とイメージ名を指定します。logConfiguration
にはコンテナのログの設定を記述します。ここでは CloudWatch Logs にログを送信するように設定しています("logDriver": "awslogs"
)。
secrets
にはコンテナ内で使用する環境変数を指定します。ここでは Mackerel の API キーを環境変数として指定しています。この環境変数は otel-collector-config.yaml
ファイル内で ${env:MACKEREL_APIKEY}
と指定した箇所で使用されます。MACKEREL_APIKEY
の値は valueFrom
から Parameter Store のパラメータ名を指定するように設定しています。
Parameter Store にはあらかじめ Mackerel の API キーを保存しておく必要があります。これは、Mackerel のウェブコンソールの「オーガニゼーション詳細」>「API キー」から確認できます。
上記のタスク定義をもとに、ECS にデプロイしましょう。これで、OpenTelemetry コレクターの起動が完了しました!
Mackerel のカスタムダッシュボードからグラフを作成する
OpenTelemetry コレクターの起動が完了してしばらくたつと、Mackerel のカスタムダッシュボード上でメトリックの一覧を表示できるようになります。API キーを取得したオーガニゼーションの Mackerel のウェブコンソールから「ダッシュボード」>「カスタムダッシュボードを追加」を選択してください。
https://mackerel.io/my/dashboards
カスタムダッシュボードを追加する画面が表示されたら、グラフウィジェットを選択してグリッド上にドラッグ&ドロップしてください。
グラフウィジェットを追加するダイアログが表示されたら、「グラフのタイプ」で「クエリグラフ」を選択しましょう(「クエリグラフ」はベータ版利用者のみに表示されます)。PromQL を記述するエディタが開き、上部のメニューからメトリック一覧を表示できます。
正しくメトリックを収集できていれば、以下のメトリックが表示されているはずです。
- nginx.requests
- nginx.connections_current
- nginx.connections_accepted
- nginx.connections_handled
例として nginx.connections_current
を選択してみると、以下のようにグラフが表示されます!(もし 0 しか表示されない場合には、グラフの表示期間を 30m など短い期間に変更してみてください)
デフォルトでは、凡例はクエリとラベルを結合したものが設定されます。nginx.connections_current
のクエリで表示されるグラフの凡例は、以下のように表示されていることがわかります。
nginx.connections_current{state="active"}
nginx.connections_current{state="waiting"}
nginx.connections_current{state="writing"}
nginx.connections_current{state="reading"}
ラベルの数が多くなると凡例の長さも非常に長くなり、グラフのメモリがどのラベルに対応するものなのかわからなくなってしまうかもしれません。そこで、凡例の表示方法を変更してみましょう。
凡例の表示方法は設定から変更できます。設定画面の「凡例」から「値」のセレクトボックスを選択すると、現在のクエリに対応するラベルの一覧が表示されます。ここでは state
を選択してみましょう。
セレクトボックスで選択された値は「凡例」の「表示」に {{state}}
と表示されます。これは凡例のテンプレート構文であり、{{}}
で囲った価がラベルのキーとして存在する場合、その値に置き換えられます。今回は state
がラベルのキーとして存在するため、{{state}}
が active
といった値に置き換えられます。
まとめ
今回は、Mackerel でラベル付きメトリックを収集する方法についてご紹介しました。ラベル付きメトリック機能は、業界標準の OpenTelemetry へ対応して、クラウド環境の進化に合わせて Mackerel の対応環境を増やすことを目的としています。
Mackerel ではラベル付きメトリック機能のベータ版テストの参加者を募集しています。ラベル付きメトリックでは従来の Mackerel の「手軽に監視を導入できる」という特徴を引き継げていないなど、まだまだ課題を抱えています。ベータ版テストの参加者の皆様のフォードバックにより、より良い製品にしていきたいと考えています。
ラベル付きメトリック機能のベータ版テストに参加してみたいという方は、ぜひ以下のフォームからご連絡ください!