Configurar una malla de varios clústeres en GKE
En esta guía se explica cómo unir dos clústeres en una sola malla de servicios de Cloud mediante Mesh CA o Istio CA 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 versión 1.11 o posterior instalado en los clústeres que usan
asmcli install
. Necesitasasmcli
, la herramientaistioctl
y muestras queasmcli
descarga en el directorio que especificaste en--output_dir
al ejecutarasmcli install
. Si necesitas configurarlo, sigue los pasos que se indican en Instalar herramientas dependientes y validar el clúster para hacer lo siguiente: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 la AC de Istio, utiliza el mismo certificado raíz personalizado en ambos clústeres.
Si tu malla de servicios de Cloud se basa en clústeres privados, te recomendamos que crees una sola subred en la misma VPC. De lo contrario, debes asegurarte de que:
- Los planos de control pueden acceder a los planos de control de clústeres privados remotos a través de las IPs privadas del clúster.
- Puedes añadir los intervalos de IPs de los planos de control de llamadas a las redes autorizadas de los clústeres privados remotos. Para obtener más información, consulta el artículo Configurar el descubrimiento de endpoints entre clústeres privados.
El servidor de la API debe ser accesible para las demás instancias del plano de control de Cloud Service Mesh en la malla multiclúster.
- Asegúrate de que los clústeres tengan habilitado el acceso global.
- Asegúrate de que la IP del plano de control de Cloud Service Mesh se haya permitido correctamente a través de la lista de permitidos con la red autorizada principal.
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
Los pasos necesarios para configurar el descubrimiento de endpoints dependen de si prefieres usar la API declarativa en los clústeres de una flota o habilitarla manualmente en clústeres públicos o clústeres privados.
Configurar el descubrimiento de endpoints entre clústeres públicos
Para configurar el descubrimiento de endpoints entre clústeres de GKE, ejecuta
asmcli create-mesh
. Este comando:
- Registra todos los clústeres en la misma flota.
- Configura la malla para que confíe en la identidad de carga de trabajo de la flota.
- Crea secretos remotos.
Puedes especificar el URI de cada clúster o la ruta del archivo kubeconfig.
URI del clúster
En el siguiente comando, sustituye FLEET_PROJECT_ID
por el ID del proyecto host de la flota y el URI del clúster por el nombre del clúster, la zona o la región, y el ID del proyecto de cada clúster.
En este ejemplo solo se muestran dos clústeres, pero puedes ejecutar el comando para habilitar la detección de endpoints en otros clústeres, siempre que no superes el número máximo de clústeres que puedes añadir a tu flota.
./asmcli create-mesh \
FLEET_PROJECT_ID \
${PROJECT_1}/${LOCATION_1}/${CLUSTER_1} \
${PROJECT_2}/${LOCATION_2}/${CLUSTER_2}
Archivo kubeconfig
En el siguiente comando, sustituye FLEET_PROJECT_ID
por el ID del proyecto host de la flota y PATH_TO_KUBECONFIG
por la ruta de cada archivo kubeconfig
. En este ejemplo solo se muestran dos clústeres, pero puedes ejecutar el comando para habilitar la detección de endpoints en otros clústeres, siempre que no superes el número máximo de clústeres que puedes añadir a tu flota.
./asmcli create-mesh \
FLEET_PROJECT_ID \
PATH_TO_KUBECONFIG_1 \
PATH_TO_KUBECONFIG_2
Configurar el descubrimiento de endpoints entre clústeres privados
Configura los secretos remotos para permitir que el servidor de la API acceda al plano de control de Cloud Service Mesh del otro clúster. Los comandos dependen del tipo de Cloud Service Mesh (en el clúster o gestionado):
A. En el caso de Cloud Service Mesh en el clúster, debes configurar las IPs privadas en lugar de las públicas, ya que no se puede acceder a las IPs públicas:
PRIV_IP=`gcloud container clusters describe "${CLUSTER_1}" --project "${PROJECT_1}" \ --zone "${LOCATION_1}" --format "value(privateClusterConfig.privateEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1} --server=https://${PRIV_IP} > ${CTX_1}.secret
PRIV_IP=`gcloud container clusters describe "${CLUSTER_2}" --project "${PROJECT_2}" \ --zone "${LOCATION_2}" --format "value(privateClusterConfig.privateEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2} --server=https://${PRIV_IP} > ${CTX_2}.secret
B. En el caso de Cloud Service Mesh gestionado:
PUBLIC_IP=`gcloud container clusters describe "${CLUSTER_1}" --project "${PROJECT_1}" \ --zone "${LOCATION_1}" --format "value(privateClusterConfig.publicEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1} --server=https://${PUBLIC_IP} > ${CTX_1}.secret
PUBLIC_IP=`gcloud container clusters describe "${CLUSTER_2}" --project "${PROJECT_2}" \ --zone "${LOCATION_2}" --format "value(privateClusterConfig.publicEndpoint)"` ./istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2} --server=https://${PUBLIC_IP} > ${CTX_2}.secret
Aplica los nuevos secretos a los clústeres:
kubectl apply -f ${CTX_1}.secret --context=${CTX_2}
kubectl apply -f ${CTX_2}.secret --context=${CTX_1}
Configurar redes autorizadas en clústeres privados
Sigue las instrucciones de esta sección solo si se cumplen todas las condiciones siguientes en tu malla:
- Estás usando clústeres privados.
- Los clústeres no pertenecen a la misma subred.
- Los clústeres tienen habilitadas las redes autorizadas.
Cuando se despliegan varios clústeres privados, el plano de control de Cloud Service Mesh de cada clúster debe llamar al plano de control de GKE de los clústeres remotos. Para permitir el tráfico, debe añadir el intervalo de direcciones de los pods del clúster de llamada a las redes autorizadas de los clústeres remotos.
Obtén el bloque CIDR de IP de los pods de cada clúster:
POD_IP_CIDR_1=`gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --format "value(ipAllocationPolicy.clusterIpv4CidrBlock)"`
POD_IP_CIDR_2=`gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --format "value(ipAllocationPolicy.clusterIpv4CidrBlock)"`
Añade los bloques CIDR de IP de los pods del clúster de Kubernetes a los clústeres remotos:
EXISTING_CIDR_1=`gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"` gcloud container clusters update ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --enable-master-authorized-networks \ --master-authorized-networks ${POD_IP_CIDR_2},${EXISTING_CIDR_1//;/,}
EXISTING_CIDR_2=`gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"` gcloud container clusters update ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --enable-master-authorized-networks \ --master-authorized-networks ${POD_IP_CIDR_1},${EXISTING_CIDR_2//;/,}
Para obtener más información, consulta Crear un clúster con redes autorizadas.
Verifica que las redes autorizadas se hayan actualizado:
gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"
gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --format "value(masterAuthorizedNetworksConfig.cidrBlocks.cidrBlock)"
Habilitar el acceso global al plano de control
Sigue las instrucciones de esta sección solo si se cumplen todas las condiciones siguientes en tu malla:
- Estás usando clústeres privados.
- Utilizas diferentes regiones para los clústeres de tu malla.
Debes habilitar el acceso global al plano de control para permitir que el plano de control de Cloud Service Mesh de cada clúster llame al plano de control de GKE de los clústeres remotos.
Habilita el acceso global al plano de control:
gcloud container clusters update ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1} \ --enable-master-global-access
gcloud container clusters update ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2} \ --enable-master-global-access
Comprueba que el acceso global al plano de control esté habilitado:
gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1}
gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2}
En la sección
privateClusterConfig
de la salida se muestra el estado demasterGlobalAccessConfig
.
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 la inserción de sidecars en los espacios de nombres creados.
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
Te recomendamos que uses la inyección predeterminada, pero también se admite la inyección basada en revisiones: Sigue estas instrucciones:
Usa el siguiente comando para localizar la etiqueta de revisión en
istiod
:kubectl get deploy -n istio-system -l app=istiod -o \ jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'
Aplica la etiqueta de revisión al espacio de nombres. En el siguiente comando,
REVISION_LABEL
es el valor de la etiqueta de revisiónistiod
que has anotado en el paso anterior.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}