MariaDB(nfs-csi)部署变更 SOP¶
变更主题:在 K8s 集群
server命名空间以 helm 方式部署 MariaDB 单实例 交付目录:mariadb-deploy/实现体:mariadb-deploy/charts/mariadb/(helm chart,声明式、原生幂等) 日常运行、使用、排障请看 RUNBOOK.md;本文档只记录本次变更的来龙去脉。 第 5 章代码块以实现体为准,用于阅读、复核与手工复现。
目录¶
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. 目标¶
变更完成后应达到以下可验证状态:
mariadb-system命名空间中mariadb-operator、mariadb-operator-webhook、mariadb-operator-cert-controller三个 Deployment 均可用。server命名空间中存在名为mariadb的 MariaDB 实例,READY=True、STATUS=Running,副本数 1。- 数据库版本为
12.3.3-MariaDB,服务端口 3306。 - root 密码取自 Secret
server/mariadb-root的password键,可正常登录。 - 数据目录
/var/lib/mysql由 StorageClassnfs-csi提供的 PVCstorage-mariadb-0(20Gi)挂载,Pod 重建后数据不丢失。 - 集群内可通过
mariadb.server.svc.cluster.local:3306访问。 - 重复执行第 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同步,请勿在站点侧修改)