本記事は、Mackerel Advent Calendar 2024 10日目の記事です。
Mackerel開発チーム SREの id:taxintt と申します。
もうすぐ2024年が終わりますね。Mackerel 的にも様々なことがあった一年ですが、その中でも大きな話題としては OpenTelemetry 対応でしょうか。
OpenTelemetry 対応のメトリックについては、2023年9月からベータ版としての提供を始めたラベル付きメトリック機能が2024年11月から正式版としてリリースされました。
2024年8月末からは OpenTelemetry のトレースに対応した分散トレーシングサービスとして Vaxila(ヴァキシラ)が利用できるようになりましたね。
OpenTelemetry の特徴の一つとして特定のベンダーやツールに依存することなく様々な Observability バックエンドと組み合わせて利用できるという点が挙げられています。
Vendor- and tool-agnostic, meaning that it can be used with a broad variety of Observability backends, including open source tools like Jaeger and Prometheus, as well as commercial offerings.
ということで今回は、Google Cloud が提供するマネージド コンピューティング プラットフォームである Cloud Run から Mackerel に対して OpenTelemetry のメトリックとトレースを送ってみようと思います。 Google Cloud での Mackerel の利用事例はあまりインターネットで見ないなと思い、せっかくなので Cloud Run を選択してみました。
サンプルコードも用意したので、宜しければご自身の Google Cloud のプロジェクトでも試してみてください。
サンプルコードの構成について
アプリケーションは GET /hello のエンドポイントを提供する API server です。OpenTelemetryのメトリックとトレースを送信するための必要最小限のコードとなっています。
今回の記事で利用するサンプルの構成としては、OpenTelemetry のメトリックとトレースを計装したアプリケーションと Opentelemetry Collector を同一の Cloud Run のサービスとしてデプロイしています。
さて、ここからはサンプルコードの中身をみていきましょう。まずは、Opentelemetry Collector の設定ファイルの中身について説明します。
receivers: otlp: protocols: grpc: endpoint: 0.0.0.0:4317 http: endpoint: 0.0.0.0:4318 processors: batch: send_batch_max_size: 200 send_batch_size: 200 timeout: 5s resourcedetection: detectors: [env, gcp] timeout: 2s override: false resource: attributes: - key: service.instance.id from_attribute: faas.id action: upsert - key: service.name value: ${env:K_SERVICE} action: insert exporters: otlp/mackerel: endpoint: otlp.mackerelio.com:4317 compression: gzip headers: Mackerel-Api-Key: ${env:MACKEREL_APIKEY} otlphttp/vaxila: endpoint: "https://otlp-vaxila.mackerelio.com" headers: Accept: "*/*" "Mackerel-Api-Key": ${env:MACKEREL_APIKEY} extensions: health_check: service: extensions: [health_check] pipelines: metrics: receivers: [otlp] processors: [batch, resourcedetection, resource] exporters: [otlp/mackerel] traces: receivers: [otlp] processors: [batch] exporters: [otlphttp/vaxila]
MackerelにOpenTelemetryのメトリックとトレースを送信する際にはテレメトリーデータの送信先は分ける必要があるので、アプリケーションから OpenTelemetry Collector にテレメトリーデータを送信し、Collector 側で送信先を分けています。
Cloud Run にはサービス側で自動的にセットされる環境変数のセットが存在するため、その中から実行されている Cloud Run サービスの名前である K_SERVICE を service.name のAttributeとしてセットしています。
また、resource detection processorを利用して、Google Cloudのmetadata serverからリソース情報を取得してAttributeとして付与するようにしています。
セットアップ ~ サンプルアプリケーションのデプロイまで
Mackerel (Vaxila) にテレメトリーデータを送信する際に利用されるAPI keyは環境変数としてセットする必要があります。 Secret Manager から API key (mackerel_apikey) を取得して Cloud Run の実行時の環境変数 (MACKEREL_APIKEY) としてセットするように事前に Secret を作成しておきましょう。
apiVersion: serving.knative.dev/v1 kind: Service metadata: name: ${SERVICE} ... spec: containers: ... - image: ${COLLECTOR_IMAGE} name: collector startupProbe: httpGet: path: / port: 13133 env: - name: "MACKEREL_APIKEY" valueFrom: secretKeyRef: key: "latest" name: mackerel_apikey
Cloud Run のアプリケーションのデプロイ処理は全て GitHub Actions で実装されています。README.md に記載していますが、Cloud Run のアプリケーションをデプロイするために幾つか準備する必要があります。
まず、アプリケーションの Docker image を push する Artifact Registry を作成します。
次に、Workload Identity Federation を利用して GitHub Actions から Google Cloud へ認証を行うことができるように各種リソースを作成します。 GitHub Actions 側のワークフローファイル内の [GCP_PROJECT_ID], [WORKLOAD_IDENTITY_POOL_ID], [SERVICE_ACCOUNT_EMAIL] といった箇所は修正が必要なので、ご自身の環境を基に設定してください。
上記の変更を GitHub の Pull Request として merge すると問題なければ Cloud Run のアプリケーションがデプロイされているはずです。
❯ gcloud run services describe --region asia-northeast1 opentelemetry-mackerel-playgrounds
✔ Service otel-metrics-and-traces-playgrounds in region asia-northeast1
URL: https://opentelemetry-mackerel-playgrounds-203216207119.asia-northeast1.run.app
Ingress: all
Traffic:
100% LATEST (currently opentelemetry-mackerel-playgrounds-00001-flg)
Last updated on 2024-12-05T11:41:08.334760Z by [SERVICE_ACCOUNT_NAME]:
Revision opentelemetry-mackerel-playgrounds-00001-flg
Container app
Image: asia-northeast1-docker.pkg.dev/[GCP_PROJECT_ID]/opentelemetry-mackerel-playgrounds/app:1e4671022d99e65542b663aae063f4d7540c2ce0
Port: 8080
Memory: 512Mi
CPU: 1000m
Env vars:
ENV_PORT 8080
Startup Probe:
TCP every 240s
Port: 8080
Initial delay: 0s
Timeout: 240s
Failure threshold: 1
Type: Default
Container Dependencies: collector
Container collector
Image: asia-northeast1-docker.pkg.dev/[GCP_PROJECT_ID]/opentelemetry-mackerel-playgrounds/collector:1e4671022d99e65542b663aae063f4d7540c2ce0
Memory: 256Mi
CPU: 1000m
Secrets:
MACKEREL_APIKEY mackerel_apikey:latest
Startup Probe:
HTTP every 10s
Path: /
Initial delay: 0s
Timeout: 1s
Failure threshold: 3
Service account: 203216207119-compute@developer.gserviceaccount.com
Concurrency: 80
Max Instances: 50
Timeout: 300s
先述の通り、本記事のサンプルアプリケーションは GET /hello のエンドポイントを提供しているので、/hello のAPIにアクセスしてみましょう。
SERVICE_URL=$(gcloud run services describe --region asia-northeast1 opentelemetry-mackerel-playgrounds --format=json | jq -r '.status.url') curl -H "Authorization: Bearer $(gcloud auth print-identity-token)" $SERVICE_URL/hello Hello, World!%
サンプルアプリケーションが提供している API にアクセスできたので、Mackerel で送信されたラベル付きメトリックを確認してみましょう。

ラベル付きメトリックを確認する時にはメトリックエクスプローラーを利用することをお勧めします。メトリックエクスプローラーって何? という方はこちらの記事もどうぞ。
次に Vaxila で送信されたトレースを見てみましょう。 サンプルコードのデフォルトの状態であればサービス名として sample-app を指定すれば送信されているトレースを確認できるはずです。

最後に
簡単ではありましたが、Cloud Run のサンプルアプリケーションを利用して OpenTelemetry のメトリック・トレースを送信し、Mackerel (Vaxila) 上でそれらを確認していきました。 このようなサンプルアプリケーションを利用して、テレメトリーデータを送信し、Mackerel の OpenTelemetry 対応機能に触れてもらえればと思います。