生产级落地:人大金仓 V9 K8s 容器化部署全攻略|持久化存储 + 固定 DNS + 主从高可用防崩方案

生产级落地:人大金仓 V9 K8s 容器化部署全攻略|持久化存储 + 固定 DNS + 主从高可用防崩方案
摘要政务信创项目上云原生是必然趋势但数据库容器化一直是烫手山芋 —— 用 Deployment 部署重启后数据全丢、IP 漂移导致业务断连、单节点宕机直接 GG。本文基于一线政务项目落地经验从零到一拆解人大金仓 V9 在 K8s 环境的生产级部署方案涵盖 StatefulSet 选型逻辑、Headless Service 固定网络标识、StorageClass 动态持久化存储、一主一备流复制高可用架构附全套可直接复制的 YAML 配置与 8 个生产踩坑点。政务选金仓金融选达梦MySQL 迁移选金仓Oracle 迁移选达梦。本文所有配置均在政务内网 K8s 1.27 集群实测跑通复制即用。一、架构选型为什么数据库上 K8s 必须用 StatefulSet核心结论数据库属于典型有状态应用绝对不能用 DeploymentStatefulSet 是唯一正确选择。很多新手图省事直接用 Deployment 跑数据库Pod 一重启就傻眼 —— 数据没了、IP 变了、连不上了。这不是玄学是 Deployment 的设计定位就是无状态应用天生不适合数据库。1.1 StatefulSet 三大核心能力数据库刚需能力维度DeploymentStatefulSet数据库为什么需要Pod 名称随机哈希后缀重启即变固定序号命名kingbase-0、kingbase-1重建后身份不变主从角色不能乱数据卷要跟定特定实例网络标识无固定身份靠 Service 负载均衡配合 Headless Service 生成固定 DNS 域名业务端需要稳定连接地址主备同步需要固定节点名存储绑定所有副本共享或无持久化每个 Pod 独立 PVCPod 重建后自动挂载原数据卷数据独立、互不影响故障恢复数据不丢部署顺序同时创建、同时销毁按序号有序部署0→1→2逆序销毁先启主库、再启备库避免集群脑裂1.2 三种部署模式对比与选型建议部署模式实现方式适用场景推荐指数单节点 StatefulSet单 Pod 持久化存储开发测试、非核心业务系统⭐⭐⭐一主一备 StatefulSet双 Pod 原生流复制 人工 / 半自动化切换生产非核心系统、中小规模政务项目⭐⭐⭐⭐Operator 全生命周期管理自定义 Operator 管控部署 / 备份 / 切换大规模多租户、统一数据库平台⭐⭐⭐⭐⭐落地建议绝大多数政务项目优先选「一主一备 StatefulSet 原生流复制」方案成熟稳定、改造成本低、排障难度小等到多实例规模超过 20 套再逐步建设 Operator 平台。二、前置环境准备镜像、存储、授权三件套2.1 基础环境要求K8s 集群版本1.24本文基于 1.27 实测容器运行时containerd 1.6存储至少配置 1 套生产级 StorageClass推荐本地 SSD 或分布式块存储网络集群 DNS 正常主备节点间网络延迟 5ms2.2 镜像制作基于官方人大金仓 V9 安装包制作 Docker 镜像核心包含数据库二进制文件与依赖库环境变量端口、数据目录、初始化参数启动脚本初始化实例、加载授权、启动服务健康检查脚本⚠️注意镜像务必内置 license.dat 授权文件或通过 ConfigMap/Secret 挂载否则实例启动 24 小时后会自动关停。2.3 存储规划生产环境强烈建议使用独立数据盘不要用系统盘单实例数据盘容量按业务预估 * 1.5 倍预留存储类型优先 ReadWriteOnce 块存储性能优于共享存储回收策略Retain防止误删 PVC 导致数据丢失三、单节点生产级部署完整 YAML从基础版开始先跑通单节点再演进到高可用。所有配置直接复制按需修改命名空间、存储类、资源配额即可。3.1 第一步创建命名空间与配置文件# kingbase-base.yaml apiVersion: v1 kind: Namespace metadata: name: kingbase labels: app: kingbase --- # 数据库核心配置 ConfigMap apiVersion: v1 kind: ConfigMap metadata: name: kingbase-config namespace: kingbase data: kingbase.conf: | listen_addresses * port 54321 max_connections 500 shared_buffers 2GB effective_cache_size 6GB work_mem 8MB maintenance_work_mem 256MB wal_level replica archive_mode on max_wal_size 4GB checkpoint_completion_target 0.9 log_min_duration_statement 1000 log_destination csvlog logging_collector on3.2 第二步Headless Service 对外服务# kingbase-service.yaml apiVersion: v1 kind: Service metadata: name: kingbase-headless namespace: kingbase labels: app: kingbase spec: type: ClusterIP clusterIP: None # 关键设为 None 即为 Headless Service selector: app: kingbase ports: - port: 54321 targetPort: 54321 name: db --- # 对外统一访问入口业务侧连接这个 Service apiVersion: v1 kind: Service metadata: name: kingbase-svc namespace: kingbase labels: app: kingbase spec: type: ClusterIP selector: app: kingbase role: master # 主库标签高可用场景切换时更新 ports: - port: 54321 targetPort: 54321 name: db3.3 第三步StatefulSet 持久化存储模板# kingbase-statefulset.yaml apiVersion: apps/v1 kind: StatefulSet metadata: name: kingbase namespace: kingbase spec: serviceName: kingbase-headless # 绑定 Headless Service replicas: 1 selector: matchLabels: app: kingbase template: metadata: labels: app: kingbase role: master spec: terminationGracePeriodSeconds: 120 # 数据库优雅关停时间 containers: - name: kingbase image: your-registry/kingbase-v9:latest # 替换为你的镜像地址 imagePullPolicy: IfNotPresent ports: - containerPort: 54321 name: db env: - name: KB_PORT value: 54321 - name: KB_USER value: system - name: KB_PASSWORD valueFrom: secretKeyRef: name: kingbase-secret key: password - name: KB_DATABASE value: testdb volumeMounts: - name: kingbase-data mountPath: /opt/kingbase/data - name: kingbase-config mountPath: /opt/kingbase/data/kingbase.conf subPath: kingbase.conf - name: license mountPath: /opt/kingbase/license.dat subPath: license.dat resources: requests: cpu: 2 memory: 4Gi limits: cpu: 8 memory: 16Gi livenessProbe: exec: command: [kb_isready, -U, system, -p, 54321] initialDelaySeconds: 60 periodSeconds: 10 timeoutSeconds: 5 failureThreshold: 3 readinessProbe: exec: command: [kb_isready, -U, system, -p, 54321] initialDelaySeconds: 30 periodSeconds: 5 timeoutSeconds: 3 volumes: - name: kingbase-config configMap: name: kingbase-config - name: license secret: secretName: kingbase-license # PVC 模板每个 Pod 自动创建独立 PVC volumeClaimTemplates: - metadata: name: kingbase-data spec: accessModes: [ReadWriteOnce] storageClassName: local-ssd # 替换为你的 StorageClass resources: requests: storage: 100Gi3.4 第四步Secret 敏感信息配置# kingbase-secret.yaml apiVersion: v1 kind: Secret metadata: name: kingbase-secret namespace: kingbase type: Opaque data: password: cGFzc3dvcmQxMjM # base64 编码后的密码 --- apiVersion: v1 kind: Secret metadata: name: kingbase-license namespace: kingbase type: Opaque data: license.dat: 你的授权文件base64内容✅部署命令kubectl apply -f kingbase-base.yaml kubectl apply -f kingbase-service.yaml kubectl apply -f kingbase-secret.yaml kubectl apply -f kingbase-statefulset.yaml四、固定网络标识Headless Service 深度配置与验证很多人误以为 K8s 里数据库没法固定 IP其实思路要变 ——不是固定 Pod IP而是固定 DNS 域名。Pod IP 本来就会漂移但 DNS 域名是永恒的。4.1 固定 DNS 原理StatefulSet Headless Service 组合会为每个 Pod 生成固定格式的 DNS 记录pod名称.service名称.namespace.svc.cluster.local对应到我们的部署就是kingbase-0.kingbase-headless.kingbase.svc.cluster.local这个域名永远指向 kingbase-0 这个 Pod无论 Pod 重建多少次、IP 怎么变域名不变。4.2 验证固定 DNS# 进入任意 Pod 验证解析 kubectl run -it --rm dns-test --imagebusybox:1.28 --namespacekingbase -- nslookup kingbase-headless正常输出会看到每个 Pod 对应的 A 记录Name: kingbase-headless Address 1: 10.244.1.56 kingbase-0.kingbase-headless.kingbase.svc.cluster.local业务侧连接建议单节点场景直接连kingbase-svc.kingbase.svc.cluster.local:54321主从场景写操作连主库域名读操作可直连备库域名不要直连 Pod IP重启就失效五、持久化存储StorageClass PVC 模板生产级方案数据是数据库的命根子容器化最担心的就是 Pod 删了数据没了。用 volumeClaimTemplates 就不会有这个问题。5.1 volumeClaimTemplates 工作机制StatefulSet 的volumeClaimTemplates不是普通的 Volume它会为每个 Pod 自动创建独立的 PVCkingbase-0 对应 PVCkingbase-data-kingbase-0kingbase-1 对应 PVCkingbase-data-kingbase-1Pod 被删除重建时PVC 不会被删除新 Pod 启动后会自动挂载原来的 PVC数据完整保留。5.2 生产级存储配置要点⚠️这 4 点不注意早晚出大事回收策略必须设 RetainStorageClass 级别的 reclaimPolicy 设为 Retain即使 PVC 被误删底层 PV 和数据仍然保留可手动恢复。访问模式用 ReadWriteOnce数据库单实例写入用 ReadWriteOnce 块存储性能最好不要图省事用 ReadWriteMany 共享存储IO 性能差一截。存储类选择优先级本地 SSD 分布式块存储Ceph RBD 分布式文件存储 NFS 生产环境绝对禁止用 NFS 跑数据库锁机制和 IO 延迟扛不住。数据备份不能省持久化存储不等于备份定期做逻辑备份 存储快照双保险。5.3 数据持久化验证# 1. 进入数据库创建测试表并插入数据 kubectl exec -it kingbase-0 -n kingbase -- ksql -U system -d testdb -c create table test(id int); insert into test values(1); # 2. 删除 Pod触发重建 kubectl delete pod kingbase-0 -n kingbase # 3. 等待重建完成后查询数据 kubectl exec -it kingbase-0 -n kingbase -- ksql -U system -d testdb -c select * from test;✅ 数据还在说明持久化生效。六、高可用防崩一主一备流复制集群落地单节点始终有单点故障风险生产核心系统必须上主备。人大金仓 V9 原生支持流复制和 PostgreSQL 逻辑一致在 K8s 上可以完美落地。6.1 整体架构业务应用 ↓ kingbase-svcClusterIP指向主库 ↓ ┌─────────────┐ 流复制 ┌─────────────┐ │ kingbase-0 │ ──────────→ │ kingbase-1 │ │ 主库 │ │ 备库 │ │ (master) │ │ (slave) │ └─────────────┘ └─────────────┘ ↓ ↓ kingbase-data-0 kingbase-data-1 (PVC) (PVC)6.2 核心配置调整1. ConfigMap 新增复制相关配置# 主库配置追加 wal_level replica max_wal_senders 10 wal_keep_size 1GB max_replication_slots 10 archive_mode on2. StatefulSet 副本数调整为 2replicas: 23. 初始化容器配置主从关系通过 initContainer 判断 Pod 序号0 号初始化为主库1 号初始化为备库并自动搭建流复制initContainers: - name: init-role image: your-registry/kingbase-v9:latest command: [/bin/sh, -c] args: - | POD_ORDINAL$(hostname | awk -F- {print $NF}) if [ $POD_ORDINAL 0 ]; then echo role: master /data/role.conf else echo role: slave /data/role.conf # 等待主库就绪后执行 pg_basebackup 搭建备库 until kb_isready -h kingbase-0.kingbase-headless.kingbase.svc.cluster.local -p 54321; do echo waiting for master... sleep 3 done # 执行备份搭建备库简化示意生产需完善异常处理 k_basebackup -h kingbase-0.kingbase-headless.kingbase.svc.cluster.local \ -U repluser -D /opt/kingbase/data -Fp -Xs -P -R fi volumeMounts: - name: kingbase-data mountPath: /opt/kingbase/data6.3 故障切换机制主库宕机时手动执行切换流程确认备库数据同步状态在备库执行promote命令提升为主库更新 Service 标签 selector将流量切到新主库修复旧主库后重新加入作为新备库进阶方案可部署 repmgr 或 Patroni 同类组件实现自动故障切换但政务场景稳定性优先建议先跑通手动切换验证成熟后再上自动化。七、生产运维 8 大避坑要点踩过的坑直接帮你避⚠️ 坑 1terminationGracePeriodSeconds 设太短默认 30 秒根本不够数据库优雅关停大事务回滚可能需要几分钟。强制关停会导致数据损坏至少设 120 秒以上。⚠️ 坑 2资源 limits 给太小导致 OOM Kill数据库是内存大户limits 内存设小了会被 K8s 直接 Kill数据文件可能损坏。建议按物理内存 70% 给 shared_bufferslimits 至少是 shared_buffers 的 3 倍。⚠️ 坑 3用 Deployment 部署数据库这个说了无数次但还是有人踩。Deployment 重启后 PVC 挂载关系全乱数据卷可能挂载到别的实例上轻则起不来重则数据错乱。⚠️ 坑 4StorageClass 回收策略是 Delete默认很多 StorageClass 回收策略是 DeletePVC 一删数据直接没了。生产环境必须改成 Retain多一层安全垫。⚠️ 坑 5授权文件没持久化license.dat 只打进镜像里后续更新授权要重打镜像、重启 Pod。建议用 Secret 挂载更新授权只需要更新 Secret 再滚动重启。⚠️ 坑 6健康检查间隔太严数据库启动慢initialDelaySeconds 设太短会导致健康检查失败K8s 不断重启 Pod形成死循环。冷启动场景建议设 60 秒以上。⚠️ 坑 7主从切换只切数据库不切 Service主备切换后如果 Service 的 selector 标签没更新业务流量还是打到宕机的旧主库等于白切换。切换流程必须包含标签更新步骤。⚠️ 坑 8不做备份迷信持久化PVC 持久化只能防 Pod 故障防不了人为误删、逻辑错误删表、存储层故障。该做的备份、快照一个都不能少。八、效果验证与常用运维命令8.1 部署状态检查# 查看 StatefulSet 状态 kubectl get statefulset -n kingbase # 查看 Pod 状态与运行节点 kubectl get pods -n kingbase -o wide # 查看 PVC 绑定状态 kubectl get pvc -n kingbase # 查看 Service kubectl get svc -n kingbase8.2 数据库运行状态# 查看数据库日志 kubectl logs -f kingbase-0 -n kingbase # 进入数据库命令行 kubectl exec -it kingbase-0 -n kingbase -- ksql -U system -d testdb # 查看主从复制状态主库执行 select * from pg_stat_replication;8.3 滚动升级配置# 更新 ConfigMap 后滚动重启 StatefulSet kubectl rollout restart statefulset kingbase -n kingbase # 查看滚动更新进度 kubectl rollout status statefulset kingbase -n kingbase总结人大金仓 V9 上 K8s 不是简单把程序塞进容器核心是抓住三个关键点用 StatefulSet 替代 Deployment保障稳定身份与存储绑定用 Headless Service 提供固定 DNS解决 IP 漂移问题用 volumeClaimTemplates StorageClass实现数据持久化不丢失在此基础上叠加原生流复制主备架构就能达到生产级可用标准。这套方案已经在多个政务信创项目落地验证稳定性可靠。政务选金仓金融选达梦MySQL 迁移选金仓Oracle 迁移选达梦。