MongoDB 无缝迁移到 Kubernetes

MongoDB 无缝迁移到 Kubernetes

这篇文章继续我们的 最近的材料 关于 RabbitMQ 迁移并致力于 MongoDB。 由于我们维护许多 Kubernetes 和 MongoDB 集群,因此我们自然需要将数据从一个安装迁移到另一个安装,并且无需停机。 主要场景是相同的:将 MongoDB 从虚拟/硬件服务器移动到 Kubernetes 或在同一 Kubernetes 集群内移动 MongoDB(从一个命名空间到另一个命名空间)。

我们的方案适用于存在运行 Kubernetes 中托管的应用程序的旧 MongoDB 集群(例如,具有 3 个节点且位于 K8s 中或旧服务器上)的情况:

MongoDB 无缝迁移到 Kubernetes

我们如何将这样的集群转移到 Kubernetes 中的新生产环境?

Теория

一般的迁移算法与RabbitMQ的情况中描述的类似。

需要注意的是,此举要求 MongoDB 和 Kubernetes 服务器位于同一网络上。 MongoDB 集群节点将使用旧服务器(旧 MongoDB 安装所在位置)的 IP 以及 K8s 中 MongoDB 的 Pod 的 DNS 名称相互通信。 因此,在硬件服务器(使用旧安装)上,您需要将路由转发到 Pod,然后将它们配置为使用在 Kubernetes 中运行的 DNS 服务器(或在 /etc/hosts,尽管一般来说最好避免这种可能性)。

下一步是在 Kubernetes Pod 中构建 MongoDB 集群。 在我们的例子中,数据库集群由 3 个节点组成,每个节点位于一个单独的 K8s pod 中 - 但是,它们的数量可能不同。 在 ConfigMap 中,您需要指定旧安装中 MongoDB master 的地址:然后位于 K8s 中 pod 中的 MongoDB 节点将立即开始与其同步。

所有 pod 启动后,就形成了 6 个节点的 MongoDB 集群:

MongoDB 无缝迁移到 Kubernetes

请注意,pod 需要很长时间才能启动,因为每个 pod 都是轮流启动的,并且在启动时会同步来自 master 的数据。

然后,您可以切换应用程序以使用新的 MongoDB 服务器:

MongoDB 无缝迁移到 Kubernetes

剩下的就是从 MongoDB 集群中删除旧节点,之后即可认为移动完成:

MongoDB 无缝迁移到 Kubernetes

我们经常在生产中使用这种方案,为了便于使用,我们在模块中实现了它 插件操作符 (我们 最近宣布),它允许典型的 MongoDB 配置分布在许多集群上。 我们计划很快发布我们的模块,但现在我们提供单独的说明,您可以在不使用插件操作符的情况下尝试实际使用建议的解决方案。

让我们在实践中尝试一下

需求

联系方式:

  • Kubernetes 集群(minikube 也可以);
  • MongoDB 集群(可以部署在裸机上,并根据官方 Helm 图表制作得像 Kubernetes 中的常规集群一样)。

在下面的示例中,旧的 MongoDB 集群将被命名为 mongo-old 并安装在同一个 Kubernetes 集群中,稍后我们将在其中安装新集群(mongo-new).

准备旧集群

1. 作为演示所描述方案的实际示例,让我们直接在 Kubernetes 中创建一个“旧”(即需要迁移)MongoDB 集群(实际上,它可以位于 K8s 之外的单独服务器上)。 为此,请下载 Helm 图表:

helm fetch --untar stable/mongodb-replicaset

...并通过设置授权对其进行一些编辑:

auth:
  enabled: true
  adminUser: mongo
  adminPassword: pa33w0rd
  # metricsUser: metrics
  # metricsPassword: password
  # key: keycontent
  # existingKeySecret:
  # existingAdminSecret:
  # exisitingMetricsSecret:

此外,在 values.yaml 您可以配置证书等等。

2. 安装图表:

helm install . --name mongo-old --namespace mongo-old

之后,将启动 MongoDB 的测试“旧”安装:

kubectl --namespace=mongo-old get pods

MongoDB 无缝迁移到 Kubernetes

让我们进入 pod 及其 master 并创建一个测试数据库:

kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')
use music
db.artists.insert({ artistname: "The Tea Party" })
show dbs

MongoDB 无缝迁移到 Kubernetes

进入不同的pod,我发现master是 mongo-old-mongodb-replicaset-0。 不过,为了更方便地解决这个问题,安装Helm图表后,会显示一条命令,告诉您如何确定 MASTER_POD。 就我而言(对于 mongo-old 3 个节点)看起来像这样:

for ((i = 0; i < 3; ++i)); do kubectl exec --namespace mongo-old mongo-old-mongodb-replicaset-$i -- sh -c 'mongo --eval="printjson(rs.isMaster())"'; done

至此,旧的 MongoDB 安装(其中的数据将被传输)的准备工作已准备就绪。

迁移 MongoDB 集群

现在让我们部署新安装的 MongoDB,它将位于 Kubernetes 中并由生产中的应用程序使用。

NB:请注意,必须使用与之前相同版本的 MongoDB。 否则,存在兼容性问题的风险。

与上一节(我们模拟“旧”MongoDB 安装)进行类比,让我们采用已经提到的 Helm 图表(使用命令 helm fetch)并配置授权以及其他参数(如果使用)。 此外,我们将更正该文件 init/on-start.sh,在第 165 行临时添加上一步中获得的主地址(或者您在各个服务器上安装 MongoDB 时获知的主地址):

peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'

我们准备创建一个新的 MongoDB 安装:

helm install . --name mongo-new --namespace mongo-new

我们等到所有 Pod 启动(如果有大量数据,那么它们的启动可能需要几个小时):

MongoDB 无缝迁移到 Kubernetes

现在我们做 exec 到新的 pod 并查看数据库列表:

kubectl --namespace=mongo-new exec -ti mongo-new-mongodb-replicaset-0 mongo

MongoDB 无缝迁移到 Kubernetes

两个 MongoDB 集群合二为一,由 6 个节点组成。

此时,您可以将应用程序切换到新集群,但还需要几个步骤才能完成迁移。

从文件 init/on-start.sh 在新安装中,我们删除添加的行:

peers='mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017'

现在让我们去旧的集群主机并“推翻”它——然后一个新的主机将被分配给集群。 我们进入 MongoDB master 的 pod:

kubectl --namespace=mongo-old exec -ti mongo-old-mongodb-replicaset-0 mongo
use admin
db.auth('mongo','password')

之后,我们更改节点的优先级并更改主节点:

cfg = rs.conf()
cfg.members[5].priority = 2
rs.reconfig(cfg)
rs.stepDown(120)

当前节点已不再是主节点 - 将选举一个新节点。 由于我们改变了优先级,我们需要的节点将成为主节点。

NB:默认情况下,所有MongoDB节点的优先级都是1。上面,我们将我们需要的节点的优先级提高到2。 这样,新集群中的一个成员肯定会成为总master。 您可以阅读有关这些机制在 MongoDB 中如何工作的更多信息: 文件资料.

让我们禁用旧的 MongoDB 安装,然后转到新向导并删除旧节点:

rs.remove("mongo-old-mongodb-replicaset-0.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")
rs.remove("mongo-old-mongodb-replicaset-1.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")
rs.remove("mongo-old-mongodb-replicaset-2.mongo-old-mongodb-replicaset.mongo-old.svc.cluster.local:27017")

至此,迁移算是完成了:我们已经成功从旧的MongoDB集群切换到新的集群了!

结果

当您需要迁移 MongoDB 或只是移动到新集群时,所描述的方案几乎适用于所有情况。

也许传输时的主要细微差别是需要将新 Pod 的 IP 地址转发到旧 MongoDB 安装的服务器(如果它位于 K8s 之外),并在 DNS 中正确命名它们(或 /etc/hosts)。 在示例中,不需要这些步骤,因为迁移发生在同一 Kubernetes 集群的不同命名空间之间。

PS

另请阅读我们的博客:

来源: habr.com

为具有 DDoS 保护、VPS VDS 服务器的站点购买可靠的主机 🔥 购买具备 DDoS 防护的可靠网站托管服务,包括 VPS 和 VDS 服务器 | ProHoster