GKE(1.7.12-gke.1)动态配置问题:目录内容存于容器FS而非卷FS
嘿,我之前在GKE上折腾PostgreSQL持久化的时候也碰到过几乎一模一样的问题,咱们来一步步排查可能的原因和解决办法:
1. 先确认PostgreSQL的实际数据目录和PVC挂载路径是否匹配
这是最容易踩的坑——你以为把PVC挂载到了/data,但PostgreSQL可能根本没把数据存在那!
先在第一个运行的PostgreSQL容器里执行这两个命令,验证数据目录:
# 查看PostgreSQL配置的实际数据存储路径 kubectl exec -it <你的第一个postgres pod名> -- psql -U postgres -c 'SHOW data_directory;' # 查看PVC实际挂载到容器的哪个路径 kubectl exec -it <你的第一个postgres pod名> -- mount | grep /data
如果输出的data_directory不是你挂载PVC的路径(比如默认可能是/var/lib/postgresql/data),那数据根本没写到PVC里,第二个容器自然看不到。这时候你需要调整Deployment里的volumeMounts,把PVC挂载到PostgreSQL的data_directory路径,或者修改PostgreSQL的配置把data_directory指向PVC挂载的路径。
2. 检查PVC和PV的状态是否正常
有时候动态创建的PV可能在第一个pod销毁后出现异常,导致第二个pod挂载的是“空”卷:
# 查看PVC状态,必须是Bound kubectl get pvc <你的PVC名称> # 查看对应PV的状态和事件 kubectl get pv <你的PVC绑定的PV名称> kubectl describe pv <你的PVC绑定的PV名称>
如果PVC状态不是Bound,或者PV的Events里有错误(比如挂载失败、权限问题),那得先解决PV的问题。另外注意:GKE动态PV默认的回收策略是Delete,但只要PVC还存在,PV就不会被删除,所以第一个pod销毁后PV应该还在。
3. 排查文件权限和容器安全上下文问题
PostgreSQL容器默认用postgres用户(UID=999,GID=999)运行,它创建的文件权限是属于这个用户的。如果第二个容器用了不同的UID运行,就会看不到这些文件。
先检查第一个容器里的数据目录权限:
kubectl exec -it <你的第一个postgres pod名> -- ls -l /data
再检查第二个容器的运行用户和目录权限:
# 看第二个容器的运行用户UID kubectl exec -it <你的第二个postgres pod名> -- id # 看/data目录的权限 kubectl exec -it <你的第二个postgres pod名> -- ls -l /data
如果第二个容器的UID不是999,你需要在Deployment的securityContext里强制指定运行用户:
spec: template: spec: securityContext: runAsUser: 999 runAsGroup: 999 fsGroup: 999
fsGroup会让挂载的PVC目录自动设置对应的GID权限,确保postgres用户能读写。
4. 确认PostgreSQL是否优雅关闭,数据是否刷盘
如果第一个pod是被强制删除的(比如用了kubectl delete pod --force),PostgreSQL可能来不及把内存中的数据刷到磁盘,导致数据没写到PVC里。
查看第一个pod的终止日志:
kubectl logs <你的第一个postgres pod名> --previous
如果日志里没有出现database system is shut down,说明pod被强制终止了。下次删除pod的时候用普通的kubectl delete pod <pod名>,给PostgreSQL足够的时间完成数据持久化。
内容的提问来源于stack exchange,提问作者jayunit100

