移除PV清单中nodeSelectorTerms后PodPending,如何让K8s自动调度?
你的Pod处于Pending状态,核心原因是Local Persistent Volume(本地PV)必须指定nodeAffinity——Local PV是节点本地的存储资源,Kubernetes需要明确知道该PV属于哪个节点,才能将依赖它的Pod调度到对应节点。你移除了PV的nodeSelectorTerms后,K8s无法识别该PV关联的节点,导致PVC无法绑定,Pod也就无法被调度。
根据你的需求,以下几种方案可以实现让Kubernetes自动决定Pod的部署位置:
方案1:保留Local PV,通过多PV+动态供应实现自动调度
如果想继续使用Local PV并让K8s自动选择节点,需要为集群中每个节点创建独立的Local PV,再通过StorageClass实现动态绑定:
为每个节点创建专属Local PV
给集群内的每个节点分别创建PV,每个PV的nodeAffinity指向对应节点:# 节点kubernetes1的PV apiVersion: v1 kind: PersistentVolume metadata: name: pv-node1 namespace: registry-space spec: capacity: storage: 5Gi volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain local: path: /opt/registry nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - kubernetes1 accessModes: - ReadWriteOnce --- # 节点kubernetes2的PV apiVersion: v1 kind: PersistentVolume metadata: name: pv-node2 namespace: registry-space spec: capacity: storage: 5Gi volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain local: path: /opt/registry nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - kubernetes2 accessModes: - ReadWriteOnce --- # 节点kubernetes3的PV apiVersion: v1 kind: PersistentVolume metadata: name: pv-node3 namespace: registry-space spec: capacity: storage: 5Gi volumeMode: Filesystem persistentVolumeReclaimPolicy: Retain local: path: /opt/registry nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: kubernetes.io/hostname operator: In values: - kubernetes3 accessModes: - ReadWriteOnce创建Local PV专属StorageClass
apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: name: local-storage provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumerWaitForFirstConsumer模式会等待Pod创建后再绑定PV,让K8s自动调度Pod到有可用PV的节点。修改PVC关联该StorageClass
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: pv1-claim namespace: registry-space spec: storageClassName: local-storage accessModes: - ReadWriteOnce volumeMode: Filesystem resources: requests: storage: 5Gi配置完成后,K8s会在Pod创建时自动选择一个有可用Local PV的节点进行调度。
方案2:改用Deployment的hostPath卷(简单快速)
如果不需要跨节点共享持久化数据,只是想让Pod能被自动调度到任意节点,可以直接去掉Local PV和PVC,在Deployment里用hostPath卷挂载节点本地目录:
修改Deployment的volumes部分:
apiVersion: apps/v1 kind: Deployment metadata: name: private-repository-k8s namespace: registry-space labels: app: private-repository-k8s spec: replicas: 1 selector: matchLabels: app: private-repository-k8s template: metadata: labels: app: private-repository-k8s spec: volumes: - name: certs-vol hostPath: path: /opt/certs type: Directory - name: registry-storage hostPath: path: /opt/registry type: Directory containers: - image: registry:2 name: private-repository-k8s imagePullPolicy: IfNotPresent env: - name: REGISTRY_HTTP_TLS_CERTIFICATE value: "/opt/certs/registry.crt" - name: REGISTRY_HTTP_TLS_KEY value: "/opt/certs/registry.key" ports: - containerPort: 5000 volumeMounts: - name: certs-vol mountPath: /opt/certs - name: registry-storage mountPath: /opt/registry
注意:每个节点的/opt/registry目录是独立的,如果Pod被重新调度到其他节点,之前存储的镜像数据会丢失。
方案3:改用共享存储(生产环境推荐)
如果需要数据持久化且Pod可以在任意节点调度,推荐使用共享存储(如NFS、GlusterFS、Ceph等)。以NFS为例:
- 在集群内搭建NFS服务器,共享目录设为
/nfs/registry - 创建NFS类型的PV和PVC:
apiVersion: v1 kind: PersistentVolume metadata: name: nfs-pv namespace: registry-space spec: capacity: storage: 5Gi volumeMode: Filesystem accessModes: - ReadWriteMany persistentVolumeReclaimPolicy: Retain nfs: server: <NFS服务器IP> path: /nfs/registry --- apiVersion: v1 kind: PersistentVolumeClaim metadata: name: nfs-pvc namespace: registry-space spec: accessModes: - ReadWriteMany resources: requests: storage: 5Gi - 修改Deployment的
volumes部分,使用这个PVC,Pod即可被调度到任意节点,且数据存储在NFS共享目录中。
执行以下命令确认Pod的具体Pending原因,辅助验证解决方案:
kubectl describe pod private-repository-k8s-6d5d954b4f-xkmj5 -n registry-space
内容的提问来源于stack exchange,提问作者Peter Penzov

