Kubernetes 部署 MongoDB Replica Set
本文介绍如何在 Kubernetes 集群中部署 MongoDB 4.4.13 分片副本集(Replica Set),使用 DaemonSet 确保每个指定节点运行一个 MongoDB 实例,通过 hostNetwork 直接暴露端口,并配置定时备份策略。
一、架构概述
该集群采用三节点副本集架构:
| 节点 | 角色 | 端口 | 说明 |
|---|---|---|---|
| mongoserver1 | PRIMARY | :30017 | 主节点,处理写入 |
| mongoserver2 | SECONDARY | :30017 | 从节点,同步复制 |
| mongoserver3 | SECONDARY | :30017 | 从节点,同步复制 |
关键设计决策:
- DaemonSet 而非 StatefulSet — 每个节点精确运行一个 Pod,与节点绑定
- hostNetwork: true — 直接使用宿主机网络,免去 Service 端口转发开销
- hostAliases — 通过主机名解析实现副本集节点互相发现
- NodePort Service — 为外部客户端提供统一访问入口
二、部署配置文件
完整的 mongo.yaml 配置:
apiVersion: v1
kind: Namespace
metadata:
name: bjac-mongo
---
apiVersion: v1
kind: Service
metadata:
labels:
app: mongo
name: mongo-out
namespace: bjac-mongo
spec:
type: NodePort
ports:
- port: 30017
targetPort: 30017
protocol: TCP
nodePort: 30018
selector:
app: mongo
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: mongo
namespace: bjac-mongo
labels:
app: mongo
spec:
selector:
matchLabels:
app: mongo
template:
metadata:
labels:
app: mongo
spec:
nodeSelector:
mongo-server: "true"
hostNetwork: true
volumes:
- name: mongostorage
hostPath:
path: /home/mongo/data
hostAliases:
- ip: "<NODE_IP_1>"
hostnames:
- "mongoserver1"
- ip: "<NODE_IP_2>"
hostnames:
- "mongoserver2"
- ip: "<NODE_IP_3>"
hostnames:
- "mongoserver3"
containers:
- name: mongo
image: mongo:4.4.13
imagePullPolicy: IfNotPresent
command:
- mongod
- "--port"
- "30017"
- "--shardsvr"
- "--replSet"
- rs0
- "--bind_ip"
- 0.0.0.0
ports:
- containerPort: 30017
volumeMounts:
- name: mongostorage
mountPath: /data/db/
配置要点说明
| 配置项 | 值 | 说明 |
|---|---|---|
kind |
DaemonSet | 每个匹配节点运行一个 Pod,与 StatefulSet 不同 |
nodeSelector |
mongo-server: "true" |
只在标记节点上部署 |
hostNetwork |
true |
Pod 直接使用宿主机网络栈 |
hostAliases |
3 个节点 IP | 在 Pod 内注入主机名解析,副本集通信必需 |
--shardsvr |
— | 分片服务器模式 |
--replSet |
rs0 |
副本集名称 |
hostPath |
/home/mongo/data |
使用宿主机目录存储数据 |
三、部署步骤
3.1 为节点打标签
查看现有节点标签:
kubectl get node --show-labels=true
为 MongoDB 服务器节点打标签:
kubectl label nodes <NODE_1> mongo-server=true
kubectl label nodes <NODE_2> mongo-server=true
kubectl label nodes <NODE_3> mongo-server=true
3.2 创建数据目录
在每个 MongoDB 节点上创建数据目录:
mkdir -p /home/mongo/data
3.3 执行部署
kubectl apply -f mongo.yaml
3.4 验证部署
# 查看 DaemonSet
kubectl get DaemonSet/mongo -n bjac-mongo -o wide
# 查看 Pod
kubectl get pod -n bjac-mongo -o wide
# 查看 Service
kubectl get svc/mongo-out -n bjac-mongo -o wide
3.5 DNS 解析测试
kubectl run -i --tty --image busybox:1.28.4 dns-test --restart=Never --rm /bin/sh
# 在容器内执行
nslookup mongo-out.bjac-mongo.svc.cluster.local
四、初始化副本集
部署完成后,需要手动初始化副本集。
4.1 进入 Pod
kubectl exec -it pod/<MONGO_POD_NAME> -n bjac-mongo -- bash
mongo --port=30017
4.2 执行初始化命令
在 MongoDB shell 中执行:
rs.initiate({
_id: "rs0",
version: 1,
protocolVersion: 1,
members: [
{ _id: 0, host: "mongoserver1:30017", priority: 10 },
{ _id: 1, host: "mongoserver2:30017", priority: 10 },
{ _id: 2, host: "mongoserver3:30017", priority: 10 }
]
})
说明:
hostAliases配置确保 Pod 内可以通过mongoserver1/2/3主机名互相解析。三个节点 priority 均为 10,MongoDB 会自动选举 PRIMARY。
4.3 查看副本集状态
rs.status()
输出应显示一个 PRIMARY 和两个 SECONDARY 节点。
4.4 客户端连接
外部客户端需要配置 hosts 解析:
<NODE_IP_1> mongoserver1
<NODE_IP_2> mongoserver2
<NODE_IP_3> mongoserver3
然后通过 NodePort 连接:
mongodb://mongoserver1:30017,mongoserver2:30017,mongoserver3:30017/?replicaSet=rs0
五、备份配置

MongoDB 备份采用 Docker Compose 部署独立的备份容器,通过 cron 定时执行 mongodump。
5.1 Docker Compose 配置
version: '3'
services:
db:
restart: always
image: mongo:4.4.13
hostname: mongo4413
ports:
- "8017:27017"
volumes:
- /home/docker/data/mongo/db:/data/db
- /home/docker/data/mongo/backup:/backups/mongo
command:
- "mongod"
- "--shardsvr"
- "--port"
- "27017"
- "--replSet"
- "rs1"
说明:此容器与 K8s 集群中的副本集是独立的,专门用于备份操作。它加入另一个副本集
rs1作为 SECONDARY,从该节点读取数据进行备份。
5.2 备份脚本
backup-mongo.sh:
#!/bin/sh
DUMP=/usr/bin/mongodump
OUT_DIR=/backups/mongo/mongod_bak_now
TAR_DIR=/backups/mongo/mongod_bak_list
DATE=`date +%Y-%m-%d`
NOW=`date +%Y-%m-%d_%H-%M-%S`
DAYS=30
TAR_BAK="mongod_bak_$NOW.tar.gz"
cd $OUT_DIR
rm -rf $OUT_DIR/*
mkdir -p $OUT_DIR/$DATE
# 备份指定数据库
$DUMP -h <SECONDARY_IP>:30017 -d bac-ucenter -o $OUT_DIR/$DATE
$DUMP -h <SECONDARY_IP>:30017 -d bac-core-api -o $OUT_DIR/$DATE
# 压缩备份
tar -zcvf $TAR_DIR/$TAR_BAK $OUT_DIR/$DATE
# 删除 30 天前的备份
find $TAR_DIR/ -mtime +$DAYS -delete
exit
最佳实践:从 SECONDARY 节点执行
mongodump,避免影响 PRIMARY 的写入性能。
5.3 定时任务配置
crontab 文件:
32 */6 * * * root docker exec mongo-db-1 /backups/mongo/backup-mongo.sh 2>&1
每 6 小时的第 32 分钟执行一次备份。
5.4 部署备份环境
# 创建目录
mkdir -p /home/docker/compose/mongo \
/home/docker/data/mongo/db \
/home/docker/data/mongo/backup/mongod_bak_now \
/home/docker/data/mongo/backup/mongod_bak_list
chmod 777 /home/docker/data/mongo
# 添加执行权限
chmod +x /home/docker/data/mongo/backup/backup-mongo.sh
# 安装 cron 配置
mv /home/docker/data/mongo/backup/crontab /etc/cron.d/backup-mongo
六、常用运维命令
| 操作 | 命令 |
|---|---|
| 查看副本集状态 | rs.status() |
| 查看节点配置 | rs.conf() |
| 添加副本集成员 | rs.add("mongoserver4:30017") |
| 移除副本集成员 | rs.remove("mongoserver4:30017") |
| 查看 Pod 状态 | kubectl get pod -n bjac-mongo -o wide |
| 查看 DaemonSet | kubectl get DaemonSet/mongo -n bjac-mongo |
| 进入 Pod | kubectl exec -it pod/<POD_NAME> -n bjac-mongo -- bash |
| 手动备份 | docker exec mongo-db-1 /backups/mongo/backup-mongo.sh |
七、注意事项
- hostAliases 必须配置正确 — 副本集节点间通过主机名通信,hosts 解析错误会导致初始化失败
- 从 SECONDARY 备份 —
mongodump应连接 SECONDARY 节点,避免影响 PRIMARY 性能 - 数据目录权限 — 确保
/home/mongo/data目录在宿主机上存在且可写 - nodeSelector 标签 — 未打标签的节点不会部署 MongoDB Pod
- 端口冲突 —
hostNetwork: true模式下,30017 端口直接绑定宿主机,确保端口未被占用 - 备份保留策略 — 默认保留 30 天,可根据磁盘容量调整
DAYS参数
附录:资源清单
资源类型 名称 数量
Namespace bjac-mongo 1
Service mongo-out (NodePort) 1
DaemonSet mongo 3 Pod (按节点数)
hostPath Volume /home/mongo/data 每节点 1