やりたいこと
Datadog APMをアプリに設定する方法として、Library Injectionというやり方があります。
通常Datadog APMを構成するためにはDatadogのトレースライブラリをアプリに組み込む必要がありますが、Library Injectionを使うとアプリケーションのコードに全く触れずにライブラリを挿入することが可能です。
今回はEKS on Fargateで動いているアプリに対してLibrary Injectionを使ってAPMを設定してみようと思います。
ここから先は特に明示がない限りKubernetes環境に対するLibrary Injectionについて記述します。
Library Injection について
Kubernetes の Admission Controller を使用して Kubernetes API へのリクエストをインターセプトし、指定されたインスツルメンテーションライブラリを挿入する仕組みです。
DeploymentにAnnotationを付与すると、Podが生成される前にinitContainersが挿入され、APMの設定に必要なライブラリが挿入されます。
Javaアプリの場合は起動オプションとして-javaagent:/datadog-lib/dd-java-agent.jar
が設定されます。
詳細はこちら。
https://docs.datadoghq.com/ja/tracing/trace_collection/library_injection_local/
Datadog Admission Controller について
Datadog Cluster Agent のコンポーネントで、アプリケーションポッドのコンフィギュレーションを簡略化できる便利なツールです。
Datadog Admission Controller は MutatingAdmissionWebhook 型に属しており、kube-apiserverがオブジェクトの作成/更新等のリクエストを受け取った際にリクエストをインターセプトします。
詳細はこちら。
https://docs.datadoghq.com/ja/containers/cluster_agent/admission_controller/
クラスターエージェントのデプロイ
ここからが本題です。
まずはEKSクラスターに対しAdmission Controllerを有効するためにクラスターエージェントをデプロイします。
デプロイはHelmで実施します。
datadog:
apiKey: <API Key>
clusterName: <Cluster Name>
agents:
enabled: false # No DaemonSet generated
clusterAgent:
enabled: true
replicas: 2
token: "aaaaaaaaaabbbbbbbbbbccccccccccdd"
admissionController:
enabled: true
clusterChecksRunner:
enabled: true
apm:
socketEnabled: false
portEnabled: true
port: 8126
useSocketVolume: false
Admission Controllerを使うために以下の設定が有効になっている必要があります。
admissionController:
enabled: true
また、APMを有効にしておくことも忘れずに。
apm:
socketEnabled: false
portEnabled: true
port: 8126
useSocketVolume: false
細かい設定内容が気になる方はKubernetes APM - トレース収集を参照ください。
上記yamlファイルを使ってクラスターエージェントをインストールします。
$ helm install cluster-agent -f cluster-agent-values.yaml datadog/datadog
Fargateの設定
FargateにDatadog Agentを設定していきます。
EC2であればエージェントをDaemonsetとして動かしていきますが、Fargateの場合はサイドカーとしてデプロイする必要があります。
EKS Fargate RBAC の設定
以下yamlに従ってAgent RBACを構成します。
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: datadog-agent
rules:
- apiGroups:
- ""
resources:
- nodes
- namespaces
- endpoints
verbs:
- get
- list
- apiGroups:
- ""
resources:
- nodes/metrics
- nodes/spec
- nodes/stats
- nodes/proxy
- nodes/pods
- nodes/healthz
verbs:
- get
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: datadog-agent
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: datadog-agent
subjects:
- kind: ServiceAccount
name: datadog-agent
namespace: default
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: datadog-agent
namespace: default
エージェントをサイドカーとして設定
apiVersion: apps/v1
kind: Deployment
metadata:
name: "sample-java"
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: "sample-java"
template:
metadata:
labels:
app: "sample-java"
admission.datadoghq.com/enabled: "true"
admission.datadoghq.com/config.mode: hostip
annotations:
admission.datadoghq.com/java-lib.version: "latest"
spec:
serviceAccountName: datadog-agent
shareProcessNamespace: true
containers:
- name: jpet
image: arey/springboot-petclinic
ports:
- containerPort: 8080
- image: datadog/agent
name: datadog-agent
ports:
- containerPort: 8126
name: traceport
protocol: TCP
env:
- name: DD_API_KEY
value: "<API Key>"
- name: DD_SITE
value: "datadoghq.com"
- name: DD_EKS_FARGATE
value: "true"
- name: DD_APM_ENABLED
value: "true"
- name: DD_CLUSTER_AGENT_AUTH_TOKEN
value: "aaaaaaaaaabbbbbbbbbbccccccccccdd"
- name: DD_CLUSTER_NAME
value: <Cluseter Name>
- name: DD_CLUSTER_AGENT_URL
value: https://cluster-agent-datadog-cluster-agent.default.svc.cluster.local:5005
- name: DD_ORCHESTRATOR_EXPLORER_ENABLED
value: "true"
- name: DD_KUBERNETES_KUBELET_NODENAME
valueFrom:
fieldRef:
apiVersion: v1
fieldPath: spec.nodeName
ポイントとなるのはこの部分です。
template:
metadata:
labels:
app: "sample-java"
admission.datadoghq.com/enabled: "true"
admission.datadoghq.com/config.mode: hostip
annotations:
admission.datadoghq.com/java-lib.version: "latest"
今回はJavaアプリケーションなので java-lib.version
を指定しましたが、アプリの言語に合わせて修正してください。
あとはこれを普通にkubectl applyするだけで完了です。
Datadog上で見るとdatadog-lib-java-init
というinitContainersが挿入されていることが確認できます。
Datadog上で見なくてもinitContainersが挿入され、Javaアプリに -javaagent:/datadog-lib/dd-java-agent.jar
オプションが追加されていることがわかります。
$ kubectl describe pod sample-java-74b7dfbfc4-9f6z4
Name: sample-java-74b7dfbfc4-9f6z4
Namespace: default
Priority: 2000001000
Priority Class Name: system-node-critical
Service Account: datadog-agent
Node: fargate-ip-192-168-181-99.ap-northeast-1.compute.internal/192.168.181.99
Start Time: Tue, 19 Dec 2023 20:43:20 +0900
Labels: admission.datadoghq.com/config.mode=hostip
admission.datadoghq.com/enabled=true
app=sample-java
eks.amazonaws.com/fargate-profile=fp-default
pod-template-hash=74b7dfbfc4
Annotations: CapacityProvisioned: 0.25vCPU 0.5GB
Logging: LoggingDisabled: LOGGING_CONFIGMAP_NOT_FOUND
admission.datadoghq.com/java-lib.version: latest
Status: Running
IP: 192.168.181.99
IPs:
IP: 192.168.181.99
Controlled By: ReplicaSet/sample-java-74b7dfbfc4
Init Containers:
datadog-lib-java-init:
Container ID: containerd://3c6848fb183c44ba60bd7d7d8d5a2372a7eaf101b6d129ac8ce181f5cf9c39de
Image: gcr.io/datadoghq/dd-lib-java-init:latest
Image ID: gcr.io/datadoghq/dd-lib-java-init@sha256:1c1d7225d251147c387250bbcda0500747fa90e3b1e00f60b1c509dcf2a9eb4f
Port: <none>
Host Port: <none>
Command:
sh
copy-lib.sh
/datadog-lib
State: Terminated
Reason: Completed
Exit Code: 0
Started: Tue, 19 Dec 2023 20:43:33 +0900
Finished: Tue, 19 Dec 2023 20:43:33 +0900
Ready: True
Restart Count: 0
Environment:
DD_ENTITY_ID: (v1:metadata.uid)
DD_AGENT_HOST: (v1:status.hostIP)
Mounts:
/datadog-lib from datadog-auto-instrumentation (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jr8qv (ro)
Containers:
jpet:
Container ID: containerd://3de6b47c52f4a8781a9dfd6a1390c9c1d09664d5cc8847c41ac9c5576b9ac33c
Image: arey/springboot-petclinic
Image ID: docker.io/arey/springboot-petclinic@sha256:b9495bb3152c5e5858ce6952f2c454bce2c3538a788445d1a02028c85aca6b3f
Port: 8080/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 19 Dec 2023 20:48:49 +0900
Last State: Terminated
Reason: OOMKilled
Exit Code: 137
Started: Tue, 19 Dec 2023 20:43:42 +0900
Finished: Tue, 19 Dec 2023 20:48:30 +0900
Ready: True
Restart Count: 1
Environment:
DD_ENTITY_ID: (v1:metadata.uid)
DD_AGENT_HOST: (v1:status.hostIP)
JAVA_TOOL_OPTIONS: -javaagent:/datadog-lib/dd-java-agent.jar
Mounts:
/datadog-lib from datadog-auto-instrumentation (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jr8qv (ro)
datadog-agent:
Container ID: containerd://d70a7e274ae363c0ff5748afc8c077ddc71299469c1876912dc414c54dc43a85
Image: datadog/agent
Image ID: docker.io/datadog/agent@sha256:ef306d23b1fb8be4877b7cf1bc174370d9b66f624bf0e3fb831362b5cb99590c
Port: 8126/TCP
Host Port: 0/TCP
State: Running
Started: Tue, 19 Dec 2023 20:48:45 +0900
Ready: True
Restart Count: 0
Environment:
DD_ENTITY_ID: (v1:metadata.uid)
DD_AGENT_HOST: (v1:status.hostIP)
DD_API_KEY: <API Key>
DD_SITE: datadoghq.com
DD_EKS_FARGATE: true
DD_APM_ENABLED: true
DD_CLUSTER_AGENT_AUTH_TOKEN: aaaaaaaaaabbbbbbbbbbccccccccccdd
DD_CLUSTER_NAME: <Cluster Name>
DD_CLUSTER_AGENT_URL: https://cluster-agent-datadog-cluster-agent.default.svc.cluster.local:5005
DD_ORCHESTRATOR_EXPLORER_ENABLED: true
DD_KUBERNETES_KUBELET_NODENAME: (v1:spec.nodeName)
JAVA_TOOL_OPTIONS: -javaagent:/datadog-lib/dd-java-agent.jar
Mounts:
/datadog-lib from datadog-auto-instrumentation (rw)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jr8qv (ro)
参考資料
公式ドキュメント: Amazon EKS on AWS Fargate