Dari edge ke mesh multi-cluster: Men-deploy aplikasi yang didistribusikan secara global melalui GKE Gateway dan Cloud Service Mesh

Last reviewed 2024-06-30 UTC

Dokumen ini menunjukkan cara menyelesaikan tugas berikut:

Panduan deployment ini ditujukan untuk administrator platform. Panduan ini juga ditujukan untuk praktisi tingkat lanjut yang menjalankan Cloud Service Mesh. Petunjuk ini juga berlaku untuk Istio di GKE.

Arsitektur

Diagram berikut menunjukkan topologi ingress default mesh layanan—load balancer TCP/UDP eksternal yang mengekspos proxy gateway ingress pada satu cluster:

Load balancer eksternal mengarahkan klien eksternal ke mesh melalui proxy gateway traffic masuk.

Panduan deployment ini menggunakan resource Gateway Google Kubernetes Engine (GKE). Secara khusus, layanan ini menggunakan gateway multi-cluster untuk mengonfigurasi load balancing multi-region di depan beberapa cluster Autopilot yang didistribusikan di dua region.

Enkripsi TLS dari klien, load balancer, dan dari mesh.

Diagram sebelumnya menunjukkan cara data mengalir melalui skenario traffic masuk cloud dan traffic masuk mesh. Untuk mengetahui informasi selengkapnya, lihat penjelasan tentang diagram arsitektur dalam dokumen arsitektur referensi terkait.

Tujuan

  • Deploy sepasang cluster GKE Autopilot di Google Cloud ke fleet yang sama.
  • Deploy Cloud Service Mesh berbasis Istio ke armada yang sama.
  • Mengonfigurasi load balancer menggunakan GKE Gateway untuk menghentikan traffic HTTPS publik.
  • Mengarahkan traffic HTTPS publik langsung ke aplikasi yang dihosting oleh Cloud Service Mesh yang di-deploy di beberapa cluster dan region.
  • Deploy aplikasi contoh whereami ke kedua cluster Autopilot.

Pengoptimalan biaya

Dalam dokumen ini, Anda akan menggunakan komponen Google Cloudyang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga.

Pengguna Google Cloud baru mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    Anda menjalankan semua perintah terminal untuk deployment ini dari Cloud Shell.

  4. Tetapkan project Google Cloud default Anda:

    export PROJECT=YOUR_PROJECT
    export PROJECT_NUMBER=$(gcloud projects describe PROJECT_ID --format="value(projectNumber)")
    gcloud config set project PROJECT_ID
    

    Ganti PROJECT_ID dengan ID project yang ingin Anda gunakan untuk deployment ini.

  5. Buat direktori kerja:

    mkdir -p ${HOME}/edge-to-mesh-multi-region
    cd ${HOME}/edge-to-mesh-multi-region
    export WORKDIR=`pwd`
    
  6. Membuat cluster GKE

    Di bagian ini, Anda akan membuat cluster GKE untuk menghosting aplikasi dan infrastruktur pendukung, yang akan Anda buat nanti dalam panduan deployment ini.

    1. Di Cloud Shell, buat file kubeconfig baru. Langkah ini memastikan Anda tidak membuat konflik dengan file kubeconfig yang sudah ada (default).

      touch edge2mesh_mr_kubeconfig
      export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
      
    2. Tentukan variabel lingkungan yang digunakan saat membuat cluster GKE dan resource di dalamnya. Ubah pilihan region default agar sesuai dengan tujuan Anda.

      export CLUSTER_1_NAME=edge-to-mesh-01
      export CLUSTER_2_NAME=edge-to-mesh-02
      export CLUSTER_1_REGION=us-central1
      export CLUSTER_2_REGION=us-east4
      export PUBLIC_ENDPOINT=frontend.endpoints.PROJECT_ID.cloud.goog
      
    3. Aktifkan Google Cloud API yang digunakan di seluruh panduan ini:

      gcloud services enable \
        container.googleapis.com \
        mesh.googleapis.com \
        gkehub.googleapis.com \
        multiclusterservicediscovery.googleapis.com \
        multiclusteringress.googleapis.com \
        trafficdirector.googleapis.com \
        certificatemanager.googleapis.com
      
    4. Buat cluster GKE Autopilot dengan node pribadi di CLUSTER_1_REGION. Gunakan flag --async agar tidak perlu menunggu cluster pertama disediakan dan didaftarkan ke fleet:

      gcloud container clusters create-auto --async \
      ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} \
      --release-channel rapid --labels mesh_id=proj-${PROJECT_NUMBER} \
      --enable-private-nodes --enable-fleet
      
    5. Buat dan daftarkan cluster Autopilot kedua di CLUSTER_2_REGION:

      gcloud container clusters create-auto \
      ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} \
      --release-channel rapid --labels mesh_id=proj-${PROJECT_NUMBER} \
      --enable-private-nodes --enable-fleet
      
    6. Pastikan cluster berjalan. Mungkin perlu waktu hingga 20 menit hingga semua cluster berjalan:

      gcloud container clusters list
      

      Outputnya mirip dengan hal berikut ini:

      NAME             LOCATION     MASTER_VERSION  MASTER_IP       MACHINE_TYPE  NODE_VERSION    NUM_NODES  STATUS
      edge-to-mesh-01  us-central1  1.27.5-gke.200  34.27.171.241   e2-small      1.27.5-gke.200             RUNNING
      edge-to-mesh-02  us-east4     1.27.5-gke.200  35.236.204.156  e2-small      1.27.5-gke.200             RUNNING
      
    7. Kumpulkan kredensial untuk CLUSTER_1_NAME.Anda membuat CLUSTER_1_NAMEsecara asinkron sehingga Anda dapat menjalankan perintah tambahan saat cluster disediakan.

      gcloud container clusters get-credentials ${CLUSTER_1_NAME} \
          --region ${CLUSTER_1_REGION}
      
    8. Untuk memperjelas nama konteks Kubernetes, ganti namanya menjadi nama cluster:

      kubectl config rename-context gke_PROJECT_ID_${CLUSTER_1_REGION}_${CLUSTER_1_NAME} ${CLUSTER_1_NAME}
      kubectl config rename-context gke_PROJECT_ID_${CLUSTER_2_REGION}_${CLUSTER_2_NAME} ${CLUSTER_2_NAME}
      

    Menginstal mesh layanan

    Di bagian ini, Anda akan mengonfigurasi Cloud Service Mesh terkelola dengan fleet API. Menggunakan fleet API untuk mengaktifkan Cloud Service Mesh memberikan pendekatan deklaratif untuk menyediakan mesh layanan.

    1. Di Cloud Shell, aktifkan Cloud Service Mesh di fleet:

      gcloud container fleet mesh enable
      
    2. Mengaktifkan pengelolaan bidang kontrol dan bidang data otomatis:

      gcloud container fleet mesh update \
        --management automatic \
        --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}
      
    3. Tunggu sekitar 20 menit. Kemudian, verifikasi bahwa status bidang kontrol adalah ACTIVE:

      gcloud container fleet mesh describe
      

      Outputnya mirip dengan hal berikut ini:

      createTime: '2023-11-30T19:23:21.713028916Z'
      membershipSpecs:
        projects/603904278888/locations/us-central1/memberships/edge-to-mesh-01:
          mesh:
            management: MANAGEMENT_AUTOMATIC
        projects/603904278888/locations/us-east4/memberships/edge-to-mesh-02:
          mesh:
            management: MANAGEMENT_AUTOMATIC
      membershipStates:
        projects/603904278888/locations/us-central1/memberships/edge-to-mesh-01:
          servicemesh:
            controlPlaneManagement:
              details:
              - code: REVISION_READY
                details: 'Ready: asm-managed-rapid'
              implementation: ISTIOD
              state: ACTIVE
            dataPlaneManagement:
              details:
              - code: OK
                details: Service is running.
              state: ACTIVE
          state:
           code: OK
            description: |-
              Revision ready for use: asm-managed-rapid.
              All Canonical Services have been reconciled successfully.
            updateTime: '2024-06-27T09:00:21.333579005Z'
        projects/603904278888/locations/us-east4/memberships/edge-to-mesh-02:
          servicemesh:
            controlPlaneManagement:
              details:
              - code: REVISION_READY
                details: 'Ready: asm-managed-rapid'
              implementation: ISTIOD
              state: ACTIVE
            dataPlaneManagement:
              details:
              - code: OK
                details: Service is running.
              state: ACTIVE
          state:
            code: OK
            description: |-
              Revision ready for use: asm-managed-rapid.
              All Canonical Services have been reconciled successfully.
            updateTime: '2024-06-27T09:00:24.674852751Z'
      name: projects/e2m-private-test-01/locations/global/features/servicemesh
      resourceState:
        state: ACTIVE
      spec: {}
      updateTime: '2024-06-04T17:16:28.730429993Z'
      

    Men-deploy Load Balancer Aplikasi eksternal dan membuat gateway ingress

    Di bagian ini, Anda akan men-deploy Load Balancer Aplikasi eksternal melalui pengontrol Gateway GKE dan membuat gateway ingress untuk kedua cluster. Resource gateway dan gatewayClass mengotomatiskan penyediaan load balancer dan health check backend. Untuk menyediakan penghentian TLS di load balancer, Anda membuat resource Certificate Manager dan melampirkannya ke load balancer. Selain itu, Anda menggunakan Endpoints untuk menyediakan nama DNS publik untuk aplikasi secara otomatis.

    Menginstal gateway ingress di kedua cluster

    Sebagai praktik terbaik keamanan, sebaiknya Anda men-deploy gateway traffic masuk di namespace yang berbeda dari bidang kontrol mesh.

    1. Di Cloud Shell, buat namespace asm-ingress khusus di setiap cluster:

      kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress
      kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingress
      
    2. Tambahkan label namespace ke namespace asm-ingress:

      kubectl --context=${CLUSTER_1_NAME} label namespace asm-ingress istio-injection=enabled
      kubectl --context=${CLUSTER_2_NAME} label namespace asm-ingress istio-injection=enabled
      

      Outputnya mirip dengan hal berikut ini:

      namespace/asm-ingress labeled
      

      Pelabelan namespace asm-ingress dengan istio-injection=enabled akan memerintahkan Cloud Service Mesh untuk otomatis memasukkan proxy sidecar Envoy saat pod di-deploy.

    3. Buat sertifikat yang ditandatangani sendiri untuk digunakan di masa mendatang:

      openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
       -subj "/CN=frontend.endpoints.PROJECT_ID.cloud.goog/O=Edge2Mesh Inc" \
       -keyout ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \
       -out ${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
      

      Sertifikat memberikan lapisan enkripsi tambahan antara load balancer dan gateway ingress mesh layanan. Layanan ini juga memungkinkan dukungan untuk protokol berbasis HTTP/2 seperti gRPC. Petunjuk tentang cara melampirkan sertifikat yang ditandatangani sendiri ke gateway ingress akan diberikan nanti di Membuat resource alamat IP eksternal, data DNS, dan sertifikat TLS.

      Untuk mengetahui informasi selengkapnya tentang persyaratan sertifikat gateway traffic masuk, lihat Enkripsi dari load balancer ke backend.

    4. Buat secret Kubernetes di setiap cluster untuk menyimpan sertifikat yang ditandatangani sendiri:

      kubectl --context ${CLUSTER_1_NAME} -n asm-ingress create secret tls \
       edge2mesh-credential \
       --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \
       --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
      kubectl --context ${CLUSTER_2_NAME} -n asm-ingress create secret tls \
       edge2mesh-credential \
       --key=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.key \
       --cert=${WORKDIR}/frontend.endpoints.PROJECT_ID.cloud.goog.crt
      
    5. Untuk berintegrasi dengan Load Balancer Aplikasi eksternal, buat varian kustomize untuk mengonfigurasi resource gateway ingress:

      mkdir -p ${WORKDIR}/asm-ig/base
      
      cat <<EOF > ${WORKDIR}/asm-ig/base/kustomization.yaml
      resources:
        - github.com/GoogleCloudPlatform/anthos-service-mesh-samples/docs/ingress-gateway-asm-manifests/base
      EOF
      
      mkdir ${WORKDIR}/asm-ig/variant
      
      cat <<EOF > ${WORKDIR}/asm-ig/variant/role.yaml
      apiVersion: rbac.authorization.k8s.io/v1
      kind: Role
      metadata:
        name: asm-ingressgateway
        namespace: asm-ingress
      rules:
      - apiGroups: [""]
        resources: ["secrets"]
        verbs: ["get", "watch", "list"]
      EOF
      
      cat <<EOF > ${WORKDIR}/asm-ig/variant/rolebinding.yaml
      apiVersion: rbac.authorization.k8s.io/v1
      kind: RoleBinding
      metadata:
        name: asm-ingressgateway
        namespace: asm-ingress
      roleRef:
        apiGroup: rbac.authorization.k8s.io
        kind: Role
        name: asm-ingressgateway
      subjects:
        - kind: ServiceAccount
          name: asm-ingressgateway
      EOF
      
      cat <<EOF > ${WORKDIR}/asm-ig/variant/service-proto-type.yaml
      apiVersion: v1
      kind: Service
      metadata:
        name: asm-ingressgateway
        namespace: asm-ingress
      spec:
        ports:
        - name: status-port
          port: 15021
          protocol: TCP
          targetPort: 15021
        - name: http
          port: 80
          targetPort: 8080
          appProtocol: HTTP
        - name: https
          port: 443
          targetPort: 8443
          appProtocol: HTTP2
        type: ClusterIP
      EOF
      
      cat <<EOF > ${WORKDIR}/asm-ig/variant/gateway.yaml
      apiVersion: networking.istio.io/v1beta1
      kind: Gateway
      metadata:
        name: asm-ingressgateway
        namespace: asm-ingress
      spec:
       servers:
        - port:
            number: 443
            name: https
            protocol: HTTPS
          hosts:
          - "*" # IMPORTANT: Must use wildcard here when using SSL, as SNI isn't passed from GFE
          tls:
            mode: SIMPLE
            credentialName: edge2mesh-credential
      EOF
      
      cat <<EOF > ${WORKDIR}/asm-ig/variant/kustomization.yaml
      namespace: asm-ingress
      resources:
      - ../base
      - role.yaml
      - rolebinding.yaml
      patches:
      - path: service-proto-type.yaml
        target:
          kind: Service
      - path: gateway.yaml
        target:
          kind: Gateway
      EOF
      
    6. Terapkan konfigurasi gateway ingress ke kedua cluster:

      kubectl --context ${CLUSTER_1_NAME} apply -k ${WORKDIR}/asm-ig/variant
      kubectl --context ${CLUSTER_2_NAME} apply -k ${WORKDIR}/asm-ig/variant
      

    Mengekspos pod gateway ingress ke load balancer menggunakan layanan multi-cluster

    Di bagian ini, Anda akan mengekspor pod gateway ingress melalui ServiceExport resource kustom. Anda harus mengekspor pod gateway ingress melalui resource kustom ServiceExport karena alasan berikut:

    1. Di Cloud Shell, aktifkan Layanan multi-cluster (MCS) untuk fleet:

      gcloud container fleet multi-cluster-services enable
      
    2. Berikan izin IAM yang diperlukan untuk MCS ke project atau fleet:

      gcloud projects add-iam-policy-binding PROJECT_ID \
       --member "serviceAccount:PROJECT_ID.svc.id.goog[gke-mcs/gke-mcs-importer]" \
       --role "roles/compute.networkViewer"
      
    3. Buat file YAML ServiceExport:

      cat <<EOF > ${WORKDIR}/svc_export.yaml
      kind: ServiceExport
      apiVersion: net.gke.io/v1
      metadata:
        name: asm-ingressgateway
        namespace: asm-ingress
      EOF
      
    4. Terapkan file YAML ServiceExport ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/svc_export.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/svc_export.yaml
      

      Jika Anda menerima pesan error berikut, tunggu beberapa saat hingga definisi resource kustom (CRD) MCS diinstal. Kemudian, jalankan kembali perintah untuk menerapkan file YAML ServiceExport ke kedua cluster.

      error: resource mapping not found for name: "asm-ingressgateway" namespace: "asm-ingress" from "svc_export.yaml": no matches for kind "ServiceExport" in version "net.gke.io/v1"
      ensure CRDs are installed first
      

    Buat resource alamat IP eksternal, catatan DNS, dan sertifikat TLS

    Di bagian ini, Anda akan membuat resource jaringan yang mendukung resource load balancing yang Anda buat nanti dalam deployment ini.

    1. Di Cloud Shell, cadangkan alamat IP eksternal statis:

      gcloud compute addresses create mcg-ip --global
      

      Alamat IP statis digunakan oleh resource GKE Gateway. Alamat IP tetap sama, meskipun load balancer eksternal dibuat ulang.

    2. Dapatkan alamat IP statis dan simpan sebagai variabel lingkungan:

      export MCG_IP=$(gcloud compute addresses describe mcg-ip --global --format "value(address)")
      echo ${MCG_IP}
      

      Untuk membuat pemetaan yang stabil dan mudah dipahami ke alamat IP Gateway, Anda harus memiliki data DNS publik.

      Anda dapat menggunakan penyedia DNS dan skema otomatisasi yang Anda inginkan. Deployment ini menggunakan Endpoints, bukan membuat zona DNS terkelola. Endpoints menyediakan data DNS yang dikelola Google gratis untuk alamat IP eksternal.

    3. Jalankan perintah berikut untuk membuat file YAML bernama dns-spec.yaml:

      cat <<EOF > ${WORKDIR}/dns-spec.yaml
      swagger: "2.0"
      info:
        description: "Cloud Endpoints DNS"
        title: "Cloud Endpoints DNS"
        version: "1.0.0"
      paths: {}
      host: "frontend.endpoints.PROJECT_ID.cloud.goog"
      x-google-endpoints:
      - name: "frontend.endpoints.PROJECT_ID.cloud.goog"
        target: "${MCG_IP}"
      EOF
      

      File dns-spec.yaml menentukan data DNS publik dalam bentuk frontend.endpoints.PROJECT_ID.cloud.goog, dengan PROJECT_ID sebagai ID project unik Anda.

    4. Deploy file dns-spec.yaml untuk membuat entri DNS. Proses ini memerlukan waktu beberapa menit.

      gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
      
    5. Buat sertifikat menggunakan Pengelola Sertifikat untuk nama entri DNS yang Anda buat pada langkah sebelumnya:

      gcloud certificate-manager certificates create mcg-cert \
          --domains="frontend.endpoints.PROJECT_ID.cloud.goog"
      

      Sertifikat TLS yang dikelola Google digunakan untuk menghentikan permintaan klien masuk di load balancer.

    6. Buat peta sertifikat:

      gcloud certificate-manager maps create mcg-cert-map
      

      Load balancer mereferensikan sertifikat melalui entri peta sertifikat yang Anda buat pada langkah berikutnya.

    7. Buat entri peta sertifikat untuk sertifikat yang Anda buat sebelumnya di bagian ini:

      gcloud certificate-manager maps entries create mcg-cert-map-entry \
          --map="mcg-cert-map" \
          --certificates="mcg-cert" \
          --hostname="frontend.endpoints.PROJECT_ID.cloud.goog"
      

    Buat kebijakan layanan backend dan resource load balancer

    Di bagian ini, Anda akan menyelesaikan tugas-tugas berikut:

    • Buat kebijakan keamanan Cloud Armor dengan aturan.
    • Buat kebijakan yang memungkinkan load balancer memeriksa responsivitas pod gateway ingress melalui file YAML ServiceExport yang Anda buat sebelumnya.
    • Gunakan GKE Gateway API untuk membuat resource load balancer.
    • Gunakan resource kustom GatewayClass untuk menetapkan jenis load balancer tertentu.
    • Aktifkan load balancing multi-cluster untuk fleet dan tetapkan salah satu cluster sebagai cluster konfigurasi untuk fleet.
    1. Di Cloud Shell, buat kebijakan keamanan Cloud Armor:

      gcloud compute security-policies create edge-fw-policy \
          --description "Block XSS attacks"
      
    2. Buat aturan untuk kebijakan keamanan:

      gcloud compute security-policies rules create 1000 \
          --security-policy edge-fw-policy \
          --expression "evaluatePreconfiguredExpr('xss-stable')" \
          --action "deny-403" \
          --description "XSS attack filtering"
      
    3. Buat file YAML untuk kebijakan keamanan, dan rujuk file YAML ServiceExport melalui file YAML ServiceImport yang sesuai:

      cat <<EOF > ${WORKDIR}/cloud-armor-backendpolicy.yaml
      apiVersion: networking.gke.io/v1
      kind: GCPBackendPolicy
      metadata:
        name: cloud-armor-backendpolicy
        namespace: asm-ingress
      spec:
        default:
          securityPolicy: edge-fw-policy
        targetRef:
          group: net.gke.io
          kind: ServiceImport
          name: asm-ingressgateway
      EOF
      
    4. Terapkan kebijakan Cloud Armor ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
      
    5. Buat file YAML kustom yang memungkinkan load balancer melakukan health check terhadap endpoint health Envoy (port 15021 di jalur /healthz/ready) pod gateway ingress di kedua cluster:

      cat <<EOF > ${WORKDIR}/ingress-gateway-healthcheck.yaml
      apiVersion: networking.gke.io/v1
      kind: HealthCheckPolicy
      metadata:
        name: ingress-gateway-healthcheck
        namespace: asm-ingress
      spec:
        default:
          config:
            httpHealthCheck:
              port: 15021
              portSpecification: USE_FIXED_PORT
              requestPath: /healthz/ready
            type: HTTP
        targetRef:
          group: net.gke.io
          kind: ServiceImport
          name: asm-ingressgateway
      EOF
      
    6. Terapkan file YAML kustom yang Anda buat pada langkah sebelumnya ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
      
    7. Aktifkan load balancing multi-cluster untuk fleet, dan tetapkan CLUSTER_1_NAME sebagai cluster konfigurasi:

      gcloud container fleet ingress enable \
        --config-membership=${CLUSTER_1_NAME} \
        --location=${CLUSTER_1_REGION}
      
    8. Berikan izin IAM untuk pengontrol Gateway di fleet:

      gcloud projects add-iam-policy-binding PROJECT_ID \
          --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress." \
          --role "roles/container.admin"
      
    9. Buat file YAML load balancer melalui resource kustom Gateway yang mereferensikan gke-l7-global-external-managed-mc gatewayClass dan alamat IP statis yang Anda buat sebelumnya:

      cat <<EOF > ${WORKDIR}/frontend-gateway.yaml
      kind: Gateway
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: external-http
        namespace: asm-ingress
        annotations:
          networking.gke.io/certmap: mcg-cert-map
      spec:
        gatewayClassName: gke-l7-global-external-managed-mc
        listeners:
        - name: http # list the port only so we can redirect any incoming http requests to https
          protocol: HTTP
          port: 80
        - name: https
          protocol: HTTPS
          port: 443
          allowedRoutes:
            kinds:
            - kind: HTTPRoute
        addresses:
        - type: NamedAddress
          value: mcg-ip
      EOF
      
    10. Terapkan file YAML frontend-gateway ke kedua cluster. Hanya CLUSTER_1_NAME yang bersifat otoritatif, kecuali jika Anda menetapkan cluster konfigurasi lain sebagai otoritatif:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      
    11. Buat file YAML HTTPRoute bernama default-httproute.yaml yang menginstruksikan resource Gateway untuk mengirim permintaan ke gateway ingress:

      cat << EOF > ${WORKDIR}/default-httproute.yaml
      apiVersion: gateway.networking.k8s.io/v1
      kind: HTTPRoute
      metadata:
        name: default-httproute
        namespace: asm-ingress
      spec:
        parentRefs:
        - name: external-http
          namespace: asm-ingress
          sectionName: https
        rules:
        - backendRefs:
          - group: net.gke.io
            kind: ServiceImport
            name: asm-ingressgateway
            port: 443
      EOF
      
    12. Terapkan file YAML HTTPRoute yang Anda buat di langkah sebelumnya ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      
    13. Untuk melakukan pengalihan HTTP ke HTTP(S), buat file YAML HTTPRoute tambahan yang disebut default-httproute-redirect.yaml:

      cat << EOF > ${WORKDIR}/default-httproute-redirect.yaml
      kind: HTTPRoute
      apiVersion: gateway.networking.k8s.io/v1
      metadata:
        name: http-to-https-redirect-httproute
        namespace: asm-ingress
      spec:
        parentRefs:
        - name: external-http
          namespace: asm-ingress
          sectionName: http
        rules:
        - filters:
          - type: RequestRedirect
            requestRedirect:
              scheme: https
              statusCode: 301
      EOF
      
    14. Terapkan file YAML pengalihan HTTPRoute ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute-redirect.yaml
      
    15. Periksa resource Gateway untuk memeriksa progres deployment load balancer:

      kubectl --context=${CLUSTER_1_NAME} describe gateway external-http -n asm-ingress
      

      Output menampilkan informasi yang Anda masukkan di bagian ini.

    Men-deploy aplikasi contoh whereami

    Panduan ini menggunakan whereami sebagai aplikasi contoh untuk memberikan masukan langsung tentang cluster mana yang merespons permintaan. Bagian berikut menyiapkan dua deployment terpisah dari whereami di kedua cluster: deployment frontend dan deployment backend.

    Deployment frontend adalah beban kerja pertama yang menerima permintaan. Kemudian, deployment backend akan dipanggil.

    Model ini digunakan untuk mendemonstrasikan arsitektur aplikasi multi-layanan. Layanan frontend dan backend di-deploy ke kedua cluster.

    1. Di Cloud Shell, buat namespace untuk whereami frontend dan whereami backend di kedua cluster dan aktifkan penyisipan namespace:

      kubectl --context=${CLUSTER_1_NAME} create ns frontend
      kubectl --context=${CLUSTER_1_NAME} label namespace frontend istio-injection=enabled
      kubectl --context=${CLUSTER_1_NAME} create ns backend
      kubectl --context=${CLUSTER_1_NAME} label namespace backend istio-injection=enabled
      kubectl --context=${CLUSTER_2_NAME} create ns frontend
      kubectl --context=${CLUSTER_2_NAME} label namespace frontend istio-injection=enabled
      kubectl --context=${CLUSTER_2_NAME} create ns backend
      kubectl --context=${CLUSTER_2_NAME} label namespace backend istio-injection=enabled
      
    2. Buat varian kustomize untuk whereami backend:

      mkdir -p ${WORKDIR}/whereami-backend/base
      
      cat <<EOF > ${WORKDIR}/whereami-backend/base/kustomization.yaml
      resources:
        - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s
      EOF
      
      mkdir ${WORKDIR}/whereami-backend/variant
      
      cat <<EOF > ${WORKDIR}/whereami-backend/variant/cm-flag.yaml
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: whereami
      data:
        BACKEND_ENABLED: "False" # assuming you don't want a chain of backend calls
        METADATA:        "backend"
      EOF
      
      cat <<EOF > ${WORKDIR}/whereami-backend/variant/service-type.yaml
      apiVersion: "v1"
      kind: "Service"
      metadata:
        name: "whereami"
      spec:
        type: ClusterIP
      EOF
      
      cat <<EOF > ${WORKDIR}/whereami-backend/variant/kustomization.yaml
      nameSuffix: "-backend"
      namespace: backend
      commonLabels:
        app: whereami-backend
      resources:
      - ../base
      patches:
      - path: cm-flag.yaml
        target:
          kind: ConfigMap
      - path: service-type.yaml
        target:
          kind: Service
      EOF
      
    3. Terapkan varian whereami backend ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      
    4. Buat varian kustomize untuk whereami frontend:

      mkdir -p ${WORKDIR}/whereami-frontend/base
      
      cat <<EOF > ${WORKDIR}/whereami-frontend/base/kustomization.yaml
      resources:
        - github.com/GoogleCloudPlatform/kubernetes-engine-samples/quickstarts/whereami/k8s
      EOF
      
      mkdir whereami-frontend/variant
      
      cat <<EOF > ${WORKDIR}/whereami-frontend/variant/cm-flag.yaml
      apiVersion: v1
      kind: ConfigMap
      metadata:
        name: whereami
      data:
        BACKEND_ENABLED: "True"
        BACKEND_SERVICE: "http://whereami-backend.backend.svc.cluster.local"
      EOF
      
      cat <<EOF > ${WORKDIR}/whereami-frontend/variant/service-type.yaml
      apiVersion: "v1"
      kind: "Service"
      metadata:
        name: "whereami"
      spec:
        type: ClusterIP
      EOF
      
      cat <<EOF > ${WORKDIR}/whereami-frontend/variant/kustomization.yaml
      nameSuffix: "-frontend"
      namespace: frontend
      commonLabels:
        app: whereami-frontend
      resources:
      - ../base
      patches:
      - path: cm-flag.yaml
        target:
          kind: ConfigMap
      - path: service-type.yaml
        target:
          kind: Service
      EOF
      
    5. Terapkan varian whereami frontend ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      
    6. Buat file YAML VirtualService untuk merutekan permintaan ke frontend whereami:

      cat << EOF > ${WORKDIR}/frontend-vs.yaml
      apiVersion: networking.istio.io/v1beta1
      kind: VirtualService
      metadata:
        name: whereami-vs
        namespace: frontend
      spec:
        gateways:
        - asm-ingress/asm-ingressgateway
        hosts:
        - 'frontend.endpoints.PROJECT_ID.cloud.goog'
        http:
        - route:
          - destination:
              host: whereami-frontend
              port:
                number: 80
      EOF
      
    7. Terapkan file YAML frontend-vs ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      
    8. Setelah men-deploy frontend-vs.yaml ke kedua cluster, coba panggil endpoint publik untuk cluster Anda:

      curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq
      

      Outputnya mirip dengan hal berikut ini:

      {
        "backend_result": {
          "cluster_name": "edge-to-mesh-02",
          "gce_instance_id": "8396338201253702608",
          "gce_service_account": "e2m-mcg-01.svc.id.goog",
          "host_header": "whereami-backend.backend.svc.cluster.local",
          "metadata": "backend",
          "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-645h",
          "pod_ip": "10.124.0.199",
          "pod_name": "whereami-backend-7cbdfd788-8mmnq",
          "pod_name_emoji": "📸",
          "pod_namespace": "backend",
          "pod_service_account": "whereami-backend",
          "project_id": "e2m-mcg-01",
          "timestamp": "2023-12-01T03:46:24",
          "zone": "us-east4-b"
        },
        "cluster_name": "edge-to-mesh-01",
        "gce_instance_id": "1047264075324910451",
        "gce_service_account": "e2m-mcg-01.svc.id.goog",
        "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog",
        "metadata": "frontend",
        "node_name": "gk3-edge-to-mesh-01-pool-2-d687e3c0-5kf2",
        "pod_ip": "10.54.1.71",
        "pod_name": "whereami-frontend-69c4c867cb-dgg8t",
        "pod_name_emoji": "🪴",
        "pod_namespace": "frontend",
        "pod_service_account": "whereami-frontend",
        "project_id": "e2m-mcg-01",
        "timestamp": "2023-12-01T03:46:24",
        "zone": "us-central1-c"
      }
      

    Jika menjalankan perintah curl beberapa kali, Anda akan melihat bahwa respons (baik dari frontend maupun backend) berasal dari region yang berbeda. Dalam responsnya, load balancer menyediakan perutean geografis. Artinya, load balancer merutekan permintaan dari klien ke cluster aktif terdekat, tetapi permintaan masih mendarat secara acak. Jika permintaan sesekali berpindah dari satu region ke region lain, latensi dan biaya akan meningkat.

    Di bagian berikutnya, Anda akan menerapkan load balancing lokalitas di mesh layanan untuk menjaga permintaan tetap lokal.

    Mengaktifkan dan menguji load balancing lokalitas untuk whereami

    Di bagian ini, Anda akan menerapkan load balancing lokalitas di service mesh untuk menjaga permintaan tetap lokal. Anda juga melakukan beberapa pengujian untuk melihat cara whereami menangani berbagai skenario kegagalan.

    Saat Anda membuat permintaan ke layanan whereami frontend, load balancer akan mengirim permintaan ke cluster dengan latensi terendah relatif terhadap klien. Artinya, pod gateway ingress dalam mesh memuat permintaan load balance ke pod whereami frontend di kedua cluster. Bagian ini akan mengatasi masalah tersebut dengan mengaktifkan load balancing lokalitas dalam mesh.

    1. Di Cloud Shell, buat file YAML DestinationRule yang mengaktifkan failover regional load balancing lokalitas ke layanan frontend:

      cat << EOF > ${WORKDIR}/frontend-dr.yaml
      apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      metadata:
        name: frontend
        namespace: frontend
      spec:
        host: whereami-frontend.frontend.svc.cluster.local
        trafficPolicy:
          connectionPool:
            http:
              maxRequestsPerConnection: 0
          loadBalancer:
            simple: LEAST_REQUEST
            localityLbSetting:
              enabled: true
          outlierDetection:
            consecutive5xxErrors: 1
            interval: 1s
            baseEjectionTime: 1m
      EOF
      

      Contoh kode sebelumnya hanya mengaktifkan perutean lokal untuk layanan frontend. Anda juga memerlukan konfigurasi tambahan yang menangani backend.

    2. Terapkan file YAML frontend-dr ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      
    3. Buat file YAML DestinationRule yang memungkinkan failover regional penyeimbangan beban lokalitas ke layanan backend:

      cat << EOF > ${WORKDIR}/backend-dr.yaml
      apiVersion: networking.istio.io/v1beta1
      kind: DestinationRule
      metadata:
        name: backend
        namespace: backend
      spec:
        host: whereami-backend.backend.svc.cluster.local
        trafficPolicy:
          connectionPool:
            http:
              maxRequestsPerConnection: 0
          loadBalancer:
            simple: LEAST_REQUEST
            localityLbSetting:
              enabled: true
          outlierDetection:
            consecutive5xxErrors: 1
            interval: 1s
            baseEjectionTime: 1m
      EOF
      
    4. Terapkan file YAML backend-dr ke kedua cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/backend-dr.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/backend-dr.yaml
      

      Dengan kedua set file YAML DestinationRule yang diterapkan ke kedua cluster, permintaan tetap bersifat lokal untuk cluster yang menjadi tujuan perutean permintaan.

      Untuk menguji failover layanan frontend, kurangi jumlah replika untuk gateway ingress di cluster utama Anda.

      Dari perspektif load balancer multi-regional, tindakan ini menyimulasikan kegagalan cluster. Hal ini menyebabkan cluster tersebut gagal dalam health check load balancer. Contoh ini menggunakan cluster di CLUSTER_1_REGION. Anda hanya akan melihat respons dari cluster di CLUSTER_2_REGION.

    5. Kurangi jumlah replika untuk gateway ingress di cluster utama Anda menjadi nol dan panggil endpoint publik untuk memverifikasi bahwa permintaan telah di-failover ke cluster lain:

      kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=0 deployment/asm-ingressgateway
      

      Output akan terlihat seperti berikut:

      $ curl -s https://frontend.endpoints.PROJECT_ID.cloud.goog | jq
      {
        "backend_result": {
          "cluster_name": "edge-to-mesh-02",
          "gce_instance_id": "2717459599837162415",
          "gce_service_account": "e2m-mcg-01.svc.id.goog",
          "host_header": "whereami-backend.backend.svc.cluster.local",
          "metadata": "backend",
          "node_name": "gk3-edge-to-mesh-02-pool-2-675f6abf-dxs2",
          "pod_ip": "10.124.1.7",
          "pod_name": "whereami-backend-7cbdfd788-mp8zv",
          "pod_name_emoji": "🏌🏽‍♀",
          "pod_namespace": "backend",
          "pod_service_account": "whereami-backend",
          "project_id": "e2m-mcg-01",
          "timestamp": "2023-12-01T05:41:18",
          "zone": "us-east4-b"
        },
        "cluster_name": "edge-to-mesh-02",
        "gce_instance_id": "6983018919754001204",
        "gce_service_account": "e2m-mcg-01.svc.id.goog",
        "host_header": "frontend.endpoints.e2m-mcg-01.cloud.goog",
        "metadata": "frontend",
        "node_name": "gk3-edge-to-mesh-02-pool-3-d42ddfbf-qmkn",
        "pod_ip": "10.124.1.142",
        "pod_name": "whereami-frontend-69c4c867cb-xf8db",
        "pod_name_emoji": "🏴",
        "pod_namespace": "frontend",
        "pod_service_account": "whereami-frontend",
        "project_id": "e2m-mcg-01",
        "timestamp": "2023-12-01T05:41:18",
        "zone": "us-east4-b"
      }
      
    6. Untuk melanjutkan perutean traffic normal, pulihkan replika gateway ingress ke nilai aslinya di cluster:

      kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=3 deployment/asm-ingressgateway
      
    7. Simulasikan kegagalan untuk layanan backend, dengan mengurangi jumlah replika di region utama menjadi 0:

      kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=0 deployment/whereami-backend
      

      Verifikasi bahwa respons dari layanan frontend berasal dari region utama us-central1 melalui load balancer, dan respons dari layanan backend berasal dari region sekunder us-east4.

      Output juga harus menyertakan respons untuk layanan frontend dari region utama (us-central1), dan respons untuk layanan backend dari region sekunder (us-east4), seperti yang diharapkan.

    8. Pulihkan replika layanan backend ke nilai aslinya untuk melanjutkan perutean traffic normal:

      kubectl --context=${CLUSTER_1_NAME} -n backend scale --replicas=3 deployment/whereami-backend
      

    Sekarang Anda memiliki load balancer HTTP(S) global yang berfungsi sebagai frontend untuk aplikasi multi-region yang dihosting di mesh layanan.

    Pembersihan

    Agar tidak dikenai biaya pada Google Cloud akun Anda untuk resource yang digunakan dalam deployment ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

    Menghapus project

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Menghapus resource satu per satu

    Jika ingin mempertahankan Google Cloud project yang Anda gunakan dalam deployment ini, hapus masing-masing resource:

    1. Di Cloud Shell, hapus resource HTTPRoute:

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute-redirect.yaml
      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/default-httproute.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/default-httproute.yaml
      
    2. Hapus resource GKE Gateway:

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml
      
    3. Hapus kebijakan:

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
      
    4. Hapus ekspor layanan:

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml
      
    5. Hapus resource Cloud Armor:

      gcloud --project=PROJECT_ID compute security-policies rules delete 1000 --security-policy edge-fw-policy --quiet
      gcloud --project=PROJECT_ID compute security-policies delete edge-fw-policy --quiet
      
    6. Hapus resource Certificate Manager:

      gcloud --project=PROJECT_ID certificate-manager maps entries delete mcg-cert-map-entry --map="mcg-cert-map" --quiet
      gcloud --project=PROJECT_ID certificate-manager maps delete mcg-cert-map --quiet
      gcloud --project=PROJECT_ID certificate-manager certificates delete mcg-cert --quiet
      
    7. Hapus entri DNS Endpoint:

      gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
      
    8. Hapus alamat IP statis:

      gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
      
    9. Hapus cluster GKE Autopilot. Langkah ini memerlukan waktu beberapa menit.

      gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_1_NAME} --region ${CLUSTER_1_REGION} --quiet
      gcloud --project=PROJECT_ID container clusters delete ${CLUSTER_2_NAME} --region ${CLUSTER_2_REGION} --quiet
      

    Langkah berikutnya

    Kontributor

    Penulis:

    Kontributor lainnya: