Da dispositivi periferici a mesh multi-cluster: esegui il deployment di applicazioni distribuite a livello globale tramite GKE Gateway e Cloud Service Mesh

Last reviewed 2024-06-30 UTC

Questo documento mostra come svolgere le seguenti attività:

Questa guida all'implementazione è rivolta agli amministratori della piattaforma. È anche destinato ai professionisti esperti che eseguono Cloud Service Mesh. Le istruzioni funzionano anche per Istio su GKE.

Architettura

Il seguente diagramma mostra la topologia di ingresso predefinita di un mesh di servizi: un bilanciatore del carico TCP/UDP esterno che espone i proxy del gateway di ingresso su un singolo cluster:

Un bilanciatore del carico esterno instrada i client esterni al mesh tramite i proxy del gateway in entrata.

Questa guida al deployment utilizza le risorse gateway di Google Kubernetes Engine (GKE). In particolare, utilizza un gateway multicluster per configurare il bilanciamento del carico multiregionale davanti a più cluster Autopilot distribuiti in due regioni.

Crittografia TLS dal client, da un bilanciatore del carico e dalla mesh.

Il diagramma precedente mostra il flusso dei dati negli scenari di ingresso cloud e ingresso mesh. Per saperne di più, consulta la spiegazione del diagramma dell'architettura nel documento di architettura di riferimento associato.

Obiettivi

  • Esegui il deployment di una coppia di cluster GKE Autopilot su Google Cloud nella stessa fleet.
  • Esegui il deployment di un Cloud Service Mesh basato su Istio nella stessa flotta.
  • Configura un bilanciatore del carico utilizzando GKE Gateway per terminare il traffico HTTPS pubblico.
  • Dirigi il traffico HTTPS pubblico alle applicazioni ospitate da Cloud Service Mesh di cui è stato eseguito il deployment in più cluster e regioni.
  • Esegui il deployment dell'applicazione di esempio whereami in entrambi i cluster Autopilot.

Ottimizzazione dei costi

In questo documento vengono utilizzati i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi in base all'utilizzo previsto, utilizza il calcolatore prezzi.

I nuovi utenti di Google Cloud potrebbero avere diritto a una prova senza costi.

Al termine delle attività descritte in questo documento, puoi evitare l'addebito di ulteriori costi eliminando le risorse che hai creato. Per ulteriori informazioni, vedi Pulizia.

Prima di iniziare

  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

    Esegui tutti i comandi del terminale per questo deployment da Cloud Shell.

  4. Imposta il progetto Google Cloud predefinito:

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

    Sostituisci PROJECT_ID con l'ID del progetto che vuoi utilizzare per questo deployment.

  5. Crea una directory di lavoro:

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

    In questa sezione, creerai cluster GKE per ospitare le applicazioni e l'infrastruttura di supporto, che creerai più avanti in questa guida al deployment.

    1. In Cloud Shell, crea un nuovo file kubeconfig. Questo passaggio assicura di non creare un conflitto con il file kubeconfig esistente (predefinito).

      touch edge2mesh_mr_kubeconfig
      export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
      
    2. Definisci le variabili di ambiente utilizzate durante la creazione dei cluster GKE e delle risorse al loro interno. Modifica le scelte della regione predefinita in base alle tue esigenze.

      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. Abilita le API Google Cloud utilizzate in questa guida:

      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. Crea un cluster GKE Autopilot con nodi privati in CLUSTER_1_REGION. Utilizza il flag --async per evitare di attendere il provisioning e la registrazione del primo cluster nel parco risorse:

      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. Crea e registra un secondo cluster Autopilot in 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. Assicurati che i cluster siano in esecuzione. Potrebbero essere necessari fino a 20 minuti prima che tutti i cluster siano in esecuzione:

      gcloud container clusters list
      

      L'output è simile al seguente:

      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. Raccogli le credenziali per CLUSTER_1_NAME.Hai creato CLUSTER_1_NAMEin modo asincrono per poter eseguire comandi aggiuntivi durante il provisioning del cluster.

      gcloud container clusters get-credentials ${CLUSTER_1_NAME} \
          --region ${CLUSTER_1_REGION}
      
    8. Per chiarire i nomi dei contesti Kubernetes, rinominali con i nomi dei 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}
      

    Installare un mesh di servizi

    In questa sezione configuri Cloud Service Mesh gestito con l'API Fleet. L'utilizzo dell'API Fleet per abilitare Cloud Service Mesh fornisce un approccio dichiarativo per il provisioning di unmesh di servizih.

    1. In Cloud Shell, abilita Cloud Service Mesh sul parco risorse:

      gcloud container fleet mesh enable
      
    2. Abilita la gestione automatica del control plane e del data plane:

      gcloud container fleet mesh update \
        --management automatic \
        --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}
      
    3. Attendi circa 20 minuti. Quindi, verifica che lo stato del control plane sia ACTIVE:

      gcloud container fleet mesh describe
      

      L'output è simile al seguente:

      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'
      

    Esegui il deployment di un bilanciatore del carico delle applicazioni esterno e crea gateway Ingress

    In questa sezione, esegui il deployment di un bilanciatore del carico delle applicazioni esterno tramite il controller GKE Gateway e crea gateway Ingress per entrambi i cluster. Le risorse gateway e gatewayClass automatizzano il provisioning del bilanciatore del carico e il controllo di integrità del backend. Per fornire la terminazione TLS sul bilanciatore del carico, crea risorse Certificate Manager e collegale al bilanciatore del carico. Inoltre, utilizzi Endpoints per eseguire il provisioning automatico di un nome DNS pubblico per l'applicazione.

    Installa un gateway in entrata su entrambi i cluster

    Come best practice di sicurezza, ti consigliamo di eseguire il deployment del gateway in entrata in uno spazio dei nomi diverso dal piano di controllo del mesh.

    1. In Cloud Shell, crea uno spazio dei nomi asm-ingress dedicato su ogni cluster:

      kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress
      kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingress
      
    2. Aggiungi un'etichetta dello spazio dei nomi agli spazi dei nomi 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
      

      L'output è simile al seguente:

      namespace/asm-ingress labeled
      

      L'etichettatura degli spazi dei nomi asm-ingress con istio-injection=enabled indica a Cloud Service Mesh di inserire automaticamente i proxy sidecar Envoy quando viene eseguito il deployment di un pod.

    3. Genera un certificato autofirmato per un utilizzo futuro:

      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
      

      Il certificato fornisce un ulteriore livello di crittografia tra il bilanciatore del carico e i gateway di ingresso del mesh di servizi. Consente inoltre il supporto di protocolli basati su HTTP/2 come gRPC. Le istruzioni su come collegare il certificato autofirmato ai gateway Ingress sono fornite più avanti in Crea risorse di indirizzo IP esterno, record DNS e certificato TLS.

      Per saperne di più sui requisiti del certificato del gateway in entrata, consulta Crittografia dal bilanciatore del carico ai backend.

    4. Crea un secret di Kubernetes su ogni cluster per archiviare il certificato autofirmato:

      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. Per l'integrazione con il bilanciatore del carico delle applicazioni esterno, crea una variante kustomize per configurare le risorse del 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. Applica la configurazione del gateway Ingress a entrambi i cluster:

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

    Esporre i pod del gateway in entrata al bilanciatore del carico utilizzando un servizio multi-cluster

    In questa sezione, esporti i pod del gateway in entrata tramite una risorsa personalizzata ServiceExport. Devi esportare i pod del gateway in entrata tramite una risorsa personalizzata ServiceExport per i seguenti motivi:

    1. In Cloud Shell, abilita i servizi multi-cluster (MCS) per il parco risorse:

      gcloud container fleet multi-cluster-services enable
      
    2. Concedi a MCS le autorizzazioni IAM richieste per il progetto o il parco risorse:

      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. Crea il 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. Applica il file YAML ServiceExport a entrambi i cluster:

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

      Se ricevi il seguente messaggio di errore, attendi qualche istante per l'installazione delle definizioni di risorse personalizzate (CRD) di MCS. Poi esegui di nuovo i comandi per applicare il file YAML ServiceExport a entrambi i 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
      

    Crea risorse di indirizzo IP esterno, record DNS e certificato TLS

    In questa sezione, creerai le risorse di networking che supportano le risorse di bilanciamento del carico che creerai più avanti in questo deployment.

    1. In Cloud Shell, prenota un indirizzo IP esterno statico:

      gcloud compute addresses create mcg-ip --global
      

      Un indirizzo IP statico viene utilizzato dalla risorsa GKE Gateway. Consente all'indirizzo IP di rimanere invariato, anche se il bilanciatore del carico esterno viene ricreato.

    2. Recupera l'indirizzo IP statico e archivialo come variabile di ambiente:

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

      Per creare un mapping stabile e intuitivo all'indirizzo IP del gateway, devi avere un record DNS pubblico.

      Puoi utilizzare qualsiasi provider DNS e schema di automazione che preferisci. Questo deployment utilizza Endpoints anziché creare una zona DNS gestita. Endpoints fornisce un record DNS gestito da Google gratuito per un indirizzo IP esterno.

    3. Esegui questo comando per creare un file YAML denominato 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
      

      Il file dns-spec.yaml definisce il record DNS pubblico nel formato frontend.endpoints.PROJECT_ID.cloud.goog, dove PROJECT_ID è il tuo identificatore di progetto univoco.

    4. Esegui il deployment del file dns-spec.yaml per creare la voce DNS. Questa procedura richiede alcuni minuti.

      gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
      
    5. Crea un certificato utilizzando Certificate Manager per il nome della voce DNS che hai creato nel passaggio precedente:

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

      Un certificato TLS gestito da Google viene utilizzato per terminare le richieste client in entrata nel bilanciatore del carico.

    6. Crea una mappa dei certificati:

      gcloud certificate-manager maps create mcg-cert-map
      

      Il bilanciatore del carico fa riferimento al certificato tramite la voce della mappa dei certificati che crei nel passaggio successivo.

    7. Crea una voce mappa di certificati per il certificato che hai creato in precedenza in questa sezione:

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

    Crea policy del servizio di backend e risorse del bilanciatore del carico

    In questa sezione svolgerai le seguenti attività:

    • Crea un criterio di sicurezza di Cloud Armor con regole.
    • Crea una policy che consenta al bilanciatore del carico di controllare la reattività dei pod del gateway in entrata tramite il file YAML ServiceExport che hai creato in precedenza.
    • Utilizza l'API GKE Gateway per creare una risorsa bilanciatore del carico.
    • Utilizza la risorsa personalizzata GatewayClass per impostare il tipo di bilanciatore del carico specifico.
    • Abilita il bilanciamento del carico multi-cluster per il parco risorse e designa uno dei cluster come cluster di configurazione per il parco risorse.
    1. In Cloud Shell, crea un criterio di sicurezza di Cloud Armor:

      gcloud compute security-policies create edge-fw-policy \
          --description "Block XSS attacks"
      
    2. Crea una regola per il criterio di sicurezza:

      gcloud compute security-policies rules create 1000 \
          --security-policy edge-fw-policy \
          --expression "evaluatePreconfiguredExpr('xss-stable')" \
          --action "deny-403" \
          --description "XSS attack filtering"
      
    3. Crea un file YAML per la policy di sicurezza e fai riferimento al file YAML ServiceExport tramite un file YAML ServiceImport corrispondente:

      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. Applica il criterio Cloud Armor a entrambi i 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. Crea un file YAML personalizzato che consenta al bilanciatore del carico di eseguire controlli di integrità sull'endpoint di integrità di Envoy (porta 15021 sul percorso /healthz/ready) dei pod del gateway di ingresso in entrambi i 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. Applica il file YAML personalizzato che hai creato nel passaggio precedente a entrambi i 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. Abilita il bilanciamento del carico multi-cluster per il parco risorse e designa CLUSTER_1_NAME come cluster di configurazione:

      gcloud container fleet ingress enable \
        --config-membership=${CLUSTER_1_NAME} \
        --location=${CLUSTER_1_REGION}
      
    8. Concedi autorizzazioni IAM per il controller Gateway nel parco risorse:

      gcloud projects add-iam-policy-binding PROJECT_ID \
          --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \
          --role "roles/container.admin"
      
    9. Crea il file YAML del bilanciatore del carico tramite una risorsa personalizzata Gateway che fa riferimento a gke-l7-global-external-managed-mc gatewayClass e all'indirizzo IP statico che hai creato in precedenza:

      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. Applica il file YAML frontend-gateway a entrambi i cluster. Solo CLUSTER_1_NAME è autorevole, a meno che tu non designi un cluster di configurazione diverso come autorevole:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      
    11. Crea un file YAML HTTPRoute denominato default-httproute.yaml che indica alla risorsa Gateway di inviare richieste ai gateway in entrata:

      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. Applica il file YAML HTTPRoute creato nel passaggio precedente a entrambi i cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      
    13. Per eseguire reindirizzamenti da HTTP a HTTP(S), crea un file YAML HTTPRoute aggiuntivo denominato 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. Applica il file YAML HTTPRoute di reindirizzamento a entrambi i 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. Ispeziona la risorsa Gateway per verificare l'avanzamento del deployment del bilanciatore del carico:

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

      L'output mostra le informazioni inserite in questa sezione.

    Esegui il deployment dell'applicazione di esempio whereami

    Questa guida utilizza whereami come applicazione di esempio per fornire un feedback diretto sui cluster che rispondono alle richieste. La sezione seguente configura due deployment separati di whereami in entrambi i cluster: un deployment frontend e un deployment backend.

    Il deployment frontend è il primo carico di lavoro a ricevere la richiesta. Poi chiama il deployment di backend.

    Questo modello viene utilizzato per dimostrare un'architettura di applicazione multiservizio. I servizi frontend e backend vengono implementati in entrambi i cluster.

    1. In Cloud Shell, crea gli spazi dei nomi per un whereami frontend e un whereami backend in entrambi i cluster e attiva l'inserimento dello spazio dei nomi:

      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. Crea una variante di kustomize per 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. Applica la variante whereami backend a entrambi i cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      
    4. Crea una variante di kustomize per 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. Applica la variante whereami frontend a entrambi i cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      
    6. Crea un file YAML VirtualService per indirizzare le richieste a whereami frontend:

      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. Applica il file YAML frontend-vs a entrambi i cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      
    8. Ora che hai eseguito il deployment di frontend-vs.yaml in entrambi i cluster, prova a chiamare l'endpoint pubblico per i tuoi cluster:

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

      L'output è simile al seguente:

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

    Se esegui il comando curl alcune volte, vedrai che le risposte (sia da frontend che da backend) provengono da regioni diverse. Nella sua risposta, il bilanciatore del carico fornisce il georouting. Ciò significa che il bilanciatore del carico instrada le richieste dal client al cluster attivo più vicino, ma le richieste vengono comunque distribuite in modo casuale. Quando le richieste passano occasionalmente da una regione all'altra, aumentano la latenza e i costi.

    Nella sezione successiva, implementerai il bilanciamento del carico locale nel mesh di servizi per mantenere le richieste locali.

    Attiva e testa il bilanciamento del carico per le località per whereami

    In questa sezione implementi il bilanciamento del carico locale nel mesh di servizi per mantenere le richieste locali. Esegui anche alcuni test per vedere come whereami gestisce vari scenari di errore.

    Quando effettui una richiesta al servizio whereami frontend, il bilanciatore del carico invia la richiesta al cluster con la latenza più bassa rispetto al client. Ciò significa che i pod del gateway in entrata all'interno del mesh bilanciano il carico delle richieste ai pod whereami frontend in entrambi i cluster. Questa sezione risolverà il problema abilitando il bilanciamento del carico locale all'interno della mesh.

    1. In Cloud Shell, crea un file YAML DestinationRule che attiva il failover regionale del bilanciamento del carico locale per il servizio 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
      

      L'esempio di codice precedente attiva il routing locale solo per il servizio frontend. È necessaria anche una configurazione aggiuntiva che gestisca il backend.

    2. Applica il file YAML frontend-dr a entrambi i cluster:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      
    3. Crea un file YAML DestinationRule che attiva il failover regionale del bilanciamento del carico locale per il servizio 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. Applica il file YAML backend-dr a entrambi i cluster:

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

      Con entrambi i set di file YAML DestinationRule applicati a entrambi i cluster, le richieste rimangono locali al cluster a cui vengono indirizzate.

      Per testare il failover per il servizio frontend, riduci il numero di repliche per il gateway in entrata nel cluster principale.

      Dal punto di vista del bilanciatore del carico multiregionale, questa azione simula un errore del cluster. In questo modo, il cluster non supera i controlli di integrità del bilanciatore del carico. Questo esempio utilizza il cluster in CLUSTER_1_REGION. Dovresti visualizzare solo le risposte del cluster in CLUSTER_2_REGION.

    5. Riduci a zero il numero di repliche per il gateway in entrata nel cluster principale e chiama l'endpoint pubblico per verificare che le richieste siano state trasferite all'altro cluster:

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

      L'output dovrebbe essere simile al seguente:

      $ 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. Per riprendere il routing del traffico tipico, ripristina le repliche del gateway in entrata al valore originale nel cluster:

      kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=3 deployment/asm-ingressgateway
      
    7. Simula un errore per il servizio backend riducendo il numero di repliche nella regione primaria a 0:

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

      Verifica che le risposte del servizio frontend provengano dalla regione principale us-central1 tramite il bilanciatore del carico e che le risposte del servizio backend provengano dalla regione secondaria us-east4.

      L'output deve includere anche una risposta per il servizio frontend della regione principale (us-central1) e una risposta per il servizio backend della regione secondaria (us-east4), come previsto.

    8. Ripristina le repliche del servizio di backend al valore originale per riprendere il routing del traffico tipico:

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

    Ora hai un bilanciatore del carico HTTP(S) globale che funge da frontend per la tua applicazione multiregionale ospitata su service mesh.

    Esegui la pulizia

    Per evitare che al tuo account Google Cloud vengano addebitati costi relativi alle risorse utilizzate in questo deployment, elimina il progetto che contiene le risorse oppure mantieni il progetto ed elimina le singole risorse.

    Elimina il progetto

    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.

    Elimina le singole risorse

    Se vuoi conservare il progetto Google Cloud che hai utilizzato in questo deployment, elimina le singole risorse:

    1. In Cloud Shell, elimina le risorse 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. Elimina le risorse del gateway GKE:

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/frontend-gateway.yaml
      
    3. Elimina le norme:

      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. Elimina le esportazioni di servizi:

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml
      
    5. Elimina le risorse 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. Elimina le risorse di 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. Elimina la voce DNS di Endpoints:

      gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
      
    8. Elimina l'indirizzo IP statico:

      gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
      
    9. Elimina i cluster GKE Autopilot. Questo passaggio richiede diversi minuti.

      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
      

    Passaggi successivi

    Collaboratori

    Autori:

    Altri collaboratori: