25. MongoDB运维-容器化部署
大约 7 分钟
25. MongoDB运维-容器化部署
概述
随着云原生技术的发展,容器化部署已成为现代应用的标准实践。MongoDB在容器环境中的部署需要考虑数据持久化、高可用性、监控管理、网络配置等多个方面。本章将详细介绍MongoDB在Docker和Kubernetes环境中的最佳实践。
想象一个微服务架构的电商平台,需要在Kubernetes集群中部署MongoDB来支持订单、用户、商品等多个服务的数据存储需求。通过合理的容器化部署策略,包括StatefulSet、PVC存储、服务发现、自动扩缩容等技术,实现了数据库的弹性伸缩和高可用部署。
知识要点
1. Docker容器化部署
1.1 单节点Docker部署
# docker-compose.yml
version: '3.8'
services:
mongodb:
image: mongo:6.0
container_name: mongodb
restart: always
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password123
MONGO_INITDB_DATABASE: myapp
ports:
- "27017:27017"
volumes:
- mongodb_data:/data/db
- mongodb_config:/data/configdb
- ./init-scripts:/docker-entrypoint-initdb.d
command: --replSet rs0 --bind_ip_all --keyFile /opt/keyfile/mongo-keyfile
networks:
- mongo-network
volumes:
mongodb_data:
driver: local
mongodb_config:
driver: local
networks:
mongo-network:
driver: bridge
1.2 Docker复制集部署
# docker-compose-replica.yml
version: '3.8'
services:
mongo1:
image: mongo:6.0
container_name: mongo1
restart: always
ports:
- "27017:27017"
environment:
MONGO_REPLICA_SET_NAME: rs0
volumes:
- mongo1_data:/data/db
- ./keyfile:/opt/keyfile
command: >
bash -c "
chmod 400 /opt/keyfile/mongo-keyfile &&
chown 999:999 /opt/keyfile/mongo-keyfile &&
exec docker-entrypoint.sh mongod --replSet rs0 --keyFile /opt/keyfile/mongo-keyfile --bind_ip_all
"
networks:
- mongo-cluster
mongo2:
image: mongo:6.0
container_name: mongo2
restart: always
ports:
- "27018:27017"
environment:
MONGO_REPLICA_SET_NAME: rs0
volumes:
- mongo2_data:/data/db
- ./keyfile:/opt/keyfile
command: >
bash -c "
chmod 400 /opt/keyfile/mongo-keyfile &&
chown 999:999 /opt/keyfile/mongo-keyfile &&
exec docker-entrypoint.sh mongod --replSet rs0 --keyFile /opt/keyfile/mongo-keyfile --bind_ip_all
"
networks:
- mongo-cluster
mongo3:
image: mongo:6.0
container_name: mongo3
restart: always
ports:
- "27019:27017"
environment:
MONGO_REPLICA_SET_NAME: rs0
volumes:
- mongo3_data:/data/db
- ./keyfile:/opt/keyfile
command: >
bash -c "
chmod 400 /opt/keyfile/mongo-keyfile &&
chown 999:999 /opt/keyfile/mongo-keyfile &&
exec docker-entrypoint.sh mongod --replSet rs0 --keyFile /opt/keyfile/mongo-keyfile --bind_ip_all
"
networks:
- mongo-cluster
volumes:
mongo1_data:
mongo2_data:
mongo3_data:
networks:
mongo-cluster:
driver: bridge
2. Kubernetes部署
2.1 StatefulSet部署配置
@Component
public class MongoKubernetesDeployment {
/**
* 生成MongoDB StatefulSet配置
*/
public void generateStatefulSetConfig() {
String statefulSetYaml = """
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mongodb
namespace: database
spec:
serviceName: mongodb-headless
replicas: 3
selector:
matchLabels:
app: mongodb
template:
metadata:
labels:
app: mongodb
spec:
terminationGracePeriodSeconds: 30
containers:
- name: mongodb
image: mongo:6.0
command:
- mongod
- --replSet=rs0
- --bind_ip_all
- --keyFile=/etc/secrets-volume/mongo-keyfile
ports:
- containerPort: 27017
name: mongodb
env:
- name: MONGO_INITDB_ROOT_USERNAME
valueFrom:
secretKeyRef:
name: mongodb-secret
key: username
- name: MONGO_INITDB_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mongodb-secret
key: password
volumeMounts:
- name: mongodb-data
mountPath: /data/db
- name: mongodb-config
mountPath: /data/configdb
- name: mongo-keyfile
mountPath: /etc/secrets-volume
readOnly: true
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
livenessProbe:
exec:
command:
- mongo
- --eval
- "db.adminCommand('ping')"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
readinessProbe:
exec:
command:
- mongo
- --eval
- "db.adminCommand('ping')"
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 1
volumes:
- name: mongo-keyfile
secret:
secretName: mongodb-keyfile
defaultMode: 0400
volumeClaimTemplates:
- metadata:
name: mongodb-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: "fast-ssd"
resources:
requests:
storage: 20Gi
""";
System.out.println("MongoDB StatefulSet配置:");
System.out.println(statefulSetYaml);
}
/**
* 生成服务发现配置
*/
public void generateServiceConfig() {
String headlessServiceYaml = """
apiVersion: v1
kind: Service
metadata:
name: mongodb-headless
namespace: database
labels:
app: mongodb
spec:
clusterIP: None
selector:
app: mongodb
ports:
- port: 27017
targetPort: 27017
name: mongodb
---
apiVersion: v1
kind: Service
metadata:
name: mongodb-external
namespace: database
labels:
app: mongodb
spec:
selector:
app: mongodb
statefulset.kubernetes.io/pod-name: mongodb-0
ports:
- port: 27017
targetPort: 27017
name: mongodb
type: ClusterIP
""";
System.out.println("MongoDB服务配置:");
System.out.println(headlessServiceYaml);
}
/**
* 生成Secret配置
*/
public void generateSecretConfig() {
String secretYaml = """
apiVersion: v1
kind: Secret
metadata:
name: mongodb-secret
namespace: database
type: Opaque
data:
username: YWRtaW4= # admin
password: cGFzc3dvcmQxMjM= # password123
---
apiVersion: v1
kind: Secret
metadata:
name: mongodb-keyfile
namespace: database
type: Opaque
data:
mongo-keyfile: |
T1BFTlNTTCBHRU5FUkFURUQgS0VZRklMRQo=
""";
System.out.println("MongoDB Secret配置:");
System.out.println(secretYaml);
}
}
2.2 初始化和配置管理
@Service
public class MongoKubernetesInitService {
/**
* 复制集初始化作业
*/
public void generateInitJob() {
String initJobYaml = """
apiVersion: batch/v1
kind: Job
metadata:
name: mongodb-init
namespace: database
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: mongodb-init
image: mongo:6.0
command:
- /bin/bash
- -c
- |
set -e
echo "等待MongoDB启动..."
until mongo --host mongodb-0.mongodb-headless:27017 --eval "print('MongoDB连接成功')" > /dev/null 2>&1; do
echo "等待中..."
sleep 2
done
echo "初始化复制集..."
mongo --host mongodb-0.mongodb-headless:27017 --eval "
rs.initiate({
_id: 'rs0',
members: [
{ _id: 0, host: 'mongodb-0.mongodb-headless:27017', priority: 2 },
{ _id: 1, host: 'mongodb-1.mongodb-headless:27017', priority: 1 },
{ _id: 2, host: 'mongodb-2.mongodb-headless:27017', priority: 1 }
]
})
"
echo "等待复制集选举..."
sleep 10
echo "创建管理员用户..."
mongo --host mongodb-0.mongodb-headless:27017 --eval "
db.getSiblingDB('admin').createUser({
user: 'admin',
pwd: 'password123',
roles: ['root']
})
"
echo "初始化完成"
""";
System.out.println("MongoDB初始化作业配置:");
System.out.println(initJobYaml);
}
/**
* ConfigMap配置管理
*/
public void generateConfigMap() {
String configMapYaml = """
apiVersion: v1
kind: ConfigMap
metadata:
name: mongodb-config
namespace: database
data:
mongod.conf: |
storage:
dbPath: /data/db
journal:
enabled: true
wiredTiger:
engineConfig:
cacheSizeGB: 1
systemLog:
destination: file
logAppend: true
path: /var/log/mongodb/mongod.log
verbosity: 1
net:
port: 27017
bindIp: 0.0.0.0
replication:
replSetName: rs0
security:
keyFile: /etc/secrets-volume/mongo-keyfile
authorization: enabled
operationProfiling:
slowOpThresholdMs: 100
mode: slowOp
""";
System.out.println("MongoDB ConfigMap配置:");
System.out.println(configMapYaml);
}
}
3. 容器监控与管理
3.1 监控配置
@Service
public class MongoContainerMonitoringService {
/**
* Prometheus监控配置
*/
public void generatePrometheusConfig() {
String monitoringYaml = """
apiVersion: v1
kind: Service
metadata:
name: mongodb-exporter
namespace: database
labels:
app: mongodb-exporter
spec:
ports:
- port: 9216
targetPort: 9216
name: metrics
selector:
app: mongodb-exporter
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mongodb-exporter
namespace: database
spec:
replicas: 1
selector:
matchLabels:
app: mongodb-exporter
template:
metadata:
labels:
app: mongodb-exporter
spec:
containers:
- name: mongodb-exporter
image: percona/mongodb_exporter:0.35
ports:
- containerPort: 9216
name: metrics
env:
- name: MONGODB_URI
value: "mongodb://admin:password123@mongodb-external:27017/admin"
- name: MONGODB_DIRECT_CONNECT
value: "true"
- name: MONGODB_COLLECT_ALL
value: "true"
resources:
requests:
memory: "128Mi"
cpu: "100m"
limits:
memory: "256Mi"
cpu: "200m"
""";
System.out.println("MongoDB Prometheus监控配置:");
System.out.println(monitoringYaml);
}
/**
* 健康检查配置
*/
public void configureHealthChecks() {
System.out.println("=== MongoDB容器健康检查配置 ===");
String livenessProbe = """
livenessProbe:
exec:
command:
- mongo
- --eval
- "db.adminCommand('ping')"
initialDelaySeconds: 30
periodSeconds: 10
timeoutSeconds: 5
failureThreshold: 3
""";
String readinessProbe = """
readinessProbe:
exec:
command:
- mongo
- --eval
- "db.adminCommand('ismaster')"
initialDelaySeconds: 5
periodSeconds: 10
timeoutSeconds: 1
successThreshold: 1
failureThreshold: 3
""";
System.out.println("存活性探针配置:");
System.out.println(livenessProbe);
System.out.println("就绪性探针配置:");
System.out.println(readinessProbe);
}
/**
* 日志收集配置
*/
public void generateLoggingConfig() {
String fluentdConfigYaml = """
apiVersion: v1
kind: ConfigMap
metadata:
name: fluentd-mongodb-config
namespace: database
data:
fluent.conf: |
<source>
@type tail
path /var/log/mongodb/mongod.log
pos_file /var/log/fluentd-mongodb.log.pos
tag mongodb.log
format json
time_format %Y-%m-%dT%H:%M:%S.%L%z
</source>
<filter mongodb.log>
@type parser
key_name message
<parse>
@type json
time_format %Y-%m-%dT%H:%M:%S.%L%z
</parse>
</filter>
<match mongodb.log>
@type elasticsearch
host elasticsearch-service
port 9200
index_name mongodb-logs
type_name _doc
</match>
""";
System.out.println("MongoDB日志收集配置:");
System.out.println(fluentdConfigYaml);
}
}
4. 自动化运维
4.1 自动扩缩容
@Service
public class MongoAutoScalingService {
/**
* HPA配置(基于CPU和内存)
*/
public void generateHPAConfig() {
String hpaYaml = """
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: mongodb-hpa
namespace: database
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: StatefulSet
name: mongodb
minReplicas: 3
maxReplicas: 7
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
behavior:
scaleUp:
stabilizationWindowSeconds: 300
policies:
- type: Percent
value: 50
periodSeconds: 60
scaleDown:
stabilizationWindowSeconds: 600
policies:
- type: Percent
value: 25
periodSeconds: 60
""";
System.out.println("MongoDB HPA配置:");
System.out.println(hpaYaml);
}
/**
* VPA配置(垂直扩缩容)
*/
public void generateVPAConfig() {
String vpaYaml = """
apiVersion: autoscaling.k8s.io/v1
kind: VerticalPodAutoscaler
metadata:
name: mongodb-vpa
namespace: database
spec:
targetRef:
apiVersion: apps/v1
kind: StatefulSet
name: mongodb
updatePolicy:
updateMode: "Auto"
resourcePolicy:
containerPolicies:
- containerName: mongodb
minAllowed:
cpu: 100m
memory: 500Mi
maxAllowed:
cpu: 2
memory: 4Gi
controlledResources: ["cpu", "memory"]
""";
System.out.println("MongoDB VPA配置:");
System.out.println(vpaYaml);
}
/**
* 自动备份CronJob
*/
public void generateBackupCronJob() {
String backupCronJobYaml = """
apiVersion: batch/v1
kind: CronJob
metadata:
name: mongodb-backup
namespace: database
spec:
schedule: "0 2 * * *" # 每天凌晨2点
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: mongodb-backup
image: mongo:6.0
command:
- /bin/bash
- -c
- |
DATE=$(date +%Y%m%d_%H%M%S)
mongodump --host mongodb-external:27017 \\
--username admin \\
--password password123 \\
--authenticationDatabase admin \\
--out /backup/mongodb_backup_$DATE
# 压缩备份文件
tar -czf /backup/mongodb_backup_$DATE.tar.gz /backup/mongodb_backup_$DATE
rm -rf /backup/mongodb_backup_$DATE
# 清理7天前的备份
find /backup -name "mongodb_backup_*.tar.gz" -mtime +7 -delete
volumeMounts:
- name: backup-storage
mountPath: /backup
volumes:
- name: backup-storage
persistentVolumeClaim:
claimName: mongodb-backup-pvc
""";
System.out.println("MongoDB自动备份CronJob配置:");
System.out.println(backupCronJobYaml);
}
}
知识扩展
1. 设计思想
MongoDB容器化部署基于以下核心原则:
- 数据持久化:使用PV/PVC确保数据在容器重启后不丢失
- 服务发现:通过Headless Service实现复制集内部通信
- 高可用性:利用StatefulSet保证Pod的有序部署和稳定网络标识
- 可观测性:集成监控、日志、健康检查等运维能力
2. 避坑指南
存储配置:
- 务必使用持久化存储,避免数据丢失
- 选择高性能存储类型(如SSD)提升I/O性能
- 合理设置存储容量和备份策略
网络配置:
- 使用StatefulSet确保Pod名称稳定
- 配置Headless Service支持集群内部发现
- 注意防火墙和网络策略配置
资源管理:
- 设置合理的CPU和内存限制
- 配置健康检查避免服务不可用
- 实施监控和告警机制
3. 深度思考题
数据迁移:如何在不停机的情况下将传统部署的MongoDB迁移到容器化环境?
灾难恢复:容器化MongoDB的灾难恢复策略应该如何设计?
性能优化:容器化部署对MongoDB性能有什么影响,如何优化?
深度思考题解答:
无停机数据迁移策略:
- 建立新的容器化复制集作为从节点
- 等待数据同步完成后进行主从切换
- 逐步迁移应用连接到新环境
- 验证数据一致性后下线旧环境
容器化灾难恢复设计:
- 跨可用区部署复制集节点
- 定期备份到对象存储(如S3)
- 实施数据恢复演练和验证
- 建立完整的故障转移预案
容器化性能优化:
- 使用专用节点运行数据库Pod
- 优化存储I/O性能(使用本地SSD)
- 调整容器资源限制和Kubernetes调度策略
- 监控和调优网络性能
MongoDB容器化部署为现代云原生应用提供了强大的数据存储支撑,需要综合考虑存储、网络、监控、安全等多个维度来构建生产级的部署方案。