跳转至

MariaDB(nfs-csi)部署变更 SOP

变更主题:在 K8s 集群 server 命名空间以 helm 方式部署 MariaDB 单实例 交付目录:mariadb-deploy/ 实现体:mariadb-deploy/charts/mariadb/(helm chart,声明式、原生幂等) 日常运行、使用、排障请看 RUNBOOK.md;本文档只记录本次变更的来龙去脉。 第 5 章代码块以实现体为准,用于阅读、复核与手工复现。

目录

  1. 背景
  2. 目标
  3. 前置条件
  4. 影响范围
  5. 分步操作
  6. 验证
  7. 回滚
  8. 风险说明
  9. 附录

1. 背景

集群需要在既有 server 命名空间中提供一套 MariaDB 数据库服务,承载业务数据(变更后实际投入承载 slurm_acct_db、rain 等库)。集群此前已部署 CloudNativePG operator 托管 PostgreSQL,数据库采用 operator 托管是既定架构风格,本次沿用。

选型中两个前置事实决定了实现路径:

  • Bitnami chart 路线不可用:实测 Docker Hub 上 bitnami/mariadb 仓库当前只保留 latest 与 sha256-* 标签,不再发布版本化 tag,无法锁定版本,不满足"新且稳定的版本"要求;且 charts.bitnami.com 的 tgz 分发返回 403,该 chart 仅经 OCI 分发,而执行机无海外链路取不到 chart。
  • 官方路线可用:mariadb-operator(MariaDB 官方维护)chart 26.6.0 可正常拉取,控制器镜像位于 ghcr.io(节点可达),数据库镜像使用官方 docker.io/library/mariadb(节点可达),且 operator 自带 cert-controller,不依赖 cert-manager(集群未安装 cert-manager)。

版本选择:MariaDB 12.3.3。12.3 系列于 2026-05-29 GA,是当前最新 LTS,社区维护至 2029-05-29;13.x 仍处 RC/Preview 阶段,不予采用。

2. 目标

变更完成后应达到以下可验证状态:

  1. mariadb-system 命名空间中 mariadb-operator、mariadb-operator-webhook、mariadb-operator-cert-controller 三个 Deployment 均可用。
  2. server 命名空间中存在名为 mariadb 的 MariaDB 实例,READY=True、STATUS=Running,副本数 1。
  3. 数据库版本为 12.3.3-MariaDB,服务端口 3306。
  4. root 密码取自 Secret server/mariadb-root 的 password 键,可正常登录。
  5. 数据目录 /var/lib/mysql 由 StorageClass nfs-csi 提供的 PVC storage-mariadb-0(20Gi)挂载,Pod 重建后数据不丢失。
  6. 集群内可通过 mariadb.server.svc.cluster.local:3306 访问。
  7. 重复执行第 5 章序列,第二次为零变更(全部跳过,K8s 对象 resourceVersion 不变)。

3. 前置条件

项目 要求 本次实测值
执行机 具备集群 admin kubeconfig 与 helm kubernetes-admin@kubernetes,helm v3.16.3
集群版本 ≥ 1.26(chart 要求) v1.36.4,4 节点(master-01、node-01/02/03),Rocky Linux 9.8
StorageClass 存在可用的 NFS CSI 存储类 nfs-csi(默认类,Immediate 绑定,Delete 回收,允许扩容)
NFS 后端 服务端与共享目录可写 192.168.31.249:/srv/nfs/k8s,可用 112G
节点出网 可拉取 docker.io 与 ghcr.io 镜像 已实测可拉取
helm repo 已添加 mariadb-operator 仓库 https://mariadb-operator.github.io/mariadb-operator
凭据 root 密码由管理员提供,禁止写入任何文件、values 或 Git 存于 Secret mariadb-root
集群既有组件 不与之冲突 已有 cnpg、gitlab、traefik、openldap、monitoring

执行前检查项:

kubectl config current-context                     # 预期输出 kubernetes-admin@kubernetes
helm version --short                               # 预期 v3.16.x 或更高
kubectl get sc nfs-csi                             # 预期存在,且为默认存储类
kubectl get ns server                              # 预期 Active
helm repo add mariadb-operator https://mariadb-operator.github.io/mariadb-operator
helm repo update mariadb-operator                  # 预期 Update Complete

若节点无法访问 docker.io / ghcr.io,需先配置镜像代理或把镜像预置到节点,否则 Pod 会停在 ImagePullBackOff。

4. 影响范围

  • 主机:新增工作负载由调度器决定落点(实测曾落 k8s-node-02,重建后落 k8s-node-03);NFS 服务端 192.168.31.249(dell-R620,即执行机)承担数据落盘。
  • 涉及组件:新增 CRD 与三个控制器(mariadb-system)、新增 MariaDB 实例(server,含 StatefulSet、Pod、2 个 Service、1 个 PVC)。
  • 是否停服:否。全部为新增资源,不修改任何既有工作负载。既有 gitlab、traefik、openldap、monitoring、cnpg 均不受影响。
  • 窗口期:无需停机窗口。首次安装含镜像拉取,约数十秒完成。
  • 在跑作业:不在 Slurm/LSF 计算节点上操作,无作业影响。资源占用为 requests 200m CPU / 512Mi 内存、limits 内存 2Gi。
  • 变更后实际观测:2026-09-19 13:38 该 Pod 被重建过一次(原因无留存证据,节点 k8s-node-02 当时健康、无 taint 与资源压力),重建后数据完好(见第 6 章持久化实证)。集群内既有业务未受影响。

5. 分步操作

对应实现体:mariadb-deploy/charts/mariadb/(Chart.yaml、values.yaml、templates/mariadb.yaml) 以下序列与实现等价,以实现体为准,不承担幂等与错误处理。 每步均以前置状态检查开头,状态一致即跳过,因此可安全重复执行。

cd mariadb-deploy                                          # 进入交付目录

# ---- 步骤 1:CRD(拆为独立 release,避免卸载 operator 时级联删除实例)----
kubectl get ns mariadb-system >/dev/null 2>&1 || kubectl create ns mariadb-system
if helm status mariadb-operator-crds -n mariadb-system >/dev/null 2>&1 && \
   diff -B <(helm get manifest mariadb-operator-crds -n mariadb-system) \
           <(helm template mariadb-operator-crds mariadb-operator/mariadb-operator-crds \
             -n mariadb-system --version 26.6.0) >/dev/null; then
  echo "[跳过] CRD 清单一致,无需变更"
else
  helm upgrade --install mariadb-operator-crds mariadb-operator/mariadb-operator-crds \
    -n mariadb-system --version 26.6.0
fi

# ---- 步骤 2:operator 控制器(含 webhook 与 cert-controller,自带证书管理)----
if helm status mariadb-operator -n mariadb-system >/dev/null 2>&1 && \
   diff -B <(helm get manifest mariadb-operator -n mariadb-system) \
           <(helm template mariadb-operator mariadb-operator/mariadb-operator \
             -n mariadb-system --version 26.6.0) >/dev/null; then
  echo "[跳过] operator 清单一致,无需变更"
else
  helm upgrade --install mariadb-operator mariadb-operator/mariadb-operator \
    -n mariadb-system --version 26.6.0
fi
kubectl -n mariadb-system rollout status deploy/mariadb-operator --timeout=280s
kubectl -n mariadb-system rollout status deploy/mariadb-operator-webhook --timeout=280s
kubectl -n mariadb-system rollout status deploy/mariadb-operator-cert-controller --timeout=280s

# ---- 步骤 3:root 密码 Secret(密码从密码管理系统注入,不入文档、不入 Git)----
# 高危:该 Secret 是 root 凭据来源,删除后实例无法获取密码;
#       变更密码后必须重启 StatefulSet 才生效(见 RUNBOOK 第 9 章)。
if kubectl -n server get secret mariadb-root >/dev/null 2>&1; then
  echo "[跳过] Secret mariadb-root 已存在"
else
  kubectl -n server create secret generic mariadb-root \
    --from-literal=password="${ROOT_PASSWORD:?请先 export ROOT_PASSWORD,值从密码管理系统获取}"
fi

# ---- 步骤 4:MariaDB 实例(chart 渲染 MariaDB CR,由 operator 生成 STS/Service/PVC)----
if helm status mariadb -n server >/dev/null 2>&1 && \
   diff -B <(helm get manifest mariadb -n server) \
           <(helm template mariadb ./charts/mariadb -n server) >/dev/null; then
  echo "[跳过] MariaDB 实例清单一致,无需变更"
else
  helm upgrade --install mariadb ./charts/mariadb -n server
fi
kubectl -n server wait --for=condition=Ready pod/mariadb-0 --timeout=280s

实例关键参数(调整参数只需改 charts/mariadb/values.yaml 后重跑步骤 4):

参数 值 说明
replicas 1 单实例,非高可用
image docker.io/library/mariadb:12.3.3 operator 仅支持 MariaDB 官方镜像
auth.existingSecret / secretKey mariadb-root / password 引用外部 Secret;CR 中 generate: false,Secret 缺失时直接报错而非自动生成随机密码
storage.size 20Gi PVC 容量,存储类支持在线扩容
storage.storageClassName nfs-csi 指定存储类
resources requests 200m/512Mi,limits 内存 2Gi 按需调整
myCnf 空 留空使用镜像默认配置,调优时写入

6. 验证

变更后逐项确认(全部命令可直接粘贴执行):

# 1) operator 三个控制器均可用——预期 3 个 Pod 全部 1/1 Running
kubectl -n mariadb-system get pods

# 2) 实例整体状态——预期 READY=True、STATUS=Running
kubectl -n server get mariadb mariadb

# 3) StatefulSet 副本——预期 READY 1/1
kubectl -n server get sts mariadb

# 4) 版本与端口——预期 version=12.3.3-MariaDB、port=3306
export MDB_ROOT_PW="$(kubectl -n server get secret mariadb-root -o jsonpath='{.data.password}' | base64 -d)"
kubectl -n server exec mariadb-0 -- env MYSQL_PWD="$MDB_ROOT_PW" \
  mariadb -uroot -e "SELECT VERSION() AS version, @@port AS port, @@datadir AS datadir;"

# 5) 存储验证——预期挂载点指向 NFS 共享,PVC 为 Bound/nfs-csi/20Gi
kubectl -n server exec mariadb-0 -- df -h /var/lib/mysql
kubectl -n server get pvc storage-mariadb-0

# 6) Service 与端点——预期 ClusterIP 10.110.57.41,端点包含 Pod IP:3306
kubectl -n server get svc mariadb
kubectl -n server get endpoints mariadb

# 7) 可写性验证(会产生并清理测试数据)
kubectl -n server exec mariadb-0 -- env MYSQL_PWD="$MDB_ROOT_PW" \
  mariadb -uroot -e "CREATE DATABASE sop_write_check; DROP DATABASE sop_write_check;"

本次实测结果:

验证项 结果
operator 三控制器 均 1/1 Running,镜像 ghcr.io/mariadb-operator/mariadb-operator:26.6.0
实例状态 READY=True、STATUS=Running、PRIMARY=mariadb-0
版本与端口 12.3.3-MariaDB-ubu2404,端口 3306,数据目录 /var/lib/mysql
存储 挂载来源 192.168.31.249:/srv/nfs/k8s/pvc-4323db6c-...;PVC storage-mariadb-0 为 Bound/20Gi/nfs-csi
Service mariadb(ClusterIP 10.110.57.41:3306)、mariadb-internal(headless)
幂等性 连续执行第 5 章序列,第二次四步全部命中「跳过」,MariaDB CR、Pod、PVC 的 resourceVersion 与首次完全一致,Pod 未重启(restartCount=0)
持久化实证 Pod 于 2026-09-19 13:38 重建(落点由 k8s-node-02 变为 k8s-node-03),重建前创建的 slurm_acct_db(09-18 05:43)、rain(09-18 14:53)两库在重建后依然存在,SHOW DATABASES 正常

日常巡检命令、指标阈值与故障处置流程见 RUNBOOK.md。

7. 回滚

7.1 数据备份(回滚前置动作,必做)

mkdir -p /srv/backup                                       # 备份目录与服务端数据盘分离,避免同故障域
export MDB_ROOT_PW="$(kubectl -n server get secret mariadb-root -o jsonpath='{.data.password}' | base64 -d)"
kubectl -n server exec mariadb-0 -- env MYSQL_PWD="$MDB_ROOT_PW" \
  mariadb-dump -uroot --all-databases --single-transaction --routines --events --triggers \
  > /srv/backup/mariadb-full-$(date +%Y%m%d-%H%M%S).sql
tail -1 /srv/backup/mariadb-full-*.sql                     # 预期包含 "Dump completed"

7.2 回滚步骤

# 1) 卸载实例:删除 CR 及 operator 派生的 STS/Service,PVC 默认保留,数据不丢
helm uninstall mariadb -n server

# 2) 确认派生资源已清理、PVC 仍然保留(数据在)
kubectl -n server get sts,svc 2>/dev/null | grep mariadb || echo "派生资源已清理"
kubectl -n server get pvc storage-mariadb-0                # 预期仍为 Bound

# 3) 彻底清理(高危:PV 回收策略为 Delete,删除 PVC 将永久丢失数据,必须先完成 7.1 备份)
# kubectl -n server delete pvc storage-mariadb-0
# kubectl -n server delete secret mariadb-root

# 4) operator 保留以便复用;确需移除时(CRD 是独立 release,不受级联影响)
# helm uninstall mariadb-operator -n mariadb-system
# helm uninstall mariadb-operator-crds -n mariadb-system

7.3 回滚后验证

kubectl -n server get pods 2>/dev/null | grep mariadb || echo "实例已移除"
kubectl -n server get pvc storage-mariadb-0                # 预期数据仍在,Bound
helm list -n server                                        # 预期不再列出 mariadb

7.4 重新部署

数据保留的前提下,重跑第 5 章步骤 3、4 即可恢复服务。StatefulSet 会重新绑定同名 PVC storage-mariadb-0,复用原有数据。

7.5 回滚触发判据

任一命中即执行回滚,不靠临场判断:

  • Pod 在 5 分钟内未 Ready;
  • kubectl -n server get mariadb mariadb 的 STATUS 持续非 Running;
  • PVC 持续非 Bound;
  • 业务侧连接报认证或连接错误,且排查超过 15 分钟未定位;
  • 数据可写性验证失败且无法在 15 分钟内恢复。

8. 风险说明

风险点 说明 缓解措施
NFS 后端跑数据库 网络文件系统无本地块设备的 fsync 语义,高并发写入时延迟抖动明显;且存储类 mountOptions 为 hard,timeo=600,retrans=3,NFS 服务端不可达时容器 IO 会挂起而非快速失败 中小负载可接受;重负载建议迁至块存储或集群已有的 local-ssd(需接受单节点绑定)
NFS 服务端单点 服务端即 192.168.31.249(dell-R620),宕机则数据库整体不可用 纳入监控告警;定期快照 /srv/nfs/k8s;处置流程见 RUNBOOK 8.3
PV 回收策略为 Delete nfs-csi 的 reclaimPolicy: Delete,误删 PVC 会连同数据一起删除 严禁随意删除 PVC;建立定期逻辑备份并存放于独立路径(RUNBOOK 第 6 章)
单实例无高可用 副本数为 1,Pod 所在节点故障期间数据库不可用 如确需 HA,应作为独立变更引入主从或 Galera 拓扑;注意直接调大 replicas 不会形成复制
无 binlog、无 PITR log_bin=0,最坏情况只能恢复到最近一次全量备份 按 RUNBOOK 建立每日备份;如需精细恢复需先开启 binlog(属变更)
root 凭据强度与范围 root 密码为指定值,强度有限;root@% 允许任意来源登录;Secret 在 etcd 中为 base64 而非加密 建议轮换为强口令并收紧来源网段;轮换流程见 RUNBOOK 第 9 章
密码变更不自动生效 修改 Secret 不会同步到运行中的实例 轮换后必须 kubectl -n server rollout restart sts/mariadb
镜像拉取依赖海外链路 节点重建或升级时需重新拉取 ghcr.io 与 docker.io 镜像 保持节点出网能力;必要时预热镜像或配置镜像代理
operator 升级风险 升级 operator 可能引入 CRD 变更,影响既有实例 升级前先备份,并先升级 mariadb-operator-crds release
本期无自动备份 未配置 Backup 资源,无 PITR 能力 按 RUNBOOK 第 6 章手工备份;后续可基于 operator 的 Backup CR 对接对象存储
Pod 曾被重建,原因未留证 2026-09-19 13:38 Pod 重建并更换节点,节点当时健康、无 taint 与资源压力,事件已过期无法追溯 数据未受影响(PVC 未重建);后续关注重启次数,必要时开启审计日志

9. 附录

9.1 交付物清单

文件 用途
mariadb-deploy/SOP.md 本文档,本次变更档案
mariadb-deploy/RUNBOOK.md 服务日常运行与使用手册(值班可用)
mariadb-deploy/charts/mariadb/Chart.yaml 实例 chart 元数据
mariadb-deploy/charts/mariadb/values.yaml 实例唯一配置入口
mariadb-deploy/charts/mariadb/templates/mariadb.yaml 实例 CR 模板

9.2 备份文件说明

本次变更未覆盖或修改任何既有文件(operator 与实例均为新增),因此没有产生 .bak 备份文件,交付目录下不存在 backup/ 与 backup/README.md。

变更涉及的数据备份(mariadb-dump 产物)属运行期数据保护,存放于 NFS 服务端 /srv/backup/,管理与恢复流程见 RUNBOOK.md 第 6 章。回滚时若需删除 PVC,务必先完成 7.1 的备份。

9.3 变更时间线

时间(CST) 事件
2026-09-18 04:26 安装 CRD release 与 operator(mariadb-system)
2026-09-18 04:27 部署 MariaDB 实例(helm revision 1),随后 Pod 首次 Ready
2026-09-18 05:43 业务库 slurm_acct_db 目录生成(使用方接入)
2026-09-18 14:53 业务库 rain 目录生成
2026-09-19 13:38 Pod 重建,落点由 k8s-node-02 变为 k8s-node-03,数据保留
2026-09-19 16:44 本次复核:实例 Running、数据完好、helm 清单未漂移

9.4 决策经过

决策点 取舍与依据
放弃 Bitnami chart 免费镜像仅剩 latest 标签,无法锁定版本;tgz 分发 403 且执行机无海外链路,取不到 chart
采用 operator 而非自建 chart 官方维护、活跃更新,与集群既有 cnpg operator 架构一致,自带证书管理与故障自愈,避免自维护 StatefulSet
版本选 12.3.3 当前最新 LTS(GA 2026-05-29,维护至 2029-05-29);13.x 仍为 RC/Preview
CRD 拆为独立 release 官方推荐做法,卸载 operator 时不会级联删除 CRD 与全部实例
实例 CR 用轻量 helm chart 封装 满足"以 helm 方式管理"的要求,helm list 可见、参数集中于 values.yaml,便于后续变更与回滚
root 密码走外部 Secret 密码不进入 chart、values、文档与 Git;CR 设 generate: false 以避免静默生成随机密码
无自动备份、不启用 metrics 本次范围仅限部署;两项作为已知能力缺口记入风险与 RUNBOOK,待后续独立变更补齐

9.5 与全局规范的偏差说明

本次未以 Python 工程承载实现体,原因是用户明确要求"本次实现不以 Python 脚本方式"。变更由声明式 helm chart 承载,幂等性由「清单比对后跳过」的前置检查保证,实测第二次执行零变更。其余约束(凭据不入文档、高危动作标注、先备份后回滚、产出配套文档)均按规范执行。


来源:/home/rain/Documents/k8s_ins/mariadb-deploy/SOP.md | 最后更新:2026-09-19 16:46(由 build/sync.py 同步,请勿在站点侧修改)