You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Kubernetes集群中PostgreSQL数据库迁移排他性访问问题问询

嘿,这个问题我在帮客户做K8s+Helm部署时碰到好多次了,确实挺头疼的——尤其是当迁移需要数据库排他锁的时候,业务Pod的连接直接把脚本卡得死死的。下面几个方案应该能帮你解决:

方案1:用Helm Hooks先停掉所有业务Pod再执行迁移

Helm的钩子(Hooks)是专门用来在Release生命周期的特定阶段执行操作的,正好可以用来在升级前缩容业务Pod:

  • 在你的Helm Chart里加一个pre-upgrade钩子Job,负责把所有业务Deployment缩容到0,并且等待Pod完全终止:
apiVersion: batch/v1
kind: Job
metadata:
  name: {{ .Release.Name }}-scale-down-services
  annotations:
    "helm.sh/hook": pre-upgrade
    "helm.sh/hook-weight": "-5"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    spec:
      restartPolicy: OnFailure
      containers:
      - name: kubectl
        image: bitnami/kubectl:latest
        command:
        - /bin/sh
        - -c
        - |
          # 替换成你的业务Deployment名称列表
          kubectl scale deployment {{ .Release.Name }}-user-service --replicas=0
          kubectl scale deployment {{ .Release.Name }}-order-service --replicas=0
          # 等待所有相关Pod被删除,避免残留连接
          kubectl wait pods -l app=user-service --for=delete --timeout=5m
          kubectl wait pods -l app=order-service --for=delete --timeout=5m
  • 等这个钩子执行完,你的initContainers迁移脚本就能获得数据库的排他访问权了
  • 迁移完成后,Helm会自动把Deployment的副本数恢复到Chart里定义的值,不用手动改配置
方案2:在迁移脚本里主动终止PostgreSQL连接

如果不想停Pod,也可以在迁移脚本开头加一段SQL,强制断开所有非当前迁移会话的连接:

-- 替换成你的数据库名和业务用户
SELECT pg_terminate_backend(pid)
FROM pg_stat_activity
WHERE datname = 'your_app_db'
  AND pid <> pg_backend_pid()
  AND usename = 'app_service_user';
  • 这段SQL执行后,就能清空数据库的其他连接,让迁移脚本顺利跑起来
  • 注意:这个方法会直接中断业务Pod的请求,最好配合Ingress临时返回维护页面,避免用户看到错误
方案3:用就绪探针控制Pod启动时机(仅适用于兼容型迁移)

如果你的迁移是向前兼容的(旧版本Pod能和迁移后的数据库正常工作),可以调整业务Deployment的就绪探针,让新Pod等迁移完成后再进入就绪状态:

  • 给业务Deployment添加就绪探针,检查迁移是否完成:
readinessProbe:
  exec:
    command:
    - /bin/sh
    - -c
    - "psql -h {{ .Values.postgres.host }} -U {{ .Values.postgres.user }} -d {{ .Values.postgres.db }} -c 'SELECT 1 FROM migration_history WHERE version = ''v2.0.0''' || exit 1"
  initialDelaySeconds: 10
  periodSeconds: 5
  • 这里假设你有一个migration_history表记录迁移版本,探针会一直等到指定版本的迁移完成后,才让Pod对外提供服务
额外提醒
  • 给迁移Job加重试机制:在Job的spec里设置backoffLimit: 3,避免临时网络波动导致迁移失败
  • 迁移前一定要备份数据库:用pg_dump做全量备份,出问题能快速回滚
  • 暂时关闭自动部署:如果有CI/CD流水线,迁移期间最好暂停自动部署,防止并发操作干扰

内容的提问来源于stack exchange,提问作者Meir Tseitlin

火山引擎 最新活动