如何阻止Kubernetes在关闭PostgreSQL服务时重启对应容器
根本原因
你遇到的容器重启现象和探针无关,核心原因是容器的生命周期和PID 1进程绑定:你使用的Crunchy PostgreSQL镜像默认将postgres进程作为容器启动的PID 1进程,当你执行pg_ctl stop停掉postgres进程时,PID 1退出会直接触发容器终止,Kubernetes StatefulSet默认的Always重启策略会自动重启终止的容器,你看到的退出码137就是kubelet强制终止容器剩余进程的信号返回值。
解决方案
方案1:临时修改StatefulSet启动命令(推荐,数据无丢失风险)
该方案通过修改启动逻辑让容器保持常驻,不自动启动postgres,你可以直接进入容器执行修复操作:
- 先备份原有StatefulSet配置,防止误操作:
kubectl get statefulset pgset-primary -n qa -o yaml > pgset-primary-backup.yaml
- 编辑StatefulSet配置,替换容器启动命令:
kubectl edit statefulset pgset-primary -n qa
找到containers下的pgset-primary容器配置段,新增/替换command和args配置:
command: ["/bin/sh", "-c"] args: ["sleep 36000"]
修改保存后,Kubernetes会自动重启对应的从库Pod,原有绑定的PVC(pgdata、backrestrepo等)会自动挂载,不会丢失任何存量数据。
3. 等待Pod重启完成后,进入容器执行同步修复操作:
kubectl exec -it pgset-primary-1 -n qa -- /bin/sh
此时容器内只有sleep进程在运行,postgres不会自动启动,你可以直接操作pgdata目录执行重新同步主从数据。
4. 修复完成后,恢复原有StatefulSet配置,删除刚才新增的command和args配置,保存后Pod会自动重启,恢复原有postgres启动逻辑即可。
方案2:使用临时调试容器(适合Kubernetes 1.23+版本,无需修改原有StatefulSet)
如果你的集群开启了临时容器特性,可以直接启动共享进程和存储的调试容器操作,无需重启原有业务Pod:
kubectl debug -it pgset-primary-1 -n qa --image=crunchy-postgres:centos7-9.6.8-1.6.0 --share-processes --copy-to=pgset-primary-debug --volumes-from=pgset-primary
进入调试容器后,你可以直接访问原有Pod的所有存储卷,执行修复操作完成后删除临时Pod即可,原有业务Pod不受影响。
内容的提问来源于stack exchange,提问作者Simon Elms

