K8s升级PostgreSQL9.6至14.x时保留旧文件的YAML配置问询
核心前提说明
直接修改PostgreSQL镜像版本无法直接启动,三个核心原因:
- PostgreSQL跨大版本不兼容旧格式数据文件,9.6版本的数据文件无法被14版本直接加载,必须通过
pg_upgrade做格式转换 - 官方PostgreSQL镜像的版本二进制文件存放在容器内非持久化路径
/usr/lib/postgresql/<版本号>/bin,Pod重建后旧版本bin文件会直接丢失,必须提前持久化留存 - 你当前配置已经将
/var/lib/postgresql挂载到PVC,旧版本9.6的数据文件已经持久化,不会因为Pod重建丢失
前置操作(仅需执行1次)
在修改Deployment YAML执行apply之前,先进入当前运行的9.6版本PostgreSQL Pod,将旧版本bin文件复制到持久化目录留存:
kubectl exec -it <当前运行的postgres Pod名称> -- bash -c "mkdir -p /var/lib/postgresql/bin/9.6 && cp -r /usr/lib/postgresql/9.6/bin/* /var/lib/postgresql/bin/9.6/"
修改后的完整Deployment YAML
apiVersion: apps/v1 kind: Deployment metadata: name: postgres spec: replicas: 1 strategy: type: Recreate template: metadata: labels: name: postgres spec: initContainers: - name: prep-new-version image: postgres:14 imagePullPolicy: Never command: - bash - -c - | mkdir -p /pg-storage/bin/14 /pg-storage/14/data cp -r /usr/lib/postgresql/14/bin/* /pg-storage/bin/14/ chown -R postgres:postgres /pg-storage/ chmod 700 /pg-storage/9.6/data /pg-storage/14/data volumeMounts: - mountPath: /pg-storage name: postgres-persistent-storage containers: - name: postgres imagePullPolicy: Never image: postgres:14 ports: - name: postgres containerPort: 5432 env: - name: POSTGRES_INITDB_ARGS value: "--encoding=UTF8 --locale=C" command: - bash - -c - | # 首次启动检测新数据目录是否存在,不存在则执行升级 if [ ! -f /var/lib/postgresql/14/data/PG_VERSION ]; then # 初始化14版本空数据目录 su postgres -c "/usr/lib/postgresql/14/bin/initdb -D /var/lib/postgresql/14/data $POSTGRES_INITDB_ARGS" # 执行升级预检查 su postgres -c "/usr/lib/postgresql/14/bin/pg_upgrade \ -b /var/lib/postgresql/bin/9.6 \ -B /var/lib/postgresql/bin/14 \ -d /var/lib/postgresql/9.6/data \ -D /var/lib/postgresql/14/data \ --check" if [ $? -ne 0 ]; then echo "PostgreSQL升级预检查失败,请校验旧数据完整性" exit 1 fi # 执行正式升级 su postgres -c "/usr/lib/postgresql/14/bin/pg_upgrade \ -b /var/lib/postgresql/bin/9.6 \ -B /var/lib/postgresql/bin/14 \ -d /var/lib/postgresql/9.6/data \ -D /var/lib/postgresql/14/data" fi # 升级完成后按官方默认逻辑启动数据库 exec docker-entrypoint.sh postgres volumeMounts: - mountPath: /var/lib/postgresql name: postgres-persistent-storage volumes: - name: postgres-persistent-storage persistentVolumeClaim: claimName: postgres-pv-claim
关键改动说明
- 将已经废弃的
extensions/v1beta1API替换为稳定版apps/v1,兼容所有现行K8s版本 - 新增
Recreate发布策略,升级过程中会先销毁旧Pod再创建新Pod,避免多实例同时读写同一个PVC导致数据损坏 - 新增初始化容器,新Pod启动前自动将14版本的二进制文件复制到PVC持久化留存,和旧版本bin、data目录统一存放,不会因为Pod重建丢失
- 新增容器启动逻辑:第一次启动14版本时自动完成数据目录初始化、升级预检查、版本升级全流程,升级完成后后续重启会直接启动14版本数据库,不会重复执行升级操作
- 所有旧版本9.6的bin、data文件都会完整保留在PVC中,后续需要回滚时只需要将镜像切回postgres:9.6,指定PGDATA为旧版本数据路径即可快速回滚
注意事项
- 升级前建议对绑定的PV做快照备份,避免升级过程异常导致数据损坏
- 升级完成后旧版本数据目录不会自动删除,确认业务运行正常不需要回滚后,可以手动进入容器删除
/var/lib/postgresql/9.6目录释放存储空间 - 如果你本地的postgres:14镜像自定义了数据目录或二进制路径,对应调整YAML里的路径值即可
内容的提问来源于stack exchange,提问作者hammer89
相关产品推荐
相关产品推荐

