CI部の村上です。
今回はEKSのノードにデプロイ可能なPodの数をDatadogで見てみたという話です。
はじめに
今回検証した環境
t3.smallのノードが1つだけある構成です。
administrator:~/environment $ kubectl get node NAME STATUS ROLES AGE VERSION ip-192-168-28-124.ap-northeast-1.compute.internal Ready <none> 175m v1.19.13-eks-8df270 administrator:~/environment $ kubectl get node ip-192-168-28-124.ap-northeast-1.compute.internal -o json | jq '.metadata.labels."beta.kubernetes.io/instance-type"' "t3.small"
ノードにデプロイできるPod数に制限があるのはなぜか
EKSはノード(EC2)のENIがもつIPアドレスを使って、各PodにIPアドレスを割り振っていきます。
EC2にはインスタンスタイプごとにアタッチできるENIの数が決まっており、また、ひとつのENIに関連付けられるIPアドレス数も決まっています。
よってPodに対して割り当てるIPアドレスが枯渇した場合、そのノードにPodをデプロイすることができなくなります。
インスタンスタイプごとの最大Pod数
以下に記載があります。t3.smallの場合は11
と記載されています。
t3.smallのEC2の場合、ENIの最大数は3
、ENIあたりの最大IPアドレス数は4
です。
よってt3.smallのEC2には、
3×4=12
のIPアドレスを付与できるのですが、各ENIのプライマリIPアドレスはPodに割り当てられませんので、
3×(4-1)=9
ただし、kube-proxy
とPodへのIPアドレスの割り振りを管理するaws-node
の2つはプライマリIPアドレスが付与されるので、
3×(4-1)+2=11
となります。
ノードにデプロイできるポッドの数を確認するには、次の式を使用します。 (Number of network interfaces for the instance type × (the number of IP addressess per network interface - 1)) + 2
https://github.com/awslabs/amazon-eks-ami/blob/master/files/eni-max-pods.txt
実際に確かめてみる
nginxのDeploymentを使い、追加でPodが10個デプロイされるようにしてみました。
administrator:~/environment $ kubectl get po --all-namespaces -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES default nginx-deployment-579c9f84b5-5rpw9 1/1 Running 0 38m 192.168.21.219 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-579c9f84b5-6mfss 1/1 Running 0 38m 192.168.4.115 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-579c9f84b5-g6ttn 1/1 Running 0 38m 192.168.0.253 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-579c9f84b5-lzv27 1/1 Running 0 38m 192.168.25.240 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-579c9f84b5-qd4fc 0/1 Pending 0 38m <none> <none> <none> <none> default nginx-deployment-579c9f84b5-qdjxt 1/1 Running 0 38m 192.168.3.18 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-579c9f84b5-qzc7w 1/1 Running 0 38m 192.168.29.223 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-579c9f84b5-r65tc 1/1 Running 0 38m 192.168.8.199 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-579c9f84b5-t7tq8 0/1 Pending 0 38m <none> <none> <none> <none> default nginx-deployment-579c9f84b5-zcqmf 0/1 Pending 0 38m <none> <none> <none> <none> kube-system aws-node-gdfpg 1/1 Running 0 114m 192.168.28.124 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> kube-system coredns-59847d77c8-4lpzk 1/1 Running 0 120m 192.168.30.32 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> kube-system coredns-59847d77c8-w5qqx 1/1 Running 0 120m 192.168.4.113 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none> kube-system kube-proxy-l7kvf 1/1 Running 0 114m 192.168.28.124 ip-192-168-28-124.ap-northeast-1.compute.internal <none> <none>
全14個のPodのうち、11個のPodがRunning
、残りはPending
になっていることが分かります。
ここで気をつけないといけないのは、kube-proxy
など最初から存在するPodがあるため、nginxのPodが7個しかデプロイされていない点です。
つまり実際は、追加でデプロイできるPod数は、EC2にデプロイできる最大Pod数よりも少ない数になります。
そもそも監視する必要があるのか
Cluster Autoscalerがデプロイされている環境では、PodがPending状態になると自動的にノードを増やしてくれます。
試しにCluster Autoscalerをデプロイして、再度nginxのPodを10個デプロイしてみます。
今度はすべてのPodがRunning
の状態になっており、ノードが2つに増えていることが分かります。
administrator:~/environment $ kubectl get pod -o wide -A NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES default nginx-deployment-7cbb8c6dc5-4nps8 1/1 Running 0 3m41s 192.168.29.69 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-5fn99 1/1 Running 0 3m41s 192.168.86.20 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-9drb4 1/1 Running 0 3m41s 192.168.16.52 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-hz5q7 1/1 Running 0 3m41s 192.168.76.2 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-jn9fd 1/1 Running 0 3m41s 192.168.69.21 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-lmhw9 1/1 Running 0 3m41s 192.168.24.198 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-mfvnp 1/1 Running 0 3m41s 192.168.88.24 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-r8j28 1/1 Running 0 3m41s 192.168.20.128 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-vgn7q 1/1 Running 0 3m41s 192.168.69.150 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-7cbb8c6dc5-wzqz7 1/1 Running 0 3m41s 192.168.1.152 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> kube-system aws-node-c9gxc 1/1 Running 0 15m 192.168.78.38 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> kube-system aws-node-zmljm 1/1 Running 0 74m 192.168.6.58 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> kube-system cluster-autoscaler-6b8bd8cc5-8s7vm 1/1 Running 0 19m 192.168.19.1 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> kube-system coredns-59847d77c8-s28hp 1/1 Running 0 80m 192.168.2.223 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> kube-system coredns-59847d77c8-wm4qn 1/1 Running 0 80m 192.168.29.232 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none> kube-system kube-proxy-jkgg8 1/1 Running 0 15m 192.168.78.38 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> kube-system kube-proxy-pshbq 1/1 Running 0 74m 192.168.6.58 ip-192-168-6-58.ap-northeast-1.compute.internal <none> <none>
よって、ノードにデプロイ可能なPod数が0になってもCluster Autoscalerがノードを増やしてくれるので、人力での対応は基本的に不要です。
なので監視は不要!とするのもひとつですが、リソースの使用状況を見るためのリソースメトリクスとして監視するのもアリだと考えます。
例えば、コンテナのCPU要求spec.containers[].resources.requests.cpu
を高くしすぎてしまった場合を考えてみます。
一度nginxのPodをすべて削除して、以下のようにnginxのDeploymentのspec.containers[].resources.requests.cpu
を400m
にして再デプロイしてみます。ちなみにmはmillicoresのことで1000m=1vCPUです。
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment labels: app: nginx spec: replicas: 10 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ports: - containerPort: 80 resources: requests: memory: "16Mi" cpu: "400m"
すると、さっきはノードが2つに増えただけでしたが、今度はノードが3つに増えていることがわかります。
administrator:~/environment $ kubectl get node NAME STATUS ROLES AGE VERSION ip-192-168-1-158.ap-northeast-1.compute.internal Ready <none> 6m58s v1.19.13-eks-8df270 ip-192-168-45-66.ap-northeast-1.compute.internal Ready <none> 7m7s v1.19.13-eks-8df270 ip-192-168-78-38.ap-northeast-1.compute.internal Ready <none> 109m v1.19.13-eks-8df270
これはノードが各コンテナに割り当てられるCPUリソースの上限を超えたため、早々にPodがノードにデプロイできなくなりPendingの状態となったことから、ノードがスケールアウトしたのが原因です。
コンテナのCPU要求spec.containers[].resources.requests.cpu
が適切な値であれば良いのですが、そうでない場合は、まだノードにPodをデプロイできる余地があるのにスケールアウトしてしまったことになります。
Podの一覧を見ても、1つのノードあたり11個のPodをデプロイできるのに、5~8個のPodしかデプロイされていません。
administrator:~/environment $ kubectl get pod -A -o wide NAMESPACE NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES default nginx-deployment-6c84f6948f-25wss 1/1 Running 0 8m58s 192.168.29.13 ip-192-168-1-158.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-2wlwv 1/1 Running 0 8m59s 192.168.69.150 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-8hzv7 1/1 Running 0 8m58s 192.168.13.101 ip-192-168-1-158.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-94r26 1/1 Running 0 8m58s 192.168.40.119 ip-192-168-45-66.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-9jwkl 1/1 Running 0 8m59s 192.168.69.21 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-9pdgf 1/1 Running 0 8m59s 192.168.85.52 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-9r92b 1/1 Running 0 8m58s 192.168.47.229 ip-192-168-45-66.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-hkfmc 1/1 Running 0 8m58s 192.168.58.177 ip-192-168-45-66.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-qvdd2 1/1 Running 0 8m58s 192.168.54.22 ip-192-168-45-66.ap-northeast-1.compute.internal <none> <none> default nginx-deployment-6c84f6948f-wnthn 1/1 Running 0 8m58s 192.168.3.105 ip-192-168-1-158.ap-northeast-1.compute.internal <none> <none> kube-system aws-node-4h7c6 1/1 Running 0 7m44s 192.168.1.158 ip-192-168-1-158.ap-northeast-1.compute.internal <none> <none> kube-system aws-node-c9gxc 1/1 Running 0 110m 192.168.78.38 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> kube-system aws-node-gwjdf 1/1 Running 0 7m52s 192.168.45.66 ip-192-168-45-66.ap-northeast-1.compute.internal <none> <none> kube-system cluster-autoscaler-6b8bd8cc5-cw6v2 1/1 Running 0 90m 192.168.86.20 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> kube-system coredns-59847d77c8-4j7t5 1/1 Running 0 90m 192.168.76.2 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> kube-system coredns-59847d77c8-dgdz4 1/1 Running 0 90m 192.168.88.24 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none> kube-system kube-proxy-6plfm 1/1 Running 0 7m44s 192.168.1.158 ip-192-168-1-158.ap-northeast-1.compute.internal <none> <none> kube-system kube-proxy-f865g 1/1 Running 0 7m52s 192.168.45.66 ip-192-168-45-66.ap-northeast-1.compute.internal <none> <none> kube-system kube-proxy-jkgg8 1/1 Running 0 110m 192.168.78.38 ip-192-168-78-38.ap-northeast-1.compute.internal <none> <none>
ですので、Cluster Autoscalerが正しく動作しているか調べるための指標として、ノードにデプロイ可能な最大Pod数に対する起動中のPod数は見れるようにしておくのもアリだと思います。
Datadogで監視する
Datadogで監視する場合、以下のメトリクスを使います。
- ノードにデプロイできる最大Pod数
- 現在ノードにデプロイされているPod数
ノードにデプロイできる最大Pod数
kubernetes_state.node.pods_allocatable
で取得できます。
t3.smallを使っている環境なので、11
と表示されています。
現在ノードにデプロイされているPod数
kubernetes.pods.running
で取得できます。
以下のとおり現在のPod数は8ですが、Datadog上でも8
と表示されています。
administrator:~/environment $ kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE default dd-agent-datadog-cluster-agent-575474dff-jgk7g 1/1 Running 0 17m default dd-agent-datadog-fq9kv 3/3 Running 0 17m default dd-agent-kube-state-metrics-7f4f4f4dd5-6b6rn 1/1 Running 0 17m kube-system aws-node-c9gxc 1/1 Running 0 51m kube-system cluster-autoscaler-6b8bd8cc5-cw6v2 1/1 Running 0 32m kube-system coredns-59847d77c8-4j7t5 1/1 Running 0 32m kube-system coredns-59847d77c8-dgdz4 1/1 Running 0 32m kube-system kube-proxy-jkgg8 1/1 Running 0 51m
まとめ
最後まで読んでいただきありがとうございました。
上記2つのメトリクスを使って、モニターやダッシュボードを設定してみてはいかがでしょうか。