Menyiapkan mesh multi-cluster di GKE

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

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

Prasyarat

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

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

    Perintah ini bergantung pada jenis cluster Anda, baik regional maupun zona:

    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 lintas cluster. Misalnya, Anda perlu membuat aturan firewall jika:

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

GKE menambahkan aturan firewall secara otomatis ke tiap node untuk mengizinkan traffic dalam subnet yang sama. Jika 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 menargetkan port 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 spesifik.

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

Langkah-langkah yang diperlukan untuk mengonfigurasi penemuan endpoint bergantung pada apakah Anda lebih memilih menggunakan API deklaratif di seluruh cluster dalam fleet, atau mengaktifkannya secara manual di cluster publik atau cluster pribadi.

Mengaktifkan penemuan endpoint antara cluster publik atau pribadi dengan API deklaratif (pratinjau)

Anda dapat mengaktifkan penemuan endpoint di seluruh cluster publik atau pribadi dalam fleet dengan menerapkan konfigurasi "multicluster_mode":"connected" dalam configmap asm-options. Untuk cluster yang mengaktifkan konfigurasi ini dalam fleet yang sama, penemuan layanan lintas cluster akan otomatis diaktifkan antara satu sama lain.

Metode ini tersedia untuk penginstalan Cloud Service Mesh terkelola pada semua saluran rilis. Ini juga merupakan cara yang direkomendasikan untuk mengonfigurasi penemuan endpoint multi-cluster jika Anda menyediakan Cloud Service Mesh terkelola menggunakan fitur Enable Cloud Service Mesh saat membuat cluster GKE baru di Konsol Google Cloud.

Sebelum melanjutkan, Anda harus sudah membuat aturan firewall.

Untuk beberapa project, Anda harus menambahkan FLEET_PROJECT_ID.svc.id.goog secara manual ke trustDomainAliases dalam meshConfig revisi jika belum ada.

Aktifkan

Jika konfigurasi peta asm-options sudah ada di cluster Anda, aktifkan penemuan endpoint untuk cluster tersebut:

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

Jika konfigurasi peta asm-options belum ada di cluster Anda, buat konfigurasi 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

Nonaktifkan 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, rahasia dapat tetap berada dalam cluster. Anda harus menghapus semua secret yang tersisa secara manual.

  1. Jalankan perintah berikut untuk menemukan rahasia yang memerlukan pembersihan:

    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.

Mengonfigurasi penemuan endpoint di antara cluster publik

Untuk mengonfigurasi penemuan endpoint di antara cluster GKE, Anda menjalankan asmcli create-mesh. Perintah ini:

  • Mendaftarkan semua cluster ke fleet yang sama.
  • Mengonfigurasi mesh untuk memercayai identitas workload fleet.
  • Membuat rahasia jarak jauh.

Anda dapat menentukan URI untuk setiap cluster atau jalur file kubeconfig.

URI Cluster

Dalam perintah berikut, ganti FLEET_PROJECT_ID dengan project ID dari project host fleet dan URI cluster dengan nama cluster, zona atau region, dan project ID untuk setiap cluster. Contoh ini hanya menunjukkan dua cluster, tetapi Anda dapat menjalankan perintah untuk mengaktifkan penemuan endpoint pada cluster tambahan, sesuai dengan jumlah cluster maksimum yang diizinkan yang dapat Anda tambahkan ke fleet Anda.

./asmcli create-mesh \
    FLEET_PROJECT_ID \
    ${PROJECT_1}/${LOCATION_1}/${CLUSTER_1} \
    ${PROJECT_2}/${LOCATION_2}/${CLUSTER_2}

file kubeconfig

Dalam perintah berikut, ganti FLEET_PROJECT_ID dengan project ID project host fisik dan PATH_TO_KUBECONFIG dengan jalur ke setiap file kubeconfig. Contoh ini hanya menampilkan dua cluster, tetapi Anda dapat menjalankan perintah untuk mengaktifkan penemuan endpoint pada cluster tambahan, sesuai dengan jumlah cluster maksimum yang diizinkan yang dapat Anda tambahkan ke fleet Anda.

./asmcli create-mesh \
    FLEET_PROJECT_ID \
    PATH_TO_KUBECONFIG_1 \
    PATH_TO_KUBECONFIG_2

Mengonfigurasi penemuan endpoint di antara cluster pribadi

  1. Konfigurasikan rahasia jarak jauh untuk mengizinkan akses server API ke cluster ke bidang kontrol Cloud Service Mesh cluster lain. Perintah ini bergantung pada jenis Cloud Service Mesh Anda (baik dalam cluster maupun terkelola):

    A. Untuk Cloud Service Mesh dalam cluster, Anda harus mengonfigurasi IP pribadi, bukan IP publik, karena IP publik tidak dapat diakses:

    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. Untuk Mesh Layanan Cloud Terkelola:

    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. Terapkan secret baru ke dalam cluster:

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

Mengonfigurasi jaringan resmi untuk cluster pribadi

Ikuti bagian ini hanya jika semua kondisi berikut berlaku untuk mesh Anda:

Saat men-deploy beberapa cluster pribadi, bidang kontrol Cloud Service Mesh di setiap cluster perlu memanggil bidang kontrol GKE dari cluster jarak jauh. Untuk mengizinkan traffic, Anda perlu menambahkan rentang alamat Pod di cluster panggilan ke jaringan resmi cluster jarak jauh.

  1. Dapatkan blok CIDR IP Pod untuk setiap 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. Tambahkan blok CIDR IP Pod cluster Kubernetes ke cluster jarak jauh:

    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//;/,}
    

    Untuk mengetahui informasi selengkapnya, lihat Membuat cluster dengan jaringan yang diizinkan.

  3. Pastikan jaringan yang diizinkan telah diperbarui:

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

Aktifkan akses global bidang kontrol

Ikuti bagian ini hanya jika semua kondisi berikut berlaku untuk mesh Anda:

  • Anda menggunakan cluster pribadi.
  • Anda akan menggunakan region yang berbeda untuk cluster di mesh.

Anda harus mengaktifkan akses global bidang kontrol agar bidang kontrol Cloud Service Mesh di setiap cluster memanggil bidang kontrol GKE dari cluster jarak jauh.

  1. Aktifkan akses global bidang kontrol:

    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. Pastikan akses global bidang kontrol diaktifkan:

    gcloud container clusters describe ${CLUSTER_1} --project ${PROJECT_1} --zone ${LOCATION_1}
    
    gcloud container clusters describe ${CLUSTER_2} --project ${PROJECT_2} --zone ${LOCATION_2}
    

    Bagian privateClusterConfig dalam output menampilkan status masterGlobalAccessConfig.

Memverifikasi konektivitas multicluster

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

Menetapkan variabel untuk direktori contoh

  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. Sampel tersebut berada di subdirektori dalam direktori --output_dir yang Anda tentukan dalam perintah asmcli install. Dalam perintah berikut, ubah OUTPUT_DIR ke direktori yang Anda tentukan dalam --output_dir.

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

Aktifkan injeksi file bantuan

  1. Temukan nilai label revisi, yang Anda gunakan di langkah-langkah berikutnya. Langkah ini bergantung pada jenis Cloud Service Mesh Anda (baik yang terkelola maupun dalam cluster).

    Terkelola

    Gunakan perintah berikut untuk menemukan label revisi, yang akan Anda gunakan di langkah-langkah berikutnya.

    kubectl get controlplanerevision -n istio-system

    Outputnya terlihat mirip dengan yang berikut ini:

     NAME                RECONCILED   STALLED   AGE
     asm-managed-rapid   True         False     89d
     

    Di output, di bawah kolom NAME, perhatikan nilai label revisi. Dalam contoh ini, nilainya adalah asm-managed-rapid. Gunakan nilai revisi pada langkah-langkah di bagian berikutnya.

    Dalam cluster

    Gunakan perintah berikut untuk menemukan label revisi, yang akan Anda gunakan di langkah-langkah berikutnya.

    kubectl -n istio-system get pods -l app=istiod --show-labels

    Outputnya terlihat mirip dengan yang berikut ini:

     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
     

    Dalam output, di bawah kolom LABELS, perhatikan nilai label revisi istiod, yang mengikuti awalan istio.io/rev=. Dalam contoh ini, nilainya adalah asm-173-3. Gunakan nilai revisi pada langkah-langkah di bagian berikutnya.

Menginstal layanan HelloWorld

  1. Buat contoh namespace dan Service Definition di setiap cluster. Dalam perintah berikut, ganti REVISION dengan label revisi istiod yang Anda catat dari langkah sebelumnya.

    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
    

    dengan REVISION adalah label revisi istiod yang Anda catat sebelumnya.

    Output-nya adalah:

    label "istio-injection" not found.
    namespace/sample labeled
    

    Anda dapat mengabaikan label "istio-injection" not found. dengan aman

  2. 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 nantinya akan membantu memverifikasi load balancing lintas 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. Pastikan HelloWorld v1 dan v2 berjalan menggunakan perintah berikut. Pastikan output 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 Tidur

  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 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 alternatif 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 dengan load balancing.

Membersihkan layanan HelloWorld

Setelah 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}