🍯

AWS Distro for OpenTelemetry Lambda を使いHoneycombにトレースを送信する

2025/03/27に公開

こんにちは。
エンジニアの古野です。

この記事では、AWS Distro for OpenTelemetry Lambda(以降ADOT Lambda) を使って、Observabilityプラットフォームの Honeycomb にトレースを送信するまでの流れをご紹介します。

ADOT Lambda とは、Lambda 関数上で OpenTelemetry エージェント(Collector)を実行できる AWS のディストリビューションです。

背景

  • 近年、サービスの可観測性(Observability)がより重視されるようになり、その一環として OpenTelemetry を採用するプロジェクトが増えています。
  • Honeycomb は、高次元の高カーディナリティデータ分析により、イベントや分散トレースなどを可視化できる Observability プラットフォームです。
  • ADOT LambdaはLambdaレイヤーとしてサポートされています。Lambdaレイヤーは.zipファイルアーカイブであり、zip形式でデプロイされた関数にレイヤー適用し、追加のライブラリやバイナリを /opt ディレクトリに展開して利用する仕組みです。そのため、コンテナイメージ (ECR) でのデプロイでは、このレイヤーをそのまま利用できません。
  • この問題を回避するため、レイヤーの中身をコンテナビルドの工程に取り込み、Collector を稼働させる方法をまとめました。

Honeycomb で API キーを取得する

まずは Honeycomb 側で API Key の作成が必要です。

  1. honeycomb.io にログインします

https://www.honeycomb.io/

  1. 初回ログインで表示されている API key は設定用のキー(Configuration Key)となっています。
    テレメトリ送信を行うには権限が強いため、専用の Ingest Key を用いることが推奨されています。
  2. Ingest Key を新規で作成し、そのキーを控えておきます。

このキーを、後ほど Collector に渡すことで Honeycomb へトレースを送信します。

https://docs.honeycomb.io/configure/environments/manage-api-keys/

https://docs.honeycomb.io/get-started/best-practices/api-keys/


Lambda(コンテナイメージ)への導入

前提

  • 例として、私が関わっているプロダクト「オクタゴン セールススイート」では、Python のバックエンド API を Docker イメージとしてビルドし、ECR にプッシュ → Lambda にデプロイしています。
  • ADOT Lambda はレイヤーで提供されていますが、コンテナイメージにはレイヤーが使えません。そのため、レイヤーの中身をコンテナビルドに含める必要があります。
  • 参考情報:

GitHub ActionsのCD例

以下は、GitHub Actions を利用したコンテナビルド&デプロイの例です。

  • adot-layerディレクトリを作成し、そこへADOT Lambdaレイヤーを展開します。
    • aws lambda get-layer-version-by-arn でARNからURLが取得できます。
    • curlでダウンロード後にunzipで展開します。
  • ADOT Lambda を有効にするための設定は、以下の箇所となります。
    • AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument
    • OPENTELEMETRY_COLLECTOR_CONFIG_URI=/var/task/otel-collector-config.yaml
    • HONEYCOMB_API_KEY
build-backend:
  runs-on: ubuntu-latest
  permissions:
    contents: read
    id-token: write
  defaults:
    run:
      working-directory: python
  steps:
    - name: checkout
      uses: actions/checkout@v4
      with:
        ref: ${{ inputs.branch }}
    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3

    - name: Configure AWS credentials
      uses: aws-actions/configure-aws-credentials@v4
      with:
        role-to-assume: ${{ secrets.role-to-assume }}
        aws-region: ap-northeast-1

    - name: Download ADOT Lambda Layer
      # @see
      # https://aws-otel.github.io/docs/getting-started/lambda/lambda-python#add-the-arn-of-the-lambda-layer
      run: |
        mkdir -p adot-layer
        LOCATION=$(aws lambda get-layer-version-by-arn \
        --arn "arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-python-arm64-ver-1-29-0:1" \
        --query 'Content.Location' --output text)
        
        curl -sSL "$LOCATION" -o adot-layer/layer.zip
        unzip -q adot-layer/layer.zip -d adot-layer
        rm adot-layer/layer.zip

    - name: Login to ECR
      id: login-ecr
      uses: aws-actions/amazon-ecr-login@v2

    - name: Build and Push
      uses: docker/build-push-action@v5
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        ECR_REPOSITORY: sales-suite-backend-${{ inputs.env }}
        IMAGE_TAG: ${{ inputs.tag }}
      with:
        push: true
        tags: ${{ env.ECR_REGISTRY }}/${{ env.ECR_REPOSITORY }}:${{ env.IMAGE_TAG }}
        context: ./python
        platforms: linux/arm64
        provenance: false
        cache-from: type=gha
        cache-to: type=gha,mode=max
        build-args: |
          AWS_LAMBDA_EXEC_WRAPPER=/opt/otel-instrument
          OPENTELEMETRY_COLLECTOR_CONFIG_URI=/var/task/otel-collector-config.yaml
          HONEYCOMB_API_KEY=${{ secrets.honeycomb-api-key }}

otel-collector-config.yaml の設定

上記の Actions では OPENTELEMETRY_COLLECTOR_CONFIG_URI=/var/task/otel-collector-config.yaml を指定しています。
このファイルをコンテナイメージ内に含めることで、Collector の起動設定を読み込ませます。

receivers:
  otlp:
    protocols:
      grpc:
        endpoint: "localhost:4317"
      http:
        endpoint: "localhost:4318"

exporters:
  debug: {}
  otlp/traces:
    endpoint: api.honeycomb.io:443
    headers:
      "x-honeycomb-team": ${env:HONEYCOMB_API_KEY}
 
service:
  pipelines:
    traces:
      receivers: [otlp]
      processors: []
      exporters: [debug, otlp/traces]
  • receivers
    • デフォルト設定です。
  • exporters.otlp/traces.endpoint
    • Honeycomb の OTLP 受信エンドポイント (443) を指定しています。
  • headers.x-honeycomb-team
    • ここで API key を設定することで、Honeycomb 側にトレースを送信できるようになります。 ${env:HONEYCOMB_API_KEY}Confmap Providers のEnv providerにより、環境変数を参照しています。
  • 標準出力に出力するためdebug exporterも指定しています。

Dockerfileの設定

展開したADOT Lambdaレイヤーを/optへ含めるようにします。

FROM python:3.11.9-slim-bookworm AS build-env

WORKDIR /app
RUN pip install poetry \
    && poetry config --local virtualenvs.in-project true
COPY pyproject.toml poetry.lock /app/
RUN poetry install --only main --no-root


FROM public.ecr.aws/lambda/python:3.11
# 追加した環境変数定義
ARG AWS_LAMBDA_EXEC_WRAPPER
ARG OPENTELEMETRY_COLLECTOR_CONFIG_URI
ARG HONEYCOMB_API_KEY
ENV AWS_LAMBDA_EXEC_WRAPPER=$AWS_LAMBDA_EXEC_WRAPPER
ENV OPENTELEMETRY_COLLECTOR_CONFIG_URI=$OPENTELEMETRY_COLLECTOR_CONFIG_URI
ENV HONEYCOMB_API_KEY=$HONEYCOMB_API_KEY

COPY --from=build-env /app/.venv ${LAMBDA_TASK_ROOT}/.venv
# /optへコピーしておく
COPY adot-layer /opt
COPY src/ ${LAMBDA_TASK_ROOT}/src/

CMD [ "src.app.handler.handler" ]

テレメトリ送信の確認

これでHoneycombへトレースが送信されます。📈

もし送信されていない場合は、CloudWatch Logsなどにログが残っているはずです。
次項の構築時の確認方法も参考に、問題解決しましょう。

構築時の確認方法

正常に送信できない場合に、問題切り分けのための方法をいくつかご紹介します。

ECR からイメージを pull して中身を確認する

  • 事前にECRからイメージを取得します。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/docker-pull-ecr-image.html

docker run -it --entrypoint /bin/sh <イメージID or タグ>
  • adot-layer ディレクトリや、otel-collector-config.yaml 、環境変数が正しく含まれているかを確認します。

otel-collector-config.yamlを検証する

ADOT CollectorのDocker imageが配布されています。
otel-collector-config.yamlの検証に利用できます。

docker pull amazon/aws-otel-collector:latest

docker run --rm -it \
  -v $(pwd)/otel-collector-config.yaml:/config/config.yaml \
  -e HONEYCOMB_API_KEY=xxxxx \
  amazon/aws-otel-collector:latest \
  --config /config/config.yaml

未解決: batch processor 利用時のエラーについて

  • ADOT Lambdaからトレースを送信する際に、batch processor を追加するとCollectorの起動に失敗してしまいました。
  • ドキュメントではbatch processor に対応していそうですが、原因を掴むことができず利用をやめました。
  • Python, arm64のLambdaレイヤーのバージョン。
    • arn:aws:lambda:ap-northeast-1:901920570463:layer:aws-otel-python-arm64-ver-1-29-0:1
{"level":"warn","ts":1742456138.0101013,"logger":"lifecycle.manager","msg":"Failed to start the extension","error":"failed to get config: cannot unmarshal the configuration: decoding failed due to the following error(s):\n\nerror decoding 'processors': unknown type: \"batch\" for id: \"batch\" (valid values: [])"}
{"level":"info","ts":1742456138.0106115,"msg":"done","error":"failed to get config: cannot unmarshal the configuration: decoding failed due to the following error(s):\n\nerror decoding 'processors': unknown type: \"batch\" for id: \"batch\" (valid values: [])";}

まとめ

  • ADOT Lambda をコンテナイメージで利用する場合は、Lambdaレイヤーの中身をビルド時に取り込み、AWS_LAMBDA_EXEC_WRAPPEROPENTELEMETRY_COLLECTOR_CONFIG_URI を指定します。
  • Honeycomb 側では Ingest Key を作成し、 otel-collector-config.yamlx-honeycomb-team ヘッダとして設定します。
  • Collector の設定ファイルをローカルで検証しておくと、Lambda 上でのトラブルシューティングが容易になります。

これで、ADOT Lambda (Collector) を使って Honeycomb にトレースを送信する仕組みが整います。

🚀🚀🚀 Observability環境の構築にぜひ活用してみてください 🚀🚀🚀

参考リンク

https://aws-otel.github.io/
https://dev.classmethod.jp/articles/adot-lambda-with-container-image/
https://docs.honeycomb.io/configure/

Globe-ingテックブログ

Discussion