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:
Overview
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ú:
Usa GKE (Google Kubernetes Engine) y Istio como herramientas para demostrar la implementación de clústeres Kubernetes múltiples.
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.
Implemente el clúster central en el
$OPERATOR_NAMESPACEy configure este clúster para supervisar$NAMESPACEy gestionar todos los clústeres de Kubernetes de los nodos.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.topologyyspec.applicationDatabase.topologyconfigurados enMultiClusterprepara la implementación para añadir más clústeres de Kubernetes.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.
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
8443por defecto.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.
Requisitos previos
Instalar Herramientas
Antes de que pueda iniciar la implementación, instale las siguientes herramientas requeridas:
Instalar Helm. Es necesario instalar Helm para la implementación del operador de Kubernetes.
Prepara el Proyecto GCP para que puedas utilizarlo para crear clústeres de GKE (Google Kubernetes motor). En el siguiente procedimiento, creará tres clúster de GKE nuevos, con un total de siete
e2-standard-4de bajo costo Spot VMs.
Autoriza en la CLI de gcloud
Instalar la CLI de gcloud y autorizarla:
gcloud auth loginInstala el plugin kubectl mongodb
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:
Descarga la versión deseada del paquete del operador de Kubernetes.
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.gzkubectl-mongodb_{{ .Version }}_darwin_arm64.tar.gzkubectl-mongodb_{{ .Version }}_linux_amd64.tar.gzkubectl-mongodb_{{ .Version }}_linux_arm64.tar.gz
Localice el archivo binario del plugin kubectl mongodb y cópielo al destino deseado.
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-mongodbAhora puedes ejecutar el plugin kubectl mongodb usando los siguientes comandos:
kubectl mongodb multicluster setupkubectl mongodb multicluster recoverPara obtener más información sobre los flags compatibles, consulte la Referencia de MongoDB kubectl plugin.
Clona el repositorio de MongoDB Controllers for Kubernetes Operator
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.4.0cd public/architecturesImportante
Algunos pasos en esta guía solo funcionan si se ejecutan desde el directorio public/samples/ops-manager-multi-cluster.
Configura variables de entorno
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.shImportante
Cada vez que actualices env_variables.sh, ejecuta source env_variables.sh para garantizar que los scripts en esta sección utilicen variables actualizadas.
Procedimiento
Este procedimiento se aplica al despliegue de una instancia de Ops Manager en múltiples clústeres de Kubernetes.
Crea clústeres de Kubernetes.
Puedes omitir este paso si ya tienes instalados y configurados tus propios clústeres de Kubernetes con una malla de servicios.
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:-""}Establezca su proyecto gcloud por defecto:
gcloud config set project "${MDB_GKE_PROJECT}"Obtén credenciales y guarda los contextos en el archivo
kubeconfigactual. Por defecto, este archivo se encuentra en el directorio~/.kube/configy es referenciado por el$KUBECONFIGvariable 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
kubectlhacen referencia a estos contextos usando las siguientes variables:$K8S_CLUSTER_0_CONTEXT_NAME$K8S_CLUSTER_1_CONTEXT_NAME$K8S_CLUSTER_2_CONTEXT_NAME
Verifica que
kubectltenga 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 nodesInstale 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
Crea namespace.
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_NAMESPACEvariable de entorno para la implementación del operador de Kubernetes.Cree el mismo
$OPERATOR_NAMESPACEen 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 --overwriteEn 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
opcional. Autorizar a los clústeres para extraer secretos de registros de imágenes privados.
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/dockerconfigjsonopcional. Verificar la conectividad del clúster.
Los siguientes scripts opcionales verifican si el service mesh está configurado correctamente para la resolución de DNS entre clústeres y la conectividad.
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: 8080EOFEjecute 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: 8080EOFEjecute 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: 8080EOFEjecuta 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=60sCrea 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"EOFCrea 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"EOFCrea 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"EOFCrear 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: echoserver0EOFCrear 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: echoserver1EOFCrear 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: echoserver2EOFVerifica 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)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)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)
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)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
Implementa una configuración multiclúster.
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-secretInstale el Kubernetes operador usando la chart de Helm.
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}"Instale el Operador de Kubernetes en el
$OPERATOR_NAMESPACE, configurado para supervisar$NAMESPACEy gestionar tres clústeres de Kubernetes nodos. En este punto del procedimiento, ServiceAccounts y roles ya están implementados por elkubectl mongodbplugin. Por lo tanto, los siguientes scripts omiten configurarlos y establecenoperator.createOperatorServiceAccount=falseyoperator.createResourcesServiceAccountsAndRoles=false. Los scripts especifican la configuraciónmultiCluster.clusterspara 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"}"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
Preparar los certificados TLS.
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:
opcional. Generar claves y certificados:
Utiliza la herramienta de línea de comandos
opensslpara 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_extCrea 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"
Instale Ops Manager.
En este punto, se ha preparado el entorno y el operador de Kubernetes para implementar el recurso Ops Manager.
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"Implemente el recurso personalizado más simple de
MongoDBOpsManagerposible (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.topologyyspec.applicationDatabase.topologyconfigurados enMultiCluster.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: falseEOFEspera 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=30sImplementa 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 podsAhora 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.
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: falseEOFEspera 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=30sEspera 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
Habilitar copia de seguridad.
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.
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}\"}]}]"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.customCertificateSecretRefsyspec.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}")"
Vuelve a implementar Ops Manager con la copia de seguridad habilitada.
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.crtEOFEspere 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
Opcional. Elimine los clústeres de GKE (Google Kubernetes Engine) y todos sus recursos asociados (máquinas virtuales).
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