error codes

ソフトウェアエンジニアリングなど、学んだこと、思ったことの記録です。

dd-agent の EKS on Fargate 対応が何をしているかざっくり調べる

dd-agent の EKS on Fargate 対応について、どのように動作しているか、少し興味があったのでざっくり調べました。

dd-agent の EKS on Fargate 対応は、現在(2020/01) はベータという位置付けです。 ドキュメントは、この辺りになります。

dd-agent コンテナは、サイドカーとして動かします。また、Pod に割り当てる ServiceAccount には、次のような権限が必要になるようです。

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: datadog-agent
rules:
  - apiGroups:
    - ""
    resources:
      - nodes/metrics
      - nodes/spec
      - nodes/stats
      - nodes/proxy
      - nodes/pods
      - nodes/healthz
    verbs:
      - get

Node の API リソースへアクセスできる必要があります。

また、コンテナに環境変数として、 DD_KUBERNETES_KUBELET_NODENAME というものを定義する必要があります。

       - name: DD_KUBERNETES_KUBELET_NODENAME
         valueFrom:
           fieldRef:
             apiVersion: v1
             fieldPath: spec.nodeName

dd-agent の Github リポジトリに、eks-fargate-beta というブランチがあります。この差分をみながら、何をしているか調べてみます。

通常の DaemonSet として各ノードに agent を配置する際は、直接 kubelet に対してリクエストを行いノード内のメトリクス収集を行うようですが、Fargate の際は api-server からノードへプロキシして、ノード内のメトリクス収集を行っているように見えます。

+    if ku.kubeletProxiedEndpoint && config.Datadog.Get("kubernetes_kubelet_nodename") != "" {
+       ku.kubeletApiEndpoint = fmt.Sprintf("https://%s:%s/api/v1/nodes/%s/proxy/", os.Getenv("KUBERNETES_SERVICE_HOST"), os.Getenv("KUBERNETES_SERVICE_PORT"), config.Datadog.Get("kubernetes_kubelet_nodename"))
+       log.Infof("EKS on Fargate mode detected, will proxy calls to the Kubelet through the APIServer at %s", ku.kubeletApiEndpoint)
+       return nil
+   }

api/v1/nodes/{node_name}/proxy/ というパスに対してリクエストすることで、対象ノードの kubelet へのリクエストをプロキシできるということでしょうか。

このURLに対して、手で curl を叩いて実際に情報が得られるか試してみます。

次のような感じの Pod を用意します。

apiVersion: v1
kind: Pod
metadata:
  name: test-myapp
  namespace: myapp
spec:
  serviceAccountName: myapp
  containers:
    - name: test
      image: debian
      env:
        - name: KUBELET_NODENAME
          valueFrom:
            fieldRef:
              apiVersion: v1
              fieldPath: spec.nodeName
      command:["tail", "-f", "/dev/null"]

コンテナに入ります。

kubectl apply -f test-pod.yaml
kubectl exec -it test-myapp sh

そして次のような curl コマンドを実行すると確かに情報が得られます。

curl \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
"https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api/v1/nodes/${KUBELET_NODENAME}/proxy/pods"

curl \
--cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt \
-H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" \
"https://${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT}/api/v1/nodes/${KUBELET_NODENAME}/proxy//metrics"

以上です。

まとめ

まだあまり Kubernetes におけるモニタリング、 kubelet や Kubernetes API の仕様・挙動には詳しくないですが、動作を追うことで少し理解が進みました。

dd-agent の EKS on Fargate 対応で、実際に十分な情報が収集できるのかはまだ検証できていないので、これから行っていこうと思います。