Configurar una malla de varios clústeres en Cloud Service Mesh gestionado
En esta guía se explica cómo unir dos clústeres en una sola malla de servicios de Cloud mediante Mesh CA o Certificate Authority Service y cómo habilitar el balanceo de carga entre clústeres. Puedes ampliar fácilmente este proceso para incorporar cualquier número de clústeres a tu malla.
Una configuración de Cloud Service Mesh de varios clústeres puede resolver varios casos prácticos cruciales para las empresas, como la escalabilidad, la ubicación y el aislamiento. Para obtener más información, consulta Casos prácticos de varios clústeres.
Requisitos previos
En esta guía se da por hecho que tienes dos o más Google Cloud clústeres de GKE que cumplen los siguientes requisitos:
- Cloud Service Mesh instalado en los clústeres. Necesitas
asmcli
, la herramientaistioctl
y muestras queasmcli
descarga en el directorio que has especificado en--output_dir
. - Los clústeres de tu malla deben tener conectividad entre todos los pods antes de configurar Cloud Service Mesh. Además, si unes clústeres que no están en el mismo proyecto, deben registrarse en el mismo proyecto de host de flota y los clústeres deben estar en una configuración de VPC compartida en la misma red. También te recomendamos que tengas un proyecto para alojar la VPC compartida y dos proyectos de servicio para crear clústeres. Para obtener más información, consulta Configurar clústeres con una VPC compartida.
- Si usas el servicio de autoridad de certificación, todos los clústeres deben tener sus respectivas cadenas de grupos de AC subordinadas al mismo grupo de AC raíz. De lo contrario, todos ellos deberán usar el mismo grupo de CAs.
Definir variables de proyecto y de clúster
Crea las siguientes variables de entorno para el ID del proyecto, la zona o la región del clúster, el nombre del clúster y el contexto.
export PROJECT_1=PROJECT_ID_1 export LOCATION_1=CLUSTER_LOCATION_1 export CLUSTER_1=CLUSTER_NAME_1 export CTX_1="gke_${PROJECT_1}_${LOCATION_1}_${CLUSTER_1}" export PROJECT_2=PROJECT_ID_2 export LOCATION_2=CLUSTER_LOCATION_2 export CLUSTER_2=CLUSTER_NAME_2 export CTX_2="gke_${PROJECT_2}_${LOCATION_2}_${CLUSTER_2}"
Si se trata de clústeres recién creados, asegúrate de obtener las credenciales de cada clúster con los siguientes comandos
gcloud
. De lo contrario, loscontext
asociados no estarán disponibles para usarse en los siguientes pasos de esta guía.Los comandos dependen del tipo de clúster, ya sea regional o zonal:
Regional
gcloud container clusters get-credentials ${CLUSTER_1} --region ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --region ${LOCATION_2}
Por zonas
gcloud container clusters get-credentials ${CLUSTER_1} --zone ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --zone ${LOCATION_2}
Crear regla de cortafuegos
En algunos casos, debe crear una regla de cortafuegos para permitir el tráfico entre clústeres. Por ejemplo, debes crear una regla de cortafuegos si:
- Utilizas subredes diferentes para los clústeres de tu malla.
- Tus pods abren puertos distintos de 443 y 15002.
GKE añade automáticamente reglas de cortafuegos a cada nodo para permitir el tráfico dentro de la misma subred. Si tu malla contiene varias subredes, debes configurar explícitamente las reglas de cortafuegos para permitir el tráfico entre subredes. Debes añadir una nueva regla de cortafuegos para cada subred con el fin de permitir los bloques CIDR de IP de origen y los puertos de destino de todo el tráfico entrante.
Las siguientes instrucciones permiten la comunicación entre todos los clústeres de tu proyecto o solo entre $CLUSTER_1
y $CLUSTER_2
.
Recopila información sobre la red de tus clústeres.
Todos los clústeres del proyecto
Si los clústeres están en el mismo proyecto, puedes usar el siguiente comando para permitir la comunicación entre todos los clústeres del proyecto. Si hay clústeres en tu proyecto que no quieres exponer, usa el comando de la pestaña Clústeres específicos.
function join_by { local IFS="$1"; shift; echo "$*"; } ALL_CLUSTER_CIDRS=$(gcloud container clusters list --project $PROJECT_1 --format='value(clusterIpv4Cidr)' | sort | uniq) ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}")) ALL_CLUSTER_NETTAGS=$(gcloud compute instances list --project $PROJECT_1 --format='value(tags.items.[0])' | sort | uniq) ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
Clústeres específicos
El siguiente comando permite la comunicación entre
$CLUSTER_1
y$CLUSTER_2
, y no expone otros clústeres de tu proyecto.function join_by { local IFS="$1"; shift; echo "$*"; } ALL_CLUSTER_CIDRS=$(for P in $PROJECT_1 $PROJECT_2; do gcloud --project $P container clusters list --filter="name:($CLUSTER_1,$CLUSTER_2)" --format='value(clusterIpv4Cidr)'; done | sort | uniq) ALL_CLUSTER_CIDRS=$(join_by , $(echo "${ALL_CLUSTER_CIDRS}")) ALL_CLUSTER_NETTAGS=$(for P in $PROJECT_1 $PROJECT_2; do gcloud --project $P compute instances list --filter="name:($CLUSTER_1,$CLUSTER_2)" --format='value(tags.items.[0])' ; done | sort | uniq) ALL_CLUSTER_NETTAGS=$(join_by , $(echo "${ALL_CLUSTER_NETTAGS}"))
Crea la regla de cortafuegos.
GKE
gcloud compute firewall-rules create istio-multicluster-pods \ --allow=tcp,udp,icmp,esp,ah,sctp \ --direction=INGRESS \ --priority=900 \ --source-ranges="${ALL_CLUSTER_CIDRS}" \ --target-tags="${ALL_CLUSTER_NETTAGS}" --quiet \ --network=YOUR_NETWORK
Autopilot
TAGS="" for CLUSTER in ${CLUSTER_1} ${CLUSTER_2} do TAGS+=$(gcloud compute firewall-rules list --filter="Name:$CLUSTER*" --format="value(targetTags)" | uniq) && TAGS+="," done TAGS=${TAGS::-1} echo "Network tags for pod ranges are $TAGS" gcloud compute firewall-rules create asm-multicluster-pods \ --allow=tcp,udp,icmp,esp,ah,sctp \ --network=gke-cluster-vpc \ --direction=INGRESS \ --priority=900 --network=VPC_NAME \ --source-ranges="${ALL_CLUSTER_CIDRS}" \ --target-tags=$TAGS
Configurar el descubrimiento de endpoints
Habilitar la detección de endpoints entre clústeres públicos o privados con la API declarativa
Si habilitas Cloud Service Mesh gestionado con la API de flota, se habilitará la detección de endpoints en este clúster. Si has aprovisionado Cloud Service Mesh gestionado con otra herramienta, puedes habilitar manualmente la detección de endpoints en clústeres públicos o privados de una flota aplicando la configuración "multicluster_mode":"connected"
en el configmap asm-options
. Los clústeres que tengan esta configuración habilitada en la misma flota tendrán habilitada automáticamente la detección de servicios entre clústeres.
Esta es la única forma de configurar el descubrimiento de endpoints multiclúster si tienes la implementación del plano de control gestionada (TD) y la forma recomendada de configurarlo si tienes la implementación gestionada (Istiod).
Antes de continuar, debe crear una regla de cortafuegos.
Habilitar
Si el configmap asm-options
ya existe en tu clúster, habilita la detección de endpoints del clúster:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"connected"}}'
Si el asm-options
configmap aún no existe en tu clúster, créalo con los datos asociados y habilita la detección de endpoints para el clúster:
kubectl --context ${CTX_1} create configmap asm-options -n istio-system --from-file <(echo '{"data":{"multicluster_mode":"connected"}}')
Inhabilitar
Para inhabilitar la detección de endpoints en un clúster, haz lo siguiente:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"manual"}}'
Si anulas el registro de un clúster de la flota sin inhabilitar el descubrimiento de endpoints, es posible que los secretos permanezcan en el clúster. Debes eliminar manualmente los secretos restantes.
Ejecuta el siguiente comando para buscar secretos que requieran limpieza:
kubectl get secrets -n istio-system -l istio.io/owned-by=mesh.googleapis.com,istio/multiCluster=true
Elimina cada secreto:
kubectl delete secret SECRET_NAME
Repite este paso con cada secreto restante.
Verificar la conectividad entre clústeres
En esta sección se explica cómo desplegar los servicios de ejemplo HelloWorld
y Sleep
en tu entorno multiclúster para verificar que el balanceo de carga entre clústeres funciona.
Definir la variable del directorio de muestras
Ve a la ubicación donde se descargó
asmcli
y ejecuta el siguiente comando para definirASM_VERSION
:export ASM_VERSION="$(./asmcli --version)"
Define una carpeta de trabajo para las muestras que usas para verificar que el balanceo de carga entre clústeres funciona. Las muestras se encuentran en un subdirectorio del directorio
--output_dir
que especificaste en el comandoasmcli install
. En el siguiente comando, cambiaOUTPUT_DIR
por el directorio que hayas especificado en--output_dir
.export SAMPLES_DIR=OUTPUT_DIR/istio-${ASM_VERSION%+*}
Habilitar la inyección de sidecar
Crea el espacio de nombres de ejemplo en cada clúster.
for CTX in ${CTX_1} ${CTX_2} do kubectl create --context=${CTX} namespace sample done
Habilita el espacio de nombres para la inyección. Los pasos dependen de la implementación del plano de control.
Gestionado (TD)
- Aplica la etiqueta de inyección predeterminada al espacio de nombres:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample istio.io/rev- istio-injection=enabled --overwrite done
Gestionado (Istiod)
Recomendación: Ejecuta el siguiente comando para aplicar la etiqueta de inyección predeterminada al espacio de nombres:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio.io/rev- istio-injection=enabled --overwrite done
Si ya eres usuario del plano de control de Istiod gestionado: Te recomendamos que utilices la inyección predeterminada, pero también se admite la inyección basada en revisiones. Sigue estas instrucciones:
Ejecuta el siguiente comando para localizar los canales de lanzamiento disponibles:
kubectl -n istio-system get controlplanerevision
El resultado debería ser similar al siguiente:
NAME AGE asm-managed-rapid 6d7h
En el resultado, el valor de la columna
NAME
es la etiqueta de revisión que corresponde al canal de lanzamiento disponible para la versión de Cloud Service Mesh.Aplica la etiqueta de revisión al espacio de nombres:
for CTX in ${CTX_1} ${CTX_2} do kubectl label --context=${CTX} namespace sample \ istio-injection- istio.io/rev=REVISION_LABEL --overwrite done
Instalar el servicio HelloWorld
Crea el servicio HelloWorld en ambos clústeres:
kubectl create --context=${CTX_1} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l service=helloworld -n sample
kubectl create --context=${CTX_2} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l service=helloworld -n sample
Desplegar HelloWorld v1 y v2 en cada clúster
Implementa
HelloWorld v1
enCLUSTER_1
yv2
enCLUSTER_2
, lo que te ayudará más adelante a verificar el balanceo de carga entre clústeres:kubectl create --context=${CTX_1} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l version=v1 -n sample
kubectl create --context=${CTX_2} \ -f ${SAMPLES_DIR}/samples/helloworld/helloworld.yaml \ -l version=v2 -n sample
Confirma que
HelloWorld v1
yv2
se están ejecutando con los siguientes comandos. Comprueba que el resultado sea similar al que se muestra:kubectl get pod --context=${CTX_1} -n sample
NAME READY STATUS RESTARTS AGE helloworld-v1-86f77cd7bd-cpxhv 2/2 Running 0 40s
kubectl get pod --context=${CTX_2} -n sample
NAME READY STATUS RESTARTS AGE helloworld-v2-758dd55874-6x4t8 2/2 Running 0 40s
Desplegar el servicio de sueño
Despliega el servicio
Sleep
en ambos clústeres. Este pod genera tráfico de red artificial con fines de demostración:for CTX in ${CTX_1} ${CTX_2} do kubectl apply --context=${CTX} \ -f ${SAMPLES_DIR}/samples/sleep/sleep.yaml -n sample done
Espera a que se inicie el servicio
Sleep
en cada clúster. Comprueba que el resultado sea similar al que se muestra:kubectl get pod --context=${CTX_1} -n sample -l app=sleep
NAME READY STATUS RESTARTS AGE sleep-754684654f-n6bzf 2/2 Running 0 5s
kubectl get pod --context=${CTX_2} -n sample -l app=sleep
NAME READY STATUS RESTARTS AGE sleep-754684654f-dzl9j 2/2 Running 0 5s
Verificar el balanceo de carga entre clústeres
Llama al servicio HelloWorld
varias veces y comprueba el resultado para verificar
respuestas alternas de las versiones 1 y 2:
Llama al servicio de
HelloWorld
:kubectl exec --context="${CTX_1}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_1}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'
La salida es similar a la que se muestra a continuación:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
Vuelve a llamar al servicio
HelloWorld
:kubectl exec --context="${CTX_2}" -n sample -c sleep \ "$(kubectl get pod --context="${CTX_2}" -n sample -l \ app=sleep -o jsonpath='{.items[0].metadata.name}')" \ -- /bin/sh -c 'for i in $(seq 1 20); do curl -sS helloworld.sample:5000/hello; done'
La salida es similar a la que se muestra a continuación:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
Enhorabuena, has verificado tu malla de servicios de Cloud con balanceo de carga y varios clústeres.
Limpiar el servicio HelloWorld
Cuando termines de verificar el balanceo de carga, elimina el servicio HelloWorld
y Sleep
de tu clúster.
kubectl delete ns sample --context ${CTX_1} kubectl delete ns sample --context ${CTX_2}