For AI agents: a documentation index is available at https://www.mongodb.com/docs/llms.txt — markdown versions of all pages are available by appending .md to any URL path.
Docs Menu

Multi-Cluster Ops Manager

The Ops Manager is responsible for facilitating workloads such as backing up data, monitoring database performance and more. To make your multi-cluster Ops Manager and the Application Database deployment resilient to entire data center or zone failures, deploy the Ops Manager Application and the Application Database on multiple Kubernetes clusters.

Before you begin the following procedure, perform the following actions:

# This script builds on top of the environment configured in the setup guides.
# It depends (uses) the following env variables defined there to work correctly.
# If you don't use the setup guide to bootstrap the environment, then define them here.
# ${K8S_CLUSTER_0_CONTEXT_NAME}
# ${K8S_CLUSTER_1_CONTEXT_NAME}
# ${K8S_CLUSTER_2_CONTEXT_NAME}
# ${OM_NAMESPACE}
# Defaults for the test RustFS S3 storage.
# If you use your own S3 storage - override any of these.
export S3_OPLOG_BUCKET_NAME="${S3_OPLOG_BUCKET_NAME:-s3-oplog-store}"
export S3_SNAPSHOT_BUCKET_NAME="${S3_SNAPSHOT_BUCKET_NAME:-s3-snapshot-store}"
export S3_ENDPOINT="${S3_ENDPOINT:-rustfs.rustfs.svc.cluster.local}"
export S3_ACCESS_KEY="${S3_ACCESS_KEY:-rustfsadmin}"
export S3_SECRET_KEY="${S3_SECRET_KEY:-rustfsadmin123}"
export OPS_MANAGER_VERSION="8.0.5"
export APPDB_VERSION="8.0.5-ent"

You can find all included source code in the MongoDB Kubernetes Operator repository.

1
kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" apply -f - <<EOF
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: om-cert
spec:
dnsNames:
- om-svc.${OM_NAMESPACE}.svc.cluster.local
duration: 240h0m0s
issuerRef:
name: my-ca-issuer
kind: ClusterIssuer
renewBefore: 120h0m0s
secretName: cert-prefix-om-cert
usages:
- server auth
- client auth
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: om-db-cert
spec:
dnsNames:
- "*.${OM_NAMESPACE}.svc.cluster.local"
duration: 240h0m0s
issuerRef:
name: my-ca-issuer
kind: ClusterIssuer
renewBefore: 120h0m0s
secretName: cert-prefix-om-db-cert
usages:
- server auth
- client auth
EOF
2

At this point, you have prepared the environment and the Kubernetes Operator to deploy the Ops Manager resource.

  1. Create the necessary credentials for the Ops Manager admin user that the Kubernetes Operator will create after deploying the Ops Manager Application instance:

    1kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" --namespace "${OM_NAMESPACE}" create secret generic om-admin-user-credentials \
    2 --from-literal=Username="admin" \
    3 --from-literal=Password="Passw0rd@" \
    4 --from-literal=FirstName="Jane" \
    5 --from-literal=LastName="Doe"
  2. Deploy the simplest MongoDBOpsManager custom resource possible (with TLS enabled) on a single member cluster, which also serves as the central cluster.

    This deployment is almost the same as the deployment for the single-cluster mode, but with spec.topology and spec.applicationDatabase.topology set to MultiCluster.

    Deploying this way shows that a single Kubernetes cluster deployment is a special case of a multi-Kubernetes cluster deployment on a single Kubernetes member cluster. You can start deploying the Ops Manager Application and the Application Database on as many Kubernetes clusters as necessary from the beginning, and don't have to start with the deployment with only a single member Kubernetes cluster.

    At this point, you have prepared the Ops Manager deployment to span more than one Kubernetes cluster, which you will do later in this procedure.

    1kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" -f - <<EOF
    2apiVersion: mongodb.com/v1
    3kind: MongoDBOpsManager
    4metadata:
    5 name: om
    6spec:
    7 topology: MultiCluster
    8 version: "${OPS_MANAGER_VERSION}"
    9 adminCredentials: om-admin-user-credentials
    10 externalConnectivity:
    11 type: LoadBalancer
    12 security:
    13 certsSecretPrefix: cert-prefix
    14 tls:
    15 ca: ca-issuer
    16 clusterSpecList:
    17 - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}"
    18 members: 1
    19 applicationDatabase:
    20 version: "${APPDB_VERSION}"
    21 topology: MultiCluster
    22 security:
    23 certsSecretPrefix: cert-prefix
    24 tls:
    25 ca: ca-issuer
    26 clusterSpecList:
    27 - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}"
    28 members: 3
    29 backup:
    30 enabled: false
    31EOF
  3. Wait for the Kubernetes Operator to pick up the work and reach the status.applicationDatabase.phase=Pending state. Wait for both the Application Database and Ops Manager deployments to complete.

    1echo "Waiting for Application Database to reach Pending phase..."
    2kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Pending opsmanager/om --timeout=30s
  4. Deploy Ops Manager. The Kubernetes Operator deploys Ops Manager by performing the following steps. It:

    • Deploys the Application Database's replica set nodes and waits for the MongoDB processes in the replica set to start running.

    • Deploys the Ops Manager Application instance with the Application Database's connection string and waits for it to become ready.

    • Adds the Monitoring MongoDB Agent containers to each Application Database's Pod.

    • Waits for both the Ops Manager Application and the Application Database Pods to start running.

    1echo "Waiting for Application Database to reach Running phase..."
    2kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=1200s
    3echo; echo "Waiting for Ops Manager to reach Running phase..."
    4kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Running opsmanager/om --timeout=1200s
    5echo; echo "MongoDBOpsManager resource"
    6kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get opsmanager/om
    7echo; echo "Pods running in cluster ${K8S_CLUSTER_0_CONTEXT_NAME}"
    8kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get pods
    9echo; echo "Pods running in cluster ${K8S_CLUSTER_1_CONTEXT_NAME}"
    10kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get pods

    Now that you have deployed a single-member cluster in a multi-cluster mode, you can reconfigure this deployment to span more than one Kubernetes cluster.

  5. On the second member cluster, deploy two additional Application Database replica set members and one additional instance of the Ops Manager Application:

    1kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" -f - <<EOF
    2apiVersion: mongodb.com/v1
    3kind: MongoDBOpsManager
    4metadata:
    5 name: om
    6spec:
    7 topology: MultiCluster
    8 version: "${OPS_MANAGER_VERSION}"
    9 adminCredentials: om-admin-user-credentials
    10 externalConnectivity:
    11 type: LoadBalancer
    12 security:
    13 certsSecretPrefix: cert-prefix
    14 tls:
    15 ca: ca-issuer
    16 clusterSpecList:
    17 - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}"
    18 members: 1
    19 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}"
    20 members: 1
    21 applicationDatabase:
    22 version: "${APPDB_VERSION}"
    23 topology: MultiCluster
    24 security:
    25 certsSecretPrefix: cert-prefix
    26 tls:
    27 ca: ca-issuer
    28 clusterSpecList:
    29 - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}"
    30 members: 3
    31 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}"
    32 members: 2
    33 backup:
    34 enabled: false
    35EOF
  6. Wait for the Kubernetes Operator to pick up the work (pending phase):

    1echo "Waiting for Application Database to reach Pending phase..."
    2kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Pending opsmanager/om --timeout=30s
    3
    4echo "Waiting for Ops Manager to reach Pending phase..."
    5kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Pending opsmanager/om --timeout=600s
  7. Wait for the Kubernetes Operator to finish deploying all components:

    1echo "Waiting for Application Database to reach Running phase..."
    2kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=1200s
    3echo; echo "Waiting for Ops Manager to reach Running phase..."
    4kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Running opsmanager/om --timeout=1200s
    5echo; echo "MongoDBOpsManager resource"
    6kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get opsmanager/om
    7echo; echo "Pods running in cluster ${K8S_CLUSTER_0_CONTEXT_NAME}"
    8kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get pods
    9echo; echo "Pods running in cluster ${K8S_CLUSTER_1_CONTEXT_NAME}"
    10kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get pods
3

In a multi-Kubernetes cluster deployment of the Ops Manager Application, you can configure only S3-based backup storage. This procedure refers to S3_* defined in env_variables.sh.

  1. Optional. Deploy S3-compatible storage for testing.

    This step provides a script that deploys a simple RustFS instance for testing purposes. You can skip this step if you have AWS S3 or other S3-compatible buckets available. Adjust the S3_* variables accordingly in env_variables.sh in this case.

    Note

    RustFS is only for testing and isn't suitable for production. For production, use your own S3 storage.

  2. Before you configure and enable backup, create secrets:

    • s3-access-secret - contains S3 credentials.

    • s3-ca-cert - contains a CA certificate that issued the bucket's server certificate. The sample RustFS deployment in this procedure serves a cert-manager-issued certificate, so the secret contains the CA certificate from the rustfs-tls secret. Because this CA certificate is not publicly trusted, you must provide it so that Ops Manager can trust the connection.

    If you use publicly trusted certificates, you may skip this step and remove the values from the spec.backup.s3Stores.customCertificateSecretRefs and spec.backup.s3OpLogStores.customCertificateSecretRefs settings.

    1kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" create secret generic s3-access-secret \
    2 --from-literal=accessKey="${S3_ACCESS_KEY}" \
    3 --from-literal=secretKey="${S3_SECRET_KEY}"
    4
    5# RustFS serves a cert-manager certificate; OM must trust the CA that signed it.
    6kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" create secret generic s3-ca-cert \
    7 --from-literal=ca.crt="$(kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${RUSTFS_NAMESPACE}" get secret rustfs-tls -o jsonpath="{.data['ca\.crt']}" | base64 --decode)"
4
  1. The Kubernetes Operator can configure and deploy all components, the Ops Manager Application, the Backup Daemon instances, and the Application Database's replica set nodes in any combination on any member clusters for which you configure the Kubernetes Operator.

    To illustrate the flexibility of the multi-Kubernetes cluster deployment configuration, deploy only one Backup Daemon instance on the third member cluster and specify zero Backup Daemon members for the first and second clusters.

    1kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" -f - <<EOF
    2apiVersion: mongodb.com/v1
    3kind: MongoDBOpsManager
    4metadata:
    5 name: om
    6spec:
    7 topology: MultiCluster
    8 version: "${OPS_MANAGER_VERSION}"
    9 adminCredentials: om-admin-user-credentials
    10 externalConnectivity:
    11 type: LoadBalancer
    12 security:
    13 certsSecretPrefix: cert-prefix
    14 tls:
    15 ca: ca-issuer
    16 clusterSpecList:
    17 - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}"
    18 members: 1
    19 backup:
    20 members: 0
    21 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}"
    22 members: 1
    23 backup:
    24 members: 0
    25 - clusterName: "${K8S_CLUSTER_2_CONTEXT_NAME}"
    26 members: 0
    27 backup:
    28 members: 1
    29 applicationDatabase:
    30 version: "${APPDB_VERSION}"
    31 topology: MultiCluster
    32 security:
    33 certsSecretPrefix: cert-prefix
    34 tls:
    35 ca: ca-issuer
    36 clusterSpecList:
    37 - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}"
    38 members: 3
    39 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}"
    40 members: 2
    41 backup:
    42 enabled: true
    43 s3Stores:
    44 - name: my-s3-block-store
    45 s3SecretRef:
    46 name: "s3-access-secret"
    47 pathStyleAccessEnabled: true
    48 s3BucketEndpoint: "${S3_ENDPOINT}"
    49 s3BucketName: "${S3_SNAPSHOT_BUCKET_NAME}"
    50 customCertificateSecretRefs:
    51 - name: s3-ca-cert
    52 key: ca.crt
    53 s3OpLogStores:
    54 - name: my-s3-oplog-store
    55 s3SecretRef:
    56 name: "s3-access-secret"
    57 s3BucketEndpoint: "${S3_ENDPOINT}"
    58 s3BucketName: "${S3_OPLOG_BUCKET_NAME}"
    59 pathStyleAccessEnabled: true
    60 customCertificateSecretRefs:
    61 - name: s3-ca-cert
    62 key: ca.crt
    63EOF
  2. Wait until the Kubernetes Operator finishes its configuration:

    1echo; echo "Waiting for Backup to reach Running phase..."
    2kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.backup.phase}'=Running opsmanager/om --timeout=1200s
    3echo "Waiting for Application Database to reach Running phase..."
    4kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=1200s
    5echo; echo "Waiting for Ops Manager to reach Running phase..."
    6kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Running opsmanager/om --timeout=1200s
    7echo; echo "MongoDBOpsManager resource"
    8kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get opsmanager/om
    9echo; echo "Pods running in cluster ${K8S_CLUSTER_0_CONTEXT_NAME}"
    10kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get pods
    11echo; echo "Pods running in cluster ${K8S_CLUSTER_1_CONTEXT_NAME}"
    12kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get pods
    13echo; echo "Pods running in cluster ${K8S_CLUSTER_2_CONTEXT_NAME}"
    14kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${OM_NAMESPACE}" get pods
5

To configure credentials, you must create an Ops Manager organization, generate programmatic API keys in the Ops Manager UI, and create a secret with your Load Balancer IP. See Create Credentials for the Kubernetes Operator to learn more.