amzon aws cni 踩坑 2
目前业务上准备试用 aws vpc cni 方案,之前遇到了一些 cni 的使用问题发现还有一些细节不了解。
遂去尝试使用它提供的一些特性开关,在试用 AWS_VPC_K8S_CNI_EXTERNALSNAT
开关,重建了 aws node ds, 发现 ec2 节点的 网卡被 deattach 了,继而导致了使用了绑定在这个网卡上的浮动 ip 的 pod 失联了。
结论:是 ipamd deattach 了 eni, 是 ipamd delete 了 eni.
ipamd 这也的逻辑很奇怪,看代码没有发现明显逻辑问题。
代码分析
下面就是 ipamd
的起手代码,无关逻辑直接删除了方便梳理核心。
1 | func _main() int { |
上述代码和重逻辑,核心在 ipamd.New
的实现中,下面就看一下这个 function
的实现
1 | // New retrieves IP address usage information from Instance MetaData service and Kubelet |
上述代码就是函数核心,看一下官方的的设计提议里面L-IPAM can immediately take one available secondary IP address from its warm pool and assign it to Pod.
, 那两行代码就是准备去满足这个设计需求的。
其实后面 nodeInit
才是这一串代码中的关键点。
1 | //TODO need to break this function down(comments from CR) |
稍微小结一下,上面是初始化流程,每一次启动的时候 ipamd 会在本地建一个地址池,并通过本地一个 dataStore
来标记地址池的分配状态。
具体的下方规则在我们这个问题里面并不关心,是因为我遇到的不是iptables
的转发问题。
看一下每次重启重新标记分配出去的 ip
的逻辑,其实核心逻辑就是 assignPodIPv4AddressUnsafe
中在内存中重建分配数据。
1 | // AssignPodIPv4Address assigns an IPv4 address to pod |
日志分析
第一段是无关代码,基本的一些版本信息
1 | 2019-11-26T02:28:11.342Z [INFO] Starting L-IPAMD v1.5.3 ... |
main 函数开始了,通过 ec2
的 metadata
接口通过 discover 函数的实现来收集 ipamd 启动需要的信息。
1 | 2019-11-26T02:28:11.380Z [INFO] Starting Pod controller |
下面就是准备 node init 了,准备本地路由表,转发规则,建立本地址池。
其中建立地址池的过程概述就是获取弹性网卡,从弹性网卡上获取浮动 ip,将浮动 ip 放到进程缓存中,然后调用 k8s 接口 和 docker 接口重建本地 ip 分配关系。
1 | 2019-11-26T02:28:11.394Z [DEBUG] Start node init |
下面就是重建地址池分配的细节
1 | 2019-11-26T02:28:11.481Z [INFO] Synced successfully with APIServer |
下面的日志就是本次问题的核心了,我还一直很奇怪为什么日志总是说 IP pool stats: total = 28, used = 0, c.maxIPsPerENI = 14
这样的信息,因为在我看来这个节点上使用 aws cni pod 的数量更本不是 0 个。
1 | 2019-11-26T02:28:11.668Z [INFO] Not able to get local containers yet (attempt 1/5): Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running? |
1 | func (c *IPAMContext) getLocalPodsWithRetry() ([]*k8sapi.K8SPodInfo, error) { |
返回 getLocalPodsWithRetry
的调用方 nodeinit
函数,看一下相关逻辑,当 container id 不存在整个ip
重新分配的逻辑就没有走… 没有走… 没有走…
1 | //TODO need to break this function down(comments from CR) |
因为 ipamd 发现我们有大量 ip 申请了,但是没有用 ipamd 处于节约考虑帮我们释放了,下面就是释放的日志了。
1 | 2019-11-26T02:47:06.317Z [DEBUG] nodeIPPoolReconcile: skipping because time since last 51.08553629s <= 1m0s |
尝试修复这个问题
修复方案 1, 让 ipamd 可以正确的与 docker 通信。
1 | root 15066 2.9 1.4 1241172 115768 ? Ssl 09:02 0:12 /usr/bin/dockerd -H unix:///var/run/docker.sock --containerd=/run/containerd/containerd.sock |
1 | guohao@pc ~ $ kubectl --kubeconfig ~/Downloads/kubeconfig -n kube-system describe ds aws-node |
/run/containerd/containerd.sock from dockersock (rw)
就是这里,本是适配社区的 containerd 做了修改,而我们自己的环境是用的 docker.
在重新看一下日志已经没有那个问题了。