K8s 达梦数据守护集群部署|容器化高可用生产落地指南

摘要

别再拿物理机那套玩达梦高可用了。本文记一次生产级 K8s 部署达梦数据守护集群的完整过程,从镜像改造、StatefulSet 编排,到主备自动切换验证,全部配置直接复制可用。文章提供关键配置文件对比表、避坑总结,助你一步到位落地容器化信创数据库高可用。

📌 政务选金仓,金融选达梦;MySQL 迁移选金仓,Oracle 迁移选达梦。


1. 背景与总体架构

达梦数据守护集群(DM Data Watch)对标 Oracle Data Guard,支持实时主备、自动故障切换。将其搬到 K8s 上,可以实现:

  • 主备实例自动编排、IP 无状态化

  • 数据持久化到 PVC,节点漂移不丢数据

  • 守护进程与确认监视器容器化,统一管理

整体部署形态:

  • 两个 StatefulSet 分别管理主库、备库(也可用同一个 StatefulSet 做双副本,但我推荐分开便于配置差异化)

  • 持久化存储:达梦数据文件、归档日志、守护进程日志均使用 PVC

  • 服务暴露:主库通过 ClusterIP Service 固定访问入口,备库提供只读服务

  • 达梦监视器(Monitor)作为独立 Deployment 持续监控集群状态

✅ 本次环境:K8s 1.28 + 达梦 DM8.1 (8.1.2.192) + NFS 存储类


2. 环境与镜像准备

2.1 基础环境信息

组件 版本/规格
Kubernetes v1.28.2
达梦数据库 DM8.1.2.192 (Docker)
存储类 nfs-client (ReadWriteOnce)
镜像仓库 harbor.dm.local

2.2 达梦容器镜像定制

官方镜像可直接用,但需要打入配置脚本。我基于 dm8:dm8_20230808_rev197567_x86_rh6_64_ent 构建新镜像,增加:

  • 初始化脚本 init.sh,用于根据 Pod 名称自动渲染配置文件

  • 所需工具:dminit, dmwatcher, dmmonitor

Dockerfile 关键片段:

复制代码
dockerfile

FROM dm8:dm8_20230808
COPY dm_init.sh /usr/local/dmdbms/bin/
COPY dm_svc.conf /etc/dm_svc.conf
RUN chmod +x /usr/local/dmdbms/bin/dm_init.sh
ENTRYPOINT ["/usr/local/dmdbms/bin/dm_init.sh"]

dm_init.sh 逻辑:判断 Pod 名称末尾 -0 则按主库配置,-1 则按备库配置。

💡 避坑: 达梦容器内默认用户为 dmdba,启动脚本必须切到此用户,否则会因权限报错。


3. 主库 StatefulSet 部署

3.1 配置文件准备

我们使用 ConfigMap 挂载主库的参数文件,方便修改。

主库 dm.ini 关键参数(与备库不同之处已标出):

复制代码
ini

INSTANCE_NAME = DMW_01        # 实例名,主备不同
PORT_NUM = 5236              # 数据库端口
MAL_INI = 1
ARCH_INI = 1
ALTER_MODE_STATUS = 0
ENABLE_OFFLINE_TS = 2
RLOG_SEND_APPLY_MON = 64
DW_PORT = 52141              # 守护进程 TCP 端口

由于篇幅,完整文件可通过 ConfigMap 注入。

dmmal.ini(MAL 通信配置,主备共用):

复制代码
ini

[MAL_INST1]
MAL_INST_NAME = DMW_01
MAL_HOST = dm-primary-0.dm-primary-svc  # 主库 StatefulSet Pod 域名
MAL_PORT = 61141
MAL_INST_HOST = dm-primary-0.dm-primary-svc
MAL_INST_PORT = 5236

[MAL_INST2]
MAL_INST_NAME = DMW_02
MAL_HOST = dm-standby-0.dm-standby-svc
MAL_PORT = 61142
MAL_INST_HOST = dm-standby-0.dm-standby-svc
MAL_INST_PORT = 5237

dmarch.ini(归档配置):

复制代码
ini

[ARCHIVE_LOCAL1]
ARCH_TYPE = LOCAL
ARCH_DEST = /dm/data/arch
ARCH_FILE_SIZE = 2048
ARCH_SPACE_LIMIT = 51200

[ARCHIVE_REALTIME1]
ARCH_TYPE = REALTIME
ARCH_DEST = DMW_02        # 备库实例名

dmwatcher.ini(守护进程配置):

复制代码
ini

[DMW_01]
DW_TYPE = GLOBAL
DW_MODE = MANUAL          # 首次手动切换
DW_ERROR_TIME = 10
INST_RECOVER_TIME = 60
INST_ERROR_TIME = 20
INST_OGUID = 453331
INST_INI = /dm/data/DAMENG/dm.ini
INST_AUTO_RESTART = 1
INST_STARTUP_CMD = /usr/local/dmdbms/bin/dmserver
RLOG_SEND_THRESHOLD = 0
RLOG_APPLY_THRESHOLD = 0

⚠️ 注意:INST_OGUID 主备必须一致,且不为 0。

3.2 StatefulSet YAML(主库)

复制代码
yaml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: dm-primary
spec:
  serviceName: dm-primary-svc
  replicas: 1
  selector:
    matchLabels:
      app: dm-primary
  template:
    metadata:
      labels:
        app: dm-primary
    spec:
      containers:
      - name: dm-primary
        image: harbor.dm.local/dm8:datawatch
        ports:
        - containerPort: 5236
          name: db
        - containerPort: 52141
          name: dw
        - containerPort: 61141
          name: mal
        env:
        - name: ROLE
          value: PRIMARY
        - name: INSTANCE_NAME
          value: DMW_01
        volumeMounts:
        - name: data
          mountPath: /dm/data
        - name: config
          mountPath: /dm/config
      volumes:
      - name: config
        configMap:
          name: dm-primary-config
  volumeClaimTemplates:
  - metadata:
      name: data
    spec:
      accessModes: [ "ReadWriteOnce" ]
      resources:
        requests:
          storage: 100Gi
      storageClassName: nfs-client

配套 Headless Service:

复制代码
yaml

apiVersion: v1
kind: Service
metadata:
  name: dm-primary-svc
spec:
  clusterIP: None
  ports:
  - port: 5236
    name: db
  - port: 52141
    name: dw
  selector:
    app: dm-primary

👉 初始化主库(在容器启动脚本中判断 ROLE=PRIMARY 时执行):

复制代码
cd /dm/data
dminit PATH=/dm/data DB_NAME=DAMENG INSTANCE_NAME=DMW_01 \
       PAGE_SIZE=32 EXTENT_SIZE=32 CASE_SENSITIVE=1 \
       CHARSET=1 PORT_NUM=5236
# 启动数据库一次,开启归档
dmserver /dm/data/DAMENG/dm.ini mount

然后通过 SQL 设置 OGUID、开启守护:

sql 复制代码
SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 1);
ALTER DATABASE MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE ADD ARCHIVELOG 'DEST=DMW_02,TYPE=REALTIME';
ALTER DATABASE OPEN FORCE;
SP_SET_OGUID(453331);
ALTER DATABASE SET STANDBY BY REAL;

4. 备库部署与守护进程配置

备库采用独立的 StatefulSet dm-standby,结构与主库类似,但副本数为 1,配置文件不同。

备库关键参数差异化对照表:

参数 主库 备库
INSTANCE_NAME DMW_01 DMW_02
PORT_NUM 5236 5237
DW_PORT 52141 52142
MAL_INST_PORT (通信端口) 5236 5237

备库 dmwatcher.iniINST_OGUID 同样为 453331。

备库初始化: 不需要执行 dminit,而是从主库备份还原。简化流程:先在主库全量备份,再在备库恢复并配置 standby。自动化脚本可实现在备库启动时,远程拉取备份并还原。

🛑 避坑: 务必备库数据库版本与主库完全一致,否则 MAL 通信会失败。

启动备库后执行:

sql 复制代码
SP_SET_PARA_VALUE(1, 'ALTER_MODE_STATUS', 1);
ALTER DATABASE MOUNT;
SP_SET_OGUID(453331);
ALTER DATABASE SET STANDBY BY REAL;
ALTER DATABASE OPEN FORCE;

5. 确认监视器与自动切换验证

部署一个独立 Deployment 运行 dmmonitor,持续观察集群。

dmmonitor 配置(dmmonitor.ini):

sql 复制代码
ini

MON_DW_CONFIRM = 1
MON_LOG_PATH = /dm/monitor/log
MON_DW_IP = dm-primary-svc:52141,dm-standby-svc:52142

使用命令启动:

sql 复制代码
bash

dmmonitor /dm/monitor/dmmonitor.ini

验证自动切换:

  1. 模拟主库宕机:kubectl delete pod dm-primary-0

  2. 观察监视器输出,备库应在 INST_ERROR_TIME 后自动切换为 PRIMARY

  3. 旧主恢复后自动成为新备库

✅ 切换成功的关键:MAL 网络互通、OGUID 一致、守护进程配置无误。


6. SpringBoot3 连接配置(含 dm_svc.conf)

达梦数据守护集群对外服务地址可以通过 dm_svc.conf 配置服务名,实现自动读写分离和故障切换。

dm_svc.conf:

sql 复制代码
TIME_ZONE=(480)
LANGUAGE=(cn)
DMSERVER=(dm://dm-primary-svc:5236?rwSeparate=true&rwPercent=70)

在 SpringBoot3 的 application.yml 中:

sql 复制代码
spring:
  datasource:
    url: jdbc:dm://dm-primary-svc:5236?schema=DAMENG&compatibleMode=oracle
    username: SYSDBA
    password: Dameng@123
    driver-class-name: dm.jdbc.driver.DmDriver

💡 提示: 连接串直接指向主库 Service,当发生切换,应用通过 dm_svc.conf 可重新解析主库地址。


7. 生产避坑清单

坑点 现象 解决方案
dmmal.ini 中主机名写错 MAL 链路无法建立,守护进程不断重启 使用 ping 测试 Pod 域名,确保 DNS 解析正确
主备实例名大小写不一致 归档失败,SQL 报错 达梦实例名大小写敏感,保持完全一致
PVC 存储类不支持 ReadWriteOnce 备库节点漂移后无法挂载数据卷 使用共享存储或本地卷 ReadWriteOnce 确保绑定节点
容器资源 limit 不足 数据库在高峰时 OOMKilled 建议内存 limit >= 4Gi,并设置 MEMORY_POOLBUFFER 参数
忘记设置 INST_OGUID 守护进程启动报 OGUID invalid 主备都必须执行 SP_SET_OGUID

🛑 致命错误: 一定要测试主库宕机场景,确保确认监视器能正常将备库提升为主,否则高可用形同虚设。


📢 专注 SpringBoot3 + 人大金仓 + 达梦信创实战,关注不迷路

这篇文章从镜像构建到 K8s 部署、再到 SpringBoot 连接,一套完整的达梦数据守护集群容器化落地模板全部给你了。你可以直接 fork 我的配置文件,稍作修改就上生产。

🔥 政务选金仓,金融选达梦;MySQL 迁移选金仓,Oracle 迁移选达梦。

相关推荐
张忠琳2 小时前
【NPU】Ascend Docker Runtime v26.0.1 之一 runtime/main.go — 超深度分析
云原生·容器·架构·kubernetes·npu·docker-runtime
画中有画2 小时前
云原生可观测性体系设计及其应用
云原生
刹那芳华19923 小时前
基于 Docker 的 LLaMA-Factory 全流程部署指南
docker·容器·llama
Freed&3 小时前
K8s 1.29 集群部署文档
云原生·容器·kubernetes
人间凡尔赛5 小时前
告别冷启动!WebAssembly + Spin 实战:Serverless 延迟从 1 秒降到 1 毫秒
后端·云原生·serverless·webassembly·spin
扶疏52518 小时前
Prometheus+Prometheus Adapter+metrics-server+Ingress实现k8s水平自动扩缩容(HPA)
容器·kubernetes·prometheus
张忠琳18 小时前
【NPU】Ascend Docker Runtime v26.0.1 系统级架构分析
云原生·容器·kubernetes·npu·docker-runtime
holidaypenguin19 小时前
前端 Docker 开发与生产部署指南
docker·容器
这是谁的博客?19 小时前
【中阶·融合】如何隔离多租户 AI 推理平台的 GPU 资源:从 Namespace 到 MIG/Kata 的五层纵深防御
人工智能·ai·云原生·kubernetes·gpu·多租户·ai安全