チュートリアル - AWS Elastic Kubernetes Service 上の Java アプリケーションのトレースを有効にする 概要 This tutorial walks you through the steps for enabling tracing on a sample Java application installed in a cluster on AWS Elastic Kubernetes Service (EKS). In this scenario, the Datadog Agent is also installed in the cluster.
ホスト、コンテナ、他のクラウドインフラストラクチャー、他の言語で書かれたアプリケーションなど、他のシナリオについては、他のトレース有効化のチュートリアル を参照してください。
Java の一般的なトレース設定ドキュメントについては、Java アプリケーションのトレース を参照してください。
前提条件 Datadog のアカウントと組織の API キー Git Kubectl eksctl Helm - 以下のコマンドを実行してインストールします。
Copy
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
以下のコマンドを実行し、Helm を構成します。
Copy
helm repo add datadog-crds https://helm.datadoghq.com
helm repo add kube-state-metrics https://prometheus-community.github.io/helm-charts
helm repo add datadog https://helm.datadoghq.com
helm repo update
サンプルの Kubernetes Java アプリケーションをインストールします。 このチュートリアルのコードサンプルは、GitHub の github.com/DataDog/apm-tutorial-java-host にあります。まずは、このリポジトリを複製してください。
Copy
git clone https://github.com/DataDog/apm-tutorial-java-host.git
The repository contains a multi-service Java application pre-configured to run inside a Kubernetes cluster. The sample app is a basic notes app with a REST API to add and change data. The docker-compose
YAML files to make the containers for the Kubernetes pods are located in the docker
directory. This tutorial uses the service-docker-compose-k8s.yaml
file, which builds containers for the application.
notes
と calendar
の各ディレクトリには、アプリケーションをビルドするための Dockerfile が、Maven と Gradle の 2 つのセットで用意されています。このチュートリアルでは Maven を使用しますが、Gradle に慣れている場合は、ビルドコマンドを変更することで、Maven の代わりに Gradle を使用することができます。
notes
アプリ、calendar
アプリ、Datadog Agent の Kubernetes の構成ファイルは、kubernetes
ディレクトリにあります。
サンプルアプリケーションを取得するまでの流れは、docker
フォルダからイメージをビルドし、レジストリにアップロードし、kubernetes
フォルダから kubernetes リソースを作成する、というものです。
クラスターを起動する 再利用したい EKS クラスターがまだない場合は、以下のコマンドを実行し、<CLUSTER_NAME>
を使用したい名前に置き換えて、クラスターを作成します。
Copy
eksctl create cluster --name <CLUSTER_NAME>
これにより、ポッドをデプロイできるマネージドノードグループを持つ EKS クラスターが作成されます。トラブルシューティングと構成の詳細については、クラスター作成に関する eksctl ドキュメント をお読みください。別の方法 (例えば AWS Web コンソール) で作成したクラスターを使用する場合は、eksctl ドキュメントに記載されているように、クラスターがローカルの kubeconfig
ファイルに接続されていることを確認します。
クラスターの作成は 15~20 分ほどかかる場合があります。クラスターの作成が完了するのを待ちながら、他の手順に進んでください。
アプリケーションイメージの構築とアップロード EKS イメージのレジストリである Amazon ECR に馴染みがない方は、Amazon ECR を AWS CLI で使う を読むとよいかもしれません。
サンプルプロジェクトの /docker
ディレクトリで、以下のコマンドを実行します。
このコマンドでユーザー名とパスワードを入力し、ECR で認証します。
Copy
aws ecr get-login-password --region us-east-1 | docker login --username <YOUR_AWS_USER> --password-stdin <USER_CREDENTIALS>
サンプルアプリの Docker イメージを構築し、プラットフォーム設定を合わせます。
Copy
DOCKER_DEFAULT_PLATFORM = linux/amd64 docker-compose -f service-docker-compose-k8s.yaml build notes
コンテナに ECR 宛先のタグを付けます。
Copy
docker tag docker-notes:latest <ECR_REGISTRY_URL>:notes
コンテナを ECR レジストリにアップロードします。
Copy
docker push <ECR_REGISTRY_URL>:notes
アプリケーションはコンテナ化され、EKS クラスターがプルできるようになります。
AWS クラスターのインバウンドセキュリティポリシーの更新 To communicate with the sample applications, ensure that the cluster’s security rules are configured with ports 30080
and 30090
open.
Open AWS Console and navigate to your deployed cluster within the EKS service.
クラスターコンソールで、networking タブを選択し、クラスターセキュリティグループをクリックします。
In your security group settings, edit the inbound rules. Add a rule allowing custom TCP traffic, a port range of 30060
to 30100
, and source of 0.0.0.0/0
.
ルールを保存します。
アプリケーションをローカルに構成してデプロイする kubernetes/notes-app.yaml
を開き、image
の項目を、上記でコンテナをプッシュした ECR イメージの URL で更新します。
Copy
spec :
containers :
- name : notes-app
image : <ECR_REGISTRY_URL>:notes
imagePullPolicy : Always
/kubernetes
ディレクトリから、以下のコマンドを実行して、notes
アプリをデプロイします。
Copy
kubectl create -f notes-app.yaml
アプリを実行するには、アプリの REST API を呼び出すための外部 IP アドレスを見つける必要があります。まず、以下のコマンドで出力される一覧から notes-app-deploy
というポッドを見つけ、そのノードをメモしておきます。
次に、次のコマンドの出力からそのノード名を見つけ、外部 IP の値をメモします。
Copy
kubectl get nodes -o wide
この例では、notes-app
はノード ip-192-189-63-129.ec2.internal
で動作しており、その外部 IP は 34.230.7.210
であることが示されています。
別のターミナルを開いて、アプリを行使するために API リクエストを送信します。ノートアプリケーションは、同じコンテナで実行されているメモリ内 H2 データベースにデータを保存する REST API です。これにいくつかのコマンドを送信します。
curl '<EXTERNAL_IP>:30080/notes'
[]
curl -X POST '<EXTERNAL_IP>:30080/notes?desc=hello'
{"id":1,"description":"hello"}
curl '<EXTERNAL_IP>:30080/notes?id=1'
{"id":1,"description":"hello"}
curl '<EXTERNAL_IP>:30080/notes'
[{"id":1,"description":"hello"}]
アプリケーションの実行を確認したら、それを停止して、トレースを有効にします。
Copy
kubectl delete -f notes-app.yaml
トレースを有効にする Java アプリケーションが動作するようになったので、トレースを有効にするための構成を行います。
Java tracing パッケージをプロジェクトに追加します。Agent は EKS クラスターで動作するため、Dockerfile が適切に構成されていることを確認し、何もインストールする必要はありません。notes/dockerfile.notes.maven
ファイルを開き、dd-java-agent
をダウンロードする行のコメントを解除します。
RUN curl -Lo dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'
同じ notes/dockerfile.notes.maven
ファイル内で、トレースなしで実行するための ENTRYPOINT
行をコメントアウトしてください。次に、トレースを有効にしてアプリケーションを実行する ENTRYPOINT
行のコメントを解除します。
ENTRYPOINT ["java" , "-javaagent:../dd-java-agent.jar", "-Ddd.trace.sample.rate=1", "-jar" , "target/notes-0.0.1-SNAPSHOT.jar"]
これにより、アプリケーションは自動的に Datadog のサービスにインスツルメンテーションされます。
注 : これらのサンプルコマンドのフラグ、特にサンプルレートは、このチュートリアル以外の環境では、必ずしも適切ではありません。実際の環境で何を使うべきかについては、
トレース構成 を読んでください。
異なるバージョンやデプロイ環境間でトレースされたサービスを識別する統合サービスタグ により、Datadog 内で相関が取れるようになり、検索やフィルターに利用できるようになります。統合サービスタグ付けに使用する環境変数は、DD_SERVICE
、DD_ENV
、DD_VERSION
の 3 つです。Kubernetes でデプロイされるアプリケーションでは、これらの環境変数をデプロイメント YAML ファイル内、特にデプロイメントオブジェクト、ポッド仕様、ポッドコンテナテンプレートに追加することができます。
このチュートリアルでは、kubernetes/notes-app.yaml
ファイルに、デプロイメントオブジェクト、ポッド仕様、ポッドコンテナテンプレートなど、ノートアプリケーションのためのこれらの環境変数がすでに定義されています。
...
spec :
replicas : 1
selector :
matchLabels :
name : notes-app-pod
app : java-tutorial-app
template :
metadata :
name : notes-app-pod
labels :
name : notes-app-pod
app : java-tutorial-app
tags.datadoghq.com/env : "dev"
tags.datadoghq.com/service : "notes"
tags.datadoghq.com/version : "0.0.1"
...
アプリケーションイメージの再構築とアップロード 前と同じ手順 で、トレースを有効にしてイメージを再構築します。
Copy
aws ecr get-login-password --region us-east-1 | docker login --username <YOUR_AWS_USER> --password-stdin <USER_CREDENTIALS>
DOCKER_DEFAULT_PLATFORM = linux/amd64 docker-compose -f service-docker-compose-k8s.yaml build notes
docker tag docker-notes:latest <ECR_REGISTRY_URL>:notes
docker push <ECR_REGISTRY_URL>:notes
トレースを有効にしたアプリケーションはコンテナ化され、EKS クラスターがプルできるようになります。
Helm を使用した Agent のインストールと実行 次に、インスツルメンテーションされたアプリケーションからトレースデータを収集するために、EKS に Agent をデプロイします。
kubernetes/datadog-values.yaml
を開くと、GKE 上の Agent と APM に最低限必要な構成が表示されます。このコンフィギュレーションファイルは、次に実行するコマンドで使用されます。
/kubernetes
ディレクトリから、API キーとクラスター名を入れて、以下のコマンドを実行します。
Copy
helm upgrade -f datadog-values.yaml --install --debug latest --set datadog.apiKey= <DD_API_KEY> --set datadog.clusterName= <CLUSTER_NAME> --set datadog.site= datadoghq.com datadog/datadog
API キーを公開しない、より安全なデプロイについては、シークレットの使用に関するこのガイド をお読みください。また、us1
以外の Datadog サイト を使用している場合は、datadoghq.com
を自分のサイトに置き換えてください。
自動トレースを見るためにアプリを起動する [前回と同じ手順](#configure the-application-locally-and-deploy)で、notes
アプリを kubectl create -f notes-app.yaml
でデプロイし、実行するノードの外部 IP アドレスを確認します。
アプリを動かすために、いくつかの curl コマンドを実行します。
curl '<EXTERNAL_IP>:30080/notes'
[]
curl -X POST '<EXTERNAL_IP>:30080/notes?desc=hello'
{"id":1,"description":"hello"}
curl '<EXTERNAL_IP>:30080/notes?id=1'
{"id":1,"description":"hello"}
curl '<EXTERNAL_IP>:30080/notes'
[{"id":1,"description":"hello"}]
しばらく待って、Datadog の APM > Traces にアクセスすると、API 呼び出しに対応するトレースの一覧が表示されます。
h2
はこのチュートリアルのために埋め込まれたメモリ内データベースで、notes
は Spring Boot アプリケーションです。トレースリストには、すべてのスパン、いつ開始したか、どのリソースがスパンで追跡されたか、どれくらいの時間がかかったか、が表示されます。
もし、数分待ってもトレースが表示されない場合は、Traces Search フィールドのフィルターをクリアしてください (使用していない ENV
などの環境変数にフィルターをかけている場合があります)。
トレースの検証 Traces ページで、POST /notes
トレースをクリックすると、各スパンにかかった時間や、あるスパンが完了する前に他のスパンが発生したことを示すフレームグラフが表示されます。グラフの上部にあるバーは、前の画面で選択したスパンです (この場合、ノートアプリケーションへの最初のエントリポイントです)。
バーの幅は、それが完了するまでにかかった時間を示します。低い深さのバーは、高い深さのバーの寿命の間に完了するスパンを表します。
POST
トレースのフレームグラフは次のようになります。
GET /notes
トレースは次のようになります。
トレーシングのコンフィギュレーション Java トレーシングライブラリは、Java のビルトイン Agent とモニタリングのサポートを利用します。Dockerfile のフラグ -javaagent:../dd-java-agent.jar
は、JVM が Java Agent として実行できるように、Java トレーシングライブラリをどこで見つけるかを指示します。Java Agent については、https://www.baeldung.com/java-instrumentation で詳しく説明されています。
dd.trace.sample.rate
フラグは、このアプリケーションのサンプルレートを設定します。Dockerfile の ENTRYPOINT コマンドでは、この値を 1
に設定しています。これは、notes
サービスに対する全てのリクエストの 100% が、分析と表示のために Datadog のバックエンドに送信されることを意味します。低容量のテストアプリケーションの場合、これは問題ありません。実稼働時や大量のデータを扱う環境では、このようなことはしないでください。代わりに、リクエストの一部をサンプリングします。例えば、-Ddd.trace.sample.rate=0.1
とすると、リクエストの 10% 分のトレースが Datadog に送信されます。トレース構成設定 とサンプリング機構 について詳しくお読みください。
このコマンドのサンプリングレートフラグは -jar
フラグの_前に_表示されていることに注意してください。これは、このフラグがアプリケーションではなく、Java Virtual Machine のパラメーターだからです。アプリケーションに Java Agent を追加するときは、このフラグを正しい場所に指定するようにしてください。
Java アプリケーションに手動インスツルメンテーションを追加する 自動インスツルメンテーションは便利ですが、より細かいスパンが欲しい場合もあります。Datadog の Java DD Trace API では、アノテーションやコードを使用してコード内のスパンを指定することができます。
次のステップでは、ビルドスクリプトを修正して Java トレーシングライブラリをダウンロードし、コードにいくつかのアノテーションを追加して、いくつかのサンプルメソッドにトレースする手順を説明します。
現在のアプリケーションデプロイを削除します。
Copy
kubectl delete -f notes-app.yaml
/notes/src/main/java/com/datadog/example/notes/NotesHelper.java
を開きます。このサンプルには、コードにカスタムトレースを設定するさまざまな方法を示す、コメントアウトされたコードがすでに含まれています。
手動トレーシングをサポートするためのライブラリをインポートしている行のコメントを解除します。
import datadog.trace.api.Trace ;
import datadog.trace.api.DDTags ;
import io.opentracing.Scope ;
import io.opentracing.Span ;
import io.opentracing.Tracer ;
import io.opentracing.tag.Tags ;
import io.opentracing.util.GlobalTracer ;
import java.io.PrintWriter ;
import java.io.StringWriter
2 つのパブリックプロセスを手動でトレースしている行のコメントを解除します。これらは、@Trace
アノテーションを使用して、operationName
や resourceName
などのアスペクトをトレースで指定することを示しています。
@Trace ( operationName = "traceMethod1" , resourceName = "NotesHelper.doLongRunningProcess" )
// ...
@Trace ( operationName = "traceMethod2" , resourceName = "NotesHelper.anotherProcess" )
また、アプリケーション内の特定のコードブロックに対して、別のスパンを作成することもできます。スパン内には、サービスやリソース名のタグ、エラー処理タグを追加します。これらのタグは、Datadog の視覚化でスパンとメトリクスを表示するフレームグラフになります。プライベートメソッドを手動でトレースする行のコメントを解除します。
Tracer tracer = GlobalTracer . get ();
// Tags can be set when creating the span
Span span = tracer . buildSpan ( "manualSpan1" )
. withTag ( DDTags . SERVICE_NAME , "NotesHelper" )
. withTag ( DDTags . RESOURCE_NAME , "privateMethod1" )
. start ();
try ( Scope scope = tracer . activateSpan ( span )) {
// Tags can also be set after creation
span . setTag ( "postCreationTag" , 1 );
Thread . sleep ( 30 );
Log . info ( "Hello from the custom privateMethod1" );
また、エラー時にタグを設定する行も:
} catch ( Exception e ) {
// Set error on span
span . setTag ( Tags . ERROR , true );
span . setTag ( DDTags . ERROR_MSG , e . getMessage ());
span . setTag ( DDTags . ERROR_TYPE , e . getClass (). getName ());
final StringWriter errorString = new StringWriter ();
e . printStackTrace ( new PrintWriter ( errorString ));
span . setTag ( DDTags . ERROR_STACK , errorString . toString ());
Log . info ( errorString . toString ());
} finally {
span . finish ();
}
notes/pom.xml
を開き、手動トレースの依存関係を構成する行のコメントを解除して、Maven ビルドを更新します。dd-trace-api
ライブラリは @Trace
アノテーションに使用され、opentracing-util
と opentracing-api
は手動でスパンを作成するために使用されます。
アプリケーションを再構築し、前回と同じ手順 に従って ECR にアップロードし、以下のコマンドを実行します。
Copy
aws ecr get-login-password --region us-east-1 | docker login --username <YOUR_AWS_USER> --password-stdin <USER_CREDENTIALS>
DOCKER_DEFAULT_PLATFORM = linux/amd64 docker-compose -f service-docker-compose-k8s.yaml build notes
docker tag docker-notes:latest <ECR_REGISTRY_URL>:notes
docker push <ECR_REGISTRY_URL>:notes
[前回と同じ手順](#configure the-application-locally-and-deploy)で、notes
アプリを kubectl create -f notes-app.yaml
でデプロイし、実行するノードの外部 IP アドレスを確認します。
いくつかの HTTP リクエスト、特にいくつかの GET
リクエストを再送します。
トレースエクスプローラーで、新しい GET
リクエストの 1 つをクリックすると、次のようなフレームグラフが表示されます。
getAll
関数にカスタムトレースが追加され、スタックトレースがより詳細になったことに注意してください。
手動でスパンを作成した privateMethod
は、他のコールとは別のブロックとして表示され、別の色でハイライトされています。@Trace
アノテーションを使用した他のメソッドは、GET
リクエスト (notes
アプリケーション) と同じサービス、同じ色で表示されます。カスタムインスツルメンテーションは、ハイライトして監視する必要があるコードの重要な部分がある場合に有効です。
詳しくは、カスタムインストルメンテーション をご覧ください。
分散型トレーシングを見るために 2 つ目のアプリケーションを追加する 単一のアプリケーションをトレースすることは素晴らしいスタートですが、トレースの本当の価値は、リクエストがサービスを通じてどのように流れるかを見ることです。これは、_分散型トレーシング_と呼ばれています。
サンプルプロジェクトには calendar
という 2 番目のアプリケーションが含まれており、呼び出されるたびにランダムな日付を返します。Notes アプリケーションの POST
エンドポイントには、add_date
という名前の 2 つ目のクエリパラメーターがあります。このパラメータが y
に設定されると、Notes はカレンダーアプリケーションを呼び出して、ノートに追加する日付を取得します。
ノートアプリと同様に、Dockerfile の起動コマンドに dd-java-agent
を追加して、トレース用の calendar
アプリの構成を確認します。calendar/dockerfile.calendar.maven
を開き、すでに dd-java-agent
がダウンロードされていることを確認します。
RUN curl -Lo dd-java-agent.jar 'https://dtdg.co/latest-java-tracer'
同じ calendar/dockerfile.calendar.maven
ファイル内で、トレースなしで実行するための ENTRYPOINT
行をコメントアウトしてください。次に、トレースを有効にしてアプリケーションを実行する ENTRYPOINT
行のコメントを解除します。
ENTRYPOINT ["java" , "-javaagent:../dd-java-agent.jar", "-Ddd.trace.sample.rate=1", "-jar" , "target/calendar-0.0.1-SNAPSHOT.jar"]
注 : 繰り返しになりますが、フラグ、特にサンプルレートは、このチュートリアル以外の環境では、必ずしも適切ではありません。実際の環境で何を使うべきかについては、
トレース構成 を読んでください。
両方のアプリケーションをビルドし、ECR に公開します。docker
ディレクトリから、以下を実行します。
Copy
aws ecr get-login-password --region us-east-1 | docker login --username <YOUR_AWS_USER> --password-stdin <USER_CREDENTIALS>
DOCKER_DEFAULT_PLATFORM = linux/amd64 docker-compose -f service-docker-compose-k8s.yaml build calendar
docker tag docker-calendar:latest <ECR_REGISTRY_URL>:calendar
docker push <ECR_REGISTRY_URL>:calendar
kubernetes/calendar-app.yaml
を開き、image
エントリを ECR イメージの URL で更新します。これは前のステップで calendar
アプリ をプッシュした場所です。
Copy
spec :
containers :
- name : calendar-app
image : <ECR_REGISTRY_URL>:calendar
imagePullPolicy : Always
カスタムインスツルメンテーションを持つようになった notes
と calendar
の両アプリをクラスター上にデプロイします。
Copy
kubectl create -f notes-app.yaml
kubectl create -f calendar-app.yaml
先ほどの方法で、notes
アプリの外部 IP を探します。
add_date
パラメーターを指定して、POST リクエストを送信します。
curl -X POST '<EXTERNAL_IP>:30080/notes?desc=hello_again&add_date=y'
{"id":1,"description":"hello_again with date 2022-11-06"}
トレースエクスプローラーで、この最新のトレースをクリックすると、2 つのサービス間の分散型トレーシングが表示されます。
notes
アプリケーションでは何も変更していないことに注意してください。Datadog は notes
から calendar
への HTTP コールに使用される okHttp
ライブラリと、notes
と calendar
の HTTP リクエストをリッスンするために使用する Jetty ライブラリの両方を自動的にインスツルメントします。これにより、トレース情報を 1 つのアプリケーションから他のアプリケーションに渡すことができ、分散型トレースをキャプチャすることができます。
確認が終わったら、すべてのリソースをクリーンアップし、デプロイを削除してください。
Copy
kubectl delete -f notes-app.yaml
kubectl delete -f calendar-app.yaml
クラスターの削除については、EKS のドキュメント を参照してください。
トラブルシューティング もし、期待通りのトレースが受信できない場合は、Java トレーサーのでデバッグモードを設定してください。詳しくはデバッグモードの有効化 を読んでください。
参考資料