解决AWS EKS占用太多子网IP的问题

AWS EKS因为一些其他Kubernetes没有的特性,在默认情况下可能会占用大量VPC内子网的IP,从而导致IP不足。

通常情况下Kubernetes的每个Node会从子网里申请一个IP,然后内部所有的Pod都使用私有IP,这样就避免了Pod数量多了之后对子网内IP的大量消耗。

但是AWS EKS默认使用了一个叫CNI的插件,这个插件可以为每个Pod一个分配VPC子网里的IP,这就产生了两个后果:

  • 大量IP会被CNI预留
  • 每个Pod都会消耗一个VPC子网里的IP

如果VPC内IP较少,比如100+,那很快就会遇到IP不足的问题,可以从两方面来解决这个问题:

  • 减少CNI的IP预留量
  • 添加一个额外的CIDR块作为新的子网

这里主要解释第一种方法。

监控程序

AWS文档中提供了一个叫cni-metrics-helper的帮助程序,部署后就可以在CloudWatch中看到EKS的IP使用情况,方便用于调试。

在上图中:

  • totalIPAddresses:总共分配给EKS的IP数
  • assignIPAddresses:EKS中真正被使用的IP数

可以看到,其中有60个IP是没被用到的,但是还是被EKS占据着,这60个IP就被浪费了。

IP分配逻辑

这60个没被使用的IP在CNI中被称为暖池,是为了能够快速给Pod分配而被预留出来的IP。

每个EKS的节点会被分配一个网络接口,同时还会有一个作为冗余,所以每个节点会有两个网络接口,而根据EKS节点型号的不同,每个网络接口里的IP数量也不同,可以在这里看到详细的对应关系。

假设EKS的节点类型是r5.2xlarge,那么根据上面的表,这个型号的网络接口每个会有15个IP,如果有两个节点,那么预留的IP数量就是15 * 2 * 2 = 60。这就是暖池大小的由来。

根据assignIPAddresses,之前已经有34个IP被使用,所以totalIPAddresses就是60+34=94。

减少IP预留量

要减少IP浪费,一种方法就是减少IP的预留量,也就是减小暖池的大小,这个操作可以通过更改CNI中WARM_IP_TARGET这个环境变量来实现。这个参数指定空闲IP地址的数量,详细的解释在这里可以找到。

注意这个参数指的是一台节点的预留量,和每台节点有几个网络接口无关,所以如果有两台节点,想把总的预留大小调整到10,那么值就应该是10 / 2 = 5。

运行以下命令来更改:

1
kubectl set env daemonset aws-node -n kube-system WARM_IP_TARGET=5

从CNI的1.5.0开始,调整完之后没用到的IP就会在几分钟内被自动释放,无需额外操作。可以通过以下命令来检查版本:

1
kubectl describe daemonset aws-node --namespace kube-system | grep Image | cut -d "/" -f 2

这个值也不能太小,推荐在6 ~ 12之间,因为当预留的IP用完之后就会触发申请,对性能会有一定影响。

几分钟后就能看到,totalIPAddresses已经降到了43,和assignIPAddresses的差额减小到了10,释放出了50个IP。


有用的资料

AWS下Jenkins的跨账号部署

评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×