目錄

EKS Nodegroup IP 的配發原理

前情提要

觀察了一下 AWS IP 的使用情況,發現 EKS Node 是耗用 IP 的一大元兇,查了些資料順手記錄一下。

從 EKS node group 中,挑一台 EC2 Instance 查看 IP 資訊

1. 透過 eksctl 查看 Node Group 資訊

1
2
3
4
5
6
eksctl get nodegroup --cluster <cluster-name>


# output
CLUSTER NODEGROUP STATUS CREATED MIN SIZE MAX SIZE DESIRED CAPACITY INSTANCE TYPE IMAGE ID ASG NAME TYPE
mcloud worker ACTIVE 2023-04-18T06:35:13Z 3 6 4 m5a.xlarge AL2_x86_64 eks-worker-xxxx managed

2. 查看 AS Group 中的 EC2 資訊

1
  aws autoscaling describe-auto-scaling-groups --auto-scaling-group-names eks-worker-xxxx --query "AutoScalingGroups[].Instances"

3. 挑其中一台來查看 IP

1
aws ec2 describe-instances --instance-ids i-xxxxx --query "Reservations[*].Instances[*].NetworkInterfaces[]"

Output:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
[
 [
     {
         "Attachment": {
             "AttachTime": "2023-04-18T06:37:00+00:00",
             "AttachmentId": "eni-attach-xxxxx",
             "DeleteOnTermination": true,
             "DeviceIndex": 1,
             "Status": "attached",
             "NetworkCardIndex": 0
         },
         "Description": "aws-K8S-i-xxxxxx5",
         "Groups": [
             {
                 "GroupName": "eks-cluster-sg-xxx-1079633432",
                 "GroupId": "sg-xxxxxx"
             }
         ],
         "Ipv6Addresses": [],
         "MacAddress": "0a:fd:28:xx:xx:xx",
         "NetworkInterfaceId": "eni-0cf25d086xxxxxxx",
         "OwnerId": "xxxxx",
         "PrivateDnsName": "ip-10-x-x-x.ap-northeast-1.compute.internal",
         "PrivateIpAddress": "10.x.x.x",
         "PrivateIpAddresses": [
             {
                 "Primary": true,
                 "PrivateDnsName": "ip-10-x-x-x.ap-northeast-1.compute.internal",
                 "PrivateIpAddress": "10.x.x.x"
             },
             {
                 "Primary": false,
                 "PrivateDnsName": "ip-10-x-x-x.ap-northeast-1.compute.internal",
                 "PrivateIpAddress": "10.x.x.x"
             },
             {
                 "Primary": false,
                 "PrivateDnsName": "ip-10-x-x-x.ap-northeast-1.compute.internal",
                 "PrivateIpAddress": "10.x.x.x"
             },
             {
                 "Primary": false,
                 "PrivateDnsName": "ip-10-x-x-x.ap-northeast-1.compute.internal",
                 "PrivateIpAddress": "10.x.x.x"
             },
:

在 Output 中,可以看到 PrivateIpAddresses 列出了所有 IP。這邊可以觀察到,光是一台 EC2 Instance 就用了 30 個 IP。

EKS NodeGroup IP 配發流程

預設 AWS EKS 使用的 CNI 是官方的 Add-ons Amazon VPC CNI ,供裝 EKS 時會自動套用。

Amazon VPC CNI 中有兩個元件[1]

  • CNI Binary
  • ipamd
IP Address Management (IPAM) daemon
ipamd 的全名是 IP Address Management (IPAM) daemon,負責 IP 的配發。

每次 Node Group 建出新的 EC2 Instance,預設會在所屬 Subnet 中綁定一個 ENI,ipamd 會負責在主 ENI 配發一定數量的 IP slot 用來卡位,這些 ENI 上的空位就是 warm pool,等著後續的 IP 配發。 (warm 的概念後面會持續提到,其實就是預配發的意思)

當主 ENI 的 IP slot 都被填入 IP,ipamd 會再綁定新的 ENI 。此時 ipamd 也同樣會配發 warm pool 給 Secondary ENI。

依此類推,隨著 Pod 的數量越多,ENI 的 pool 一直被塞滿,ipamd 不斷地配新的 ENI ,直到 EC2 Instance 不能再綁定更多 ENI 為止。

至於一個 Instance 能綁多少個 ENI、一個 ENI 能綁多少個 IP,則是由 instance type 決定[2]。

https://aws.github.io/aws-eks-best-practices/networking/vpc-cni/image.png
IP 配發流程


WARM POOL 數量對於 EKS 的影響

在符合 EC2 Instance 規格的限制之下,warm pool 數量是可以被調整的,使用者可在 aws-node daemonset 中,藉由調整環境變數 WARM_ENI_TARGETWARM_IP_TARGETMINIMUM_IP_TARGET 來設定。

WARM_ENI_TARGET: 除了主 ENI,要額外預綁定的 ENI 數量

情境: 我的 Instance 綁定了 2 個 ENI,每個 ENI 各支援 5 個 IP 若 Node 已經用了 5 個 IP,此情況下表示有一個 ENI 已滿,另一個 ENI 還是 warm 的狀態。

這時若有新 Pod 被分配到這個 Node ,要配發的新 IP 會被塞到第二個 ENI 的空 slot 中,這時候就沒有任何 warm ENI 了,

ipamd 就會綁定 WARM_ENI_TARGET 個 ENI 作為備用。

WARM_IP_TARGET: ENI 中,warm pool 的 IP 數量

情境: 我的 Instance 綁定 1 個 ENI,支援 20 個 IP,且 WARM_ENI_TARGET=0

在 WARM_IP_TARGET=5 的情況下,當這個 Node 開始要求第 16 個 IP ,這時表示 warm IP 數量已經小於 5 ,ipamd 會即時呼叫 EC2 API 要求一個新的 ENI。

待新的 ENI 綁定後,會得到一個具有 20 個空位的 warm ENI,一直到下次warm ip 不夠,才會再次要求新 ENI。

MINIMUM_IP_TARGET: ENI 要分配的最少 IP 數

情境: 我的 Instance 綁定 1 個 ENI,支援 10 個 IP 若 MINIMUM_IP_TARGET=100,ipamd 會立刻綁定 9 個 warm ENI (加上原本的 1 個 ENI,這樣 IP 空位才足夠 100)

結論

EKS 中,Pod 也會佔用 ENI 的 IP,在規劃 Subnet 大小的時候需特別注意

如果 EKS 在一個小的 subnet 中供裝,IP 有限,則可透過調整 WARM_IP_TARGETMINIMUM_IP_TARGET,確保 Node 有足夠 IP 可用。


調整設定前,必須先估計好扣除其他服務,整個 Subnet 有多少剩餘 IP 以及大概每個 Node 會執行多少 Pods,可以透過這個 IP 計算機,它能根據 EKS Instance type 和 Pods 數量等,估計出 EKS IP 使用情況。

當然這是以一個 Subnet 估算,若 EKS 供裝在多 AZ 架構,可以再自行推估一下。


整體調整的方向大概是這樣:

先查詢 instance type ,得知 ENI 和 IP 數量。以 m5a.xlarge 為例,它支援 4 個 ENI ,各 15 個 IP。

如果估計出的 Pod 數不會這麼多,可以將 MINIMUM_IP_TARGET 調小,讓它不要預先配好 15 個 IP

MINIMUM_IP_TARGET 必須大於估計的 Pods 數就是了,否則沒有意義


參考資料

[1] https://aws.github.io/aws-eks-best-practices/networking/vpc-cni/

[2] https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/eni-and-ip-target.md