Menyiapkan mesh multi-cluster di Cloud Service Mesh terkelola

Panduan ini menjelaskan cara menggabungkan dua cluster ke dalam satu Cloud Service Mesh menggunakan CA Mesh atau Certificate Authority Service dan mengaktifkan load balancing lintas cluster. Anda dapat dengan mudah memperluas proses ini untuk menggabungkan sejumlah cluster ke dalam mesh Anda.

Konfigurasi Cloud Service Mesh multi-cluster dapat menyelesaikan beberapa skenario penting perusahaan, seperti skala, lokasi, dan isolasi. Untuk mengetahui informasi selengkapnya, lihat Kasus penggunaan multi-cluster.

Prasyarat

Panduan ini mengasumsikan bahwa Anda memiliki dua atau lebih Google Cloud cluster GKE yang memenuhi persyaratan berikut:

  • Cloud Service Mesh diinstal di cluster. Anda memerlukan asmcli, alat istioctl, dan sampel yang didownload asmcli ke direktori yang Anda tentukan di --output_dir.
  • Cluster di mesh Anda harus memiliki konektivitas antar-semua pod sebelum Anda mengonfigurasi Cloud Service Mesh. Selain itu, jika Anda menggabungkan cluster yang tidak berada dalam project yang sama, cluster tersebut harus didaftarkan ke project host fleet yang sama, dan cluster tersebut harus berada dalam konfigurasi VPC bersama bersama di jaringan yang sama. Sebaiknya Anda memiliki satu project untuk menghosting VPC Bersama, dan dua project layanan untuk membuat cluster. Untuk mengetahui informasi selengkapnya, lihat Menyiapkan cluster dengan VPC Bersama.
  • Jika Anda menggunakan Certificate Authority Service, semua cluster harus memiliki rantai kumpulan subordinate CA masing-masing ke kumpulan root CA yang sama. Jika tidak, semuanya harus menggunakan kumpulan CA yang sama.

Menetapkan variabel project dan cluster

  1. Buat variabel lingkungan berikut untuk project ID, zona atau region cluster, nama cluster, dan konteks.

    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. Jika ini adalah cluster yang baru dibuat, pastikan untuk mengambil kredensial untuk setiap cluster dengan perintah gcloud berikut. Jika tidak, context terkait tidak akan tersedia untuk digunakan pada langkah berikutnya dalam panduan ini.

    Perintah bergantung pada jenis cluster Anda, baik regional maupun 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}
    

Buat aturan firewall

Dalam beberapa kasus, Anda perlu membuat aturan firewall untuk mengizinkan traffic antar-cluster. Misalnya, Anda perlu membuat aturan firewall jika:

  • Anda menggunakan subnet yang berbeda untuk cluster di mesh Anda.
  • Pod Anda membuka port selain 443 dan 15002.

GKE otomatis menambahkan aturan firewall ke setiap node untuk mengizinkan traffic dalam subnet yang sama. Jika jaringan mesh Anda berisi beberapa subnet, Anda harus menyiapkan aturan firewall secara eksplisit untuk mengizinkan traffic lintas subnet. Anda harus menambahkan aturan firewall baru untuk setiap subnet guna mengizinkan blok CIDR IP sumber dan port target dari semua traffic masuk.

Petunjuk berikut memungkinkan komunikasi antara semua cluster dalam project Anda atau hanya antara $CLUSTER_1 dan $CLUSTER_2.

  1. Kumpulkan informasi tentang jaringan cluster Anda.

    Semua cluster project

    Jika cluster berada dalam project yang sama, Anda dapat menggunakan perintah berikut untuk mengizinkan komunikasi antara semua cluster dalam project Anda. Jika ada cluster dalam project yang tidak ingin Anda ekspos, gunakan perintah di tab Cluster tertentu.

    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 tertentu

    Perintah berikut memungkinkan komunikasi antara $CLUSTER_1 dan $CLUSTER_2 serta tidak mengekspos cluster lain dalam project Anda.

    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. Buat aturan 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
    

Mengonfigurasi penemuan endpoint

Mengaktifkan penemuan endpoint antara cluster publik atau pribadi dengan API deklaratif

Mengaktifkan Cloud Service Mesh terkelola dengan fleet API akan mengaktifkan penemuan endpoint untuk cluster ini. Jika Anda menyediakan Cloud Service Mesh terkelola dengan alat yang berbeda, Anda dapat mengaktifkan penemuan endpoint secara manual di seluruh cluster publik atau pribadi dalam armada dengan menerapkan config "multicluster_mode":"connected" di configmap asm-options. Cluster dengan konfigurasi ini yang diaktifkan dalam fleet yang sama akan mengaktifkan penemuan layanan lintas cluster secara otomatis di antara satu sama lain.

Ini adalah satu-satunya cara untuk mengonfigurasi penemuan endpoint multi-cluster jika Anda memiliki implementasi bidang kontrol Terkelola (TD), dan cara yang direkomendasikan untuk mengonfigurasinya jika Anda memiliki implementasi Terkelola (Istiod).

Sebelum melanjutkan, Anda harus membuat aturan firewall.

Aktifkan

Jika configmap asm-options sudah ada di cluster Anda, aktifkan penemuan endpoint untuk cluster:

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

Jika asm-options configmap belum ada di cluster Anda, buat dengan data terkait dan aktifkan penemuan endpoint untuk cluster:

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

Nonaktifkan

Menonaktifkan penemuan endpoint untuk cluster:

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

Jika Anda membatalkan pendaftaran cluster dari fleet tanpa menonaktifkan penemuan endpoint, secret dapat tetap berada di cluster. Anda harus menghapus rahasia yang tersisa secara manual.

  1. Jalankan perintah berikut untuk menemukan secret yang perlu dibersihkan:

    kubectl get secrets -n istio-system -l istio.io/owned-by=mesh.googleapis.com,istio/multiCluster=true
    
  2. Hapus setiap secret:

    kubectl delete secret SECRET_NAME
    

    Ulangi langkah ini untuk setiap secret yang tersisa.

Memverifikasi konektivitas multi-cluster

Bagian ini menjelaskan cara men-deploy layanan HelloWorld dan Sleep contoh ke lingkungan multi-cluster Anda untuk memverifikasi bahwa load balancing lintas cluster berfungsi.

Tetapkan variabel untuk direktori sampel

  1. Buka tempat asmcli didownload, lalu jalankan perintah berikut untuk menyetel ASM_VERSION

    export ASM_VERSION="$(./asmcli --version)"
    
  2. Tetapkan folder kerja ke sampel yang Anda gunakan untuk memverifikasi bahwa load balancing lintas cluster berfungsi. Contoh terletak di subdirektori dalam direktori --output_dir yang Anda tentukan dalam perintah asmcli install. Dalam perintah berikut, ubah OUTPUT_DIR ke direktori yang Anda tentukan di --output_dir.

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

Mengaktifkan injeksi sidecar

  1. Buat namespace contoh di setiap cluster.

    for CTX in ${CTX_1} ${CTX_2}
    do
        kubectl create --context=${CTX} namespace sample
    done
    
  2. Aktifkan namespace untuk injeksi. Langkah-langkahnya bergantung pada implementasi bidang kontrol Anda.

    Terkelola (TD)

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

    Terkelola (Istiod)

    Direkomendasikan: Jalankan perintah berikut untuk menerapkan label injeksi default ke namespace:

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

    Jika Anda adalah pengguna lama dengan bidang kontrol Managed Istiod: Sebaiknya gunakan injeksi default, tetapi injeksi berbasis revisi didukung. Gunakan petunjuk berikut:

    1. Jalankan perintah berikut untuk menemukan saluran rilis yang tersedia:

      kubectl -n istio-system get controlplanerevision
      

      Outputnya mirip dengan hal berikut ini:

      NAME                AGE
      asm-managed-rapid   6d7h
      

      Dalam output, nilai di kolom NAME adalah label revisi yang sesuai dengan saluran rilis yang tersedia untuk versi Cloud Service Mesh.

    2. Terapkan label revisi ke namespace:

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

Menginstal layanan HelloWorld

  • Buat layanan HelloWorld di kedua 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
    

Men-deploy HelloWorld v1 dan v2 ke setiap cluster

  1. Deploy HelloWorld v1 ke CLUSTER_1 dan v2 ke CLUSTER_2, yang akan membantu memverifikasi load balancing lintas cluster nanti:

    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. Konfirmasi bahwa HelloWorld v1 dan v2 berjalan menggunakan perintah berikut. Pastikan output-nya mirip dengan yang ditampilkan.:

    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

Men-deploy layanan Sleep

  1. Deploy layanan Sleep ke kedua cluster. Pod ini menghasilkan traffic jaringan buatan untuk tujuan demonstrasi:

    for CTX in ${CTX_1} ${CTX_2}
    do
        kubectl apply --context=${CTX} \
            -f ${SAMPLES_DIR}/samples/sleep/sleep.yaml -n sample
    done
    
  2. Tunggu hingga layanan Sleep dimulai di setiap cluster. Pastikan output-nya mirip dengan yang ditampilkan:

    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

Memverifikasi load balancing lintas cluster

Panggil layanan HelloWorld beberapa kali dan periksa output untuk memverifikasi balasan bergantian dari v1 dan v2:

  1. Panggil layanan 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'
    

    Outputnya mirip dengan yang ditampilkan:

    Hello version: v2, instance: helloworld-v2-758dd55874-6x4t8
    Hello version: v1, instance: helloworld-v1-86f77cd7bd-cpxhv
    ...
  2. Panggil layanan HelloWorld lagi:

    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'
    

    Outputnya mirip dengan yang ditampilkan:

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

Selamat, Anda telah memverifikasi Cloud Service Mesh multi-cluster yang di-load balance.

Mempertahankan traffic dalam cluster

Dalam beberapa kasus, perilaku load balancing lintas cluster default tidak diinginkan. Untuk menjaga traffic "cluster-local" (yaitu traffic yang dikirim dari cluster-a hanya akan mencapai tujuan di cluster-a), tandai nama host atau karakter pengganti sebagai clusterLocal menggunakan MeshConfig.serviceSettings.

Misalnya, Anda dapat menerapkan traffic lokal cluster untuk layanan individual, semua layanan dalam namespace tertentu, atau secara global untuk semua layanan dalam mesh, sebagai berikut:

per-layanan

serviceSettings:
- settings:
    clusterLocal: true
  hosts:
  - "mysvc.myns.svc.cluster.local"

per-namespace

serviceSettings:
- settings:
    clusterLocal: true
  hosts:
  - "*.myns.svc.cluster.local"

global

serviceSettings:
- settings:
    clusterLocal: true
  hosts:
  - "*"

Anda juga dapat menyempurnakan akses layanan dengan menetapkan aturan global lokal cluster dan menambahkan pengecualian eksplisit, yang dapat berupa pengecualian spesifik atau karakter pengganti. Pada contoh berikut, semua layanan di cluster akan tetap bersifat lokal cluster, kecuali layanan apa pun di namespace myns:

serviceSettings:
- settings:
    clusterLocal: true
  hosts:
  - "*"
- settings:
    clusterLocal: false
  hosts:
  - "*.myns.svc.cluster.local"

Mengaktifkan Layanan Cluster Lokal

  1. Periksa peta konfigurasi MeshConfig di cluster

    kubectl get configmap -n istio-system
    

    Anda akan melihat peta konfigurasi dengan salah satu nama istio-asm-managed, istio-asm-managed-rapid, atau istio-asm-managed-stable.

    Jika Anda telah bermigrasi dari implementasi ISTIOD ke implementasi TRAFFIC_DIRECTOR, Anda mungkin melihat lebih dari satu peta konfigurasi. Dalam hal ini, Anda dapat menentukan saluran dengan menjalankan perintah berikut:

    kubectl get controlplanerevision -n istio-system
    

    Saluran Revisi Bidang Kontrol yang disesuaikan adalah saluran yang ingin Anda pilih.

  2. Perbarui Config Map

    cat <<EOF > config.yaml
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: CONFIGMAP_NAME
      namespace: istio-system
    data:
      mesh: |-
        serviceSettings:
        - settings:
            clusterLocal: true
          hosts:
          - "*"
    EOF
    

    Ganti CONFIGMAP_NAME dengan nama ConfigMap yang Anda temukan di langkah 1 dan perbarui ConfigMap.

    kubectl apply --context=${CTX_1} -f config.yaml
    
  3. Pastikan fitur Cluster Lokal berfungsi seperti yang diharapkan menggunakan perintah berikut. Output untuk memanggil HelloWorld dengan CTX_1 mirip dengan:

    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'
    

    Anda akan melihat Only v1 is response dalam output:

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

    Jika Anda memanggil HelloWorld dengan CTX_2:

    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'
    

    Anda akan melihat balasan bergantian dari v1 dan v2 di output.

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

Menghapus layanan HelloWorld

Setelah Anda selesai memverifikasi load balancing, hapus layanan HelloWorld dan Sleep dari cluster Anda.

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

Mengonfigurasi Load Balancing Lokalitas

Cloud Service Mesh memungkinkan Anda mengontrol cara traffic didistribusikan di berbagai region dan zona menggunakan perilaku perutean utama:

  • SPRAY_TO_WORLD (Default): Traffic didistribusikan menggunakan round-robin di semua endpoint yang responsif secara global, terlepas dari lokasi klien.
  • WATERFALL_BY_ZONE: Traffic dirutekan ke zona responsif terdekat. Jika zona lokal tidak responsif, traffic akan dirutekan ke zona responsif terdekat berikutnya.

Panduan ini menjelaskan cara mengonfigurasi perilaku ini menggunakan resource DestinationRule dan MeshConfig Istio.

Mengaktifkan Perutean Waterfall

Untuk memicu WATERFALL_BY_ZONE, pengguna harus mengonfigurasi DestinationRule.TrafficPolicy.outlierDetection DAN salah satu hal berikut di DestinationRule (atau secara global di MeshConfig):

  • localityLbSetting.enabled sebagai true
  • localityLbSetting.failover.from
  • localityLbSetting.failover.to

Mengaktifkan Waterfall Menggunakan DestinationRule

Berikut ini menjelaskan konfigurasi yang berhasil mengaktifkan perutean Waterfall untuk layanan tertentu menggunakan DestinationRule:

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: backend-waterfall-rule
spec:
  host: my-backend.default.svc.cluster.local
  trafficPolicy:
    outlierDetection: {}
    loadBalancer:
      localityLbSetting:
        enabled: true # or failover: []

Mengaktifkan Waterfall Menggunakan MeshConfig + DestinationRule

Atau, Anda dapat mengaktifkan Load Balancing Lokalitas secara global untuk seluruh mesh di cluster menggunakan MeshConfig (misalnya, di istio-asm-managed ConfigMap). Jika localityLbSetting diterapkan ke seluruh mesh, setiap DestinationRule hanya memerlukan blok outlierDetection kosong untuk memicu perutean Waterfall.

File YAML berikut memberikan contoh MeshConfig dan DestinationRule untuk konfigurasi ini:

MeshConfig (Global):

apiVersion: v1
kind: ConfigMap
metadata:
  name: istio-asm-managed
  namespace: istio-system
data:
  mesh: |-
    localityLbSetting:
      enabled: true # or failover: []

DestinationRule (Khusus Layanan):

apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: backend-waterfall-rule
spec:
  host: my-backend.default.svc.cluster.local
  trafficPolicy:
    outlierDetection: {}

Menerapkan Setelan Lokalitas per Versi Workload

Karena setelan lokalitas khusus subset dan khusus port tidak didukung di DestinationRule, Anda dapat menggunakan beberapa definisi Layanan Kubernetes untuk memberikan setelan perutean per layanan guna mencapai perilaku lokalitas campuran.