在MongoDB中迁移数据库是一个非常容易理解的问题领域,并且在主机级别上有许多可用的工具来做到这一点。 mongodump
上从mongoexport
和data files到rsync
的所有内容。如果您非常喜欢,可以使用SSHFS和NFS之类的网络安装来减轻磁盘空间和IOPS约束问题。
在主机上迁移数据库
# Using a temporary archive
mongodump --db my_db --gzip --archive /tmp/my_db.dump --port 27017
mongorestore --db my_db --gzip --archive /tmp/my_db.dump --port 27018
rm /tmp/my_db.dump
# Or you can stream it...
mongodump --db my_db --port 27017 --archive \
| mongorestore --db my_db --port 27018 --archive
但是,在容器化环境中执行相同的迁移可能会更加复杂,并且容器的轻量级,针对特定目的的性质意味着您通常没有可用的同一套工具。
作为一名管理容器化基础架构的工程师,我对可以使用哪种方法将数据库从一个容器/集群迁移到另一个容器/集群进行备份,集群迁移或开发(数据采样)的目的感兴趣。
出于这个问题的目的,我们假设数据库不是是一个分布在多个主机上的多TB群集,每秒看到数千(++)次写入(即您可以进行备份并拥有“足够”的数据,使其有价值,而不必担心复制操作日志等)。
答案 0 :(得分:1)
我以前使用过几种方法来解决这个问题。具体方法取决于我在做什么以及需要满足哪些要求。
# Dump the old container's DB to an archive file within the container
docker exec $OLD_CONTAINER \
bash -c 'mongodump --db my_db --gzip --archive /tmp/my_db.dump'
# Copy the archive from the old container to the new one
docker cp $OLD_CONTAINER:/tmp/my_db.dump $NEW_CONTAINER:/tmp/my_db.dump
# Restore the archive in the new container
docker exec $NEW_CONTAINER \
bash -c 'mongorestore --db my_db --gzip --archive /tmp/my_db.dump'
此方法效果很好,并且避免了在stdout
上管道传输数据时遇到的许多编码问题,但是,当迁移到不同主机上的容器时,它也不能很好地工作(您需要docker cp
到一个本地文件,然后重复该过程以将该本地文件复制到新主机),以及从Docker迁移到Kubernetes的过程。
迁移到其他Docker集群
# Dump the old container's DB to an archive file within the container
docker -H old_cluster exec $OLD_CONTAINER \
bash -c 'mongodump --db my_db --gzip --archive /tmp/my_db.dump'
docker -H old_cluster exec $OLD_CONTAINER rm /tmp/my_db.dump
# Copy the archive from the old container to the new one (via your machine)
docker -H old_cluster cp $OLD_CONTAINER:/tmp/my_db.dump /tmp/my_db.dump
docker -H new_cluster cp /tmp/my_db.dump $NEW_CONTAINER:/tmp/my_db.dump
rm /tmp/my_db.dump
# Restore the archive in the new container
docker -H new_cluster exec $NEW_CONTAINER \
bash -c 'mongorestore --db my_db --gzip --archive /tmp/my_db.dump'
docker -H new_cluster exec $NEW_CONTAINER rm /tmp/my_db.dump
缺点
此方法的最大缺点是需要在各处存储临时转储文件。在基本情况下,旧容器中将有一个转储文件,新容器中将有一个转储文件。在最坏的情况下,本地计算机上可能排在第3位(如果需要scp
/ rsync
,则可能在多台计算机上排第3位)。这些临时文件很可能会被遗忘,浪费了不必要的空间并混乱了容器的文件系统。
# Copy the database over stdout (base64 encoded)
docker exec $OLD_CONTAINER \
bash -c 'mongodump --db my_db --gzip --archive 2>/dev/null | base64' \
| docker exec $NEW_CONTAINER \
bash -c 'base64 --decode | mongorestore --db my_db --gzip --archive'
通过stdout
复制档案并将其通过stdin
传递到新容器,这样您就可以删除复制步骤,并将命令加入一个漂亮的小衬板中(对于一些精美的定义)。它还允许您潜在地混合搭配主机甚至容器调度程序...
在不同的Docker集群之间迁移
# Copy the database over stdout (base64 encoded)
docker -H old_cluster exec $(docker -H old_cluster ps -q -f 'name=mongo') \
bash -c 'mongodump --db my_db --gzip --archive 2>/dev/null | base64' \
| docker -H new_cluster exec $(docker -H new_cluster ps -q -f 'name=mongo') \
bash -c 'base64 --decode | mongorestore --db my_db --gzip --archive'
从Docker迁移到Kubernetes
# Copy the database over stdout (base64 encoded)
docker exec $(docker ps -q -f 'name=mongo') \
bash -c 'mongodump --db my_db --gzip --archive 2>/dev/null | base64' \
| kubectl exec mongodb-0 \
bash -c 'base64 --decode | mongorestore --db my_db --gzip --archive'
缺点
此方法在“成功”情况下效果很好,但是在无法正确转储数据库的情况下,抑制stderr
流(使用2>/dev/null
的需求可能会导致调试时出现严重的麻烦原因。
与文件情况相比,它的网络效率也降低了33%,因为它需要base64
编码数据以进行传输(对于大型数据库来说这可能是一个大问题)。与所有流式传输模式一样,也没有办法检查事后发送的数据,如果您需要查找问题,则可能是个问题。