Kubernetes部署PostgreSQL遇Pending状态:PVC未找到问题排查
PostgreSQL Pod 处于Pending状态的排查与解决
问题现象
部署NextJS应用时,PostgreSQL Pod始终处于Pending状态,执行kubectl describe pod postgres-deployment-69894b4656-sqwvh输出如下:
Name: postgres-deployment-69894b4656-sqwvh Namespace: k8s-datamaker Priority: 0 Service Account: default Node: <none> Labels: component=postgres-deployment pod-template-hash=69894b4656 Annotations: <none> Status: Pending IP: IPs: <none> Controlled By: ReplicaSet/postgres-deployment-69894b4656 Containers: postgres: Image: postgres Port: 5432/TCP Host Port: 0/TCP Limits: cpu: 125m memory: 32Mi Requests: cpu: 63m memory: 16Mi Environment Variables from: postgres-config ConfigMap Optional: false Environment: POSTGRES_PASSWORD: <set to the key 'DB_PASSWORD' in secret 'dbpassword'> Optional: false Mounts: /var/lib/postgresql/data from postgredb (rw,path="postgres") /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-zv7hj (ro) Conditions: Type Status PodScheduled False Volumes: postgredb: Type: PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace) ClaimName: postgres-pv-claim ReadOnly: false kube-api-access-zv7hj: Type: Projected (a volume that contains injected data from multiple sources) TokenExpirationSeconds: 3607 ConfigMapName: kube-root-ca.crt ConfigMapOptional: <nil> DownwardAPI: true QoS Class: Burstable Node-Selectors: <none> Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s node.kubernetes.io/unreachable:NoExecute op=Exists for 300s Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning FailedScheduling 4m19s (x111 over 9h) default-scheduler 0/1 nodes are available: persistentvolumeclaim "postgres-pv-claim" not found. preemption: 0/1 nodes are available: 1 Preemption is not helpful for scheduling..
用户提供的PostgreSQL Deployment文件:
apiVersion: apps/v1 kind: Deployment metadata: name: postgres-deployment namespace: k8s-app spec: replicas: 1 selector: matchLabels: component: postgres-deployment template: metadata: labels: component: postgres-deployment spec: containers: - name: postgres image: postgres imagePullPolicy: "IfNotPresent" ports: - containerPort: 5432 resources: requests: memory: "16Mi" cpu: "63m" limits: memory: "32Mi" cpu: "125m" envFrom: - configMapRef: name: postgres-config env: - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: dbpassword key: DB_PASSWORD volumeMounts: - mountPath: /var/lib/postgresql/data subPath: postgres name: postgredb volumes: - name: postgredb persistentVolumeClaim: claimName: postgres-pv-claim
PostgreSQL PersistentVolumeClaim文件:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-pv-claim labels: component: postgres-pv-claim spec: resources: requests: storage: 1Gi accessModes: - ReadWriteMany
更新信息:执行kubectl describe pv输出:
Name: pvc-d5e43434-972f-4385-99a6-1af11117c8b3 Labels: <none> Annotations: hostPathProvisionerIdentity: a87b44e1-28cc-4f23-bc79-28c3fccd1cbb pv.kubernetes.io/provisioned-by: k8s.io/minikube-hostpath Finalizers: [kubernetes.io/pv-protection] StorageClass: standard Status: Bound Claim: default/postgres-pv-claim Reclaim Policy: Delete Access Modes: RWX VolumeMode: Filesystem Capacity: 1Gi Node Affinity: <none> Message: Source: Type: HostPath (bare host directory volume) Path: /tmp/hostpath-provisioner/default/postgres-pv-claim HostPathType: Events: <none>
问题根源
Namespace不匹配:
- Pod实际运行在
k8s-datamakernamespace,但需要的PVCpostgres-pv-claim被创建在defaultnamespace(从PV绑定信息可确认)。Kubernetes要求PVC必须与Pod处于同一个namespace才能被引用。 - Deployment文件中指定的namespace是
k8s-app,但实际Pod却在k8s-datamaker,说明部署Deployment时可能使用了错误的namespace参数,导致资源实际所在namespace与定义不符。
- Pod实际运行在
PVC部署位置错误:
创建PVC时未指定namespace,默认部署到defaultnamespace,而Pod所在的k8s-datamakernamespace中不存在同名PVC,因此调度失败。
解决步骤
方法一:将PVC部署到Pod所在的k8s-datamaker namespace
- 修改PVC文件,添加namespace字段:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: postgres-pv-claim namespace: k8s-datamaker labels: component: postgres-pv-claim spec: resources: requests: storage: 1Gi accessModes: - ReadWriteMany
- 删除原PVC:
kubectl delete pvc postgres-pv-claim -n default
- 重新创建PVC:
kubectl apply -f pvc.yaml -n k8s-datamaker
方法二:统一所有资源到同一个namespace(推荐)
选择一个目标namespace(如k8s-app),将所有相关资源部署到该namespace下:
- 确保目标namespace存在:
kubectl create namespace k8s-app
- 删除当前错误的资源:
kubectl delete deployment postgres-deployment -n k8s-datamaker kubectl delete pvc postgres-pv-claim -n default
- 重新部署Deployment和PVC到目标namespace:
kubectl apply -f deployment.yaml -n k8s-app kubectl apply -f pvc.yaml -n k8s-app
- 验证关联资源(ConfigMap、Secret)是否在同一namespace:
kubectl get configmap postgres-config -n k8s-app kubectl get secret dbpassword -n k8s-app
若不在,需重新创建或移动到目标namespace。
验证
执行以下命令确认PVC状态:
kubectl get pvc -n <目标namespace>
当PVC状态变为Bound后,Pod会自动开始调度。
内容的提问来源于stack exchange,提问作者Stefan Radonjic
相关产品推荐
相关产品推荐

