亚马逊AWS官方博客

从大模型训练与推理出发:亚马逊云科技容器环境 IP 消耗、规划与 VPC CNI 优化

摘要:本文源于大模型训练与推理场景中的一个实际问题:大型GPU节点通常只运行少量Pod,但Amazon VPC CNI可能预留大量IP,从而造成子网地址浪费,并影响训练集群扩容和推理服务弹性。文档由此延伸到EKS、ECS和自建Kubernetes在EC2/VPC中的IP消耗、容量突增、升级与蓝绿并存风险,以及相应的规划和治理方案。本文面向负责或参与AI/ML平台、亚马逊云科技容器平台、网络和容量规划的读者


1. 阅读声明

阅读说明:本文源于大模型训练与推理场景中的一个实际问题:大型GPU节点通常只运行少量Pod,但Amazon VPC CNI可能预留大量IP,从而造成子网地址浪费,并影响训练集群扩容和推理服务弹性。文档由此延伸到EKS、ECS和自建Kubernetes在EC2/VPC中的IP消耗、容量突增、升级与蓝绿并存风险,以及相应的规划和治理方案。本文面向负责或参与AI/ML平台、亚马逊云科技容器平台、网络和容量规划的读者;如果您的工作不涉及大模型基础设施、容器网络或VPC子网容量,可只阅读各章节结论,无需继续深入。

1.1 重要注意事项

在使用本文进行架构设计或配置变更前,请先确认以下事项:

  1. 本文主要讨论 IPv4。重点是 EC2 ENI、secondary IPv4 和 Amazon VPC CNI 的地址管理。IPv6、Windows节点、EKS Auto Mode及其他CNI/IPAM模式可能具有不同默认行为和配置方式,应单独查阅对应版本文档。
  2. 实例规格中的IP数量是容量上限,不是默认分配量。文中的g7e.48xlarge和“每张ENI最多64个IPv4”用于说明规划方法;实施前应使用当前区域和实例类型的EC2规格数据确认实际ENI、Network Card、IPv4及prefix上限。
  3. 不要把示例值10直接应用到所有节点。MINIMUM_IP_TARGET=10是针对低Pod密度大型节点的示例,实际值必须根据系统Pod、业务Pod、扩容速度、可接受启动延迟和子网容量计算。
  4. VPC CNI没有通用的每ENI IP硬上限。本文的MINIMUM_IP_TARGET=10WARM_IP_TARGET=0WARM_ENI_TARGET=0MAX_ENI=1组合用于把节点预分配目标降至10个Pod IP并限制CNI使用的ENI数量,不等同于支持“多张ENI、每张最多10个IP”,也不能脱离版本验证视为原生硬上限。
  5. 固定IP数量会牺牲弹性。地址耗尽后,新Pod可能出现failed to assign an IP address to containerWARM_IP_TARGET过低还可能增加EC2 API调用、Pod启动延迟和API限流风险;过高则会浪费子网地址。
  6. CNI容量和调度容量必须一致。调整CNI参数时,应同步检查kubelet maxPods、DaemonSet、hostNetwork Pod、Autoscaler/Karpenter和工作负载调度策略,避免调度器继续把Pod放到没有可用IP的节点。
  7. 特殊网络功能必须单独评估。EFA、多Network Card、Multus、Custom Networking、Security Groups for Pods、Prefix Delegation和ECS Trunking都会改变ENI/IP的使用方式;启用这些能力时,不应只依据主ENI或普通secondary IP数量作判断。
  8. 生产环境不要直接全量修改。建议先在非生产环境或一台全新节点验证,再按AZ和节点组逐步滚动;变更前记录当前DaemonSet、ENI/IP数量、Pod密度和回退配置。不要仅凭存量节点判断,因为旧IP/ENI回收可能存在延迟。
  9. 升级可能覆盖现场配置。重新应用官方manifest、Helm升级、VPC CNI升级或集群重建可能恢复默认值。正式环境应使用固定版本的Helm values、Kustomize或GitOps管理,并在每次升级后重新验证。
  10. 必须按AZ和峰值规划。不要只看VPC总剩余地址或日常平均值;应分别核算每个子网在最大扩容、滚动升级、蓝绿并存、Spot替换和单AZ故障切换时的峰值需求。
  11. 架构优化优先于压缩warm pool。亚马逊云科技更推荐优先评估IPv6、VPC/子网扩容、Secondary CIDR、Custom Networking和Enhanced Subnet Discovery。限制warm IP适合解决利用效率问题,但不应替代长期地址规划。
  12. 上线后需要持续监控。至少监控子网剩余地址、已分配ENI/IP、实际Pod/Task IP、warm pool浪费比,以及InsufficientFreeAddressesInSubnetInsufficientCidrBlocks和CNI分配失败事件。

变更原则:先测量、再计算、后变更;先验证单节点,再滚动到节点组;任何限制方案都必须具备监控、验收和回退路径。

2. 哪些场景需要关注 IP 消耗

容器环境中的 IP 问题不应仅被理解为“Pod 太多”。需要同时关注以下五类风险:

  1. 静态浪费:IP 已分配到 ENI,但没有被 Pod/Task 实际使用;
  2. 稳态真实消耗:大量 Pod/Task 确实需要独立 VPC IP;
  3. 动态突增:扩容事件在短时间内快速增加节点、ENI 和 IP;
  4. 新旧系统并存:滚动升级、蓝绿迁移和故障替换使两套容量同时存在;
  5. 地址存在但不可用:AZ 不均衡、子网碎片化、cooldown 或回收延迟导致实际无法分配。

这个问题同时适用于:

  • Amazon EKSAmazon ECS 和 Fargate;
  • 客户自建 Kubernetes;
  • Kubernetes on EC2、ECS on EC2;
  • 其他直接使用 EC2 ENI/VPC IP 的容器平台;
  • AI/ML、HPC、微服务、批处理和 CI/CD 工作负载。

2.1 大语言模型训练

大规模 LLM 训练是最需要关注 IP 消耗的场景之一,通常具备以下特征:

  • 使用 p5p6g6g7e 等大型 GPU 实例;
  • 一个训练 Pod 占用整台节点,或每节点只有少量 Worker Pod;
  • 单个训练任务一次启动数十至数百台节点;
  • 使用 Kubeflow、MPI Operator、PyTorchJob、Ray 或 Kubernetes 上的 Slurm;
  • Karpenter/Cluster Autoscaler 按 Job 规模快速创建 GPU 节点。

这种场景中,计算资源利用率可能很高,但 Pod IP 利用率很低:

GPU 利用率:高
Pod/节点:1
VPC CNI 已分配 IP/节点:可能数十个

如果 100 台大型 GPU 节点每台只运行一个训练 Pod,业务可能只需要约 100 个 Pod IP,但默认 WARM_ENI_TARGET=1 可能让每台节点预留一整张 ENI 的地址容量,最终预占数千个地址。

其他需要注意的因素:

  • 训练 Job 生命周期短,节点频繁创建和删除;
  • 多个 Job 重叠会抬高瞬时节点和 IP 峰值;
  • 节点等待 Autoscaler 回收期间仍占用 ENI/IP;
  • 即使训练 Pod 使用 hostNetwork: true,节点上的 aws-node/ipamd 仍可能维护默认 warm pool;
  • EFA 或多网卡配置可能额外占用 ENI 和地址资源,需要与 CNI 管理的 ENI 分开核算。

结论:大型 GPU 实例、每节点一个 Pod 和大规模自动扩容的组合,是 warm pool IP 浪费风险最高的场景之一。

2.2 大语言模型推理

LLM 推理的风险取决于部署模式。

2.2.1 单模型独占 GPU 节点

例如一个 vLLM、TGI 或 Triton Pod 占用整台 GPU 节点,或一个模型副本使用节点上的全部 GPU。该模式与训练类似:节点很大、Pod 密度低,主要风险是 warm pool 浪费。

2.2.2 多模型、多副本密集部署

如果每个模型、版本或租户分别部署 Pod,并在单台 GPU 节点上运行多个副本,主要风险会转变为真实 Pod IP 消耗:

实际 Pod IP 需求 ≈ 普通非 hostNetwork Pod 数量

2.2.3 HPA/KEDA 突发扩容

在线推理可能基于 QPS、队列深度、GPU 利用率、Token 生成速率或延迟扩容:

流量突增
→ 推理 Pod 扩容
→ 新建 GPU 节点
→ 节点申请主 IP 和 warm pool
→ 推理 Pod 获取独立 IP

同一时刻会增加节点主 IP、CNI warm IP、Pod IP 和负载均衡相关地址。

2.2.4 Scale-to-zero

KServe、Knative 等平台可能频繁执行 0 → N → 0 扩缩容,带来 IP cooldown、EC2 API 调用增加、warm pool 反复变化和节点回收延迟。

2.2.5 多节点模型分片

Tensor Parallel、Pipeline Parallel、Prefill/Decode 分离和多节点 Ray 推理中,一个模型副本可能包含 Router、Prefill Worker、Decode Worker、Cache 和观测组件,需要按完整拓扑核算 IP,而不是只按“模型副本数”核算。

推理模式 主要 IP 风险
一个推理 Pod 独占 GPU 节点 warm pool 浪费
每节点多个模型 Pod 真实 Pod IP 消耗
HPA/KEDA 快速扩容 IP 瞬时峰值
Scale-to-zero 高频申请/释放和 cooldown
多节点模型分片 节点 IP、warm pool 和 Pod IP 同时增长

2.3 其他 AI/ML、HPC 和大数据场景

2.3.1 传统机器学习训练与 HPC/MPI

TensorFlow、PyTorch、Horovod、MPI 和 HPC 作业通常使用大型实例、低 Pod 密度和多节点并发,与 LLM 训练具有相同风险。

2.3.2 Ray

Ray 通常由一个 Head Pod 和多个 Worker Pod组成。如果一个 Worker 独占一台节点,主要是 warm pool 浪费;如果每节点运行多个 Worker,则真实 Pod IP 消耗增加。Ray Autoscaler 还会造成动态峰值。

2.3.3 Spark、Flink、Dask

Spark Executor、Flink TaskManager 和 Dask Worker 可能快速创建数十至数千个 Pod。Dynamic Allocation 会进一步增加地址申请和释放频率。

2.3.4 数据预处理和 Embedding 批处理

特征工程、数据清洗、向量生成、图片/视频处理等任务通常具有高并发、短生命周期和突发扩容特征,应按最大并发 Job 而不是日常平均值规划。

2.4 大规模微服务和多租户集群

Amazon VPC CNI 通常为每个普通 Pod 分配一个 VPC IP,因此数千 Pod 会真实消耗数千个地址。此外还需要计算:

  • 节点主 IP;
  • CNI warm pool;
  • Ingress/Egress Gateway;
  • Load Balancer;
  • EKS 控制面 X-ENI;
  • VPC Endpoint 和其他共享服务。

多租户集群还会聚合多个团队、环境、Operator、Agent 和测试资源,单个团队规模不大也可能形成较高的总体地址消耗。

Service Mesh sidecar 与业务容器在同一个 Pod 中共享 Pod IP,不会因 sidecar 自动翻倍;但独立 Gateway、Waypoint、控制面和 Telemetry Pod 仍会消耗独立地址。

2.5 批处理、CI/CD 和短生命周期任务

需要关注的场景包括:

  • Kubernetes Job/CronJob;
  • Argo Workflows、Tekton;
  • Jenkins、GitLab/GitHub Runner;
  • AWS Batch on Amazon EKS/Amazon ECS;
  • 大量一次性测试和数据处理任务。

风险来自短时间创建大量 Pod/Task、删除后的 IP cooldown、失败重试、节点扩容和 EC2 API 调用增加。AWS Batch 如果使用 Amazon ECS awsvpc,每个 Task 还需要独立 VPC IP。

2.6 ECS awsvpc 和 Fargate

ECS awsvpc 通常为每个运行中的 Task 分配独立网络接口和私有 IP:

1000 个并发 awsvpc Task ≈ 1000 个 Task IP

以下场景风险较高:

  • ECS Service Auto Scaling;
  • 大规模异步任务;
  • AWS Batch;
  • Fargate/Fargate Spot;
  • 蓝绿部署;
  • 多个服务共享同一组子网。

这类场景没有 VPC CNI 整张 ENI warm pool 的同类问题,但真实地址消耗与 Task 数量直接相关。

2.7 节点扩缩容、Spot、升级和蓝绿并存

2.7.1 Karpenter 或 Cluster Autoscaler 快速扩容

新增节点同时需要节点主 IP、CNI secondary IP/prefix 和 warm pool。地址不足时可能出现:

InsufficientFreeAddressesInSubnet

从而形成 Pod Pending、节点又无法创建的闭环故障。

2.7.2 节点组滚动升级

滚动升级期间旧节点尚未删除,新节点已经启动;每台新节点又会立即建立 CNI warm pool,因此 IP 峰值可能高于普通节点数量翻倍。

2.7.3 蓝绿迁移

新旧 EKS 集群、节点组、AMI、实例类型或 CNI 模式并存时,需要同时容纳:

旧节点/旧集群 IP
+ 新节点/新集群 IP
+ 两套 warm pool
+ 两套负载均衡和基础组件

2.7.4 Spot 替换

Spot 中断前可能提前创建替换节点,新旧节点短时并存。大规模 Spot 波动会形成明显峰值。

2.7.5 AZ 故障切换

子网属于单个 AZ。即使 VPC 总体仍有大量 IP,承接流量的目标 AZ 子网也可能耗尽,因此必须按 AZ/子网独立规划。

2.8 Prefix Delegation、Pod安全组和共享子网

2.8.1 Prefix Delegation 子网碎片化

IPv4 Prefix Delegation 需要连续 /28 地址块。即使子网还有许多零散地址,只要没有连续16个地址,也会出现:

InsufficientCidrBlocks

2.8.2 Security Groups for Pods

部分 Pod 使用 branch ENI 和独立安全组,需要同时关注 Pod IP、branch ENI、trunk ENI及实例支持的branch ENI密度;普通 warm target 不能完整代表这部分容量。

2.8.3 Custom Networking

Custom Networking把Pod地址转移到专用Pod子网或Secondary CIDR,能够缓解节点主子网耗尽,但不会消除地址需求。Pod子网仍需按AZ、Pod增长、warm pool和升级峰值规划。

2.8.4 共享子网

同一子网还可能承载EC2、ECS、RDS、Load Balancer、NAT Gateway、Interface VPC Endpoint、Lambda VPC ENI和EKS控制面X-ENI。任何一个系统扩容都可能影响其他系统。

2.9 统一容量模型和治理触发条件

建议按每个AZ/子网分别计算:

容器场景峰值 IP 需求 =
  主 ENI 的主 IP(即节点主 IP)
+ 每张额外 ENI 的主 IP
+ 实际 Pod/Task IP
+ CNI warm pool
+ Fargate/awsvpc IP
+ 升级或蓝绿重叠容量
+ AZ 故障转移容量
+ 共享基础设施 IP
+ 安全余量

以下任一情况出现时应开始治理:

  • 剩余地址无法支持一次最大节点扩容;
  • 剩余地址无法支持一次节点组滚动升级或蓝绿切换;
  • 某个AZ子网无法承接故障切换;
  • 已分配secondary IP远大于实际使用独立IP的Pod;
  • 出现 InsufficientFreeAddressesInSubnet
  • Pod 出现 failed to assign an IP address to container
  • Prefix Delegation出现 InsufficientCidrBlocks
  • ECS awsvpc Task因ENI/IP不足无法启动。

一个实用但非亚马逊云科技官方的观察指标是:

IP浪费比 = CNI已分配secondary IP / 实际使用独立IP的Pod数
场景 风险等级 主要原因
大规模LLM分布式训练 大型GPU节点、每节点Pod少、节点数量多
单模型独占节点的LLM推理 低Pod密度导致warm pool浪费
多模型/高副本推理 实际Pod IP多、扩容快
Ray/Spark/Flink/Dask Worker Pod多、动态扩缩
HPC/MPI/EFA 大实例、低Pod密度、多节点并发
数千Pod微服务集群 每Pod一个VPC IP
ECS awsvpc/Fargate 每Task一个独立IP
滚动升级/蓝绿迁移 高峰值 新旧节点及warm pool同时存在
Prefix Delegation+碎片化 缺少连续/28地址块
CI/CD和短任务 中高 高频创建删除和突发并发
少量固定节点+大型子网 较低 地址空间充足且变化少
Overlay CNI 较低 Pod通常不消耗VPC子网IP
IPv6 Pod网络 较低 基本消除私有IPv4容量约束

3. 亚马逊云科技默认的 IP 分配行为

3.1 核心原则

EC2实例类型定义最大ENI和IP容量,但默认不会因为实例规格较大就自动拿满地址。实际分配量由启动参数、网络插件和编排平台决定:

EC2实例规格:决定最大容量
网络插件或编排平台:决定实际分配量
工作负载数量:驱动后续动态增长

3.2 普通 EC2

如果没有显式配置额外网卡、secondary IP或prefix,普通EC2启动时通常会:

  1. 创建或附加一张主ENI,即eth0
  2. 从子网分配一个主私有IPv4;
  3. 不主动分配secondary IPv4;
  4. 不主动创建额外ENI。

假设实例每张ENI最多支持64个私有IPv4:

容量上限:每张 ENI 64 个 IPv4
默认实际分配:1 张主 ENI + 1 个主私有 IPv4
未使用容量:63 个 secondary IPv4 槽位

主私有IPv4通常随ENI保留,实例停止/启动后不变,ENI删除后才释放。Secondary IPv4只有在用户、Launch Template、VPC CNI或其他亚马逊云科技服务显式请求时才会分配。

如果子网或启动参数启用自动分配公有IPv4,EC2可能获得一个映射到主私有IPv4的公有地址;它不是额外的secondary私有IP。

3.3 EKS EC2节点与Amazon VPC CNI

标准EKS EC2节点通常运行:

aws-node DaemonSet
└── ipamd

EKS控制面不直接为普通Pod申请secondary IP;节点上的ipamd调用EC2 API,管理ENI、secondary IP和warm pool。

IPv4集群通常默认使用:

ENABLE_PREFIX_DELEGATION=false
WARM_ENI_TARGET=1

WARM_ENI_TARGET=1表示ipamd尝试保持一张没有被Pod使用的warm ENI及其地址容量。典型过程是:

  1. 节点先获得主ENI和节点主IP;
  2. aws-node读取实例ENI/IP容量;
  3. CNI建立secondary IP warm pool;
  4. 普通非hostNetwork Pod每个消耗一个secondary IP;
  5. 已有ENI被Pod使用后,CNI可能附加新ENI以继续满足warm目标;
  6. 持续到负载下降、达到实例上限或MAX_ENI限制。

因此,大型实例即使只有少量Pod,也可能分配一整张ENI对应的地址容量。具体初始化时刻和ENI数量可能受CNI版本、Pod数量和当前状态影响,但默认目标仍是完整warm ENI,而不是严格按实际Pod数分配。

3.3.1 Prefix Delegation

如果启用:

ENABLE_PREFIX_DELEGATION=true

CNI 按 IPv4 /28 prefix分配:

1个 /28 prefix = 16个IPv4地址

默认通常使用WARM_PREFIX_TARGET=1,保持一个完整空闲prefix。Prefix Delegation提高单节点Pod密度并减少EC2 API调用,但要求子网存在连续地址块。

3.3.2 maxPods

kubelet maxPods:控制可调度Pod总量
VPC CNI warm配置:控制预先和动态申请的IP数量

仅降低maxPods不一定减少默认warm pool,需要同步评估CNI参数。

3.3.3 Custom Networking与Pod安全组

  • Custom Networking通常让主ENI服务节点,Pod从ENIConfig指定的其他子网获取地址;
  • Security Groups for Pods可能为Pod使用branch ENI;
  • 此类场景不能只看主ENI判断节点全部IP消耗。

3.4 自建 Kubernetes

Kubernetes本身不会调用EC2 API为Pod分配VPC IP,实际行为取决于CNI/IPAM。

3.4.1 自建Kubernetes + Amazon VPC CNI

如果部署了相同的aws-node DaemonSet,其行为基本与标准EKS一致:

  • ipamd调用EC2 API;
  • IPv4默认使用secondary IP模式;
  • 默认WARM_ENI_TARGET=1;
  • 根据实例类型和warm target申请/释放ENI与IP;
  • 使用相同环境变量进行调优。

该行为来自VPC CNI,不依赖EKS控制面。自建集群需要自行配置IAM权限、EC2 API访问、CNI目录、子网、安全组和路由。

3.4.2 自建Kubernetes + Overlay CNI

Flannel、Calico Overlay、Cilium VXLAN等通常从独立Pod CIDR为Pod分配地址:

EC2节点:1个VPC主私有IPv4
Pod:使用10.244.0.0/16等Overlay地址

这时每个Pod通常不消耗VPC子网IP,VPC地址消耗主要随节点数量增长,但Pod不一定是VPC中的一等网络实体,网络路径和安全模型也不同。

其他直接管理Amazon EC2 ENI的CNI使用自己的IPAM参数,不能套用Amazon VPC CNI的warm target。

3.5 ECS简要行为

ECS由Task Definition中的networkMode决定地址策略:

  • bridge:Task共享节点IP,通过端口映射/NAT通信;
  • host:Task直接使用节点网络;
  • awsvpc:每个Task获得独立任务网络接口和私有IP;
  • awsvpcTrunking:使用trunk/branch ENI提高Task密度,但每个Task仍需要独立IP;
  • Fargate:强制awsvpc,按Task生命周期分配网络接口/IP。

ECS awsvpc的地址消耗通常随运行Task数量变化,不是VPC CNI按完整warm ENI预留的同类模型。

3.6 行为对比

场景 初始地址 Pod/Task是否消耗独立VPC IP 额外分配策略
普通EC2 通常1张主ENI、1个主IPv4 不适用 只有显式请求才增加
EKS + VPC CNI 节点主IP + CNI warm pool 默认按完整warm ENI管理
自建K8s + VPC CNI 与EKS类似 由VPC CNI参数控制
自建K8s + Overlay 通常只有节点主IP 通常否 Pod使用Overlay CIDR
ECS bridge/host 节点主IP Task共享节点网络
ECS awsvpc 节点主IP Task启动时按需分配ENI/IP
Fargate 用户不管理节点 按Task/Pod生命周期分配

3.7 g7e.48xlarge示例

假设每张ENI最多支持64个私有IPv4:(每ENI支持IP数量参考https://docs.aws.amazon.com/zh_cn/AWSEC2/latest/UserGuide/AvailableIpPerENI.html)

  • 普通EC2:默认通常只有1个主私有IPv4;
  • ECS `bridge`/`host`:多个Task共享节点网络;
  • ECS `awsvpc`:节点1个主IP,每个Task额外约1个IP;
  • VPC CNI Kubernetes节点:默认WARM_ENI_TARGET=1可能申请大量secondary IP,并在Pod使用后继续附加warm ENI。

大型GPU节点只运行少量Pod时,VPC CNI默认行为最容易造成地址浪费。

4. 可选的 IP 规划与优化方案

本节基于亚马逊云科技官方《Optimizing IP Address Utilization》提炼。总体原则是:优先解决VPC和子网架构问题,再考虑通过CNI参数压缩warm pool。

4.1 从业务峰值反推VPC和子网容量

这是IPv4场景的第一道防线。规划时应同时计算:

  • 节点主IP和Pod/Task实际IP;
  • CNI warm pool;
  • 最大自动扩容事件;
  • 滚动升级和蓝绿并存;
  • 单AZ故障转移;
  • Load Balancer、RDS、VPC Endpoint等共享资源;
  • EKS控制面X-ENI及升级期间的新旧X-ENI。

亚马逊云科技指出Amazon EKS控制面最多可以创建4张X-ENI,控制面升级期间会先创建新X-ENI再删除旧X-ENI,因此关联到EKS控制面的子网建议至少为/28。多数常规工作负载可从更大的子网起步;最终大小应根据业务峰值而不是示例固定选择。

如果已有子网不足,可以在VPC原有CIDR范围中创建新子网,并更新EKS集群关联的子网和安全组。

4.2 优先考虑IPv6

亚马逊云科技将IPv6列为首选方向。IPv6可避免RFC1918私有IPv4空间限制,让Pod和Service使用IPv6进行集群内通信,同时保留与遗留IPv4端点互通的能力。

适合:

  • 新建平台;
  • 长期大规模增长;
  • 多集群、多租户和高Pod密度环境;
  • 能够完成应用、可观测性、安全和上下游IPv6兼容性评估的组织。

限制:EKS集群IP族通常需要在创建时决定,现有IPv4集群迁移应作为架构项目实施,而不是简单切换参数。

4.3 Prefix Delegation提高节点级Pod密度

Prefix Delegation把IPv4 /28或IPv6 /80 prefix分配给ENI,可提高每节点Pod密度并减少频繁的EC2 API调用,也支持Custom Networking。

适合:

  • 每节点需要运行大量Pod;
  • 实例CPU/内存仍有余量,但secondary IP槽位限制了Pod密度;
  • 希望减少ENI数量和EC2 API调用。

注意:

  • IPv4按16个地址一组分配;
  • 它提升单节点地址容量,不会消除每Pod地址需求;
  • 子网必须有连续/28空间;
  • 建议使用新子网或Subnet CIDR Reservation避免碎片化;
  • maxPods需要与Prefix Delegation容量匹配。

4.4 Secondary CIDR + Custom Networking

当RFC1918空间紧张且暂时无法迁移IPv6时,可以:

  1. 为VPC关联Secondary CIDR;
  2. 为Pod创建专用子网;
  3. 通过ENIConfig让VPC CNI从专用Pod子网分配地址;
  4. 将节点地址和Pod地址分离。

亚马逊云科技建议可考虑RFC 6598共享地址空间100.64.0.0/10,例如100.64.0.0/16,因为它通常比RFC1918地址更少与企业网络重叠,但仍需验证VPC Secondary CIDR限制以及与本地、其他VPC和第三方网络的路由兼容性。

适合:

  • 现有主VPC CIDR难以扩大;
  • 企业RFC1918空间紧张;
  • 希望保留可路由地址给节点和其他基础设施;
  • 需要按AZ建立专用Pod地址池。

Custom Networking是转移和扩展Pod地址空间,不是消除地址消耗;Pod子网仍需规划warm pool、升级和故障转移容量。

4.5 Enhanced Subnet Discovery

VPC CNI 1.18.0起默认启用Enhanced Subnet Discovery,可通过新增并标记子网扩展Pod地址空间:

1. 为VPC关联新CIDR;

2. 在新CIDR中创建子网;

3. 添加标签:

kubernetes.io/role/cni=1

4. 确保:

ENABLE_SUBNET_DISCOVERY=true

现有工作负载可以继续运行,新创建的ENI可使用新发现的子网。该方案通常比完整Custom Networking迁移更轻量,但仍应验证CNI版本、AZ覆盖、路由、安全组和组织治理要求。

4.6 优化VPC CNI warm pool

默认VPC CNI保留完整ENI及其地址,大型实例上可能浪费大量IP。可评估:

WARM_IP_TARGET
MINIMUM_IP_TARGET
WARM_ENI_TARGET
MAX_ENI

推荐思路:

  • MINIMUM_IP_TARGET接近预期Pod密度;
  • 使用较小但非零的WARM_IP_TARGET保留弹性;
  • 避免大型低Pod密度节点默认保留完整warm ENI;
  • 批处理或突发负载应保留足够warm容量,避免启动延迟;
  • 不要把WARM_IP_TARGET设置得过低,否则会增加EC2 API调用并可能触发限流。

亚马逊云科技明确提醒:优化VPC设计、IPv6和Secondary CIDR是更推荐的长期方案;压缩warm pool应视为战术优化,错误配置可能干扰集群运行。

CNI升级可能把现场环境变量重置为默认值,应通过Helm values、Kustomize或GitOps持久管理,并在升级后验证。

4.7 监控地址库存和使用效率

可使用CNI Metrics Helper和CloudWatch监控:

  • 最大可支持ENI数量;
  • 已分配ENI数量;
  • 当前分配给Pod的IP数量;
  • 可用和最大IP数量;
  • 子网剩余地址;
  • 已分配IP与实际Pod的差异。

确保VPC CNI:

DISABLE_METRICS=false

建议按每个AZ/子网设置告警,告警阈值应能覆盖一次最大扩容、升级或故障切换,而不仅是固定剩余百分比。

4.8 多VPC和多账户架构

超大规模场景还可以考虑:

  • 将不同环境或租户拆分到多个VPC;
  • 共享VPC跨账户使用;
  • 通过Transit Gateway、PrivateLink或VPC Lattice优化跨VPC连接;
  • 避免所有集群和服务竞争同一个IPv4地址池。

该方案治理复杂度更高,适合组织级网络架构设计,而不是单集群临时修复。

4.9 方案选择摘要

问题 优先方案 补充方案
新平台长期大规模增长 IPv6 多VPC、容量监控
现有IPv4空间不足 Secondary CIDR + Custom Networking Enhanced Subnet Discovery
单节点Pod密度受限 Prefix Delegation 调整实例类型和maxPods
大型GPU节点IP浪费 调整warm pool 专用GPU子网、限制ENI/IP
子网碎片导致prefix失败 新子网/Subnet CIDR Reservation 整理或替换旧节点
突发扩容启动慢 合理warm pool 提前扩容、预留子网容量
多集群争抢地址 多VPC/共享VPC治理 独立Pod子网
无法立即改造架构 临时调优CNI参数 严格监控和回退方案

5. 控制单节点IP分配目标的详细操作

5.1 需求和边界

目标示例:g7e.48xlarge每张ENI最多支持64个IPv4地址,但Kubernetes节点只需要有限Pod IP,希望单节点最多分配10个secondary Pod IP,而不是使用默认完整ENI容量。

g7e.48xlarge在这里仅用于说明规划方法。实施前必须通过当前区域的EC2实例规格重新确认目标实例类型的ENI、Network Card、每ENI IPv4和prefix容量。

需要区分:

  1. 支持:单节点只使用一张ENI,总共最多准备10个secondary Pod IP;
  2. 不直接支持:允许多张ENI自动扩展,但要求每张ENI分别最多10个IP。

因此,本文方案限制的是单节点总Pod IP和CNI使用的ENI数量。

5.2 配置示例

以下配置适用于普通IPv4 secondary-IP模式,目标是在全新节点上预分配10个Pod IP,并禁止VPC CNI通过额外ENI扩展。必须在固定的CNI版本和目标实例类型上完成第5.7节的验收,确认实际状态符合预期后才能滚动应用。

kubectl -n kube-system set env daemonset/aws-node \
  ENABLE_PREFIX_DELEGATION=false \
  MINIMUM_IP_TARGET=10 \
  WARM_IP_TARGET=0 \
  WARM_ENI_TARGET=0 \
  MAX_ENI=1

等待更新完成:

kubectl -n kube-system rollout status daemonset/aws-node

验收目标(全新节点、普通IPv4 secondary-IP模式、无额外ENI需求):

  • ipamd最多允许节点附加一张ENI;
  • 主ENI包含一个节点主IPv4;
  • CNI准备10个供Pod使用的secondary IPv4;
  • 该ENI合计11个私有IPv4;
  • 10个地址用完后,不再补充分配secondary IP;
  • 后续需要独立IP的Pod无法创建网络。

如果要求“ENI合计最多10个IPv4”并包含节点主IP,应设置:

MINIMUM_IP_TARGET=9

即:

1个主IPv4 + 9个secondary IPv4 = 10个IPv4

MAX_ENI是上限而不是目标。例如改为MAX_ENI=2不会要求CNI主动附加第二张ENI:如果第一张ENI足以容纳节点总目标10个secondary IP,通常仍保持一张;只有第一张ENI容量不足以满足节点总目标,或其他网络功能需要额外ENI时,第二张ENI才可能出现。即使使用两张ENI,MINIMUM_IP_TARGET=10仍表示节点合计10个Pod IP,而不是每张ENI各10个。

5.3 参数说明

5.3.1 ENABLE_PREFIX_DELEGATION=false

关闭IPv4 Prefix Delegation,避免按/28即16个地址的粒度分配。

5.3.2 MINIMUM_IP_TARGET=10

要求CNI至少分配合计10个可供Pod使用的secondary IP,不包含ENI的主IP。该参数的官方语义是节点总Pod IP数量的下限(floor),不是“每张ENI 10个”,也不是独立的最大值。是否能把实际分配量维持在10,还取决于warm target、MAX_ENI、CNI版本、节点现有状态和其他网络功能,因此建议以全新节点进行实验。

5.3.3 WARM_IP_TARGET=0WARM_ENI_TARGET=0

官方文档把大于0的值视为启用相应warm目标。这里显式把两个warm target都设为0,表示不要求保留额外空闲IP或完整warm ENI,避免未设置WARM_ENI_TARGET时继续采用默认值1。

如果把WARM_IP_TARGET设为正数,CNI会随着Pod使用地址继续补充IP,以维持指定数量的空闲地址。亚马逊云科技建议生产环境将MINIMUM_IP_TARGET与正数WARM_IP_TARGET配合使用;将warm target设为0会牺牲突发扩容能力,并可能使地址耗尽后的新Pod网络创建失败。

5.3.4 MAX_ENI=1

指定VPC CNI可使用的ENI数量上限为1;它是ceiling,不是目标值,也不提供“每ENI最多10个IP”的能力。该设置用于阻止普通secondary-IP池通过第二张ENI扩展,不适用于依赖额外EFA、Multus、多Network Card、Custom Networking、Security Groups for Pods或手动ENI的节点。

5.4 同步配置kubelet maxPods

CNI地址上限不等于调度上限。如果kubelet仍报告较大的Pod capacity,调度器可能继续分配Pod,最终出现:

failed to assign an IP address to container

自建Kubernetes应按以下公式配置:

maxPods = S + 计划允许的普通业务Pod数量

其中S是该节点上会被kubelet Pod容量计数占用的基线系统Pod数量,不能假设为0。例如,测得S=1且计划允许10个普通业务Pod时,可配置:

# /var/lib/kubelet/config.yaml;示例值
maxPods: 11

maxPods统计全部计入节点容量的Pod;系统DaemonSet和部分hostNetwork Pod也可能占用槽位。因此生产值必须先测量S,再计算为S+10,而不能机械设置为10。达到调度上限时应出现FailedScheduling: Too many pods;这与VPC CNI地址池耗尽导致的网络分配失败是两个独立限制面。

生产环境修改kubelet通常需要逐节点重启或滚动替换。

5.5 配置持久化

kubectl set env 修改的是 Kubernetes API 中 DaemonSet 的 Pod Template:

  • aws-node Pod重建时会读取更新后的Pod Template;
  • 加入集群的新节点通常运行同一个DaemonSet模板,但仍应在新节点复核ENI/IP状态;
  • 重新应用官方CNI manifest、Helm升级、插件升级或集群重建可能覆盖配置。

正式环境建议使用以下方式之一。

5.5.1 Helm values

# values-vpc-cni.yaml
env:
  ENABLE_PREFIX_DELEGATION: "false"
  MINIMUM_IP_TARGET: "10"
  WARM_IP_TARGET: "0"
  WARM_ENI_TARGET: "0"
  MAX_ENI: "1"

升级时始终使用固定版本和同一个values文件:

helm upgrade --install aws-vpc-cni eks/aws-vpc-cni \
  --namespace kube-system \
  --values values-vpc-cni.yaml \
  --version <PINNED_CHART_VERSION>

不同Chart版本的values结构可能变化,升级前应检查对应版本并使用helm template或dry-run验证。

5.5.2 Kustomize patch

aws-node-env-patch.yaml:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: aws-node
  namespace: kube-system
spec:
  template:
    spec:
      containers:
        - name: aws-node
          env:
            - name: ENABLE_PREFIX_DELEGATION
              value: "false"
            - name: MINIMUM_IP_TARGET
              value: "10"
            - name: WARM_IP_TARGET
              value: "0"
            - name: WARM_ENI_TARGET
              value: "0"
            - name: MAX_ENI
              value: "1"

kustomization.yaml:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
  - aws-k8s-cni.yaml
patches:
  - path: aws-node-env-patch.yaml

如果上游manifest或其他配置层设置了正数warm target,必须确保最终渲染结果将WARM_IP_TARGETWARM_ENI_TARGET都显式设为0。

5.5.3 GitOps

使用Argo CD或Flux持续同步Helm values/Kustomize,可在现场配置被修改后自动恢复,并保留审计记录。节点本地/etc/cni/net.d/不是这些IPAM参数的推荐持久化位置。

5.6 实施条件

  1. 使用IPv4 secondary-IP模式;
  2. VPC CNI至少为支持MINIMUM_IP_TARGET的版本(v1.6.0+),并在固定版本上验证后再发布;
  3. ENABLE_PREFIX_DELEGATION=false;
  4. WARM_IP_TARGET=0WARM_ENI_TARGET=0,最终DaemonSet模板中不存在其他配置层覆盖;
  5. 已确认目标CNI版本在该参数组合下的实际ENI/IP分配和耗尽行为;
  6. 使用MAX_ENI=1时,节点不依赖额外ENI功能;
  7. 最好在工作节点加入集群前完成配置;
  8. 存量节点修改后地址回收可能不是即时的,建议新建测试节点验证后滚动替换;
  9. 超过地址上限后新Pod网络失败是固定上限生效后的预期结果,而不是自动扩容信号。

5.7 验证步骤

5.7.1 检查DaemonSet配置

kubectl -n kube-system get daemonset aws-node \
  -o jsonpath='{range .spec.template.spec.containers[?(@.name=="aws-node")].env[*]}{.name}={.value}{"\n"}{end}'

确认:

ENABLE_PREFIX_DELEGATION=false
MINIMUM_IP_TARGET=10
MAX_ENI=1
WARM_IP_TARGET=0
WARM_ENI_TARGET=0

5.7.2 检查ENI地址数量

aws ec2 describe-network-interfaces \
  --filters Name=attachment.instance-id,Values=<INSTANCE_ID> \
  --query 'NetworkInterfaces[].{ENI:NetworkInterfaceId,Total:length(PrivateIpAddresses),Secondary:length(PrivateIpAddresses[?Primary==`false`])}'

预期:

[
  {
    "ENI": "eni-xxxxxxxxxxxxxxxxx",
    "Total": 11,
    "Secondary": 10
  }
]

5.7.3 验证不继续申请IP

  1. 使用全新测试节点;
  2. 为隔离CNI地址边界,先确保kubelet maxPods至少允许基线系统Pod和11个测试Pod同时被调度;
  3. 部署10个需要独立Pod IP的测试Pod,确认全部Running并获得secondary IP;
  4. 创建第11个需要独立IP的Pod;
  5. 确认前10个仍Running,第11个因VPC CNI IP分配失败而无法建立Pod sandbox,而不是因Too many pods或子网耗尽失败;
  6. 连续多次检查ENI/IP,确认稳定为1 ENI/10 secondary且没有动态增长;
  7. 检查目标子网仍有充足可用地址;
  8. 删除测试资源并检查CNI日志。
kubectl describe pod <POD_NAME>

kubectl -n kube-system logs \
  --selector k8s-app=aws-node \
  --container aws-node \
  --tail=200

5.7.4 独立验证kubelet maxPods

完成CNI地址边界验证后,再把maxPods设置为测得的S+10。在10个测试Pod已运行时,再创建一个测试Pod,应观察到:

FailedScheduling: Too many pods

如果出现CNI IP分配错误,说明测试仍然命中了地址池边界,不能据此判定maxPods生效。

5.7.5 升级或重启后复核

kubectl -n kube-system rollout status daemonset/aws-node
kubectl -n kube-system get pods -l k8s-app=aws-node -o wide

每次CNI/集群升级后,都应重新检查DaemonSet环境变量和一台新节点的ENI地址数量。

5.8 风险和回退

风险包括:

  • 超过地址容量的Pod发生CNI分配失败;
  • maxPods设置不当导致过度调度或容量浪费;
  • EFA、多网卡、Multus、Custom Networking、Pod安全组改变ENI行为;
  • CNI版本差异影响具体实现;
  • 无warm余量会降低突发扩容能力。

恢复动态扩展并保留少量空闲IP:

kubectl -n kube-system set env daemonset/aws-node \
  MINIMUM_IP_TARGET=10 \
  WARM_IP_TARGET=2 \
  WARM_ENI_TARGET- \
  MAX_ENI-

该配置不再以10个Pod IP为验收边界。CNI会随Pod增长继续分配IP,并以2个空闲地址为目标。

恢复默认warm ENI行为:

kubectl -n kube-system set env daemonset/aws-node \
  MINIMUM_IP_TARGET- \
  WARM_IP_TARGET- \
  WARM_ENI_TARGET- \
  MAX_ENI-

此后默认WARM_ENI_TARGET=1重新生效,可能再次预留完整ENI地址容量。

5.9 操作方案结论

  • MINIMUM_IP_TARGET描述节点总Pod IP floor,warm target描述预留容量,MAX_ENI只描述ENI ceiling;这些参数都不是“每ENI IP上限”;
  • 本节参数组合把初始Pod IP目标设为10、禁用warm目标并限制CNI只使用一张ENI,但1 ENI/10 secondary仅作为版本和实例相关的实验目标,具体值请根据实际情况进行设置;
  • 如果需要控制可调度Pod数量,应将maxPods规划为S+10;它控制调度容量,不替代CNI地址池;
  • 应使用声明式配置持久化,在全新节点完成ENI/IP数量、地址耗尽、调度边界和回退验证后,再滚动应用到生产环境;
  • 亚马逊云科技更建议MINIMUM_IP_TARGET配合正数WARM_IP_TARGET保留弹性;将warm target设为0必须接受,分配Pod达到IP限制后,新Pod网络创建失败和突发扩容能力下降的风险;
  • 对于长期IPv4容量不足,应优先采用第4章的IPv6、Secondary CIDR、Custom Networking或子网扩展方案,而不是仅依赖参数压缩。

6. 参考资料

➡️ 下一步行动:

相关产品:

✦ 还没有 AWS 账户?免费创建账户,即刻体验 →

相关文章:

*前述特定亚马逊云科技生成式人工智能相关的服务目前在亚马逊云科技海外区域可用。亚马逊云科技中国区域相关云服务由西云数据和光环新网运营,具体信息以中国区域官网为准。

本篇作者

刘天龙

AWS解决方案架构师,负责支持客户完成各种Workload在AWS上的架构设计,加入AWS之前先后服务于运营商、电力等大型企业,以及Microsoft和Citrix等外企,熟悉大型网络构建及优化,迁移上云及容灾等解决方案

桂冬艳

AWS 技术客户经理,主要支持游戏,互联网行业客户的架构优化、成本管理、技术咨询等工作,并专注在 IAAS,大数据和容器等方向的技术选型,方案落地和实践。在加入 AWS 之前,曾就职于 EMC 和微软,腾讯等科技公司,拥有近 10 年虚拟化与公有云领域的架构优化和技术支持经验。


AWS 架构师中心:云端创新的引领者

探索 AWS 架构师中心,获取经实战验证的最佳实践与架构指南,助您高效构建安全、可靠的云上应用