K8s环境下Postgres StatefulSet挂载PV后数据不持久化问题咨询
Postgres StatefulSet 重部署后数据丢失原因及修复方案
核心原因
1. 持久卷目录权限不匹配
Postgres官方镜像默认使用UID为999的postgres用户运行,你配置的hostPath路径/home/tp/projects/bitbuyer在宿主机上的所有者默认为root或当前登录用户,Postgres进程没有写入该目录的权限。
第一次启动时Postgres会因无法写入挂载的/data目录,自动在容器的可写层初始化数据库,你写入的测试数据全部存储在容器层,删除StatefulSet后容器销毁,数据自然丢失。你可以通过kubectl logs <第一次启动的Postgres Pod名>查看日志,会存在明确的Permission denied报错。
2. PV回收策略配置缺失
你定义的静态PV未显式设置persistentVolumeReclaimPolicy字段,默认值为Delete,如果操作过程中误删PVC,关联的PV及其中的数据会被自动清除。
3. StatefulSet存储配置不规范
你当前手动定义固定名称的PVC直接关联StatefulSet,不符合StatefulSet的设计规范,多副本场景下会出现多个Pod争抢同一个PVC的问题,单副本场景下也存在误删PVC导致数据丢失的风险。
修复步骤
- 给PV添加Retain回收策略,避免数据被误删,修改PV配置如下:
apiVersion: v1 kind: PersistentVolume metadata: name: postgres-pv labels: type: local spec: storageClassName: manual persistentVolumeReclaimPolicy: Retain # 新增这一行 capacity: storage: 1Gi accessModes: - ReadWriteOnce hostPath: path: "/home/tp/projects/bitbuyer" - 修正持久卷目录权限,两种方案二选一即可:
- 直接在宿主机执行命令修改目录所有者:
sudo chown -R 999:999 /home/tp/projects/bitbuyer - 在StatefulSet中添加初始化容器自动修正权限:
# 在StatefulSet的spec.template.spec下添加initContainers字段 initContainers: - name: fix-perms image: busybox:latest command: ["/bin/chown", "-R", "999:999", "/data"] volumeMounts: - name: postgres-pv mountPath: /data
- 直接在宿主机执行命令修改目录所有者:
- (可选优化)将手动定义的PVC替换为StatefulSet专属的
volumeClaimTemplates,自动为每个副本生成独立的PVC,修改后可以删除原有的静态PVC配置:apiVersion: apps/v1 kind: StatefulSet metadata: name: postgresql-db spec: serviceName: postgresql-db-service selector: matchLabels: app: postgresql-db replicas: 1 template: metadata: labels: app: postgresql-db spec: # 如果添加了initContainers放在此处 containers: - name: postgresql-db image: postgres:latest volumeMounts: - name: postgres-storage mountPath: /data env: - name: POSTGRES_PASSWORD value: pgpassword - name: PGDATA value: /data/pgdata # 新增volumeClaimTemplates,删除原有的volumes字段 volumeClaimTemplates: - metadata: name: postgres-storage spec: storageClassName: manual accessModes: - ReadWriteOnce resources: requests: storage: 1Gi
内容的提问来源于stack exchange,提问作者Preston
相关产品推荐
相关产品推荐

