StatefulSet Pod处于Pending状态排查:多Persistent Volume Claim配置异常
我仔细看了你的配置和问题描述,Pod一直卡着Pending、第二个PVC无法绑定的问题,核心出在StorageClass的provisioner配置错误,还有对StatefulSet存储挂载逻辑的小误解,具体分析和解决办法如下:
一、直接问题:第二个PVC绑定失败的根源
从kubectl describe pod cassandra-0的事件日志里能看到关键错误:pod has unbound immediate PersistentVolumeClaims,而第二个PVC一直处于Pending状态,原因是你定义的k8s-eu-1-worker-2这个StorageClass的provisioner是无效的:
provisioner: k8s-sigs.io/k8s-eu-1-worker-2
你部署的NFS provisioner pod是k8s-eu-1-worker-1-nfs-subdir-external-provisioner-79fff4ff2qx7k,这类nfs-subdir-external-provisioner的标准provisioner名称应该是k8s-sigs.io/nfs-subdir-external-provisioner,不是你自定义的worker节点名称。Kubernetes找不到你写的这个provisioner,自然没法为第二个PVC动态创建对应的PV,导致PVC一直Pending,Pod也就无法被调度到节点上。
二、其他配置误区
没必要为每个worker单独创建StorageClass
你现在给每个worker写了一个StorageClass,但如果都是用同一个NFS provisioner,其实只需要一个StorageClass就够了,不同的存储需求可以通过参数或标签区分。volumeClaimTemplate的用法不符合你的需求
你想要挂载已经存在的5个NFS共享目录,但volumeClaimTemplate是用来动态生成PVC的,适合需要自动分配存储的场景。如果你已经有现成的NFS共享,更合适的方式是手动创建PV/PVC绑定,再在StatefulSet里直接引用。
三、具体解决步骤
方案1:修正StorageClass的provisioner(适合动态创建场景)
- 确认NFS provisioner的正确名称:可以查看provisioner的部署yaml文件,或者查看pod日志,通常nfs-subdir-external-provisioner的provisioner是
k8s-sigs.io/nfs-subdir-external-provisioner。 - 修改两个StorageClass的provisioner字段为正确值:
kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: k8s-eu-1-worker-1 provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 替换为正确的provisioner名称 parameters: type: pd-ssd --- kind: StorageClass apiVersion: storage.k8s.io/v1 metadata: name: k8s-eu-1-worker-2 provisioner: k8s-sigs.io/nfs-subdir-external-provisioner # 同样修正 parameters: type: pd-ssd
- 重新应用StorageClass,然后删除Pending的PVC,让StatefulSet重新创建:
kubectl apply -f your-storageclass.yaml kubectl delete pvc k8s-eu-1-worker-2-cassandra-0
方案2:手动创建PV/PVC(适合挂载已有NFS共享)
如果你想直接使用已有的5个NFS目录,推荐这种更直接的方式:
- 为每个NFS共享创建PV,比如第一个:
apiVersion: v1 kind: PersistentVolume metadata: name: pv-worker-1 spec: capacity: storage: 1Gi accessModes: - ReadWriteOnce nfs: server: aa.aaa.aaa.aaa # 你的NFS服务器IP path: /srv/shared-k8s-eu-1-worker-1 # 对应的共享路径 storageClassName: k8s-eu-1-worker-1
- 创建对应的PVC绑定这个PV:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pvc-worker-1 spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: k8s-eu-1-worker-1
- 修改StatefulSet配置,去掉volumeClaimTemplate,改用volumes字段引用这些PVC:
volumeMounts: - name: k8s-eu-1-worker-1 mountPath: /srv/shared-k8s-eu-1-worker-1 - name: k8s-eu-1-worker-2 mountPath: /srv/shared-k8s-eu-1-worker-2 volumes: - name: k8s-eu-1-worker-1 persistentVolumeClaim: claimName: pvc-worker-1 - name: k8s-eu-1-worker-2 persistentVolumeClaim: claimName: pvc-worker-2
- 重新应用StatefulSet配置,Pod应该就能正常调度了。
四、额外提醒
你在master节点上把NFS挂载到/mnt/data的操作,和Pod里的存储挂载没有直接关系。Pod运行在worker节点上,必须通过Kubernetes的PV/PVC机制,或者直接在volume里配置NFS参数,才能访问NFS共享目录。
备注:内容来源于stack exchange,提问作者Raphael10

