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。
评论(需梯子)