环境:MongoDB 4.0.25,Alma Linux(建议使用 Linux)
部署的时候是在同一个机器上操作的,实际可以放在不同机器上。
截止到 2024年05月,MongoDB 已经到 7.x 版本,后续再补一个 7.x 较新版本的安装方法。
注意:主要是测试环境使用,如果是生产环境不推荐使用 Docker 进行部署数据库的相关组件。
该方式同样适用于 k8s 部署 MongoDB,但是要注意以下几个必要条件:
- 做好数据目录的映射,以保持数据的持久化,从而防止重启丢失数据。
- 保证两个数据库容器的网络互通性。
- 确保集群认证文件(下面的
mongo-keyfile
文件)可被多个 MongoDB 实例访问。
该镜像使用的 Docker 官方提供的镜像:https://hub.docker.com/_/mongo,并不是 MongoDB 官方提供的;官方 MongoDB 提供的是:https://hub.docker.com/r/mongodb/mongodb-community-server。
两者的参数简单的对比了一下几乎是通用的,但是建议搭建集群的时候使用一样的 image 以及 tag,不要混用。
【注】为了方便测试环境测试,需要设置允许任意 IP
访问 MongoDB
实例;在启动容器时将--bind_ip
选项设置为 0.0.0.0
即可,这将允许 MongoDB
监听所有网络接口。另外,为了确保安全性,建议使用适当的防火墙规则和安全组来限制访问。
1. 生成 mongo-file
示例中将 mongo-keyfile
放到了 /home
目录下,实际根据需要修改路径即可。
因为是同一个 Docker 主机,所以其他容器都挂载了同一个认证文件;但是实际上只要保证文件内容一样即可,在每个服务器上都创建一样内容的认证文件,并同时保证权限正确即可。
# 生成一个756字节长的随机数据,使用base64编码后保存到文件中
openssl rand -base64 756 > /home/mongo-keyfile
# OR 也可以自定义数据生成,以保证在各个服务器中是一样的
echo "yourSecureKeyContent" > /home/mongo-keyfile
# 设置文件权限
cd /home
# 》》》【看这里】这一步很关键,一定要将文件的所有者设置为 999 用户和用户组,
# 999 对应的是 Mongo 容器中的 mongodb 用户和 mongodb 用户组
# 否则就会出现很头疼的权限问题
chown 999:999 mongo-keyfile
# 给个最小权限即可
chmod 400 mongo-keyfile
# OR
chmod 600 mongo-keyfile
【注】999:999
这仅适用于 Docker 容器,如果是虚拟机直接部署的话,还需要根据实际情况设置权限:看运行 MongoDB 实例的是哪个用户,就将 mongo-keyfile 的所有者设置为哪个用户即可。
👉 mongo-keyfile
生成的内容也是有要求的,建议不带特殊符号,只用字母组合+数字组合。
# 比如带有 - 就会有报错
echo "your-secure-key-content" > /home/mongo-keyfile
# 报错如下
I ACCESS [main] invalid char in key file /home/mongo-keyfile: -
👉 生成的文件要设置合适的权限,否则会报错:
# 权限太大
ACCESS [main] permissions on /home/mongo-keyfile are too open
# 没有权限
ACCESS [main] error opening file: /home/mongo-keyfile: Permission denied
如果使用 windows 的话,文件权限比较麻烦;建议直接用用 Linux 虚拟机,或者把文件映射到 Linux 容器中来设置。
2. 启动主节点
docker run -d \
--name mongo_primary \
-p 27017:27017 \
-v /xxxx/mongodb/mongo-keyfile:/home/mongo-keyfile
-v /xxxx/mongodb/primary:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=123456 \
mongo:4.0.25 \
--replSet rs0 --bind_ip 0.0.0.0 --keyFile /home/mongo-keyfile
MongoDB
的数据存储路径,默认是/data/db
。这是最重要的路径,需要将其映射到主机上的持久存储,以确保数据在容器重启或删除后不会丢失。--keyFile
:指定集群认证文件。
3. 启动从节点
如果不部署的话,就一个节点也可以设置为集群(只有一个主节点)。还需要注意的是 MongoDB 仅主节点可以读写,从节点是只读的。
docker run -d \
--name mongo_slave001 \
-p 27018:27017 \
-v /xxxx/mongodb/mongo-keyfile:/home/mongo-keyfile
-v /xxxx/mongodb/slave001:/data/db \
-e MONGO_INITDB_ROOT_USERNAME=admin \
-e MONGO_INITDB_ROOT_PASSWORD=123456 \
mongo:4.0.25 \
--replSet rs0 --bind_ip 0.0.0.0 --keyFile /home/mongo-keyfile
参数大部分与主节点一样,如果是在同一个机器上需要注意端口冲突。因为示例中是在同一个 host
上部署了两个容器,所以从节点使用了 27018
端口。
如果是多个从节点的话就继续部署多个即可,保证认证文件 (
monog-keyfile
) 的内容是一样的。
4. 配置副本集
等到容器启动后,进入主节点容器:
# 进入容器内部
docker exec -it mongo_primary bash
# 容器内部
mongo -u admin -p 123456 --authenticationDatabase admin
在MongoDB shell中运行以下命令以初始化副本集:
rs.initiate({
_id: "rs0",
members: [
{ _id: 0, host: "192.168.10.110:27017", priority: 2 },
{ _id: 1, host: "192.168.10.110:27018", priority: 1 }
]
})
IP
不要使用127.0.0.1
,如果使用的话是表示本容器,将无法访问其他容器中的服务;建议使用宿主机器的IP
。- 这里为了省事就在同一个机器上部署了多个 MongoDB 容器,条件允许的话可以在多个机器上部署 MongoDB 容器。
- 初始化副本集的
rs0
名称要与运行容器时指定的--replSet rs0
参数保持一致,这种一致性确保了所有实例能够正确地识别和加入同一个副本集, - 一个节点也可以设置为集群(只有一个主节点),但是实际生产中推荐至少三个节点。
priority
来设置每个成员的优先级,优先级高的成员更有可能被选为主节点。
主从节点选举:当运行
rs.initiate()
时,MongoDB
会自动选举一个主节点。默认情况下,启动rs.initiate()
命令的节点会成为主节点,但这并不是绝对的,尤其是在复杂配置中。但是通过在配置副本集成员时设置priority
参数来影响选举过程。优先级越高的成员越有可能被选举为主节点。
等待副本集初始化完成,然后通过运行以下命令检查副本集状态:
rs.status()
5. 注意事项
- 安全性: 将
MongoDB
实例暴露给任意IP
访问可能会带来安全风险,确保白名单的配置。如果使用云厂商提供的数据库,请确保在生产环境中使用防火墙或云提供商的安全组来限制对MongoDB
实例的访问。 - 防火墙配置: 如果您在云环境中运行
MongoDB
实例,请确保安全组或防火墙规则允许对MongoDB
端口(如27017
)的访问。 - 使用SSL/TLS: 考虑启用
SSL/TLS
来加密客户端和Mongo
DB服务器之间的通信。