En esta guía, se explica cómo unir dos clústeres en una sola Anthos Service Mesh mediante la CA de Mesh o la CA de Istio, 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.
Usa configuración de Anthos 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. Además, debes optimizar las aplicaciones para aprovechar la malla de servicios al máximo. Si deseas obtener más información, consulta Prepara una aplicación para Anthos Service Mesh.
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:
- Anthos Service Mesh versión 1.6.8 o posterior instalada en los clústeres.
- Si tus clústeres están en el mismo proyecto, consulta Descripción general de la instalación a fin de instalar o actualizar los clústeres a la versión requerida.
- Si tus clústeres están en proyectos diferentes, consulta Instalación y migración multiproyecto para instalar o actualizar tus clústeres a la versión requerida.
- Si unes clústeres que no están en el mismo proyecto, deben instalarse mediante el perfil
asm-gcp-multiproject
y deben estar juntos en una configuración de VPC compartida. en la misma red. Además, te recomendamos que tengas un proyecto para alojar la VPC compartida y dos proyectos de servicio a fin de crear clústeres. Para obtener más información, consulta Configura clústeres con VPC compartida. - Si usas la CA de Istio, usa el mismo certificado raíz personalizado para ambos clústeres.
- Si Anthos Service Mesh está compilada en clústeres privados, te recomendamos crear una sola subred en la misma VPC, de lo contrario, debes asegurarte de lo siguiente:
- Los planos de control pueden alcanzar los planos de control del clúster privado remoto a través de las IP privadas del clúster.
- Puedes agregar los rangos de IP de los planos de control de llamadas a las redes autorizadas de los clústeres privados. Para obtener más información, consulta Configura el descubrimiento de extremos entre clústeres privados.
Configura variables de proyecto y clúster
Establece una carpeta de trabajo para mayor comodidad. Esta es la carpeta en la que descargaste y extrajiste los archivos de Anthos Service Mesh en el paso previo, Prepárate para instalar Anthos Service Mesh.
export PROJECT_DIR=YOUR_WORKING_FOLDER
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:gcloud container clusters get-credentials ${CLUSTER_1} gcloud container clusters get-credentials ${CLUSTER_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 entre clústeres
Configura el descubrimiento de extremos para el balanceo de cargas entre clústeres mediante los siguientes comandos. En este paso, se realizan las siguientes tareas:
- El comando
istioctl
crea un secreto que otorga acceso al servidor de la API de Kube a un clúster. - El comando
kubectl
aplica el secreto a otro clúster para que el segundo clúster pueda leer los extremos del servicio del primero.
istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1_NAME} | \ kubectl apply -f - --context=${CTX_2}
istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2_NAME} | \ kubectl apply -f - --context=${CTX_1}
Configura el descubrimiento de extremos entre clústeres privados
Cuando usas clústeres privados, debes configurar las IP privadas de los clústeres remotos en lugar de las IP públicas, ya que las IP públicas no son accesibles.
Escribe los secretos con IP públicas en archivos temporales:
istioctl x create-remote-secret --context=${CTX_1} --name=${CLUSTER_1_NAME} > ${CTX_1}.secret
istioctl x create-remote-secret --context=${CTX_2} --name=${CLUSTER_2_NAME} > ${CTX_2}.secret
Recupera las IP privadas de los clústeres privados y reemplaza las IP públicas con ellas en los Secrets de los archivos temporales:
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
Aplica los Secrets nuevos en los clústeres:
kubectl apply -f ${CTX_1}.secret --context=${CTX_2}
kubectl apply -f ${CTX_2}.secret --context=${CTX_1}
Configura redes autorizadas para clústeres privados
Sigue esta sección solo si se cumplen todas las siguientes condiciones en la malla:
- Usas clústeres privados.
- Los clústeres no pertenecen a la misma subred.
- Los clústeres habilitaron redes autorizadas.
Cuando se implementan varios clústeres en Anthos Service Mesh, el Istio de cada clúster necesita llamar al plano de control de GKE de los clústeres remotos. Para permitir el tráfico, debes agregar el rango de direcciones del Pod en el clúster que realiza la llamada a las redes autorizadas de los clústeres remotos.
Obtén el bloque CIDR de IP del Pod para 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)"`
Agrega los bloques CIDR de IP del Pod de 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 Crea un clúster con redes autorizadas.
Verifica que las redes autorizadas estén actualizadas:
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)"
Habilita el acceso global al plano de control
Sigue esta sección solo si se cumplen todas las siguientes condiciones en la malla:
- Usas clústeres privados.
- Usas subredes diferentes para los clústeres de tu malla.
Debes habilitar el acceso global al plano de control para permitir que istiod
en 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
Verifica que el acceso global al plano de control esté habilitado:
gcloud container clusters describe ${CLUSTER_1} --zone ${LOCATION_1}
gcloud container clusters describe ${CLUSTER_2} --zone ${LOCATION_2}
La sección
privateClusterConfig
en el resultado muestra el estado demasterGlobalAccessConfig
.
Verifique su implementación
En esta sección, se explica cómo implementar un servicio HelloWorld
de muestra en el entorno de varios clústeres para verificar que funcione el balanceo de cargas entre clústeres.
Habilita la inserción de sidecar
Usa el siguiente comando para localizar el valor de la etiqueta de revisión del servicio
istiod
, que usarás en pasos posteriores.kubectl -n istio-system get pods -l app=istiod --show-labels
El resultado es similar al siguiente:
NAME READY STATUS RESTARTS AGE LABELS istiod-asm-173-3-5788d57586-bljj4 1/1 Running 0 23h app=istiod,istio.io/rev=asm-173-3,istio=istiod,pod-template-hash=5788d57586 istiod-asm-173-3-5788d57586-vsklm 1/1 Running 1 23h app=istiod,istio.io/rev=asm-173-3,istio=istiod,pod-template-hash=5788d57586
En el resultado, en la columna
LABELS
, observa el valor de la etiqueta de revisiónistiod
, que está después del prefijoistio.io/rev=
. En este ejemplo, el valor esasm-173-3
. Use el valor de revisión en los pasos de la siguiente sección.
Instala el servicio HelloWorld
Crea el espacio de nombres de muestra y la definición del servicio en cada clúster. En el siguiente comando, sustituye REVISION por la etiqueta de revisión istiod
que anotaste del paso anterior.
for CTX in ${CTX_1} ${CTX_2} do kubectl create --context=${CTX} namespace sample kubectl label --context=${CTX} namespace sample \ istio-injection- istio.io/rev=REVISION --overwrite done
En el ejemplo anterior, REVISION es la etiqueta de revisión istiod
que anotaste antes.
El resultado es el siguiente:
label "istio-injection" not found. namespace/sample labeled
Puedes ignorar a label "istio-injection" not found.
de forma segura
Crea el servicio HelloWorld en ambos clústeres:
kubectl create --context=${CTX_1} \ -f ${PROJECT_DIR}/samples/helloworld/helloworld.yaml \ -l service=helloworld -n sample
kubectl create --context=${CTX_2} \ -f ${PROJECT_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 ${PROJECT_DIR}/samples/helloworld/helloworld.yaml \ -l version=v1 -n sample
kubectl create --context=${CTX_2} \ -f ${PROJECT_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 ${PROJECT_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}')" \ -- curl -sS helloworld.sample:5000/hello
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}')" \ -- curl -sS helloworld.sample:5000/hello
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 Anthos 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}