k8s-pvc延迟绑定模式(waitforfirstconsumer)的一个小坑
背景
某集群部署了rancher的local-path-provisioner供有持久化需求的业务pod使用
今天接到同事的求助:发现在部署几个statefulset的时候,有些pod正常,而有些pod会由于pvc unbound status卡住,同事未能检查出原因。
排查
首先进行常规排查:
- 对出问题的应用yaml进行垂直、链式检查:
statefulset->pvc->storageclass->pv
,先排除拼写错误、命名空间错误等低级错误 - 尝试重协调(类似于重启大法):通过重启出问题的pod,重建pvc,排除一些概率性的问题
- 在确定是必然复现的问题后,继续考虑垂直链路,storageclass到pv之间还有local-path-privisioner的日志可以查看,于是结合2的过程看日志,发现不管怎么重启,provisioner并未被触发,因此pvc也就不会被bound了
- 尝试google一下,并没有发现特别的思路
- 奇怪的是,同时创建的几个应用没有出现该问题,所以必须水平对比yaml,看看他们的不同,这些关键的不同应该就是解决问题的方法了。快速对比发现,正常的有问题的应用pvc yaml没有什么不同,但是出问题的应用指定了
nodeName
- 看到这里恍然大悟:pod如果指定了
nodeName
,那么会跳过调度器的核心工作流程,而pvc的wait for first consumer是为了优化调度而设计的,显然是不能脱离调度器的
解决
- pvc引用的storageclass使用了
volumeBindingMode: WaitForFirstConsumer
时,不能直接指定pod的nodeName
字段。后来发现k8s官网也已经对这个小坑进行了提示。 - 在还没找到问题时,有考虑过临时把storageclass改成
volumeBindingMode: Immediate
模式,先临时解决问题。但是改完发现local-path-privisoner会报出no node was specified
的错误,并不能快速完成切换。(经过快速搜索发现local-path-provisioner需要通过外部注解volume.kubernetes.io/selected-node: master1
确定pvc的node)
参考
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。