☁️

Splunk Observability - ECS on Fargate + Java に OpenTelemetry で計装を行う

2023/12/14に公開

Hi, Splunk Observability の導入支援を行っている、kntr_nkgm です。
12月に入ってから既に2回風邪をひいています。皆様お体には気を付けてお過ごしくださいね。

この記事は Splunk Advent Calendar 2023 の14日目の記事です。
一つ前の記事は、13日目に @odorusatoshi さんが公開している Splunkの画面表示不具合の報告が5分で済んで思ったより楽だった件 です。
https://qiita.com/odorusatoshi/items/aed304440b23ec1782cd

なお、今回のアドベントカレンダーでは、8日目にも記事を投稿しています。
Splunk Observability IM の Navigator をカスタマイズする
https://zenn.dev/kntr_nkgm/articles/7b4078ced73a4f

前回は Splunk Observability の IM に触れたので、今回は APM の話題にしようと思います。

Splunk Observability は、OpenTelemetry に完全準拠したオブザーバビリティプラットフォームです。
以下は、Splunk Observability にメトリクスやトレースなどのデータを送るように設定をしていますが、基本的なアプローチは OpenTelemetry ベースで計装する場合でもほぼ同じような形になるはずです。ご参考にしていただければと思います。

サーバレス環境における計装

今回は、ECS on Fargate 上に Java アプリケーションを実行している環境に対して、IM + APM を組み込んでいきましょう。
基本的なセットアップの流れは以下の通りです。

  1. OpenTelemetry Collector をサイドカーとして設定・起動
  2. アプリケーションを実行するコンテナ内で、言語別の OpenTelemetry エージェントを実行
  3. 必要に応じて、アプリケーションのコードに手を加えていく(手動計装)

今回扱うのは、1,2 の部分までです。
3に関しては、いろんな言語で実装されたアプリケーションに計装を行う - Java(kotlin)編 にて、他のサンプルアプリケーションを利用して紹介しています。あわせてご参考にしてください。

今回は、Springフレームワークの有名なサンプルアプリケーション "Spring PetClinic" Docker 版 を使っていきます。

Spring PetClinic - 動物病院での応対・往診記録などが実装されたサンプルアプリケーションです

環境セットアップ

まずは、普通に PetClinic アプリケーションを ECS on Fargate で実行できるようにします。
あくまで前提の準備に過ぎないので、以下は、いろいろと省略しています。

コンテナイメージの作成とECRへのPush

Github 上の README に従ってイメージ作成。

$ git clone https://github.com/dockersamples/spring-petclinic.git
$ cd spring-petclinic
$ docker build -t adventcalendar-petclinic . -f Dockerfile

ECR 上でレポジトリを作成すると、認証トークンの取得・Dockerクライアント認証~コンテナ作成~イメージプッシュまでの手順がガイドされるはずです。これに従って実行

$ aws ecr get-login-password --region <my_region> | docker login --username AWS --password-stdin <ECR_repository>
(Dockerイメージ作成コマンドは実行済みなので割愛)
$ docker tag adventcalendar-petclinic:latest <ECR_repository>/adventcalendar-petclinic:latest
$ docker push <ECR_repostiory>/adventcalendar-petclinic:latest

ECSクラスタ作成・タスク定義・サービス作成

ECS - タスク定義では、"adventcalendar-petclinic-taskdef" を作成。
起動タイプは "AWS Fargate" です。
コンテナ - 1 にて、先ほど作成したコンテナイメージを選択します。
ポートマッピングにて、8080 を指定しておきます。

ECS - クラスターにて、"adventcalendar-petclinic-cluster" を作成。
この時に、インフラストラクチャとしては、AWS Fargate を選択しておきました。

この ECS クラスターにて、サービスを作成していきます。
タスク定義にて、先ほど作成した "adventcalendar-petclinic-taskdef" を指定。
サービス名は "adventcalendar-petclinic-service" としておきました。
ネットワーキングに関しては、いい感じにやっておきました。

正常にデプロイが完了したらOKです。
今回はパブリックIPを付与する形にしているので、<パブリックIP>:8080 にアクセスすると、上に貼っているスクリーンショットのようなアプリケーションが表示されるはずです。

OpenTelemetry Collector をサイドカーとして追加

さて、ここからが本題です。
まず、OpenTelemetry Collector をサイドカーとして追加していきます。

ガイド手順の確認

手順はそれほど複雑ではなく、Splunk Observability の UI からガイドを確認することができます。

"Data Management" 内の "Deploy the Splunk OpenTelemetry Collector" を押すと、

プラットフォームが選べるので、"Amazon ECS Fargate" を選択し、

いくつかの設定値を入力すると、

インストラクションが表示されます。

これに従って設定を追加していきます。
具体的にやっていきましょう。

タスク定義への追加

インストラクション内で表示されているのは、Splunk OpenTelemetry Collector を実行させるタスク定義です(黒塗り箇所はトークン情報)

これを、先ほどアプリケーションのタスク定義に追加します。

ECS - タスク定義 - "adventcalendar-petclinic-taskdef"(アプリケーション用のタスク定義)にて、「新しいリビジョンの作成」-「JSONを使用した新しいリビジョンの作成」を選択

先ほど表示されたタスク定義をコピーして、"containerDefinitions" の箇所に追加します。

{
    "family": "adventcalendar-petclinic-taskdef",
    "containerDefinitions": [
        {
	    // 元のアプリケーションの定義
            "name": "adventcalendar-petclinic",
            "image": "<ECR_Repository>/adventcalendar-petclinic:latest",
	    //
	    // 以下、しばらく割愛。特に既存のアプリケーション設定には変更は加えません
	    //
        },
	// ここから追加。ウィザードに表示されている内容をコピペしただけです。
	// ただ、ちょっと長いので、一部割愛します。
	{
	  "environment": [
	    {
	      "name": "SPLUNK_ACCESS_TOKEN",
	      "value": "<access_token>"
	    },
	    //
	    // 省略
	    //
	  ],
	  "image": "quay.io/signalfx/splunk-otel-collector:latest",
	  "essential": true,
	  "name": "splunk-otel-collector"
	}
    ],
    //
    // 以下略
    //
}

さて、更新をすると、タスク定義のリビジョンが一つ進み、コンテナとして、"splunk-otel-collecor" が表示されるようになるはずです。

これをデプロイしましょう。
"サービスの更新" から、作成済みのクラスター("adventcalendar-petclinic-cluster")、サービス("adventcalendar-petclinic-service")を選択
「新しいデプロイの強制」も選んでおいて実行します。

デプロイが完了すると、例えば、コンテナ用のDashboardでは、以下のようにメトリクスを表示できるようになります。

また、AWS Integration を行うと、ECSに関連するメタデータなども含めながら、以下のような情報も表示してくれるようになります。

いい感じですね。それでは、次はAPMに進みましょう。

APMエージェントの導入

Java APM エージェントは、Javaアプリケーション起動時の引数として -javaagent を指定することで、自動計装を行ってくれます。
アプリケーションの名称を指定する必要があったり、いくつか設定しておいた方が便利な起動時オプションもあったりします。
順番にやっていきましょう。

Javaエージェントの入手と配置

Dockerfileをのぞいてみると、以下のようになっています。

Dockerfile
FROM eclipse-temurin:17-jdk-jammy

WORKDIR /app

COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:resolve

COPY src ./src

CMD ["./mvnw", "spring-boot:run"]

Java APM エージェントも、WORKDIR である /app 以下に置いてあげることにしましょう。
以下を追記する形になります。

ADD https://github.com/signalfx/splunk-otel-java/releases/latest/download/splunk-otel-javaagent.jar .

起動時引数の設定

今回は、JAVA_TOOL_OPTIONS の環境変数で、起動時引数を指定しておきます。
今回のアプリケーションでは、mvnw spring-boot:run でアプリケーションが実行されていますが、例えば、java コマンドを ENTRYPOINT として利用している場合は、直接そのコマンド分として設定するようなことももちろん可能です。

以下のようなオプションを設定していきます。

JAVA_TOOL_OPTIONS="-javaagent:/app/splunk-otel-javaagent.jar \
	-Dotel.service.name=adventcalendar-petclinic \
	-Dotel.resource.attributes='deployment.environment=adventcalendar-petclinic-env,service.version=0.1' \
	-Dsplunk.profiler.enabled=true \
	-Dsplunk.profiler.memory.enabled=true \
	-Dsplunk.metrics.enabled=true" 

Dockerfileの更新とアプリケーションの更新

上のような変更を取り込んで、Dockerfileを更新していきましょう。

Dockerfile
FROM eclipse-temurin:17-jdk-jammy

# JAVA_TOOL_OPTIONS を更新
ENV JAVA_TOOL_OPTIONS "-javaagent:/app/splunk-otel-javaagent.jar \
	-Dotel.service.name=adventcalendar-petclinic \
	-Dotel.resource.attributes='deployment.environment=adventcalendar-petclinic-env,service.version=0.1' \
	-Dsplunk.profiler.enabled=true \
	-Dsplunk.profiler.memory.enabled=true \
	-Dsplunk.metrics.enabled=true" 

WORKDIR /app

# Java APM エージェント取込
ADD https://github.com/signalfx/splunk-otel-java/releases/latest/download/splunk-otel-javaagent.jar .

COPY .mvn/ .mvn
COPY mvnw pom.xml ./

RUN ./mvnw dependency:resolve

COPY src ./src

CMD ["./mvnw", "spring-boot:run"]

上で記載したような形で、改めて docker build して docker tag して docker push します。

ECSの画面にて、サービスを更新して、新しいコンテナイメージによって起動させます。
アプリケーション起動後には、アプリにアクセスして、何度か検索をかけたり、ERRORを発生させたりするボタンを押します。

すると、APM の画面に、こんな感じで、Fargate上で稼働するJavaアプリの情報が表示されるようになるはずです。

サービスマップもこんな感じで表示されるようになりましたね。

自動計装の範囲でデータが取れるようになれば、ここからの活用方法はさまざまです。
トレース、Tag Spotlightなどからエラーの傾向や原因を探っていったり、アプリケーションへのアクセス頻度やエラーの発生率からアラート通知の設定を行ったり、、、
AZをまたぐようにコンテナを配置しているような場合は、"cloud.availability_zone" などのタグ情報から調査をしたりするようなこともできるでしょう。

取得されたデータを活用して問題分析を行っていく手法については、例えば、以下のようなブログにて紹介していますので、あわせてご覧ください。
Splunk APMのTag Spotlightで爆速トラブルシューティング
https://qiita.com/symmr/items/5388fe16db890b753c4b
Splunk APMのビジネスワークフロー分析でサービスがまずい状態を見逃さない
https://qiita.com/symmr/items/188ddd99ff1cfc80ceb6

もちろん、自動計装では分析に足りないという可能性もあるので、その場合は、すこしずつ手動計装を試みていくことになります。
上でも書きましたが、はい、こんな感じ。
いろんな言語で実装されたアプリケーションに計装を行う - Java(kotlin)編
https://zenn.dev/kntr_nkgm/articles/d42a3116d2df63

おわりに

今回はサーバレス環境での計装を取り上げてみました。
こういったコンテナ環境、サーバレス環境を本番環境でも利用しているという声は、少しずつですが確実に増えてきております。
こういった環境にももちろん Splunk Observability は対応していますので、ぜひご参考にしていただければと思います。

明日は @huaiboz さんの [Splunk MLTKにONNXモデルをアップロードしてみた] が更新される予定です。みなさまお楽しみにー!

それでは、よい12月を~。

Discussion