Multi-Cluster-Mesh in verwaltetem Cloud Service Mesh einrichten

In dieser Anleitung wird erläutert, wie Sie zwei Cluster mit Mesh CA oder Certificate Authority Service zu einem einzigen Cloud Service Mesh zusammenführen und das clusterübergreifende Load Balancing aktivieren. Sie können diesen Prozess problemlos erweitern, um eine beliebige Anzahl von Clustern in Ihr Mesh-Netzwerk einzubinden.

Eine Cloud Service Mesh-Konfiguration mit mehreren Clustern kann in mehreren wichtigen Unternehmensszenarien wie Skalierung, Standortwahl und Isolation eine Lösung sein. Weitere Informationen finden Sie unter Multi-Cluster-Anwendungsfälle.

Vorbereitung

In dieser Anleitung wird davon ausgegangen, dass Sie mindestens zwei Google Cloud-GKE-Cluster haben, die folgende Anforderungen erfüllen:

  • Cloud Service Mesh auf den Clustern installiert. Sie benötigen asmcli, das istioctl-Tool und Beispiele, die asmcli in das Verzeichnis herunterlädt, das Sie in --output_dir angegeben haben.
  • Cluster in Ihrem Mesh müssen eine Verbindung zwischen allen Pods haben, bevor Sie Cloud Service Mesh konfigurieren. Wenn Sie Cluster zusammenführen, die sich nicht im selben Projekt befinden, müssen sie außerdem im selben Flottenhostprojekt registriert sein und die Cluster müssen sich zusammen in einer Konfiguration mit freigegebener VPC im selben Netzwerk befinden. Außerdem empfehlen wir, dass Sie ein Projekt zum Hosten der freigegebenen VPC und zwei Dienstprojekte zum Erstellen von Clustern haben. Weitere Informationen finden Sie unter Cluster mit freigegebener VPC einrichten.
  • Wenn Sie Certificate Authority Service verwenden, muss die entsprechende untergeordnete CA-Poolskette aller Cluster mit demselben Stamm-CA-Pool verknüpft sein. Andernfalls müssen alle denselben Zertifizierungsstellenpool verwenden.

Projekt- und Clustervariablen festlegen

  1. Erstellen Sie die folgenden Umgebungsvariablen für die Projekt-ID, die Clusterzone oder -region, den Clusternamen und den Kontext.

    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. Wenn es sich um neu erstellte Cluster handelt, müssen Sie mit den folgenden gcloud-Befehlen Anmeldedaten für jeden Cluster abrufen. Andernfalls ist der zugehörige context nicht für die nächsten Schritte dieser Anleitung verfügbar:

    Die Befehle hängen vom Clustertyp ab, entweder regional oder 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}
    

Firewallregel erstellen

In einigen Fällen müssen Sie eine Firewallregel erstellen, um clusterübergreifenden Traffic zuzulassen. In folgenden Fällen müssen Sie beispielsweise eine Firewallregel erstellen:

  • Sie verwenden unterschiedliche Subnetze für die Cluster in Ihrem Mesh-Netzwerk.
  • Ihre Pods öffnen andere Ports als 443 und 15002.

GKE fügt jedem Knoten automatisch Firewallregeln hinzu, die Traffic innerhalb eines Subnetzes zulassen. Wenn Ihr Mesh-Netzwerk mehrere Subnetze enthält, müssen Sie die Firewallregeln explizit so einrichten, dass subnetzübergreifender Traffic zulässig ist. Sie müssen dabei für jedes Subnetz eine neue Firewallregel hinzufügen, die die CIDR-Blöcke der Quell-IP-Adresse und die Zielports des gesamten eingehenden Traffics zulässt.

Die folgende Anleitung ermöglicht die Kommunikation zwischen allen Clustern in Ihrem Projekt oder nur zwischen $CLUSTER_1 und $CLUSTER_2.

  1. Sammeln Sie Informationen zum Netzwerk Ihres Clusters.

    Alle Projektcluster

    Wenn sich die Cluster im selben Projekt befinden, können Sie den folgenden Befehl verwenden, um die Kommunikation zwischen allen Clustern in Ihrem Projekt zuzulassen. Wenn in Ihrem Projekt Cluster enthalten sind, die Sie nicht verfügbar machen möchten, verwenden Sie den Befehl auf dem Tab Bestimmte Cluster.

    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}"))
    

    Bestimmte Cluster

    Der folgende Befehl ermöglicht die Kommunikation zwischen $CLUSTER_1 und $CLUSTER_2 und macht keine anderen Cluster in Ihrem Projekt verfügbar.

    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. Firewallregel erstellen

    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
    

Endpunkterkennung konfigurieren

Endpunkterkennung zwischen öffentlichen oder privaten Clustern mit der deklarativen API aktivieren

Wenn Sie das verwaltete Cloud Service Mesh mit der Flotten-API aktivieren, wird die Endpunkterkennung aktiviert für diesen Cluster. Wenn Sie verwaltetes Cloud Service Mesh mit einem anderen Tool bereitgestellt haben, können Sie die Endpunkterkennung für öffentliche oder private Cluster in einer Flotte manuell aktivieren. Wenden Sie dazu die Konfiguration "multicluster_mode":"connected" in der ConfigMap asm-options an. Bei Clustern, für die diese Konfiguration in derselben Flotte aktiviert ist, wird die clusterübergreifende Diensterkennung automatisch miteinander aktiviert.

Dies ist die einzige Möglichkeit, die Multi-Cluster-Endpunkterkennung zu konfigurieren, wenn Sie die Steuerungsebenenimplementierung vom Typ „Verwaltet (TD)“ verwenden. Bei der Implementierung vom Typ „Verwaltet (Istiod)“ wird diese Methode empfohlen.

Bevor Sie fortfahren, müssen Sie eine Firewallregel erstellt haben.

Aktivieren

Wenn die asm-options-ConfigMap bereits in Ihrem Cluster vorhanden ist, aktivieren Sie die Endpunkterkennung für den Cluster:

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

Wenn die asm-options-Configmap noch nicht in Ihrem Cluster vorhanden ist, erstellen Sie sie mit den zugehörigen Daten und aktivieren Sie die Endpunkterkennung für den Cluster:

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

Deaktivieren

Deaktivieren Sie die Endpunkterkennung für einen Cluster:

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

Wenn Sie die Registrierung eines Clusters bei der Flotte aufheben, ohne die Endpunkterkennung zu deaktivieren, können Secrets im Cluster verbleiben. Sie müssen die verbleibenden Secrets manuell bereinigen.

  1. Führen Sie den folgenden Befehl aus, um Secrets zu finden, die bereinigt werden müssen:

    kubectl get secrets -n istio-system -l istio.io/owned-by=mesh.googleapis.com,istio/multiCluster=true
    
  2. Löschen Sie jedes Secret:

    kubectl delete secret SECRET_NAME
    

    Wiederholen Sie diesen Schritt für jedes verbleibende Secret.

Multicluster-Konnektivität prüfen

In diesem Abschnitt wird erläutert, wie Sie die Beispieldienste HelloWorld und Sleep in Ihrer Multi-Cluster-Umgebung bereitstellen, um zu überprüfen, ob das clusterübergreifende Load-Balancing funktioniert.

Variable für Beispielverzeichnis festlegen

  1. Gehen Sie zu dem Speicherort, an dem asmcli heruntergeladen wurde, und führen Sie den folgenden Befehl aus, um ASM_VERSION festzulegen:

    export ASM_VERSION="$(./asmcli --version)"
    
  2. Legen Sie einen Arbeitsordner für die Beispiele fest, mit denen Sie prüfen, ob das clusterübergreifende Load-Balancing funktioniert. Die Beispiele befinden sich in einem Unterverzeichnis im Verzeichnis --output_dir, das Sie im Befehl asmcli install angegeben haben. Ändern Sie im folgenden Befehl OUTPUT_DIR in das Verzeichnis, das Sie in --output_dir angegeben haben.

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

Sidecar-Injektion aktivieren

  1. Erstellen Sie den Beispiel-Namespace in jedem Cluster.

    for CTX in ${CTX_1} ${CTX_2}
    do
        kubectl create --context=${CTX} namespace sample
    done
    
  2. Aktivieren Sie den Namespace für die Injection: Die Schritte hängen von Ihrer Implementierung der Steuerungsebene ab.

    Verwaltet (TD)

    1. Wenden Sie das Standard-Injection-Label auf den Namespace an:
    for CTX in ${CTX_1} ${CTX_2}
    do
       kubectl label --context=${CTX} namespace sample
          istio.io/rev- istio-injection=enabled --overwrite
    done
    

    Verwaltet (Istiod)

    Empfohlen: Führen Sie den folgenden Befehl aus, um das Standard-Injektionslabel auf den Namespace anzuwenden:

     for CTX in ${CTX_1} ${CTX_2}
     do
        kubectl label --context=${CTX} namespace sample \
           istio.io/rev- istio-injection=enabled --overwrite
     done
    

    Wenn Sie bereits Nutzer mit der Managed Istiod-Steuerungsebene sind: Wir empfehlen die Standardeinschleusung, aber die überarbeitete Injektion ist unterstützt. Gehe dazu so vor:

    1. Führen Sie den folgenden Befehl aus, um die verfügbaren Release-Versionen zu finden:

      kubectl -n istio-system get controlplanerevision
      

      Die Ausgabe sieht in etwa so aus:

      NAME                AGE
      asm-managed-rapid   6d7h
      

      In der Ausgabe ist der Wert in der NAME-Spalte das Überarbeitungslabel, das dem verfügbaren Release-Kanal für die Cloud Service Mesh-Version entspricht.

    2. Wenden Sie das Überarbeitungslabel auf den Namespace an.

      for CTX in ${CTX_1} ${CTX_2}
      do
        kubectl label --context=${CTX} namespace sample \
           istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      done
      

HelloWorld-Dienst installieren

  • Erstellen Sie in beiden Clustern den HelloWorld-Dienst:

    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
    

HelloWorld v1 und v2 in jedem Cluster bereitstellen

  1. Stellen Sie HelloWorld v1 in CLUSTER_1 und v2 in CLUSTER_2 bereit. Das erleichtert später die Prüfung des clusterübergreifenden Load-Balancings.

    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. Prüfen Sie mit den folgenden Befehlen, ob HelloWorld v1 und v2 ausgeführt werden. Prüfen Sie, ob die Ausgabe in etwa so aussieht:

    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

Sleep-Dienst bereitstellen

  1. Stellen Sie den Sleep-Dienst in beiden Clustern bereit. Dieser Pod generiert künstlichen Netzwerktraffic zur Veranschaulichung:

    for CTX in ${CTX_1} ${CTX_2}
    do
        kubectl apply --context=${CTX} \
            -f ${SAMPLES_DIR}/samples/sleep/sleep.yaml -n sample
    done
    
  2. Warten Sie, bis der Sleep-Dienst in jedem Cluster gestartet wurde. Prüfen Sie, ob die Ausgabe in etwa so aussieht:

    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

Clusterübergreifendes Load-Balancing prüfen

Rufen Sie den HelloWorld-Dienst mehrmals auf und prüfen Sie die Ausgabe, um abwechselnde Antworten von v1 und v2 zu prüfen:

  1. Rufen Sie den Dienst HelloWorld auf:

    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'
    

    Die Ausgabe sollte in etwa so aussehen:

    Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8
    Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv
    ...
  2. Rufen Sie den Dienst HelloWorld noch einmal auf:

    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'
    

    Die Ausgabe sollte in etwa so aussehen:

    Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8
    Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv
    ...

Herzlichen Glückwunsch, Sie haben Ihr Cloud Service Mesh mit Load-Balancing und mehreren Clustern geprüft.

HelloWorld-Dienst bereinigen

Entfernen Sie nach der Prüfung des Load-Balancings die Dienste HelloWorld und Sleep aus dem Cluster.

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