背景

某集群部署了rancher的local-path-provisioner供有持久化需求的业务pod使用

今天接到同事的求助:发现在部署几个statefulset的时候,有些pod正常,而有些pod会由于pvc unbound status卡住,同事未能检查出原因。

排查

首先进行常规排查:

  1. 对出问题的应用yaml进行垂直、链式检查:statefulset->pvc->storageclass->pv,先排除拼写错误、命名空间错误等低级错误
  2. 尝试重协调(类似于重启大法):通过重启出问题的pod,重建pvc,排除一些概率性的问题
  3. 在确定是必然复现的问题后,继续考虑垂直链路,storageclass到pv之间还有local-path-privisioner的日志可以查看,于是结合2的过程看日志,发现不管怎么重启,provisioner并未被触发,因此pvc也就不会被bound了
  4. 尝试google一下,并没有发现特别的思路
  5. 奇怪的是,同时创建的几个应用没有出现该问题,所以必须水平对比yaml,看看他们的不同,这些关键的不同应该就是解决问题的方法了。快速对比发现,正常的有问题的应用pvc yaml没有什么不同,但是出问题的应用指定了nodeName
  6. 看到这里恍然大悟:pod如果指定了nodeName,那么会跳过调度器的核心工作流程,而pvc的wait for first consumer是为了优化调度而设计的,显然是不能脱离调度器的

解决

  1. pvc引用的storageclass使用了volumeBindingMode: WaitForFirstConsumer时,不能直接指定pod的nodeName字段。后来发现k8s官网也已经对这个小坑进行了提示
  2. 在还没找到问题时,有考虑过临时把storageclass改成volumeBindingMode: Immediate模式,先临时解决问题。但是改完发现local-path-privisoner会报出no node was specified的错误,并不能快速完成切换。(经过快速搜索发现local-path-provisioner需要通过外部注解volume.kubernetes.io/selected-node: master1确定pvc的node)

参考

kubernetes - WaitForFirstConsumer PersistentVolumeClaim waiting for first consumer to be created before binding - Stack Overflow

failed to provision volume with StorageClass "local-storage": configuration error, no node was specified · Issue #332 · rancher/local-path-provisioner (github.com)

Pod with nodeName hangs while waiting for PVC to be provisioned · Issue #383 · rancher/local-path-provisioner (github.com)

文章目录