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 attivare il bilanciamento del carico tra i cluster. Puoi estendere facilmente questo processo per incorporare un numero qualsiasi di cluster nel tuo mesh.

Una configurazione multi-cluster Cloud Service Mesh può risolvere diverse fasi aziendali cruciali come la scalabilità, la posizione e l'isolamento. Per ulteriori informazioni, consulta Casi d'uso multi-cluster.

Prerequisiti

Questa guida presuppone che tu abbia due o più cluster GKE di Google Cloud che soddisfano i seguenti requisiti:

Impostazione di variabili di progetto e cluster

  1. Crea le seguenti variabili di ambiente per l'ID progetto e il cluster zona o regione, nome del cluster e 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}"
    
  2. Se si tratta di cluster appena creati, assicurati di recuperare le credenziali per ogni cluster con i seguenti comandi gcloud, altrimenti il relativo context non sarà disponibile per l'utilizzo nei passaggi successivi di questa guida.

    I comandi dipendono dal tipo di cluster, regionale o zonale:

    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 i cluster. Ad esempio, devi creare una regola firewall se:

  • Puoi utilizzare subnet diverse per i cluster nella tua rete mesh.
  • I pod aprono porte diverse da 443 e 15002.

GKE aggiunge automaticamente regole firewall a ciascun nodo per consentire il traffico all'interno della stessa sottorete. Se la tua rete mesh contiene più subnet, devi configurare esplicitamente le regole firewall per consentire il traffico tra subnet. Devi aggiungi una nuova regola firewall per ogni subnet per consentire i blocchi CIDR IP di origine e le porte di destinazione di tutte le per il traffico in entrata.

Le seguenti istruzioni consentono la comunicazione tra tutti i cluster del progetto o solo tra $CLUSTER_1 e $CLUSTER_2.

  1. Raccogli informazioni sui cluster in ogni rete.

    Tutti i cluster del progetto

    Se i cluster si trovano nello stesso progetto, puoi utilizzare il comando seguente per consentire la comunicazione tra tutti i cluster del progetto. Se ci sono nel progetto che non vuoi esporre, utilizza il comando la 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}"))
    
  2. 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 il rilevamento degli endpoint dipendono dalla tua preferenza per utilizzare l'API dichiarativa nei cluster in un parco risorse o abilitalo manualmente cluster pubblici o cluster privati.

Abilita il rilevamento degli endpoint tra cluster pubblici o privati con un'API dichiarativa (anteprima)

Puoi attivare il rilevamento degli endpoint nei cluster pubblici o privati di un parco applicando la configurazione "multicluster_mode":"connected" nel configmap asm-options. Cluster con questa configurazione abilitata nello stesso parco risorse Service Discovery tra cluster sarà automaticamente abilitato tra ogni e l'altro.

Questo metodo è disponibile per le installazioni gestite di Cloud Service Mesh su tutti canali di rilascio. Questo è anche il modo migliore per configurare cluster il rilevamento degli endpoint se hai eseguito il provisioning di Cloud Service Mesh gestito utilizzando Abilita la funzionalità Cloud Service Mesh durante la creazione di un nuovo cluster GKE nella console Google Cloud.

Prima di procedere, devi aver creato una regola firewall.

Per più progetti, devi aggiungere manualmente Da FLEET_PROJECT_ID.svc.id.goog a trustDomainAliases nel della revisione meshConfig, se non è già presente.

Attiva

Se la configmap asm-options esiste già nel tuo cluster, abilita rilevamento degli endpoint per il cluster:

kubectl patch configmap/asm-options -n istio-system --type merge -p '{"data":{"multicluster_mode":"connected"}}'

Se il configmap asm-options non esiste ancora nel tuo cluster, crealo con i dati associati e abilita il rilevamento degli endpoint per il cluster:

kubectl --context ${CTX_1} create configmap asm-options -n istio-system --from-file <(echo '{"data":{"multicluster_mode":"connected"}}')

Disabilita

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 disabilitare il rilevamento degli endpoint, potrebbero rimanere nel cluster. Devi rimuovere manualmente eventuali elementi i tuoi segreti.

  1. 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
    
  2. Elimina ogni secret:

    kubectl delete secret SECRET_NAME
    

    Ripeti questo passaggio per ogni secret rimanente.

Configura il rilevamento degli endpoint tra cluster pubblici

Per configurare il rilevamento degli endpoint tra i cluster GKE, esegui asmcli create-mesh. Questo comando:

  • Registra tutti i cluster nello stesso parco risorse.
  • Configura il mesh in modo che attenda l'identità del carico di lavoro 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 del progetto host del parco risorse e l'URI del cluster con il nome, la zona o la regione del cluster e l'ID progetto per ciascun cluster. Questo esempio mostra solo due cluster, ma puoi eseguire il comando per attivare il rilevamento degli endpoint su altri cluster, rispettando il 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 ciascun file kubeconfig. Questo esempio mostra solo due cluster, ma puoi eseguire per abilitare il rilevamento degli endpoint su cluster aggiuntivi, in base alle 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

  1. Configura i secret remoti per consentire all'API server di accedere al cluster al piano di controllo Cloud Service Mesh dell'altro cluster. I comandi dipendono Tipo di Cloud Service Mesh (in-cluster o gestito):

    A. Per Cloud Service Mesh nel cluster, devi configurare gli IP privati di 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 Cloud Service Mesh gestito:

    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
    
  2. Applica i nuovi secret ai cluster:

    kubectl apply -f ${CTX_1}.secret --context=${CTX_2}
    
    kubectl apply -f ${CTX_2}.secret --context=${CTX_1}
    

Configurare le reti autorizzate per i cluster privati

Segui questa sezione solo se al mesh si applicano tutte le seguenti condizioni:

Quando esegui il deployment di 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.

  1. Ottieni il blocco CIDR IP del 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)"`
    
  2. Aggiungi i blocchi CIDR degli IP dei 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 ulteriori informazioni, consulta la sezione Creare un cluster con reti autorizzate.

  3. 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 l'accesso globale al piano di controllo

Segui questa sezione solo se al tuo mesh si applicano tutte le seguenti condizioni:

  • Stai utilizzando cluster privati.
  • Utilizzi regioni diverse per i cluster nel mesh.

Devi abilitare l'accesso globale al piano di controllo per consentire al piano di controllo di Cloud Service Mesh in ciascun cluster di chiamare dal piano di controllo GKE dei cluster remoti.

  1. 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
    
  2. Verifica che l'accesso globale al piano di controllo 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 di masterGlobalAccessConfig.

Verificare la connettività multicluster

Questa sezione spiega come eseguire il deployment dei servizi HelloWorld e Sleep di esempio all'ambiente multi-cluster per verificare il carico tra cluster l'equilibrio.

Imposta variabile per la directory di esempio

  1. Vai alla posizione in cui è stato scaricato asmcli ed esegui questo comando per impostare ASM_VERSION

    export ASM_VERSION="$(./asmcli --version)"
    
  2. Imposta una cartella di lavoro sugli esempi che utilizzi per verificare il bilanciamento del carico tra cluster. I sample si trovano in una sottodirectory della directory --output_dir specificata nel comando asmcli install. Nel seguente comando, sostituisci OUTPUT_DIR con la directory specificata in --output_dir.

    export SAMPLES_DIR=OUTPUT_DIR/istio-${ASM_VERSION%+*}
    

Attiva inserimento file collaterale

  1. Individua il valore dell'etichetta di revisione, che utilizzerai nei passaggi successivi. Passaggio dipende dal tipo di Cloud Service Mesh (gestito o in-cluster).

    Gestito

    Utilizza il seguente comando per individuare l'etichetta di 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 la il valore della revisione nei passaggi della prossima sezione.

    All'interno del cluster

    Utilizza il seguente comando per individuare l'etichetta di 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 della revisione istiod, che segue il prefisso istio.io/rev=. In questo esempio, Il valore è asm-173-3. Utilizza il valore della revisione nei passaggi della sezione successiva.

Installa il servizio HelloWorld

  1. Crea lo spazio dei nomi di esempio e la definizione del servizio in ogni cluster. Nella questo comando, sostituisci REVISION con istiod l'etichetta di revisione annotata 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.

  2. 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

  1. Esegui il deployment di HelloWorld v1 in CLUSTER_1 e di v2 in CLUSTER_2, il che ti aiuterà in un secondo momento 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
  2. Verifica che HelloWorld v1 e v2 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 Sleep

  1. 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
    
  2. 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 più volte il servizio HelloWorld e controlla l'output per verificare risposte alternate da v1 a v2:

  1. 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
    ...
  2. 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 mesh di servizi Cloud multi-cluster con bilanciamento del carico.

Eliminazione del servizio HelloWorld

Al termine della verifica del bilanciamento del carico, rimuovi HelloWorld e Sleep dal tuo cluster.

kubectl delete ns sample --context ${CTX_1}
kubectl delete ns sample --context ${CTX_2}