14.4 止步不前的PLEG

了解了原理之后,我们来看一下PLEG的日志。日志基本上可以分为两部分,其中skipping pod synchronization这部分是Kubelet同步函数syncLoop输出的,说明它跳过了一次Pod同步;而剩余的PLEG is not healthy:pleg was last seen active<time>ago;threshold is 3m0s,则很清楚地展现了上一节提到的relist超时3分钟的问题。

能直接看到relist函数执行情况的,是Kubelet的调用栈。我们只要向Kubelet进程发送SIGABRT信号,golang运行时就会帮我们输出Kubelet进程的所有调用栈。需要注意的是,这个操作会“杀死”Kubelet进程。但是因为在这个问题中重启Kubelet并不会破坏重现环境,所以影响不大。

以下调用栈是PLEG relist函数的调用栈。从下往上我们可以看到,relist等在通过grpc获取PodSandboxStatus。

使用PodSandboxStatus搜索Kubelet调用栈,很容易找到下面这个线程,此线程是真正查询Sandbox状态的线程,从下往上看,我们会发现这个线程在Plugin Manager里尝试去拿一个Mutex。

而这个Mutex只有在Plugin Manager里边能用到,所以我们查看所有Plugin Manager的相关调用栈。线程中一部分在等Mutex,而剩余的都是在等Terway CNI Plugin。