对于 AI 代理:可在 https://www.mongodb.com/zh-cn/docs/llms.txt 获取文档索引—通过在任何 URL 路径后添加 .md 可获取所有页面的 Markdown 版本。

迁移应用程序数据库到外部部署

您可以将使用内部托管的应用程序数据库的 MongoDB Ops Manager 资源转换为使用 外部 应用程序数据库的资源,即将 spec.role 设置为 AppDB 的 MongoDB 自定义资源。这样就可以让 MongoDB Ops Manager 备份和恢复应用程序数据库。要了解更多信息,请参阅 备份 MongoDB Ops Manager 应用程序数据库。

此次迁移将现有的应用程序数据库 StatefulSet 及其 持久卷 的所有权从 MongoDB Ops Manager 资源重新指向 MongoDB 资源。Kubernetes 操作符 不会移动或重新创建您的数据,也不会重启 Ops Manager Pod。

MongoDB Ops Manager 资源以内部托管的应用程序数据库开始,Kubernetes 操作符拥有名为 <primary-om-name>-db 的 StatefulSet。迁移如下进行:

  1. 您创建一个 MongoDB 资源,将 spec.role 设置为 AppDB,并使用与 StatefulSet 相同的名称,该资源位于由 管理 MongoDB Ops Manager 实例托管的项目中。MongoDB 资源尚无法获取 StatefulSet 的所有权,因此它保持在 Pending 阶段,并显示一条消息,指出它无法获取应用程序数据库 StatefulSet 的所有权。

  2. 您将 spec.externalApplicationDatabaseRef 添加到 MongoDB Ops Manager 资源中。Kubernetes Operator 通过删除 MongoDB Ops Manager 资源的所有者引用并将 StatefulSet 标记为可迁移,从而分离 StatefulSet。然后,MongoDB 资源将获取其所有权。

由于 Kubernetes Operator 计算出的连接字符串与之前相同(使用相同的主机名),因此 MongoDB Ops Manager Pod 不会重启。

在开始之前,请完成以下任务:

在迁移之前,请查看以下考虑因素:

  • 在 MongoDB 资源上设置的应用程序数据库版本必须与内部托管的应用程序数据库运行的版本匹配,并且必须是管理 MongoDB Ops Manager 实例提供的 MongoDB 版本。

  • Kubernetes 操作符在迁移过程中不支持 spec.applicationDatabase.passwordSecretKeyRef。Kubernetes 操作符 生成新密码,并且它轮换您提供的任何密码。

  • 如果 MongoDB 资源配置与内部托管的应用程序数据库配置不同(例如不同的 Pod 模板或不同的容器集),应用程序数据库可能会在 1 到 2 分钟内不可用。如果这两种配置在语义上相同,则应用程序数据库保持可用。

  • Kubernetes 操作符只支持在单个 Kubernetes 集群上迁移。

1
export K8S_CTX="<your-kube-context>"
export MDB_NS="mongodb"
export MANAGEMENT_OM_NAME="management-om"
export PRIMARY_OM_NAME="primary-om"
export APPDB_NAME="${PRIMARY_OM_NAME}-db"
export APPDB_VERSION="8.0.5-ent"
export MANAGEMENT_OM_URL="http://${MANAGEMENT_OM_NAME}-svc.${MDB_NS}.svc.cluster.local:8080"
export MANAGEMENT_OM_ADMIN_KEY_SECRET="<your-operator-credentials-secret>"
export APPDB_PROJECT_CONFIGMAP="${APPDB_NAME}-config"
export APPDB_PROJECT_NAME="external-appdb"
2
  1. 确认主节点 (primary node in the replica set) Ops Manager 资源及其内部托管的应用程序数据库处于 Running 阶段:

    kubectl get om "${PRIMARY_OM_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" \
    -o jsonpath='{.status.opsManager.phase} / appdb={.status.applicationDatabase.phase}{"\n"}'
  2. 确认 MongoDB Ops Manager 资源控制应用程序数据库 StatefulSet:

    kubectl get statefulset "${APPDB_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" \
    -o jsonpath='{range .metadata.ownerReferences[*]}{.kind}/{.name}{"\n"}{end}'

    该命令返回 MongoDBOpsManager/${PRIMARY_OM_NAME}。

3

orgId 值是必填项。如果您将其设置为空 string,Kubernetes Operator 会创建一个与您的项目同名的组织。

kubectl create configmap "${APPDB_PROJECT_CONFIGMAP}" \
--context "${K8S_CTX}" -n "${MDB_NS}" \
--from-literal=baseUrl="${MANAGEMENT_OM_URL}" \
--from-literal=projectName="${APPDB_PROJECT_NAME}" \
--from-literal=orgId=""
4

为该资源指定与现有应用程序数据库 StatefulSet 相同的名称。

kubectl apply --context "${K8S_CTX}" -n "${MDB_NS}" -f - <<EOF
apiVersion: mongodb.com/v1
kind: MongoDB
metadata:
name: ${APPDB_NAME}
spec:
members: 3
version: ${APPDB_VERSION}
type: ReplicaSet
role: AppDB
opsManager:
configMapRef:
name: ${APPDB_PROJECT_CONFIGMAP}
credentials: ${MANAGEMENT_OM_ADMIN_KEY_SECRET}
persistent: true
security:
authentication:
enabled: true
modes: ["SCRAM"]
ignoreUnknownUsers: true
EOF
5

直到 MongoDB Ops Manager 资源释放 StatefulSet,MongoDB 资源会保持在 Pending 阶段。这是预期的,并不是错误。

kubectl wait --for=jsonpath='{.status.phase}'=Pending \
mdb/"${APPDB_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" --timeout=300s
kubectl get mdb "${APPDB_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" \
-o jsonpath='{.status.message}{"\n"}'

状态消息报告称,资源无法拥有应用程序数据库 StatefulSet。

6
kubectl patch om "${PRIMARY_OM_NAME}" \
--context "${K8S_CTX}" -n "${MDB_NS}" \
--type merge \
-p "{\"spec\":{\"externalApplicationDatabaseRef\":{\"name\":\"${APPDB_NAME}\",\"kind\":\"MongoDB\"}}}"

您可以在同一个补丁中删除 spec.applicationDatabase。将其保留在原位没有影响:设置 spec.externalApplicationDatabaseRef 后,Kubernetes 操作符将停止管理此资源的内部应用程序数据库。

7
kubectl wait --for=jsonpath='{.status.phase}'=Running \
mdb/"${APPDB_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" --timeout=1200s
kubectl wait --for=jsonpath='{.status.opsManager.phase}'=Running \
om/"${PRIMARY_OM_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" --timeout=1800s
8
  1. 确认 MongoDB 资源拥有应用程序数据库 StatefulSet:

    kubectl get statefulset "${APPDB_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" \
    -o jsonpath='{range .metadata.ownerReferences[*]}{.kind}/{.name}{"\n"}{end}'

    该命令返回 MongoDB/${APPDB_NAME}。

  2. 确认 MongoDB Ops Manager 资源将其应用程序数据库报告为 Disabled,这意味着 Kubernetes 操作符不再为其托管内部应用程序数据库:

    kubectl get om "${PRIMARY_OM_NAME}" --context "${K8S_CTX}" -n "${MDB_NS}" \
    -o jsonpath='{.status.applicationDatabase.phase}{"\n"}'
  3. 通过检查 Ops Manager Pod 的运行时间和重启次数,确认它们没有重启:

    kubectl get pods --context "${K8S_CTX}" -n "${MDB_NS}"

如果 MongoDB 资源报告 Failed 且消息显示 MongoDB 版本不可用,请将 spec.version 设置为管理 Ops Manager 实例提供的版本,并确保 Ops Manager 版本和应用程序数据库版本处于同一主版本。

Kubernetes 操作符必须分离 StatefulSet,然后 MongoDB 资源才能取得其所有权。确认您已将 spec.externalApplicationDatabaseRef 应用于主节点 (primary node in the replica set) Ops Manager 资源,并且 spec.externalApplicationDatabaseRef.name 的值为正好 <primary-om-name>-db。

如果 MongoDB 资源因项目或注册错误而停留在 Pending 阶段,则在您创建资源时,管理 MongoDB Ops Manager 公共 API 可能尚未准备就绪。确认管理 MongoDB Ops Manager 资源处于 Running 阶段,并且其 API 回答请求,然后再次协调该资源。

如果 MongoDB Ops Manager Pod 重启,计算出的连接字符串会发生变化。对于使用默认端口的副本集,迁移前后的连接字符串是相同的。Kubernetes 操作符 不支持此迁移的非默认端口。