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 di piattaforma. È destinato anche ai professionisti avanzati che utilizzano Cloud Service Mesh. Le istruzioni sono valide anche per Istio on GKE.

Architettura

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

Un bilanciatore del carico esterno instrada i client esterni al mesh tramite i proxy del gateway di ingresso.

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

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

Il diagramma precedente mostra come i dati fluiscono attraverso il traffico in entrata nel cloud e il mesh scenari in entrata. Per ulteriori informazioni, consulta la spiegazione del diagramma dell'architettura nel documento dell'architettura di riferimento associato.

Obiettivi

  • Esegui il deployment di un paio GKE Autopilot cluster su Google Cloud flotta.
  • Distribuisci un Cloud Service Mesh basato su Istio nella stessa flotta.
  • Configura un bilanciatore del carico utilizzando GKE Gateway per terminare il traffico HTTPS pubblico.
  • Indirizza il traffico HTTPS pubblico alle applicazioni ospitati da Cloud Service Mesh e il cui deployment viene eseguito tra cluster e regioni.
  • Esegui il deployment dove di esempio in entrambi i cluster Autopilot.

Ottimizzazione dei costi

In questo documento utilizzi i seguenti componenti fatturabili di Google Cloud:

Per generare una stima dei costi basata sull'utilizzo previsto, utilizza il Calcolatore prezzi. I nuovi utenti di Google Cloud potrebbero essere idonei per una prova gratuita.

Una volta completate le attività descritte in questo documento, puoi evitare la fatturazione continua eliminando le risorse che hai creato. Per ulteriori informazioni, consulta la pagina 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. Make sure 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 da 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`
    

crea cluster GKE

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

  1. In Cloud Shell, crea un nuovo file kubeconfig. Questo passaggio garantisce di non creare un conflitto con le query esistenti (impostazione predefinita) kubeconfig.

    touch edge2mesh_mr_kubeconfig
    export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
    
  2. Definisci le variabili di ambiente da utilizzare durante la creazione cluster GKE e le risorse al loro interno. Modifica le opzioni per la 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 tutti i cluster sono 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 altri comandi di cui è stato eseguito 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}
    

Installa un service mesh

In questa sezione, configurerai Cloud Service Mesh gestito con l'API del parco risorse. L'utilizzo dell'API del parco risorse per abilitare Cloud Service Mesh fornisce una l'approccio dichiarativo al provisioning di un mesh di servizi.

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

    gcloud container fleet mesh enable
    
  2. Attiva la gestione automatica del piano di controllo e del piano dati:

    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 piano di controllo 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 di ingresso

In questa sezione eseguirai il deployment di un bilanciatore del carico delle applicazioni esterno tramite Gateway GKE e crea gateway in entrata per entrambi cluster. Le risorse gateway e gatewayClass automatizzano il provisioning del bilanciatore del carico e del controllo di integrità del backend. Per fornire la terminazione TLS su al bilanciatore del carico, crei Gestore certificati e collegarle al bilanciatore del carico. Inoltre, utilizzi Endpoint per eseguire il provisioning automatico di un nome DNS pubblico per l'applicazione.

Installa un gateway di ingresso su entrambi i cluster

Come best practice per la sicurezza, ti consigliamo di eseguire il deployment del gateway in entrata in uno spazio dei nomi diverso dal piano di controllo 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 incarica Cloud Service Mesh di iniettare automaticamente i proxy sidecar Envoy quando viene eseguito il deployment di un pod.

  3. Genera un certificato autofirmato da utilizzare in 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 il bilanciatore del carico e i gateway in entrata del mesh di servizi. Inoltre, consente per i protocolli basati su HTTP/2 come gRPC. Le istruzioni su come collegare il certificato autofirmato ai gateway in entrata sono fornite più avanti nella sezione Creare risorse di indirizzo IP esterno, record DNS e certificato TLS.

    Per ulteriori informazioni sui requisiti del gateway in entrata certificato, vedi Crittografia dal bilanciatore del carico ai backend.

  4. crea un secret Kubernetes su ciascun cluster per archiviare l'oggetto autofirmato certificato:

    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 di ingresso:

    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 in entrata 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
    

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

In questa sezione esporterai i pod del gateway in entrata tramite un ServiceExport risorsa personalizzata. 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 le definizioni di risorse personalizzate (CRD) MCS da installare. Poi esegui nuovamente 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 risorse di networking che supportano delle risorse di bilanciamento del carico create in un secondo momento in questo deployment.

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

    gcloud compute addresses create mcg-ip --global
    

    Il gateway GKE utilizza un indirizzo IP statico risorsa. Consente di mantenere invariato l'indirizzo IP, anche se il bilanciatore del carico esterno viene ricreato.

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

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

    Per creare una mappatura stabile e facile da usare all'indirizzo IP del gateway, devi avere un record DNS pubblico.

    Puoi utilizzare qualsiasi provider DNS e schema di automazione che preferisci. Questo Il deployment utilizza Endpoints invece di creare un DNS gestito zona di destinazione. Endpoints offre un servizio di DNS gestito da Google 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 sotto forma di frontend.endpoints.PROJECT_ID.cloud.goog, dove PROJECT_ID è il tuo identificativo 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 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 al 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 della mappa dei 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 criteri del servizio di backend e risorse del bilanciatore del carico

In questa sezione svolgerai le seguenti attività:

  • Crea un criterio di sicurezza di Google Cloud Armor con regole.
  • Crea un criterio che consenta al bilanciatore del carico di controllare la reattività dei pod della porta di accesso in entrata tramite il file YAML ServiceExport che hai creato in precedenza.
  • Utilizza l'API GKE Gateway per creare un bilanciatore del carico risorsa.
  • 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 Google 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 il criterio di sicurezza e fai riferimento al ServiceExport file YAML 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 Google 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 di gateway in entrata 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 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 designaCLUSTER_1_NAME come cluster di configurazione:

    gcloud container fleet ingress enable \
      --config-membership=${CLUSTER_1_NAME} \
      --location=${CLUSTER_1_REGION}
    
  8. Concedi le autorizzazioni IAM per il controller del 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 non specifichi una di configurazione di Compute Engine 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 insegni alla risorsa Gateway di inviare richieste ai gateway di ingresso:

    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 che hai creato nel passaggio precedente a in 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 i reindirizzamenti da HTTP a HTTP(S), crea un altro file HTTPRoute YAML 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 di reindirizzamento HTTPRoute 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. Esamina la risorsa gateway per verificare l'avanzamento del bilanciatore del carico deployment:

    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 in cui in entrambi i cluster: un deployment frontend e un backend e deployment continuo.

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

Questo modello viene utilizzato per dimostrare un'architettura delle applicazioni multi-servizio. Viene eseguito il deployment di entrambi i servizi frontend e backend in entrambi i cluster.

  1. In Cloud Shell, crea gli spazi dei nomi per un whereamifrontend e un whereami backend in entrambi i cluster e attiva l'iniezione 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 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 "dove" 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 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 "dove" 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 VirtualService File YAML per instradare le richieste alla posizione 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 di frontend che di backend) provengono da regioni diverse. Nella sua risposta, il bilanciatore del carico fornisce il geo-routing. Ciò significa il bilanciatore del carico instrada le richieste dal client al cluster attivo più vicino, ma le richieste arrivano comunque a caso. Quando le richieste passano occasionalmente da una regione all'altra, aumentano la latenza e il costo.

Nella sezione successiva, implementerai il bilanciamento del carico a livello di località nel mesh di servizi per mantenere le richieste locali.

Abilita e testa il bilanciamento del carico delle località per dove

In questa sezione, implementi il bilanciamento del carico a livello di località nel service mesh per mantenere le richieste locali. Esegui anche alcuni test per vedere il modo in cui doveami gestisce i 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 di alto profilo. Ciò significa che i pod del gateway in entrata all'interno del carico della rete mesh bilanciare le richieste ai pod frontend, in entrambi i cluster. Questa sezione risolverà il problema attivando il bilanciamento del carico per le località all'interno della mesh.

  1. In Cloud Shell, crea un file YAML DestinationRule che abiliti il bilanciamento del carico a livello di località e il failover regionale 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 abilita 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 abiliti il bilanciamento del carico per località con failover regionale per il servizio backend:

    cat << EOF > ${WORKDIR}/backend-dr.yaml
    apiVersion: networking.istio.io/v1beta1
    kind: DestinationRule
    metadata:
    n    ame: 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 gli insiemi di file YAML DestinationRule applicati a entrambi i cluster, le richieste rimangono locali per il cluster a cui vengono indirizzate.

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

    Dal punto di vista del bilanciatore del carico multiregionale, questa azione simula un errore del cluster. provoca un errore di caricamento del cluster di integrità dei bilanciatori del carico. In questo esempio viene utilizzato il cluster in CLUSTER_1_REGION. Dovresti vedere solo le risposte del cluster in CLUSTER_2_REGION.

  5. Riduci il numero di repliche per il gateway in entrata nella tua istanza principale il cluster su zero e chiamare l'endpoint pubblico per verificare che le richieste non siano riuscite nell'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 della porta di ingresso 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 di repliche nella regione principale 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 un'applicazione multiregionale ospitata su una rete mesh di servizi.

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 mantenere il progetto Google Cloud utilizzato in questo dispiegamento, 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 i criteri:

    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 del servizio:

    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 Google 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 del Gestore certificati:

    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 degli endpoint:

    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: