目錄

透過 Pod SNAT 節省 EKS IP 資源

前情提要

繼上次發現 EKS Pods 會佔用 ENI 後,為了解決這個問題,我新增另一組 Private IP 和 VPC 關聯,再透過 Private NAT Gateway 做一層轉換,如此就可以讓所有 EKS Pod 透過同一個 Intranet IP 和地端網段溝通,達到節省 IP 的目的,本篇文會記錄一下實作細節與相關說明。

1. 新增另一組 Private CIDR,與 VPC 關聯

直接配發一個 Private IP 網段,這邊我新增了一個 100.64.0.0/16 網段。
設定方式非常簡單,可以直接從 AWS Console 新增,但團隊有導入 IaC , 就以 Terraform 來建立了:

resource "aws_vpc_ipv4_cidr_block_association" "secondary_cidr" {
  vpc_id     = var.vpc_id
  cidr_block = "100.64.0.0/16"
}

2. 新增 Subnet 並配發 Private IP 網段

由於我的 VPC 實際上是 Intranet IP 網段,該網段的 IP 數量有限,因此必須建立真正意義的 Private Subnet。

建立方式就不詳述了,若是 Multi-AZ 架構,記得每個 AZ 都要建一個 Subnet


2. 新增 Private NAT Gateway,更新 Route Table

在 Intranet 網段建制 Private NAT Gateway,並配置 Route Table 將來自 Private Subnet 的 IP 轉換為 Intranet IP

resource "aws_nat_gateway" "example" {
  connectivity_type = "private"
  subnet_id         = aws_subnet.example.id
}


這邊要特別注意,必須讓 Private Subnet 的預設路由 0.0.0.0/0 走向 Private NAT GW

DestinationTarget
0.0.0.0/0nat-xxx
10.x.x.x/x (vpc)local
100.64.0.0/16local

3. 客製 EKS 網路設定

依據官方文件[1],首先要在 aws-node DaemonSet 中,將 AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG 環境變數設定為 true

1
kubectl set env daemonset aws-node -n kube-system AWS_VPC_K8S_CNI_CUSTOM_NETWORK_CFG=true

再針對步驟 2 所新增的 Private Subnet 新增 ENIConfig:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
cat >$az_1.yaml <<EOF
apiVersion: crd.k8s.amazonaws.com/v1alpha1
kind: ENIConfig
metadata:
  name: $az_1
spec:
  securityGroups:
    - $cluster_security_group_id
  subnet: $new_subnet_id_1
EOF

接著也是最關鍵的一步,為 EKS Pod 設定 SNAT 連線[2]
如此就所有的 Pod 都可以透過 Private NAT Gateay IP 連出去了

1
kubectl set env daemonset -n kube-system aws-node AWS_VPC_K8S_CNI_EXTERNALSNAT=true

結論

本文探討了如何有效管理有限的私有 IP 資源,通過新增一組私有 IP 網段,並將其關聯到 VPC ,並創建了真正的 Private Subnet,以確保 IP 資源的最佳利用。接著透過 Private NAT Gateway 進行轉換,使得所有的 EKS Pod 能夠透過相同的內部 IP 地址與地端網段進行通信,從而節省了 IP 資源。透過這些措施,我們達到了優化 IP 資源使用的目的,同時確保了內部網絡的順暢連接。


參考資料

[1] https://docs.aws.amazon.com/eks/latest/userguide/cni-custom-network.html

[2] https://docs.aws.amazon.com/eks/latest/userguide/external-snat.html