Para agentes de IA: hay un índice de documentación disponible en https://www.mongodb.com/es/docs/llms.txt — versiones en markdown de todas las páginas están disponibles agregando .md a cualquier ruta URL.

Implementar recursos de Ops Manager en varios clústeres de Kubernetes

Para que la implementación de Ops Manager y la base de datos de la aplicación en múltiples clústeres sean resilientes a caídas de centros de datos completos o zonas enteras, implemente la aplicación Ops Manager y la base de datos de la aplicación en múltiples clústeres de Kubernetes.

Para obtener más información sobre la arquitectura, la red, las limitaciones y el rendimiento de las implementaciones de múltiples clústeres de Kubernetes para los recursos de Ops Manager, consulta:

Nota

El siguiente procedimiento requiere que implemente una malla de servicios en todos sus clústeres de Kubernetes. Si necesitas implementar Ops Manager en varios clústeres de Kubernetes sin un service mesh, consulta Ops Manager Multiclúster sin Service Mesh para aprender más.

Cuando implementas la Ops Manager aplicación y la base de datos de la aplicación utilizando el procedimiento en esta sección, tú:

  1. Usa GKE (Google Kubernetes Engine) y Istio como herramientas para demostrar la implementación de clústeres Kubernetes múltiples.

  2. Instale el operador de Kubernetes en uno de los clústeres de Kubernetes nodo, que sirve como el clúster central. El clúster central actúa como un Hub en el patrón "Hub and Spoke" utilizado por el operador de Kubernetes para gestionar implementaciones en varios clúster de Kubernetes.

  3. Implemente el clúster central en el $OPERATOR_NAMESPACE y configure este clúster para supervisar $NAMESPACE y gestionar todos los clústeres de Kubernetes de los nodos.

  4. Implemente la base de datos de la aplicación y la aplicación Ops Manager en un clúster de Kubernetes de un solo nodo para demostrar la similitud entre una implementación multi-clúster y una implementación de clúster único. Un única implementación de clúster con spec.topology y spec.applicationDatabase.topology configurados en MultiCluster prepara la implementación para añadir más clústeres de Kubernetes.

  5. Implemente un conjunto de réplicas adicional de la base de datos de la aplicación en el segundo nodo del clúster de Kubernetes para mejorar la resiliencia de la base de datos de la aplicación. También implementa una instancia adicional de la aplicación de Ops Manager en el segundo nodo del clúster de Kubernetes.

  6. Cree certificados válidos para el cifrado TLS y establezca conexiones cifradas con TLShacia y desde la aplicación de Ops Manager y entre los nodos del set de réplicas de la base de datos de la aplicación. Cuando se ejecuta sobre HTTPS, Ops Manager se ejecuta en el puerto 8443 por defecto.

  7. Habilite la copia de seguridad utilizando almacenamiento compatible con S3e implemente el daemon de copias de seguridad en el tercer clúster de Kubernetes de nodo. Para simplificar la configuración de cubos de almacenamiento compatibles con S3, implemente el MinIO operador. Habilita el daemon de copias de seguridad solo en un clúster de nodos en su implementación. Sin embargo, también puede configurar otros clústeres de nodos para host los recursos del daemon de copias de seguridad. Solo se admiten copias de seguridad S3 en implementaciones de clúster múltiple de MongoDB Ops Manager.

Antes de que pueda iniciar la implementación, instale las siguientes herramientas requeridas:

Instalar la CLI de gcloud y autorizarla:

gcloud auth login

El plugin kubectl mongodb automatiza la configuración de los clústeres de Kubernetes. Esto permite al operador de Kubernetes implementar recursos, funciones necesarias y servicios para las cuentas de la aplicación Ops Manager, la base de datos de la aplicación y los recursos de MongoDB en estos clústeres.

Para instalar el plugin kubectl mongodb:

1

Descargue la versión deseada del paquete del operador de Kubernetes desde la Página de lanzamiento del Repositorio del operador MongoDB Controllers for Kubernetes.

El nombre del paquete utiliza este patrón: kubectl-mongodb_{{ .Version }}_{{ .Os }}_{{ .Arch }}.tar.gz.

Utilice uno de los siguientes paquetes:

  • kubectl-mongodb_{{ .Version }}_darwin_amd64.tar.gz

  • kubectl-mongodb_{{ .Version }}_darwin_arm64.tar.gz

  • kubectl-mongodb_{{ .Version }}_linux_amd64.tar.gz

  • kubectl-mongodb_{{ .Version }}_linux_arm64.tar.gz

2

Desempaqueta el paquete, como en el siguiente ejemplo:

tar -zxvf kubectl-mongodb_<version>_darwin_amd64.tar.gz
3

Encuentra el binario kubectl-mongodb en el directorio desenpaquetado y muévelo a su destino deseado, dentro del PATH para el usuario del Operador de Kubernetes, como se muestra en el siguiente ejemplo:

mv kubectl-mongodb /usr/local/bin/kubectl-mongodb

Ahora puedes ejecutar el plugin kubectl mongodb usando los siguientes comandos:

kubectl mongodb multicluster setupkubectl mongodb multicluster recover

Para obtener más información sobre los flags compatibles, consulte la Referencia de MongoDB kubectl plugin.

Clonar el repositorio de Controladores de MongoDB para Kubernetes operador, cambiar al directorio mongodb-kubernetes y obtener la versión actual.

git clone https://github.com/mongodb/mongodb-kubernetes.gitcd mongodb-kubernetesgit checkout 1.6.1cd public/architectures

Importante

Algunos pasos en esta guía solo funcionan si se ejecutan desde el directorio public/samples/ops-manager-multi-cluster.

Todos los pasos en esta guía hacen referencia a las variables de entorno definidas en env_variables.sh.

export MDB_GKE_PROJECT="### Set your GKE project name here ###" export NAMESPACE="mongodb"export OPERATOR_NAMESPACE="mongodb-operator" # comma-separated key=value pairs# export OPERATOR_ADDITIONAL_HELM_VALUES="" # Adjust the values for each Kubernetes cluster in your deployment.# The deployment script references the following variables to get values for each cluster.export K8S_CLUSTER_0="k8s-mdb-0"export K8S_CLUSTER_0_ZONE="europe-central2-a"export K8S_CLUSTER_0_NUMBER_OF_NODES=3export K8S_CLUSTER_0_MACHINE_TYPE="e2-standard-4"export K8S_CLUSTER_0_CONTEXT_NAME="gke_${MDB_GKE_PROJECT}_${K8S_CLUSTER_0_ZONE}_${K8S_CLUSTER_0}" export K8S_CLUSTER_1="k8s-mdb-1"export K8S_CLUSTER_1_ZONE="europe-central2-b"export K8S_CLUSTER_1_NUMBER_OF_NODES=3export K8S_CLUSTER_1_MACHINE_TYPE="e2-standard-4"export K8S_CLUSTER_1_CONTEXT_NAME="gke_${MDB_GKE_PROJECT}_${K8S_CLUSTER_1_ZONE}_${K8S_CLUSTER_1}" export K8S_CLUSTER_2="k8s-mdb-2"export K8S_CLUSTER_2_ZONE="europe-central2-c"export K8S_CLUSTER_2_NUMBER_OF_NODES=1export K8S_CLUSTER_2_MACHINE_TYPE="e2-standard-4"export K8S_CLUSTER_2_CONTEXT_NAME="gke_${MDB_GKE_PROJECT}_${K8S_CLUSTER_2_ZONE}_${K8S_CLUSTER_2}" # Comment out the following line so that the script does not create preemptible nodes.# DO NOT USE preemptible nodes in production.export GKE_SPOT_INSTANCES_SWITCH="--preemptible" export S3_OPLOG_BUCKET_NAME=s3-oplog-storeexport S3_SNAPSHOT_BUCKET_NAME=s3-snapshot-store # minio defaultsexport S3_ENDPOINT="minio.tenant-tiny.svc.cluster.local"export S3_ACCESS_KEY="console"export S3_SECRET_KEY="console123" export OFFICIAL_OPERATOR_HELM_CHART="mongodb/mongodb-kubernetes"export OPERATOR_HELM_CHART="${OFFICIAL_OPERATOR_HELM_CHART}" # (Optional) Change the following setting when using the external URL.# This env variable is used in OpenSSL configuration to generate# server certificates for Ops Manager Application.export OPS_MANAGER_EXTERNAL_DOMAIN="om-svc.${NAMESPACE}.svc.cluster.local" export OPS_MANAGER_VERSION="7.0.4"export APPDB_VERSION="7.0.9-ubi8"

Ajusta la configuración en el ejemplo anterior según tus necesidades, tal como se indica en los comentarios, y cárgala en tu shell de la siguiente manera:

source env_variables.sh

Importante

Cada vez que actualices env_variables.sh, ejecuta source env_variables.sh para garantizar que los scripts en esta sección utilicen variables actualizadas.

Este procedimiento se aplica al despliegue de una instancia de Ops Manager en múltiples clústeres de Kubernetes.

1

Puedes omitir este paso si ya tienes instalados y configurados tus propios clústeres de Kubernetes con una malla de servicios.

  1. Crea tres clústeres de GKE (Google Kubernetes Engine):

    gcloud container clusters create "${K8S_CLUSTER_0}" \ --zone="${K8S_CLUSTER_0_ZONE}" \ --num-nodes="${K8S_CLUSTER_0_NUMBER_OF_NODES}" \ --machine-type "${K8S_CLUSTER_0_MACHINE_TYPE}" \ ${GKE_SPOT_INSTANCES_SWITCH:-""}
    gcloud container clusters create "${K8S_CLUSTER_1}" \ --zone="${K8S_CLUSTER_1_ZONE}" \ --num-nodes="${K8S_CLUSTER_1_NUMBER_OF_NODES}" \ --machine-type "${K8S_CLUSTER_1_MACHINE_TYPE}" \ ${GKE_SPOT_INSTANCES_SWITCH:-""}
    gcloud container clusters create "${K8S_CLUSTER_2}" \ --zone="${K8S_CLUSTER_2_ZONE}" \ --num-nodes="${K8S_CLUSTER_2_NUMBER_OF_NODES}" \ --machine-type "${K8S_CLUSTER_2_MACHINE_TYPE}" \ ${GKE_SPOT_INSTANCES_SWITCH:-""}
  2. Establezca su proyecto gcloud por defecto:

    gcloud config set project "${MDB_GKE_PROJECT}"
  3. Obtén credenciales y guarda los contextos en el archivo kubeconfig actual. Por defecto, este archivo se encuentra en el directorio ~/.kube/config y es referenciado por el $KUBECONFIG variable de entorno.

    gcloud container clusters get-credentials "${K8S_CLUSTER_0}" --zone="${K8S_CLUSTER_0_ZONE}"gcloud container clusters get-credentials "${K8S_CLUSTER_1}" --zone="${K8S_CLUSTER_1_ZONE}"gcloud container clusters get-credentials "${K8S_CLUSTER_2}" --zone="${K8S_CLUSTER_2_ZONE}"

    Todos los comandos de kubectl hacen referencia a estos contextos usando las siguientes variables:

    • $K8S_CLUSTER_0_CONTEXT_NAME

    • $K8S_CLUSTER_1_CONTEXT_NAME

    • $K8S_CLUSTER_2_CONTEXT_NAME

  4. Verifica que kubectl tenga acceso a los clústeres de Kubernetes:

    echo "Nodes in cluster ${K8S_CLUSTER_0_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" get nodesecho; echo "Nodes in cluster ${K8S_CLUSTER_1_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" get nodesecho; echo "Nodes in cluster ${K8S_CLUSTER_2_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" get nodes
  5. Instale Istio la service mesh para permitir la resolución cruzada de DNS y la conectividad de red entre clústeres de Kubernetes:

    CTX_CLUSTER1=${K8S_CLUSTER_0_CONTEXT_NAME} \CTX_CLUSTER2=${K8S_CLUSTER_1_CONTEXT_NAME} \CTX_CLUSTER3=${K8S_CLUSTER_2_CONTEXT_NAME} \ISTIO_VERSION="1.20.2" \../multi-cluster/install_istio_separate_network.sh
2

Nota

Para habilitar la inyección sidecar en Istio, los siguientes comandos añaden las etiquetas istio-injection=enabled a los espacios de nombres $OPERATOR_NAMESPACE y mongodb en cada clúster nodo. Si utilizas otra malla de servicios, configúrala para gestionar el tráfico de red en los espacios de nombres creados.

  • Cree un namespace separado, mongodb-operator, referenciado por la $OPERATOR_NAMESPACE variable de entorno para la implementación del operador de Kubernetes.

  • Cree el mismo $OPERATOR_NAMESPACE en cada clúster de nodo de Kubernetes. Esto es necesario para que el plugin kubectl MongoDB plugin pueda crear una cuenta de servicio para el operador de Kubernetes en cada clúster nodo. El Operador de Kubernetes utiliza estas cuentas de servicio en el clúster del operador para ejecutar operaciones en cada clúster nodo.

    kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" create namespace "${OPERATOR_NAMESPACE}"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" label namespace "${OPERATOR_NAMESPACE}" istio-injection=enabled --overwrite kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" create namespace "${OPERATOR_NAMESPACE}"kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" label namespace "${OPERATOR_NAMESPACE}" istio-injection=enabled --overwrite kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" create namespace "${OPERATOR_NAMESPACE}"kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" label namespace "${OPERATOR_NAMESPACE}" istio-injection=enabled --overwrite
  • En cada clúster de nodo, incluido el clúster de nodo que sirve como clúster central, cree otro namespace independiente, mongodb. El operador de Kubernetes utiliza este namespace para los recursos y componentes de Ops Manager.

    kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" create namespace "${NAMESPACE}"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" label namespace "${NAMESPACE}" istio-injection=enabled --overwrite kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" create namespace "${NAMESPACE}"kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" label namespace "${NAMESPACE}" istio-injection=enabled --overwrite kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" create namespace "${NAMESPACE}"kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" label namespace "${NAMESPACE}" istio-injection=enabled --overwrite
3

Este paso es opcional si utilizas gráficas e imágenes oficiales de Helm provenientes del registro Quay.

kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OPERATOR_NAMESPACE}" create secret generic "image-registries-secret" \ --from-file=.dockerconfigjson="${HOME}/.docker/config.json" --type=kubernetes.io/dockerconfigjsonkubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" create secret generic "image-registries-secret" \ --from-file=.dockerconfigjson="${HOME}/.docker/config.json" --type=kubernetes.io/dockerconfigjsonkubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" create secret generic "image-registries-secret" \ --from-file=.dockerconfigjson="${HOME}/.docker/config.json" --type=kubernetes.io/dockerconfigjsonkubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" create secret generic "image-registries-secret" \ --from-file=.dockerconfigjson="${HOME}/.docker/config.json" --type=kubernetes.io/dockerconfigjson
4

Los siguientes scripts opcionales verifican si el service mesh está configurado correctamente para la resolución de DNS entre clústeres y la conectividad.

  1. Ejecute este script en el clúster 0:

    kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOF apiVersion: apps/v1 kind: StatefulSet metadata: name: echoserver0 spec: replicas: 1 selector: matchLabels: app: echoserver0 template: metadata: labels: app: echoserver0 spec: containers: - image: k8s.gcr.io/echoserver:1.10 imagePullPolicy: Always name: echoserver0 ports: - containerPort: 8080EOF
  2. Ejecute este script en el clúster 1:

    kubectl apply --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOF apiVersion: apps/v1 kind: StatefulSet metadata: name: echoserver1 spec: replicas: 1 selector: matchLabels: app: echoserver1 template: metadata: labels: app: echoserver1 spec: containers: - image: k8s.gcr.io/echoserver:1.10 imagePullPolicy: Always name: echoserver1 ports: - containerPort: 8080EOF
  3. Ejecute este script en el clúster 2:

    kubectl apply --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOF apiVersion: apps/v1 kind: StatefulSet metadata: name: echoserver2 spec: replicas: 1 selector: matchLabels: app: echoserver2 template: metadata: labels: app: echoserver2 spec: containers: - image: k8s.gcr.io/echoserver:1.10 imagePullPolicy: Always name: echoserver2 ports: - containerPort: 8080EOF
  4. Ejecuta este script para esperar la creación de StatefulSets:

    kubectl wait --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" --for=condition=ready pod -l statefulset.kubernetes.io/pod-name=echoserver0-0 --timeout=60skubectl wait --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" --for=condition=ready pod -l statefulset.kubernetes.io/pod-name=echoserver1-0 --timeout=60skubectl wait --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" --for=condition=ready pod -l statefulset.kubernetes.io/pod-name=echoserver2-0 --timeout=60s
  5. Crea un servicio de Pods en el clúster 0:

    kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: v1kind: Servicemetadata: name: echoserver0-0spec: ports: - port: 8080 targetPort: 8080 protocol: TCP selector: statefulset.kubernetes.io/pod-name: "echoserver0-0"EOF
  6. Crea un servicio de Pods en el clúster 1:

    kubectl apply --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: v1kind: Servicemetadata: name: echoserver1-0spec: ports: - port: 8080 targetPort: 8080 protocol: TCP selector: statefulset.kubernetes.io/pod-name: "echoserver1-0"EOF
  7. Crea un servicio de Pods en el clúster 2:

    kubectl apply --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: v1kind: Servicemetadata: name: echoserver2-0spec: ports: - port: 8080 targetPort: 8080 protocol: TCP selector: statefulset.kubernetes.io/pod-name: "echoserver2-0"EOF
  8. Crear un servicio round robin en el clúster 0:

    kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: v1kind: Servicemetadata: name: echoserverspec: ports: - port: 8080 targetPort: 8080 protocol: TCP selector: app: echoserver0EOF
  9. Crear un servicio round robin en el clúster 1:

    kubectl apply --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: v1kind: Servicemetadata: name: echoserverspec: ports: - port: 8080 targetPort: 8080 protocol: TCP selector: app: echoserver1EOF
  10. Crear un servicio round robin en el clúster 2:

    kubectl apply --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: v1kind: Servicemetadata: name: echoserverspec: ports: - port: 8080 targetPort: 8080 protocol: TCP selector: app: echoserver2EOF
  11. Verifica el Pod 0 del clúster 1:

    source_cluster=${K8S_CLUSTER_1_CONTEXT_NAME}target_pod="echoserver0-0"source_pod="echoserver1-0"target_url="http://${target_pod}.${NAMESPACE}.svc.cluster.local:8080"echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"out=$(kubectl exec --context "${source_cluster}" -n "${NAMESPACE}" "${source_pod}" -- \ /bin/bash -c "curl -v ${target_url}" 2>&1);grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}" && echo "SUCCESS" || (echo "ERROR: ${out}" && return 1)
  12. Verifica el Pod 1 del clúster 0:

    source_cluster=${K8S_CLUSTER_0_CONTEXT_NAME}target_pod="echoserver1-0"source_pod="echoserver0-0"target_url="http://${target_pod}.${NAMESPACE}.svc.cluster.local:8080"echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"out=$(kubectl exec --context "${source_cluster}" -n "${NAMESPACE}" "${source_pod}" -- \ /bin/bash -c "curl -v ${target_url}" 2>&1);grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}" && echo "SUCCESS" || (echo "ERROR: ${out}" && return 1)
  13. Verifica el Pod 1 del clúster 2:

    source_cluster=${K8S_CLUSTER_2_CONTEXT_NAME}target_pod="echoserver1-0"source_pod="echoserver2-0"target_url="http://${target_pod}.${NAMESPACE}.svc.cluster.local:8080"echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"out=$(kubectl exec --context "${source_cluster}" -n "${NAMESPACE}" "${source_pod}" -- \ /bin/bash -c "curl -v ${target_url}" 2>&1);grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}" && echo "SUCCESS" || (echo "ERROR: ${out}" && return 1)
  1. Verifica el Pod 2 del clúster 0:

    source_cluster=${K8S_CLUSTER_0_CONTEXT_NAME}target_pod="echoserver2-0"source_pod="echoserver0-0"target_url="http://${target_pod}.${NAMESPACE}.svc.cluster.local:8080"echo "Checking cross-cluster DNS resolution and connectivity from ${source_pod} in ${source_cluster} to ${target_pod}"out=$(kubectl exec --context "${source_cluster}" -n "${NAMESPACE}" "${source_pod}" -- \ /bin/bash -c "curl -v ${target_url}" 2>&1);grep "Hostname: ${target_pod}" &>/dev/null <<< "${out}" && echo "SUCCESS" || (echo "ERROR: ${out}" && return 1)
  2. Ejecute el script de limpieza:

    kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" delete statefulset echoserver0kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" delete statefulset echoserver1kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" delete statefulset echoserver2kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" delete service echoserverkubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" delete service echoserverkubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" delete service echoserverkubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" delete service echoserver0-0kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" delete service echoserver1-0kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" delete service echoserver2-0
5

En este paso, utilizas el plugin kubectl mongodb para automatizar la configuración del clúster de Kubernetes, que es necesaria para que el operador de Kubernetes gestione cargas de trabajo en varios clústeres de Kubernetes.

Debido a que configuras los clústeres de Kubernetes antes de instalar el operador de Kubernetes, cuando implementas el operador de Kubernetes para la operación de clústeres múltiples de Kubernetes, toda la configuración necesaria para multi-clúster ya está en su lugar.

Como se indica en la Introducción, el Operador Kubernetes tiene la configuración para tres clústeres nodos que puedes usar para implementar bases de datos de MongoDB en Ops Manager. El primer clúster también se utiliza como clúster central, donde se instala el operador de Kubernetes y se implementan los recursos personalizados.

kubectl mongodb multicluster setup \ --central-cluster="${K8S_CLUSTER_0_CONTEXT_NAME}" \ --member-clusters="${K8S_CLUSTER_0_CONTEXT_NAME},${K8S_CLUSTER_1_CONTEXT_NAME},${K8S_CLUSTER_2_CONTEXT_NAME}" \ --member-cluster-namespace="${NAMESPACE}" \ --central-cluster-namespace="${OPERATOR_NAMESPACE}" \ --create-service-account-secrets \ --install-database-roles=true \ --image-pull-secrets=image-registries-secret
6
  1. Añade y actualiza el repositorio Helm de MongoDB. Verifica que la caché local de Helm haga referencia a la versión correcta del operador de Kubernetes:

    helm repo add mongodb https://mongodb.github.io/helm-chartshelm repo update mongodbhelm search repo "${OFFICIAL_OPERATOR_HELM_CHART}"
  2. Instale el Operador de Kubernetes en el $OPERATOR_NAMESPACE, configurado para supervisar $NAMESPACE y gestionar tres clústeres de Kubernetes nodos. En este punto del procedimiento, ServiceAccounts y roles ya están implementados por el kubectl mongodb plugin. Por lo tanto, los siguientes scripts omiten configurarlos y establecen operator.createOperatorServiceAccount=false y operator.createResourcesServiceAccountsAndRoles=false. Los scripts especifican la configuración multiCluster.clusters para indicar que la gráfica de Helm debe implementar el Operador de Kubernetes en modo multi-cluster.

    helm upgrade --install \ --debug \ --kube-context "${K8S_CLUSTER_0_CONTEXT_NAME}" \ mongodb-kubernetes-operator-multi-cluster \ "${OPERATOR_HELM_CHART}" \ --namespace="${OPERATOR_NAMESPACE}" \ --set namespace="${OPERATOR_NAMESPACE}" \ --set operator.namespace="${OPERATOR_NAMESPACE}" \ --set operator.watchNamespace="${NAMESPACE}" \ --set operator.name=mongodb-kubernetes-operator-multi-cluster \ --set operator.createOperatorServiceAccount=false \ --set operator.createResourcesServiceAccountsAndRoles=false \ --set "multiCluster.clusters={${K8S_CLUSTER_0_CONTEXT_NAME},${K8S_CLUSTER_1_CONTEXT_NAME},${K8S_CLUSTER_2_CONTEXT_NAME}}" \ --set "${OPERATOR_ADDITIONAL_HELM_VALUES:-"dummy=value"}"
  3. Verifica la implementación de Kubernetes Operator:

    kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OPERATOR_NAMESPACE}" rollout status deployment/mongodb-kubernetes-operator-multi-clusterecho "Operator deployment in ${OPERATOR_NAMESPACE} namespace"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OPERATOR_NAMESPACE}" get deploymentsecho; echo "Operator pod in ${OPERATOR_NAMESPACE} namespace"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${OPERATOR_NAMESPACE}" get pods
7

En este paso, habilita TLS para la base de datos de la aplicación y la aplicación MongoDB Ops Manager. Si no desea utilizar TLS, remueva los siguientes campos de los recursos MongoDBOpsManager:

  1. opcional. Generar claves y certificados:

    Utiliza la herramienta de línea de comandos openssl para generar ACs y certificados autofirmados con fines de prueba.

    mkdir certs || true cat <<EOF >certs/ca.cnf[ req ]default_bits = 2048prompt = nodefault_md = sha256distinguished_name = dnx509_extensions = v3_ca [ dn ]C=USST=New YorkL=New YorkO=Example CompanyOU=IT DepartmentCN=exampleCA [ v3_ca ]basicConstraints = CA:TRUEkeyUsage = critical, keyCertSign, cRLSignsubjectKeyIdentifier = hashauthorityKeyIdentifier = keyid:always,issuerEOF cat <<EOF >certs/om.cnf[ req ]default_bits = 2048prompt = nodefault_md = sha256distinguished_name = dnreq_extensions = req_ext [ dn ]C=USST=New YorkL=New YorkO=Example CompanyOU=IT DepartmentCN=${OPS_MANAGER_EXTERNAL_DOMAIN} [ req_ext ]subjectAltName = @alt_nameskeyUsage = critical, digitalSignature, keyEnciphermentextendedKeyUsage = serverAuth, clientAuth [ alt_names ]DNS.1 = ${OPS_MANAGER_EXTERNAL_DOMAIN}DNS.2 = om-svc.${NAMESPACE}.svc.cluster.localEOF cat <<EOF >certs/appdb.cnf[ req ]default_bits = 2048prompt = nodefault_md = sha256distinguished_name = dnreq_extensions = req_ext [ dn ]C=USST=New YorkL=New YorkO=Example CompanyOU=IT DepartmentCN=AppDB [ req_ext ]subjectAltName = @alt_nameskeyUsage = critical, digitalSignature, keyEnciphermentextendedKeyUsage = serverAuth, clientAuth [ alt_names ]# multi-cluster mongod hostnames from service for each podDNS.1 = *.${NAMESPACE}.svc.cluster.local# single-cluster mongod hostnames from headless serviceDNS.2 = *.om-db-svc.${NAMESPACE}.svc.cluster.localEOF # generate CA keypair and certificateopenssl genrsa -out certs/ca.key 2048openssl req -x509 -new -nodes -key certs/ca.key -days 1024 -out certs/ca.crt -config certs/ca.cnf # generate OpsManager's keypair and certificateopenssl genrsa -out certs/om.key 2048openssl req -new -key certs/om.key -out certs/om.csr -config certs/om.cnf # generate AppDB's keypair and certificateopenssl genrsa -out certs/appdb.key 2048openssl req -new -key certs/appdb.key -out certs/appdb.csr -config certs/appdb.cnf # generate certificates signed by CA for OpsManager and AppDBopenssl x509 -req -in certs/om.csr -CA certs/ca.crt -CAkey certs/ca.key -CAcreateserial -out certs/om.crt -days 365 -sha256 -extfile certs/om.cnf -extensions req_extopenssl x509 -req -in certs/appdb.csr -CA certs/ca.crt -CAkey certs/ca.key -CAcreateserial -out certs/appdb.crt -days 365 -sha256 -extfile certs/appdb.cnf -extensions req_ext
  2. Crea secretos con claves TLS:

    Si prefieres usar tus propias claves y certificados, omite el paso anterior de generación y coloca las claves y certificados en los siguientes archivos:

    • certs/ca.crt - Certificados CA. estos no son necesarios al utilizar certificados de confianza.

    • certs/appdb.key - llave privada para la base de datos de la aplicación.

    • certs/appdb.crt - Certificado para la base de datos de la aplicación.

    • certs/om.key - clave privada para Ops Manager.

    • certs/om.crt - certificado para Ops Manager.

    kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" create secret tls cert-prefix-om-cert \ --cert=certs/om.crt \ --key=certs/om.key kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" create secret tls cert-prefix-om-db-cert \ --cert=certs/appdb.crt \ --key=certs/appdb.key kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" create configmap om-cert-ca --from-file="mms-ca.crt=certs/ca.crt"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" create configmap appdb-cert-ca --from-file="ca-pem=certs/ca.crt"
8

En este punto, se ha preparado el entorno y el operador de Kubernetes para implementar el recurso Ops Manager.

  1. Crea las credenciales necesarias para el usuario administrador de Ops Manager que creará el operador de Kubernetes después de implementar la instancia de Ops Manager aplicación:

    kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" --namespace "${NAMESPACE}" create secret generic om-admin-user-credentials \ --from-literal=Username="admin" \ --from-literal=Password="Passw0rd@" \ --from-literal=FirstName="Jane" \ --from-literal=LastName="Doe"
  2. Implemente el recurso personalizado más simple de MongoDBOpsManager posible (con TLS activado) en un clúster de un solo nodo, que también se conoce como el clúster central.

    Esta implementación es casi igual que para el modo de un solo clúster, pero con spec.topology y spec.applicationDatabase.topology configurados en MultiCluster.

    Implementar de esta manera muestra que la implementación de un solo clúster de Kubernetes es un caso especial de implementación de clústeres multi-Kubernetes en un solo clúster nodo de Kubernetes. Puedes iniciar la implementación de la aplicación de Ops Manager y la base de datos de la aplicación en tantos clústeres de Kubernetes como sea necesario desde el principio, y no es necesario que comiences la implementación con un único clúster nodo de Kubernetes.

    En este punto, ya deberías haber preparado la implementación de Ops Manager para expandirse a más de un clúster de Kubernetes, lo cual harás más adelante en este procedimiento.

    kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: mongodb.com/v1kind: MongoDBOpsManagermetadata: name: omspec: topology: MultiCluster version: "${OPS_MANAGER_VERSION}" adminCredentials: om-admin-user-credentials security: certsSecretPrefix: cert-prefix tls: ca: om-cert-ca clusterSpecList: - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}" members: 1 applicationDatabase: version: "${APPDB_VERSION}" topology: MultiCluster security: certsSecretPrefix: cert-prefix tls: ca: appdb-cert-ca clusterSpecList: - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}" members: 3 backup: enabled: falseEOF
  3. Espera a que el operador de Kubernetes recoja el trabajo y alcance el estado status.applicationDatabase.phase=Pending. Espera a que se completen tanto la base de datos de la aplicación como las implementaciones de Ops Manager.

    echo "Waiting for Application Database to reach Pending phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Pending opsmanager/om --timeout=30s
  4. Implementa Ops Manager. El Operador de Kubernetes implementa Ops Manager realizando los siguientes pasos. It:

    • Implementa los nodos del set de réplicas de la Base de datos de la aplicación y espera que los procesos de MongoDB en el set de réplicas comiencen a ejecutarse.

    • Implementa la instancia de la aplicación Ops Manager con la cadena de conexión de la base de datos de la aplicación y espera que esté lista.

    • Agrega los contenedores de supervisión de MongoDB Agent a cada pod de la base de datos de la aplicación.

    • Espera que tanto la aplicación Ops Manager como los pods de la base de datos de la aplicación comiencen a ejecutarse.

    echo "Waiting for Application Database to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=900secho; echo "Waiting for Ops Manager to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Running opsmanager/om --timeout=900secho; echo "Waiting for Application Database to reach Pending phase (enabling monitoring)..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=900secho "Waiting for Application Database to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=900secho; echo "Waiting for Ops Manager to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Running opsmanager/om --timeout=900secho; echo "MongoDBOpsManager resource"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" get opsmanager/omecho; echo "Pods running in cluster ${K8S_CLUSTER_0_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" get podsecho; echo "Pods running in cluster ${K8S_CLUSTER_1_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" get pods

    Ahora que ha desplegado un clúster de un solo nodo en un modo multiclúster, puede volver a configurar esta implementación para abarcar más de un clúster de Kubernetes.

  5. En el segundo clúster de miembros, implemente dos miembros adicionales del set de réplicas de la base de datos de la aplicación y una instancia adicional de la aplicación de Ops Manager:

    kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: mongodb.com/v1kind: MongoDBOpsManagermetadata: name: omspec: topology: MultiCluster version: "${OPS_MANAGER_VERSION}" adminCredentials: om-admin-user-credentials security: certsSecretPrefix: cert-prefix tls: ca: om-cert-ca clusterSpecList: - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}" members: 1 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}" members: 1 applicationDatabase: version: "${APPDB_VERSION}" topology: MultiCluster security: certsSecretPrefix: cert-prefix tls: ca: appdb-cert-ca clusterSpecList: - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}" members: 3 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}" members: 2 backup: enabled: falseEOF
  6. Espera a que el Operador de Kubernetes recoja el trabajo (fase pendiente):

    echo "Waiting for Application Database to reach Pending phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Pending opsmanager/om --timeout=30s
  7. Espera a que Kubernetes operador termine de implementar todos los componentes:

    echo "Waiting for Application Database to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=600secho; echo "Waiting for Ops Manager to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Running opsmanager/om --timeout=600secho; echo "MongoDBOpsManager resource"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" get opsmanager/omecho; echo "Pods running in cluster ${K8S_CLUSTER_0_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" get podsecho; echo "Pods running in cluster ${K8S_CLUSTER_1_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" get pods
9

En una implementación multi-Kubernetes de la aplicación Ops Manager, solo puedes configurar almacenamiento de copia de seguridad basado en S3. Este procedimiento se refiere a S3_* definido en env_variables.sh.

  1. opcional. Instala el Operador MinIO.

    Este procedimiento implementa almacenamiento compatible con S3para sus copias de seguridad mediante el MinIO operador. Puede omitir este paso si tiene AWS S3 u otros buckets compatibles con S3disponibles. Ajuste las S3_* variables en consecuencia en env_variables.sh en este caso.

    kubectl kustomize "github.com/minio/operator/resources/?timeout=120&ref=v5.0.12" | \ kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" apply -f - kubectl kustomize "github.com/minio/operator/examples/kustomization/tenant-tiny?timeout=120&ref=v5.0.12" | \ kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" apply -f - # add two buckets to the tenant configkubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "tenant-tiny" patch tenant/myminio \ --type='json' \ -p="[{\"op\": \"add\", \"path\": \"/spec/buckets\", \"value\": [{\"name\": \"${S3_OPLOG_BUCKET_NAME}\"}, {\"name\": \"${S3_SNAPSHOT_BUCKET_NAME}\"}]}]"
  2. Antes de configurar y habilitar la copia de seguridad, crea secretos:

    • s3-access-secret - contiene S3 credenciales.

    • s3-ca-cert - contiene un certificado CA que emitió el certificado de servidor del bucket. En el caso de la muestra MinIO implementación utilizado en este procedimiento, se utiliza el certificado por defecto de Kubernetes Root CA para firmar el certificado. Debido a que no es un certificado de CA de confianza pública, debe proporcionarlo para que Ops Manager pueda confiar en la conexión.

    Si usás certificados de confianza pública, podés omitir este paso y remover los valores de las configuraciones de spec.backup.s3Stores.customCertificateSecretRefs y spec.backup.s3OpLogStores.customCertificateSecretRefs.

    kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" create secret generic s3-access-secret \ --from-literal=accessKey="${S3_ACCESS_KEY}" \ --from-literal=secretKey="${S3_SECRET_KEY}" # minio TLS secrets are signed with the default k8s root CAkubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" create secret generic s3-ca-cert \ --from-literal=ca.crt="$(kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n kube-system get configmap kube-root-ca.crt -o jsonpath="{.data.ca\.crt}")"
10
  1. El operador de Kubernetes puede configurar e implementar todos los componentes, la aplicación Ops Manager, las instancias del daemon de copias de seguridad y los nodos del set de réplicas de la base de datos de la aplicación en cualquier combinación en cualquier clúster miembro para los cuales configure el operador de Kubernetes.

    Para ilustrar la flexibilidad de la configuración de implementación de clústeres múltiples de Kubernetes, se debe implementar solo una instancia del daemon de copias de seguridad en el tercer clúster nodo y se debe especificar cero nodos de daemon de copias de seguridad para el primer y segundo clúster.

    kubectl apply --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" -f - <<EOFapiVersion: mongodb.com/v1kind: MongoDBOpsManagermetadata: name: omspec: topology: MultiCluster version: "${OPS_MANAGER_VERSION}" adminCredentials: om-admin-user-credentials security: certsSecretPrefix: cert-prefix tls: ca: om-cert-ca clusterSpecList: - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}" members: 1 backup: members: 0 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}" members: 1 backup: members: 0 - clusterName: "${K8S_CLUSTER_2_CONTEXT_NAME}" members: 0 backup: members: 1 configuration: # to avoid configuration wizard on first login mms.adminEmailAddr: email@example.com mms.fromEmailAddr: email@example.com mms.ignoreInitialUiSetup: "true" mms.mail.hostname: smtp@example.com mms.mail.port: "465" mms.mail.ssl: "true" mms.mail.transport: smtp mms.minimumTLSVersion: TLSv1.2 mms.replyToEmailAddr: email@example.com applicationDatabase: version: "${APPDB_VERSION}" topology: MultiCluster security: certsSecretPrefix: cert-prefix tls: ca: appdb-cert-ca clusterSpecList: - clusterName: "${K8S_CLUSTER_0_CONTEXT_NAME}" members: 3 - clusterName: "${K8S_CLUSTER_1_CONTEXT_NAME}" members: 2 backup: enabled: true s3Stores: - name: my-s3-block-store s3SecretRef: name: "s3-access-secret" pathStyleAccessEnabled: true s3BucketEndpoint: "${S3_ENDPOINT}" s3BucketName: "${S3_SNAPSHOT_BUCKET_NAME}" customCertificateSecretRefs: - name: s3-ca-cert key: ca.crt s3OpLogStores: - name: my-s3-oplog-store s3SecretRef: name: "s3-access-secret" s3BucketEndpoint: "${S3_ENDPOINT}" s3BucketName: "${S3_OPLOG_BUCKET_NAME}" pathStyleAccessEnabled: true customCertificateSecretRefs: - name: s3-ca-cert key: ca.crtEOF
  2. Espere hasta que el Operador de Kubernetes finalice su configuración:

    echo; echo "Waiting for Backup to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.backup.phase}'=Running opsmanager/om --timeout=1200secho "Waiting for Application Database to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.applicationDatabase.phase}'=Running opsmanager/om --timeout=600secho; echo "Waiting for Ops Manager to reach Running phase..."kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" wait --for=jsonpath='{.status.opsManager.phase}'=Running opsmanager/om --timeout=600secho; echo "MongoDBOpsManager resource"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" get opsmanager/omecho; echo "Pods running in cluster ${K8S_CLUSTER_0_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_0_CONTEXT_NAME}" -n "${NAMESPACE}" get podsecho; echo "Pods running in cluster ${K8S_CLUSTER_1_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_1_CONTEXT_NAME}" -n "${NAMESPACE}" get podsecho; echo "Pods running in cluster ${K8S_CLUSTER_2_CONTEXT_NAME}"kubectl --context "${K8S_CLUSTER_2_CONTEXT_NAME}" -n "${NAMESPACE}" get pods
11

Ejecutar el siguiente script para borrar los clústeres de GKE y limpiar el entorno.

Importante

Los siguientes comandos no son reversibles. Eliminan todos los clústeres mencionados en env_variables.sh. No ejecutes estos comandos si quieres mantener los clústeres de GKE, por ejemplo, si no creaste los clústeres de GKE como parte de este procedimiento.

yes | gcloud container clusters delete "${K8S_CLUSTER_0}" --zone="${K8S_CLUSTER_0_ZONE}" &yes | gcloud container clusters delete "${K8S_CLUSTER_1}" --zone="${K8S_CLUSTER_1_ZONE}" &yes | gcloud container clusters delete "${K8S_CLUSTER_2}" --zone="${K8S_CLUSTER_2_ZONE}" &wait
Califique esta página