Configurazione di un mesh multi-cluster su GKE
Questa guida spiega come unire due cluster in un unico Cloud Service Mesh utilizzando Mesh CA o Istio CA e come attivare il bilanciamento del carico tra cluster. Puoi estendere facilmente questo processo per incorporare qualsiasi numero di cluster nella tua mesh.
Una configurazione di Cloud Service Mesh multi-cluster può risolvere diversi scenari aziendali cruciali, come scalabilità, posizione e isolamento. Per ulteriori informazioni, vedi Casi d'uso multi-cluster.
Prerequisiti
Questa guida presuppone che tu disponga di due o più Google Cloud cluster GKE che soddisfano i seguenti requisiti:
Cloud Service Mesh versione 1.11 o successive installata sui cluster che utilizzano
asmcli install
. Deviasmcli
, lo strumentoistioctl
e gli esempi cheasmcli
scarica nella directory specificata in--output_dir
quando hai eseguitoasmcli install
Se devi configurare il tutto, segui i passaggi descritti in Installare gli strumenti dipendenti e convalidare il cluster per:Prima di configurare Cloud Service Mesh, i cluster nel mesh devono avere connettività tra tutti i pod. Inoltre, se unisci cluster che non si trovano nello stesso progetto, devono essere registrati nello stesso progetto host del parco risorse e i cluster devono trovarsi in una configurazione VPC condivisa insieme sulla stessa rete. Ti consigliamo inoltre di avere un progetto per ospitare il VPC condiviso e due progetti di servizio per la creazione di cluster. Per maggiori informazioni, consulta Configurazione di cluster con VPC condiviso.
Se utilizzi Istio CA, utilizza lo stesso certificato radice personalizzato per entrambi i cluster.
Se Cloud Service Mesh è basato su cluster privati, ti consigliamo di creare una singola subnet nello stesso VPC. In caso contrario, devi assicurarti che:
- I control plane possono raggiungere i control plane cluster privato remoti tramite gli IP privati del cluster.
- Puoi aggiungere gli intervalli IP dei control plane chiamanti alle reti autorizzate dei cluster privati remoti. Per maggiori informazioni, vedi Configurare l'individuazione degli endpoint tra cluster privati.
Il server API deve essere raggiungibile dalle altre istanze del piano di controllo di Cloud Service Mesh nel mesh multicluster.
- Assicurati che i cluster abbiano l'accesso globale abilitato.
- Assicurati che l'IP del control plane di Cloud Service Mesh sia stato consentito correttamente tramite la lista consentita con la rete autorizzata master.
Impostazione delle variabili di progetto e cluster
Crea le seguenti variabili di ambiente per l'ID progetto, la zona o la regione del cluster, il nome del cluster e il contesto.
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}"
Se si tratta di cluster appena creati, assicurati di recuperare le credenziali per ciascun cluster con i seguenti comandi
gcloud
, altrimenti il relativocontext
non sarà disponibile per l'uso nei passaggi successivi di questa guida.I comandi dipendono dal tipo di cluster, regionale o di zona:
Regionale
gcloud container clusters get-credentials ${CLUSTER_1} --region ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --region ${LOCATION_2}
A livello di zona
gcloud container clusters get-credentials ${CLUSTER_1} --zone ${LOCATION_1} gcloud container clusters get-credentials ${CLUSTER_2} --zone ${LOCATION_2}
Crea regola firewall
In alcuni casi, devi creare una regola firewall per consentire il traffico tra cluster. Ad esempio, devi creare una regola firewall se:
- Utilizzi subnet diverse per i cluster nel mesh.
- I pod aprono porte diverse da 443 e 15002.
GKE aggiunge automaticamente regole firewall a ogni nodo per consentire il traffico all'interno della stessa subnet. Se la tua mesh contiene più subnet, devi configurare esplicitamente le regole firewall per consentire il traffico tra le subnet. Devi aggiungere una nuova regola firewall per ogni subnet per consentire i blocchi CIDR IP di origine e le porte di destinazione di tutto il traffico in entrata.
Le seguenti istruzioni consentono la comunicazione tra tutti i cluster del tuo progetto o solo tra $CLUSTER_1
e $CLUSTER_2
.
Raccogli informazioni sulla rete dei tuoi cluster.
Tutti i cluster del progetto
Se i cluster si trovano nello stesso progetto, puoi utilizzare il seguente comando per consentire la comunicazione tra tutti i cluster del progetto. Se nel tuo progetto sono presenti cluster che non vuoi esporre, utilizza il comando nella scheda Cluster specifici.
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}"))
Cluster specifici
Il seguente comando consente la comunicazione tra
$CLUSTER_1
e$CLUSTER_2
e non espone altri cluster nel tuo progetto.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 regola 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 il rilevamento degli endpoint
I passaggi necessari per configurare l'individuazione degli endpoint dipendono dal fatto che tu preferisca utilizzare l'API dichiarativa nei cluster di un parco progetti o abilitarla manualmente nei cluster pubblici o nei cluster privati.
Abilitare l'individuazione degli endpoint tra cluster pubblici o privati con l'API dichiarativa (anteprima)
Puoi abilitare l'individuazione degli endpoint nei cluster pubblici o privati di un parco progetti
applicando la configurazione "multicluster_mode":"connected"
nel
configmap asm-options
. I cluster con questa configurazione abilitata nello stesso parco risorse
avranno ilService Discoveryo di rilevamento tra cluster abilitato automaticamente tra loro.
Questo metodo è disponibile per le installazioni gestite di Cloud Service Mesh su tutti i canali di rilascio. Questo è anche il modo preferito per configurare l'individuazione degli endpoint multicluster se hai eseguito il provisioning di Cloud Service Mesh gestito utilizzando la funzionalità Attiva Cloud Service Mesh durante la creazione di un nuovo cluster GKE nella console Google Cloud .
Prima di procedere, devi creare una regola firewall.
Per più progetti, devi aggiungere manualmente
FLEET_PROJECT_ID.svc.id.goog
a trustDomainAliases
nella
meshConfig
della revisione, se non è già presente.
Attiva
Se la configmap asm-options
esiste già nel cluster, attiva
il rilevamento degli endpoint per il cluster:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"connected"}}'
Se la configmap asm-options
non esiste ancora nel tuo cluster, creala con i dati associati e attiva l'individuazione degli endpoint per il cluster:
kubectl --context ${CTX_1} create configmap asm-options -n istio-system --from-file <(echo '{"data":{"multicluster_mode":"connected"}}')
Disattiva
Disabilita il rilevamento degli endpoint per un cluster:
kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"manual"}}'
Se annulli la registrazione di un cluster dal parco risorse senza disattivare l'individuazione degli endpoint, i secret potrebbero rimanere nel cluster. Devi pulire manualmente i secret rimanenti.
Esegui questo comando per trovare i secret che richiedono la pulizia:
kubectl get secrets -n istio-system -l istio.io/owned-by=mesh.googleapis.com,istio/multiCluster=true
Elimina ogni secret:
kubectl delete secret SECRET_NAME -n istio-system
Ripeti questo passaggio per ogni secret rimanente.
Configura l'individuazione degli endpoint tra cluster pubblici
Per configurare l'individuazione degli endpoint tra i cluster GKE, esegui
asmcli create-mesh
. Questo comando:
- Registra tutti i cluster nello stesso parco risorse.
- Configura la mesh in modo che consideri attendibile l'identità del workload del parco risorse.
- Crea secret remoti.
Puoi specificare l'URI per ogni cluster o il percorso del file kubeconfig.
URI cluster
Nel comando seguente, sostituisci FLEET_PROJECT_ID
con
l'ID progetto del progetto host del parco risorse e l'URI del cluster con il
nome del cluster, la zona o la regione e l'ID progetto per ogni cluster.
Questo esempio mostra solo due cluster, ma puoi eseguire il comando per attivare
l'individuazione degli endpoint su altri cluster, in base al
numero massimo consentito di cluster che puoi aggiungere al tuo parco risorse.
./asmcli create-mesh \
FLEET_PROJECT_ID \
${PROJECT_1}/${LOCATION_1}/${CLUSTER_1} \
${PROJECT_2}/${LOCATION_2}/${CLUSTER_2}
file kubeconfig
Nel comando seguente, sostituisci FLEET_PROJECT_ID
con l'ID progetto del progetto host del parco risorse e PATH_TO_KUBECONFIG
con il percorso di ogni file kubeconfig
. Questo esempio mostra solo due cluster, ma puoi eseguire il comando per attivare l'individuazione degli endpoint su cluster aggiuntivi, in base al numero massimo consentito di cluster che puoi aggiungere al tuo parco risorse.
./asmcli create-mesh \
FLEET_PROJECT_ID \
PATH_TO_KUBECONFIG_1 \
PATH_TO_KUBECONFIG_2
Configura il rilevamento degli endpoint tra cluster privati
Configura i secret remoti per consentire all'API server l'accesso al cluster al control plane di Cloud Service Mesh dell'altro cluster. I comandi dipendono dal tipo di Cloud Service Mesh (in-cluster o gestito):
A. Per Cloud Service Mesh in-cluster, devi configurare gli IP privati anziché gli IP pubblici perché questi ultimi non sono accessibili:
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. Per Managed Cloud Service Mesh:
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
Applica i nuovi secret ai cluster:
kubectl apply -f ${CTX_1}.secret --context=${CTX_2}
kubectl apply -f ${CTX_2}.secret --context=${CTX_1}
Configura le reti autorizzate per i cluster privati
Segui questa sezione solo se tutte le seguenti condizioni si applicano alla tua mesh:
- Utilizzi cluster privati.
- I cluster non appartengono alla stessa subnet.
- I cluster hanno abilitato le reti autorizzate.
Quando vengono implementati più cluster privati, il control plane di Cloud Service Mesh in ogni cluster deve chiamare il control plane GKE dei cluster remoti. Per consentire il traffico, devi aggiungere l'intervallo di indirizzi dei pod nel cluster chiamante alle reti autorizzate dei cluster remoti.
Recupera il blocco CIDR IP pod per ogni cluster:
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)"`
Aggiungi i blocchi CIDR IP pod del cluster Kubernetes ai cluster remoti:
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//;/,}
Per saperne di più, consulta Creazione di un cluster con reti autorizzate.
Verifica che le reti autorizzate siano aggiornate:
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)"
Abilita accesso globale control plane
Segui questa sezione solo se tutte le seguenti condizioni si applicano alla tua mesh:
- Stai utilizzando cluster privati.
- Utilizzi regioni diverse per i cluster nel mesh.
Devi abilitare l'accesso globale al control plane per consentire al control plane Cloud Service Mesh in ogni cluster di chiamare il control plane GKE dei cluster remoti.
Abilita l'accesso globale al control plane:
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 che l'accesso globale control plane sia abilitato:
gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1}
gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2}
La sezione
privateClusterConfig
nell'output mostra lo stato dimasterGlobalAccessConfig
.
Verificare la connettività multicluster
Questa sezione spiega come eseguire il deployment dei servizi HelloWorld
e Sleep
di esempio nell'ambiente multi-cluster per verificare che il bilanciamento del carico tra cluster funzioni.
Imposta la variabile per la directory degli esempi
Vai alla posizione in cui è stato scaricato
asmcli
ed esegui questo comando per impostareASM_VERSION
export ASM_VERSION="$(./asmcli --version)"
Imposta una cartella di lavoro per gli esempi che utilizzi per verificare che il bilanciamento del carico cross-cluster funzioni. Gli esempi si trovano in una sottodirectory della directory
--output_dir
specificata nel comandoasmcli install
. Nel comando seguente, modificaOUTPUT_DIR
nella directory specificata in--output_dir
.export SAMPLES_DIR=OUTPUT_DIR/istio-${ASM_VERSION%+*}
Attiva l'inserimento di sidecar
Individua il valore dell'etichetta di revisione, che utilizzerai nei passaggi successivi. Il passaggio dipende dal tipo di Cloud Service Mesh (gestito o in-cluster).
Gestito
Utilizza il seguente comando per individuare l'etichetta della revisione, che utilizzerai nei passaggi successivi.
kubectl get controlplanerevision -n istio-system
L'output è simile al seguente:
NAME RECONCILED STALLED AGE asm-managed-rapid True False 89d
Nell'output, nella colonna
NAME
, prendi nota del valore dell'etichetta della revisione. In questo esempio, il valore èasm-managed-rapid
. Utilizza il valore della revisione nei passaggi della sezione successiva.In-cluster
Utilizza il seguente comando per individuare l'etichetta della revisione, che utilizzerai nei passaggi successivi.
kubectl -n istio-system get pods -l app=istiod --show-labels
L'output è simile al seguente:
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
Nell'output, nella colonna
LABELS
, prendi nota del valore dell'etichetta di revisioneistiod
, che segue il prefissoistio.io/rev=
. In questo esempio, il valore èasm-173-3
. Utilizza il valore della revisione nei passaggi della sezione successiva.
Installa il servizio HelloWorld
Crea lo spazio dei nomi di esempio e la definizione del servizio in ogni cluster. Nel comando seguente, sostituisci REVISION con l'etichetta di revisione
istiod
che hai annotato nel passaggio precedente.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
dove REVISION è l'etichetta di revisione
istiod
che hai annotato in precedenza.L'output è:
label "istio-injection" not found. namespace/sample labeled
Puoi ignorare tranquillamente
label "istio-injection" not found.
Crea il servizio HelloWorld in entrambi i cluster:
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
Esegui il deployment di HelloWorld v1 e v2 in ogni cluster
Esegui il deployment di
HelloWorld v1
suCLUSTER_1
e div2
suCLUSTER_2
, il che ti aiuterà in seguito a verificare il bilanciamento del carico tra cluster: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
Verifica che
HelloWorld v1
ev2
siano in esecuzione utilizzando i seguenti comandi. Verifica che l'output sia simile a quello mostrato: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
Esegui il deployment del servizio per il sonno
Esegui il deployment del servizio
Sleep
in entrambi i cluster. Questo pod genera traffico di rete artificiale a scopo dimostrativo:for CTX in ${CTX_1} ${CTX_2} do kubectl apply --context=${CTX} \ -f ${SAMPLES_DIR}/samples/sleep/sleep.yaml -n sample done
Attendi l'avvio del servizio
Sleep
in ogni cluster. Verifica che l'output sia simile a quello mostrato: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 il bilanciamento del carico tra cluster
Chiama il servizio HelloWorld
più volte e controlla l'output per verificare
risposte alternate dalle versioni 1 e 2:
Chiama il servizio
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'
L'output è simile a quello mostrato:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
Chiama di nuovo il servizio
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'
L'output è simile a quello mostrato:
Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8 Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv ...
Congratulazioni, hai verificato il tuo Cloud Service Mesh multicluster con bilanciamento del carico.
Pulisci il servizio HelloWorld
Al termine della verifica del bilanciamento del carico, rimuovi i servizi HelloWorld
e Sleep
dal cluster.
kubectl delete ns sample --context ${CTX_1} kubectl delete ns sample --context ${CTX_2}