MongoDB 高可用集群部署
一、方案概述
1.1 目标
在 K8s 高可用集群上,部署一套 MongoDB 高可用集群,具备:
- 高可用:3 数据节点副本集,容忍 1 个节点故障
- 自动故障转移:主节点故障时,从节点自动提升为主
- 仲裁节点:避免偶数节点脑裂
- 持久化:每个节点独立 PVC,数据落盘
- 外部访问:Ingress + HTTPS(可选)
1.2 技术选型
| 组件 | 用途 |
|---|---|
| Bitnami MongoDB Helm Chart | 部署 MongoDB 副本集 |
| StatefulSet | 管理 MongoDB Pod |
| PersistentVolumeClaim | 每个节点的持久化存储 |
| Longhorn | 分布式存储 |
| MongoDB Replica Set | 副本集高可用 |
1.3 架构
应用
↓
Service: mongodb.mongodb.svc.cluster.local:27017
↓
MongoDB Replica Set (3 数据节点 + 1 仲裁)
├── mongodb-0 (PRIMARY)
├── mongodb-1 (SECONDARY)
├── mongodb-2 (SECONDARY)
└── mongodb-arbiter-0 (ARBITER)
↓
PersistentVolume (longhorn)
二、前置条件
2.1 集群状态
- K8s 集群
kubectl get nodes全部Ready - Longhorn 已部署,
longhornStorageClass 就绪 - 节点数量 ≥ 3(保证副本集能选举)
2.2 存储要求
MongoDB 需要 PVC 持久化数据。必须提前配好 StorageClass。
kubectl get storageclass
这命令看 StorageClass 列表,预期看到 longhorn。
2.3 Longhorn 存储设置
这是关键步骤,不改的话,Longhorn 会因为"空间不足"拒绝调度副本。
kubectl patch settings.longhorn.io storage-over-provisioning-percentage -n longhorn-system --type=merge -p '{"value":"200"}'
这条命令允许 Longhorn 超配到磁盘总容量的 200%。
kubectl patch settings.longhorn.io storage-minimal-available-percentage -n longhorn-system --type=merge -p '{"value":"10"}'
这条命令把最小可用空间从 25% 降到 10%。
2.4 镜像网络要求
MongoDB 的镜像在 registry-1.docker.io/bitnami/mongodb 上。Bitnami 从 2025 年 8 月 28 日起移除了 Docker Hub 公共目录的免费镜像,直接拉会返回 403。
解决方案 :用 bitnami/mongodb:latest 标签,DaoCloud 代理可用。
ansible k8s_cluster -i inventory.ini -m shell -a "crictl pull docker.m.daocloud.io/bitnami/mongodb:latest" -b
这条命令在所有节点上从 DaoCloud 代理拉 bitnami/mongodb:latest。
ansible k8s_cluster -i inventory.ini -m shell -a "ctr -n k8s.io images tag docker.m.daocloud.io/bitnami/mongodb:latest registry-1.docker.io/bitnami/mongodb:latest" -b
这条命令给镜像打标签,让 containerd 认为本地有 registry-1.docker.io/bitnami/mongodb:latest。
三、下载 MongoDB Chart
3.1 从 DaoCloud 拉取
不能用 helm repo add bitnami,因为 Bitnami 的 chart 走 Docker Hub OCI,国内不通。
helm pull oci://docker.m.daocloud.io/bitnamicharts/mongodb --version 19.3.0
这条命令从 DaoCloud 代理拉 MongoDB chart。
预期输出:
Pulled: docker.m.daocloud.io/bitnamicharts/mongodb:19.3.0
Digest: sha256:fe65e88b838f225d13a1df988e323d47715c7c85f14863f5b05837c12ceed000
下载后本地会有 :mongodb-19.3.0.tgz
四、部署 MongoDB
4.1 生成密码和密钥
openssl rand -base64 24
这条命令生成一个随机密码,执行两次,分别得到 root 密码和副本集密钥。
把两次输出保存下来。
4.2 安装 MongoDB
helm install mongodb ./mongodb-19.3.0.tgz \
--namespace mongodb \
--create-namespace \
--set architecture=replicaset \
--set replicaCount=3 \
--set auth.rootPassword=<root密码> \
--set auth.replicaSetKey=<副本集密钥> \
--set persistence.storageClass=longhorn \
--set persistence.size=10Gi
这条命令用本地 chart 安装 MongoDB 副本集。
逐项解析:
| 参数 | 含义 |
|---|---|
mongodb |
release 名 |
./mongodb-19.3.0.tgz |
本地 chart 包 |
--namespace mongodb |
装到 mongodb 命名空间 |
--create-namespace |
自动创建命名空间 |
architecture=replicaset |
副本集模式 |
replicaCount=3 |
3 个数据节点 |
auth.rootPassword |
root 密码 |
auth.replicaSetKey |
副本集内部认证密钥 |
persistence.storageClass=longhorn |
用 Longhorn 存储 |
persistence.size=10Gi |
每个节点 10Gi |
4.3 观察 Pod 启动
kubectl get pods -n mongodb -w
这条命令观察 Pod 启动,按 Ctrl+C 退出。
预期:
mongodb-0 1/1 Running
mongodb-1 1/1 Running
mongodb-2 1/1 Running
mongodb-arbiter-0 1/1 Running
注意 :chart 会自动加一个 arbiter 节点,用于投票,不存数据。
五、验证 MongoDB
5.1 查看 Pod 和 PVC
kubectl get pods -n mongodb
kubectl get pvc -n mongodb
这两条命令看 Pod 和 PVC 状态。
预期:
- 4 个 Pod 全部
Running。 - PVC 全部
Bound,STORAGECLASS是longhorn。
5.2 查看副本集状态
kubectl exec -it -n mongodb mongodb-0 -- mongosh -u root -p <root密码> --authenticationDatabase admin --eval "rs.status()"
这条命令查看副本集状态。
预期:
- 1 个
PRIMARY - 2 个
SECONDARY - 1 个
ARBITER - 所有成员
health: 1
5.3 测试读写
kubectl exec -it -n mongodb mongodb-0 -- mongosh -u root -p <root密码> --authenticationDatabase admin --eval "db.test.insertOne({name: 'hello'})"
这条命令插入一条测试数据。
kubectl exec -it -n mongodb mongodb-0 -- mongosh -u root -p <root密码> --authenticationDatabase admin --eval "db.test.find()"
这条命令查询数据,预期返回刚才插入的记录。
六、应用接入
6.1 连接信息
在集群内部:
| 用途 | 地址 |
|---|---|
| MongoDB | mongodb.mongodb.svc.cluster.local:27017 |
简写(同命名空间):
mongodb:27017
跨命名空间:
mongodb.mongodb.svc.cluster.local:27017
用户名 :root
密码:从 Secret 取。
6.2 取密码
kubectl get secret -n mongodb mongodb -o jsonpath='{.data.mongodb-root-password}' | base64 -d
echo
这条命令从 Secret 取 root 密码。
6.3 应用配置示例
Python (pymongo):
from pymongo import MongoClient
client = MongoClient(
'mongodb://root:<密码>@mongodb.mongodb.svc.cluster.local:27017/?replicaSet=rs0&authSource=admin'
)
Node.js (mongodb):
const { MongoClient } = require('mongodb');
const client = new MongoClient(
'mongodb://root:<密码>@mongodb.mongodb.svc.cluster.local:27017/?replicaSet=rs0&authSource=admin'
);
Java (mongodb-driver):
MongoClient client = MongoClients.create(
"mongodb://root:<密码>@mongodb.mongodb.svc.cluster.local:27017/?replicaSet=rs0&authSource=admin"
);
Go (mongo-go-driver):
client, err := mongo.Connect(context.TODO(), options.Client().ApplyURI(
"mongodb://root:<密码>@mongodb.mongodb.svc.cluster.local:27017/?replicaSet=rs0&authSource=admin",
))
6.4 部署后端服务到 K8s
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-backend
namespace: default
spec:
replicas: 2
selector:
matchLabels:
app: my-backend
template:
metadata:
labels:
app: my-backend
spec:
containers:
- name: my-backend
image: my-backend:latest
ports:
- containerPort: 8080
env:
- name: MONGODB_HOST
value: "mongodb.mongodb.svc.cluster.local"
- name: MONGODB_PORT
value: "27017"
- name: MONGODB_USER
value: "root"
- name: MONGODB_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb
key: mongodb-root-password
七、常见问题
7.1 Pod 卡在 ImagePullBackOff
原因 :MongoDB 镜像在 registry-1.docker.io 上,国内拉取超时。
解决:
ansible k8s_cluster -i inventory.ini -m shell -a "crictl pull docker.m.daocloud.io/bitnami/mongodb:latest" -b
ansible k8s_cluster -i inventory.ini -m shell -a "ctr -n k8s.io images tag docker.m.daocloud.io/bitnami/mongodb:latest registry-1.docker.io/bitnami/mongodb:latest" -b
kubectl delete pod -n mongodb --all
7.2 Bitnami 镜像 403
原因:Bitnami 从 2025 年 8 月 28 日起移除了 Docker Hub 公共目录的免费镜像。
解决 :用 bitnami/mongodb:latest 标签,DaoCloud 代理可用。
7.3 PVC 绑不上
原因:Longhorn 卷调度失败。
排查:
kubectl get volumes.longhorn.io -n longhorn-system
kubectl get volume.longhorn.io <volume-name> -n longhorn-system -o yaml | grep -A5 "type: Scheduled"
如果报 insufficient storage:
kubectl patch settings.longhorn.io storage-over-provisioning-percentage -n longhorn-system --type=merge -p '{"value":"200"}'
kubectl patch settings.longhorn.io storage-minimal-available-percentage -n longhorn-system --type=merge -p '{"value":"10"}'
7.4 副本集 PRIMARY 选举失败
原因:节点不够,或网络不通。
排查:
kubectl logs -n mongodb mongodb-0 --tail=50
关注:
election failednot enough healthy nodes
7.5 写操作失败
原因 :没有 PRIMARY,或多数派不可用。
排查:
kubectl exec -it -n mongodb mongodb-0 -- mongosh -u root -p <密码> --authenticationDatabase admin --eval "rs.status()"
如果所有节点都是 SECONDARY,说明选举失败。
八、常用操作
8.1 查看 MongoDB 状态
kubectl get pods -n mongodb
kubectl get pvc -n mongodb
kubectl get svc -n mongodb
8.2 查看日志
kubectl logs -n mongodb mongodb-0 --tail=100
8.3 连接 MongoDB
kubectl exec -it -n mongodb mongodb-0 -- mongosh -u root -p <密码> --authenticationDatabase admin
8.4 扩容
helm upgrade mongodb ./mongodb-19.3.0.tgz \
--namespace mongodb \
--set replicaCount=5
这条命令把副本集从 3 节点扩到 5 节点。
8.5 删除 MongoDB
helm uninstall mongodb -n mongodb
kubectl delete pvc -n mongodb --all
kubectl delete namespace mongodb
警告 :删除 PVC 会删除所有数据,操作前先备份。
九、架构总结
9.1 组件清单
| 组件 | 数量 | 作用 |
|---|---|---|
| mongodb | 3 | 数据节点,1 主 2 从 |
| mongodb-arbiter | 1 | 仲裁节点,不存数据,只投票 |
| StatefulSet | 1 | 管理 MongoDB Pod |
| PVC | 3 | 每个数据节点一块存储 |
| Service | 2 | 集群内部通信和客户端入口 |
| Secret | 1 | root 密码 |
9.2 端口速查
| 端口 | 用途 |
|---|---|
| 27017 | MongoDB 客户端连接 |
| 27018 | MongoDB 内部通信 |
9.3 高可用机制
| 故障场景 | 影响 | 恢复方式 |
|---|---|---|
| 从节点故障 | 无影响 | 主节点继续服务,从节点重建后重新同步 |
| 主节点故障 | 短暂不可写 | 从节点自动选举为新主,10-30 秒恢复 |
| 仲裁节点故障 | 无影响 | 只影响选举,不影响读写 |
| 多个节点故障 | 可能不可写 | 如果超过半数节点故障,副本集停止服务 |
9.4 已知隐患
| 隐患 | 影响 | 解决方案 |
|---|---|---|
| Longhorn 空间调度保守 | 卷报 insufficient storage |
改 over-provisioning 和 minimal-available |
| Bitnami 免费镜像移除 | 无法拉取最新镜像 | 用 bitnami/mongodb:latest |
| registry-1.docker.io 超时 | 镜像拉不下来 | 用 DaoCloud 代理拉并打标签 |
| 未配备份 | 数据无法恢复 | 用 mongodump 定期备份 |
十、总结
这套 MongoDB 基于 Bitnami Helm Chart 部署,提供了:
- 高可用:3 数据节点副本集 + 1 仲裁节点,容忍 1 个节点故障
- 自动故障转移:主节点故障时,从节点自动提升
- 持久化:每个数据节点独立 PVC
- 声明式管理:Helm chart 一条命令部署
部署中最容易踩的坑:
- Bitnami 免费镜像移除 :必须用
bitnami/mongodb:latest标签。 - registry-1.docker.io 超时:必须配 DaoCloud 代理拉镜像并打标签。
- Longhorn 空间调度保守 :改
storage-over-provisioning-percentage=200和storage-minimal-available-percentage=10。 - chart 拉取超时:用 DaoCloud 的 OCI 代理。
解决了这四个问题,MongoDB 就能稳定运行。