Configura una malla de varios clústeres en Cloud Service Mesh administrado
En esta guía, se explica cómo unir dos clústeres en una sola malla de Cloud Service Mesh mediante la CA de Mesh o Certificate Authority Service, y habilitar el balanceo de cargas entre clústeres. Puedes ampliar con facilidad este proceso para incorporar cualquier cantidad de clústeres en la malla.
Una configuración de Cloud Service Mesh de varios clústeres puede resolver varias situaciones empresariales fundamentales, como el escalamiento, la ubicación y el aislamiento. Para obtener más información, consulta Casos de uso de varios clústeres.
Requisitos previos
En esta guía, se da por hecho que tienes dos o más clústeres de GKE de Google Cloud que cumplen los siguientes requisitos:
- Cloud Service Mesh instalado en los clústeres Necesitas
asmcli
, la herramienta deistioctl
y las muestras queasmcli
descarga en el directorio que especificaste 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 estar registrados en el mismo proyecto host de la flota y los clústeres deben estar en la configuración de una 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 Configura clústeres con VPC compartida.
- Si usas Certificate Authority Service, 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 deberán usar el mismo grupo de AC.
Configura variables de proyecto y clúster
Crea las siguientes variables de entorno para el ID del proyecto, la zona o región del clúster, el nombre y el contexto del clúster.
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 estos clústeres son nuevos, asegúrate de recuperar las credenciales para cada uno con los siguientes comandos de
gcloud
. De lo contrario, sucontext
asociado no estará disponible para su uso en los pasos siguientes 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}
Zonal
gcloud container clusters get-credentials ${CLUSTER_1} --zone ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --zone ${LOCATION_2}
Crear regla de firewall
En algunos casos, debes crear una regla de firewall para permitir el tráfico entre clústeres. Por ejemplo, debes crear una regla de firewall si se cumple lo siguiente:
- Usas subredes diferentes para los clústeres de tu malla.
- Tus Pods abren puertos distintos de 443 y 15002.
GKE agrega automáticamente reglas de firewall 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 firewall para permitir el tráfico entre subredes. Debes agregar una regla de firewall nueva para cada subred a fin de permitir los bloques CIDR de IP de destino 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 deseas exponer, usa el comando en 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 en 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 firewall.
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
Configura la detección de extremos
Habilita el descubrimiento de extremos entre clústeres públicos o privados con la API declarativa
Si habilitas Cloud Service Mesh administrado con la API de Fleet, se habilitará el descubrimiento de extremos para este clúster. Si aprovisionaste Cloud Service Mesh administrado con una herramienta diferente, puedes habilitar manualmente el descubrimiento de extremos en clústeres públicos o privados de una flota aplicando la configuración "multicluster_mode":"connected"
en el configmap de asm-options
. Los clústeres con esta configuración habilitada en la misma flota tendrán habilitado el descubrimiento de servicios entre clústeres de forma automática entre sí.
Esta es la única forma de configurar la detección de extremos de varios clústeres si tienes la implementación del plano de control administrada (TD) y la forma recomendada de configurarla si tienes la implementación administrada (Istiod).
Antes de continuar, debes crear una regla de firewall.
Habilitar
Si el ConfigMap de asm-options
ya existe en tu clúster, habilita el descubrimiento de extremos para el clúster:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"connected"}}'
Si el configmap asm-options
aún no existe en tu clúster, créalo con los datos asociados y habilita el descubrimiento de extremos para el clúster:
kubectl --context ${CTX_1} create configmap asm-options -n istio-system --from-file <(echo '{"data":{"multicluster_mode":"connected"}}')
Inhabilitar
Inhabilita la detección de extremos para un clúster:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"manual"}}'
Si cancelas el registro de un clúster en la flota sin inhabilitar el descubrimiento de extremos, los secretos podrían permanecer en el clúster. Debes limpiar manualmente los secretos restantes.
Ejecuta el siguiente comando para buscar los secretos que requieran limpieza:
kubectl get secrets -n istio-system -l istio.io/owned-by=mesh.googleapis.com,istio/multiCluster=true
Borra cada secreto:
kubectl delete secret SECRET_NAME
Repite este paso para cada secreto restante.
Verifica la conectividad de varios clústeres
En esta sección, se explica cómo implementar los servicios HelloWorld
y Sleep
de muestra en el entorno de varios clústeres para verificar que el balanceo de cargas entre clústeres funcione.
Configura una variable para el directorio de muestras
Navega al lugar en que se descargó
asmcli
y ejecuta el siguiente comando para configurarASM_VERSION
export ASM_VERSION="$(./asmcli --version)"
Configura una carpeta de trabajo para las muestras que usas para verificar que funcione el balanceo de cargas entre clústeres. Las muestras se encuentran en un subdirectorio en el directorio
--output_dir
que especificaste en el comandoasmcli install
. En el siguiente comando, cambiaOUTPUT_DIR
por el directorio que especificaste en--output_dir
.export SAMPLES_DIR=OUTPUT_DIR/istio-${ASM_VERSION%+*}
Habilita la inyección de sidecar
Crea el espacio de nombres de muestra 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 inserción. Los pasos dependen de tu implementación del plano de control.
Administrado (TD)
- Aplica la etiqueta de inserció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
Administrada (Istiod)
Recomendado: Ejecuta el siguiente comando para aplicar la etiqueta de inserció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 eres un usuario existente con el plano de control de Istio administrado, te recomendamos que uses la inserción predeterminada, pero también se admite la inserción basada en revisiones. Sigue estas instrucciones:
Ejecuta el siguiente comando para ubicar los canales de versiones disponibles:
kubectl -n istio-system get controlplanerevision
El resultado es similar a este:
NAME AGE asm-managed-rapid 6d7h
En el resultado, el valor en la columna
NAME
es la etiqueta de revisión que corresponde al canal de versiones 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
Instala 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
Implementa HelloWorld v1 y v2 en cada clúster
Implementa
HelloWorld v1
enCLUSTER_1
yv2
enCLUSTER_2
, lo que más adelante ayudará a verificar el balanceo de cargas 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
Ejecuta los siguientes comandos para verificar que
HelloWorld v1
yv2
se estén ejecutando. Verifica que el resultado sea similar al siguiente: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
Implementa el servicio de suspensión
Implementa el servicio
Sleep
en ambos clústeres. En este Pod, se 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. Verifica que el resultado sea similar al siguiente: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
Verifica el balanceo de cargas entre clústeres
Llama al servicio HelloWorld
varias veces y observa el resultado para verificar respuestas alternativas de v1 y v2:
Llama al servicio
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'
El resultado es similar al que se muestra:
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'
El resultado es similar al que se muestra:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
Felicitaciones, ya verificaste el funcionamiento de Cloud Service Mesh de varios clústeres con balanceo de cargas.
Limpia el servicio HelloWorld
Cuando termines de verificar el balanceo de cargas, quita los servicios HelloWorld
y Sleep
del clúster.
kubectl delete ns sample --context ${CTX_1} kubectl delete ns sample --context ${CTX_2}