De la périphérie au réseau multicluster : déployez des applications distribuées à l'échelle mondiale via GKE Gateway et Cloud Service Mesh

Last reviewed 2024-06-30 UTC

Ce document vous explique comment effectuer les tâches suivantes :

Ce guide de déploiement s'adresse aux administrateurs de plates-formes. Il s'adresse également aux professionnels avancés qui utilisent Cloud Service Mesh. Les instructions fonctionnent également pour Istio sur GKE.

Architecture

Le schéma suivant illustre la topologie d'entrée par défaut d'un maillage de services, à savoir un équilibreur de charge TCP/UDP externe qui expose les proxys de passerelle d'entrée sur un seul cluster :

Un équilibreur de charge externe achemine les clients externes vers le maillage via des proxys de passerelle d'entrée.

Ce guide de déploiement utilise les ressources de passerelle Google Kubernetes Engine (GKE). Plus précisément, il utilise une passerelle multicluster pour configurer l'équilibrage de charge multirégional devant plusieurs clusters Autopilot répartis sur deux régions.

Chiffrement TLS à partir du client, d'un équilibreur de charge et du maillage

Le schéma précédent montre comment les données circulent dans les scénarios d'entrée cloud et d'entrée de maillage. Pour en savoir plus, consultez l'explication du schéma d'architecture dans le document d'architecture de référence associé.

Objectifs

  • Déployez une paire de clusters GKE Autopilot sur Google Cloud dans la même flotte.
  • Déployez un Cloud Service Mesh basé sur Istio sur le même parc.
  • Configurez un équilibreur de charge à l'aide de GKE Gateway pour arrêter le trafic HTTPS public.
  • Dirigez le trafic HTTPS public directement vers les applications hébergées par Cloud Service Mesh et déployées dans plusieurs clusters et régions.
  • Déployer l'exemple d'application whereami sur les deux clusters Autopilot.

Optimisation des coûts

Dans ce document, vous utilisez les composants facturables de Google Cloudsuivants :

Obtenez une estimation des coûts en fonction de votre utilisation prévue à l'aide du simulateur de coût.

Les nouveaux utilisateurs de Google Cloud peuvent bénéficier d'un essai gratuit.

Une fois que vous avez terminé les tâches décrites dans ce document, supprimez les ressources que vous avez créées pour éviter que des frais vous soient facturés. Pour en savoir plus, consultez la section Effectuer un nettoyage.

Avant de commencer

  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

    Vous exécutez toutes les commandes de terminal de ce déploiement depuis Cloud Shell.

  4. Définissez votre projet Google Cloud par défaut :

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

    Remplacez PROJECT_ID par l'ID du projet que vous souhaitez utiliser pour ce déploiement.

  5. Créez un répertoire de travail :

    mkdir -p ${HOME}/edge-to-mesh-multi-region
    cd ${HOME}/edge-to-mesh-multi-region
    export WORKDIR=`pwd`
    
  6. Créer des clusters GKE

    Dans cette section, vous allez créer des clusters GKE pour héberger les applications et l'infrastructure associée, que vous créerez plus tard dans ce guide de déploiement.

    1. Dans Cloud Shell, créez un fichier kubeconfig. Cette étape vous permet de ne pas créer de conflit avec votre fichier kubeconfig (par défaut) existant.

      touch edge2mesh_mr_kubeconfig
      export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
      
    2. Définissez les variables d'environnement utilisées lors de la création des clusters GKE et des ressources qu'ils contiennent. Modifiez les choix de région par défaut en fonction de vos besoins.

      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. Activez les API Google Cloud utilisées tout au long de ce guide :

      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. Créez un cluster GKE Autopilot avec des nœuds privés dans CLUSTER_1_REGION. Utilisez l'option --async pour éviter d'attendre que le premier cluster soit provisionné et enregistré dans le parc :

      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. Créez et enregistrez un deuxième cluster Autopilot dans 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. Assurez-vous que les clusters sont en cours d'exécution. Un délai de 20 minutes peut être nécessaire avant que tous les clusters ne soient en cours d'exécution :

      gcloud container clusters list
      

      Le résultat ressemble à ce qui suit :

      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. Rassemblez les identifiants de CLUSTER_1_NAME. Vous avez créé CLUSTER_1_NAME de manière asynchrone afin de pouvoir exécuter des commandes supplémentaires pendant le provisionnement du cluster.

      gcloud container clusters get-credentials ${CLUSTER_1_NAME} \
          --region ${CLUSTER_1_REGION}
      
    8. Pour clarifier les noms des contextes Kubernetes, renommez-les avec les noms des clusters :

      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}
      

    Installer un maillage de services

    Dans cette section, vous configurez le service Cloud Service Mesh géré avec l'API Fleet. L'utilisation de l'API Fleet pour activer Cloud Service Mesh fournit une approche déclarative pour provisionner un maillage de services.

    1. Dans Cloud Shell, activez Cloud Service Mesh sur le parc :

      gcloud container fleet mesh enable
      
    2. Activez la gestion automatique du plan de contrôle et du plan de données :

      gcloud container fleet mesh update \
        --management automatic \
        --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}
      
    3. Patientez 20 minutes environ. Vérifiez ensuite que l'état du plan de contrôle est ACTIVE :

      gcloud container fleet mesh describe
      

      Le résultat ressemble à ce qui suit :

      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'
      

    Déployer un équilibreur de charge d'application externe et créer des passerelles d'entrée

    Dans cette section, vous allez déployer un équilibreur de charge d'application externe via le contrôleur GKE Gateway et créer des passerelles Ingress pour les deux clusters. Les ressources gateway et gatewayClass automatisent le provisionnement de l'équilibreur de charge et la vérification de l'état du backend. Pour fournir une terminaison TLS sur l'équilibreur de charge, vous devez créer des ressources Certificate Manager et les associer à l'équilibreur de charge. De plus, vous utilisez Cloud Endpoints pour provisionner automatiquement un nom DNS public pour l'application.

    Installer une passerelle d'entrée sur les deux clusters

    Pour des raisons de sécurité, nous vous recommandons de déployer la passerelle d'entrée dans un espace de noms différent du plan de contrôle maillé.

    1. Dans Cloud Shell, créez un espace de noms asm-ingress dédié sur chaque cluster :

      kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress
      kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingress
      
    2. Ajoutez un libellé d'espace de noms à l'espace de noms 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
      

      Le résultat ressemble à ce qui suit :

      namespace/asm-ingress labeled
      

      L'ajout d'un libellé istio-injection=enabled aux espaces de noms asm-ingress indique à Cloud Service Mesh d'injecter automatiquement des proxys side-car Envoy lors du déploiement d'un pod.

    3. Générez un certificat autosigné pour une utilisation ultérieure :

      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
      

      Le certificat fournit une couche de chiffrement supplémentaire entre l'équilibreur de charge et les passerelles d'entrée du maillage de services. Il permet également d'utiliser les protocoles basés sur HTTP/2, tels que gRPC. Les instructions pour associer le certificat autosigné aux passerelles d'entrée sont fournies plus loin dans Créer des ressources d'adresse IP externe, d'enregistrement DNS et de certificat TLS.

      Pour en savoir plus sur les exigences liées au certificat de passerelle d'entrée, consultez Chiffrement entre l'équilibreur de charge et les backends.

    4. Créez un secret Kubernetes sur chaque cluster pour stocker le certificat autosigné :

      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. Pour procéder à l'intégration à l'équilibreur de charge d'application externe, créez une variante kustomize pour configurer les ressources de passerelle d'entrée :

      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. Appliquez la configuration de la passerelle d'entrée aux deux clusters :

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

    Exposer les pods de passerelle d'entrée à l'équilibreur de charge à l'aide d'un service multicluster

    Dans cette section, vous allez exporter les pods de la passerelle d'entrée via une ressource personnalisée ServiceExport. Vous devez exporter les pods de la passerelle d'entrée via une ressource personnalisée ServiceExport pour les raisons suivantes :

    1. Dans Cloud Shell, activez les services multiclusters (MCS) pour le parc :

      gcloud container fleet multi-cluster-services enable
      
    2. Accordez à MCS les autorisations IAM requises pour le projet ou le parc :

      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. Créez le fichier YAML ServiceExport :

      cat <<EOF > ${WORKDIR}/svc_export.yaml
      kind: ServiceExport
      apiVersion: net.gke.io/v1
      metadata:
        name: asm-ingressgateway
        namespace: asm-ingress
      EOF
      
    4. Appliquez le fichier YAML ServiceExport aux deux clusters :

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

      Si vous recevez le message d'erreur suivant, attendez quelques instants que les définitions de ressources personnalisées (CRD) MCS s'installent. Ensuite, réexécutez les commandes pour appliquer le fichier YAML ServiceExport aux deux clusters.

      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
      

    Créer des ressources d'adresse IP externe, d'enregistrement DNS et de certificat TLS

    Dans cette section, vous allez créer des ressources réseau qui prennent en charge les ressources d'équilibrage de charge que vous créerez plus tard dans ce déploiement.

    1. Dans Cloud Shell, réservez une adresse IP externe statique :

      gcloud compute addresses create mcg-ip --global
      

      Une adresse IP statique est utilisée par la ressource GKE Gateway. Elle permet à l'adresse IP de rester identique, même si l'équilibreur de charge externe est recréé.

    2. Obtenez l'adresse IP statique et stockez-la en tant que variable d'environnement :

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

      Pour créer un mappage stable et lisible avec votre adresse IP Gateway, vous devez disposer d'un enregistrement DNS public.

      Vous pouvez utiliser le fournisseur DNS de votre choix et l'automatisation de votre choix. Ce déploiement utilise Endpoints au lieu de créer une zone DNS gérée. Endpoints offre un enregistrement DNS géré par Google gratuit pour une adresse IP externe.

    3. Exécutez la commande suivante pour créer un fichier YAML nommé 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
      

      Le fichier dns-spec.yaml définit l'enregistrement DNS public sous la forme frontend.endpoints.PROJECT_ID.cloud.goog, où PROJECT_ID est votre identifiant de projet unique.

    4. Déployez le fichier dns-spec.yaml pour créer l'entrée DNS. Ce processus prend quelques minutes.

      gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
      
    5. Créez un certificat à l'aide du gestionnaire de certificats pour le nom d'entrée DNS que vous avez créé à l'étape précédente :

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

      Un certificat TLS géré par Google est utilisé pour mettre fin aux requêtes client entrantes au niveau de l'équilibreur de charge.

    6. Créer un mappage de certificat

      gcloud certificate-manager maps create mcg-cert-map
      

      L'équilibreur de charge référence le certificat via l'entrée du mappage de certificats que vous allez créer à l'étape suivante.

    7. Créez une entrée de mappage de certificat pour le certificat que vous avez créé précédemment dans cette section :

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

    Créer des règles de service de backend et des ressources d'équilibreur de charge

    Dans cette section, vous allez effectuer les tâches suivantes :

    • Créez une stratégie de sécurité Cloud Armor avec des règles.
    • Créer une règle qui permet à l'équilibreur de charge de vérifier la réactivité des pods de la passerelle d'entrée via le fichier YAML ServiceExport que vous avez créé précédemment.
    • Utiliser l'API GKE Gateway pour créer une ressource d'équilibreur de charge.
    • Utiliser la ressource personnalisée GatewayClass pour définir le type d'équilibreur de charge spécifique.
    • Activer l'équilibrage de charge multicluster pour le parc et désigner l'un des clusters comme cluster de configuration pour le parc.
    1. Dans Cloud Shell, créez une stratégie de sécurité Cloud Armor :

      gcloud compute security-policies create edge-fw-policy \
          --description "Block XSS attacks"
      
    2. Créer une règle pour votre stratégie de sécurité :

      gcloud compute security-policies rules create 1000 \
          --security-policy edge-fw-policy \
          --expression "evaluatePreconfiguredExpr('xss-stable')" \
          --action "deny-403" \
          --description "XSS attack filtering"
      
    3. Créez un fichier YAML pour la stratégie de sécurité et référencer le fichier YAML ServiceExport via un fichier YAML ServiceImport correspondant :

      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. Appliquez la stratégie Cloud Armor aux deux clusters :

      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. Créez un fichier YAML personnalisé qui permet à l'équilibreur de charge d'effectuer des vérifications d'état par rapport au point de terminaison d'état Envoy (port 15021 sur le chemin /healthz/ready) des pods de passerelle d'entrée dans les deux clusters :

      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. Appliquez le fichier YAML personnalisé que vous avez créé à l'étape précédente aux deux clusters :

      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. Activez l'équilibrage de charge multicluster pour le parc et désignez CLUSTER_1_NAME comme cluster de configuration :

      gcloud container fleet ingress enable \
        --config-membership=${CLUSTER_1_NAME} \
        --location=${CLUSTER_1_REGION}
      
    8. Accordez des autorisations IAM pour le contrôleur Gateway dans le parc :

      gcloud projects add-iam-policy-binding PROJECT_ID \
          --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \
          --role "roles/container.admin"
      
    9. Créez le fichier YAML de l'équilibreur de charge via une ressource personnalisée Gateway qui fait référence à gke-l7-global-external-managed-mc gatewayClass et à l'adresse IP statique que vous avez créée précédemment :

      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. Appliquez le fichier YAML frontend-gateway aux deux clusters. Seul CLUSTER_1_NAME fait autorité, sauf si vous désignez un autre cluster de configuration comme faisant autorité :

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      
    11. Créez un fichier YAML HTTPRoute appelé default-httproute.yaml qui indique à la ressource Gateway d'envoyer des requêtes aux passerelles d'entrée :

      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. Appliquez le fichier YAML HTTPRoute que vous avez créé à l'étape précédente aux deux clusters :

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      
    13. Pour effectuer des redirections HTTP vers HTTP(S), créez un fichier YAML HTTPRoute supplémentaire appelé 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. Appliquez le fichier YAML de redirection HTTPRoute aux deux clusters :

      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. Inspectez la ressource Gateway pour vérifier la progression du déploiement de l'équilibreur de charge :

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

      Le résultat affiche les informations que vous avez saisies dans cette section.

    Déployer l'exemple d'application "whereami"

    Ce guide utilise whereami comme exemple d'application pour fournir un retour direct sur les clusters qui répondent aux requêtes. La section suivante configure deux déploiements distincts sur les deux clusters : un déploiement frontend et un déploiement backend.

    Le déploiement frontend est la première charge de travail à recevoir la requête. Il appelle ensuite le déploiement backend.

    Ce modèle est utilisé pour illustrer une architecture d'application multiservice. Les services frontend et backend sont déployés sur les deux clusters.

    1. Dans Cloud Shell, créez les espaces de noms pour un frontend et un backend whereami sur les deux clusters, puis activez l'injection d'espaces de noms :

      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. Créez une variante kustomize pour le backend whereami :

      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. Appliquez la variante backend whereami aux deux clusters :

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      
    4. Créez une variante kustomize pour le frontend whereami :

      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. Appliquez la variante frontend whereami aux deux clusters :

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      
    6. Créez un fichier YAML VirtualService pour acheminer les requêtes vers le 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. Appliquez le fichier YAML frontend-vs aux deux clusters :

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      
    8. Maintenant que vous avez déployé frontend-vs.yaml sur les deux clusters, essayez d'appeler le point de terminaison public de vos clusters :

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

      Le résultat ressemble à ce qui suit :

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

    Si vous exécutez la commande curl plusieurs fois, vous constaterez que les réponses (de frontend et backend) proviennent de différentes régions. Dans sa réponse, l'équilibreur de charge fournit un routage géographique. Cela signifie que l'équilibreur de charge achemine les requêtes du client vers le cluster actif le plus proche, mais que les requêtes arrivent toujours de manière aléatoire. Lorsque des requêtes passent occasionnellement d'une région à une autre, la latence et les coûts augmentent.

    Dans la section suivante, vous allez implémenter l'équilibrage de charge local dans le maillage de services pour conserver les requêtes en local.

    Activer et tester l'équilibrage de charge de la localité pour whereami

    Dans cette section, vous allez implémenter l'équilibrage de charge local dans le maillage de services pour que les requêtes restent locales. Vous effectuez également des tests pour voir comment whereami gère différents scénarios d'échec.

    Lorsque vous envoyez une requête au service frontend whereami, l'équilibreur de charge envoie la requête au cluster ayant la latence la plus faible par rapport au client. Cela signifie que les pods de passerelle d'entrée du réseau maillé équilibrent la charge des requêtes vers les pods frontend whereami sur les deux clusters. Cette section abordera ce problème en activant l'équilibrage de charge de localité dans le maillage.

    1. Dans Cloud Shell, créez un fichier YAML DestinationRule qui active le basculement régional d'équilibrage de charge de la zone vers le service 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'exemple de code précédent n'active le routage local que pour le service frontend. Vous avez également besoin d'une configuration supplémentaire pour gérer le backend.

    2. Appliquez le fichier YAML frontend-dr aux deux clusters :

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      
    3. Créez un fichier YAML DestinationRule qui active le basculement régional d'équilibrage de charge de la zone vers le service 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. Appliquez le fichier YAML backend-dr aux deux clusters :

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

      Une fois les deux ensembles de fichiers YAML DestinationRule appliqués aux deux clusters, les requêtes restent locales au cluster vers lequel elles sont acheminées.

      Pour tester le basculement du service frontend, réduisez le nombre d'instances répliquées de la passerelle d'entrée dans votre cluster principal.

      Du point de vue de l'équilibreur de charge multirégional, cette action simule une défaillance de cluster. Cela entraîne l'échec des vérifications de l'état de l'équilibreur de charge de ce cluster. Cet exemple utilise le cluster dans CLUSTER_1_REGION. Vous ne devriez voir que les réponses du cluster dans CLUSTER_2_REGION.

    5. Réduisez à zéro le nombre d'instances répliquées de la passerelle d'entrée de votre cluster principal, puis appelez le point de terminaison public pour vérifier que les requêtes ont basculé vers l'autre cluster :

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

      La sortie doit ressembler à ceci :

      $ 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. Pour reprendre le routage du trafic standard, restaurez les instances répliquées de la passerelle d'entrée à la valeur d'origine dans le cluster :

      kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=3 deployment/asm-ingressgateway
      
    7. Simulez une défaillance du service backend en réduisant le nombre d'instances répliquées dans la région principale à 0 :

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

      Vérifiez que les réponses du service frontend proviennent de la région principale us-central1 via l'équilibreur de charge et que les réponses du service backend proviennent de la région secondaire us-east4.

      Le résultat doit également inclure une réponse pour le service frontend de la région principale (us-central1) et une réponse pour le service backend de la région secondaire (us-east4), comme prévu.

    8. Restaurez les instances répliquées du service de backend à leur valeur d'origine pour reprendre le routage du trafic classique :

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

    Vous disposez maintenant d'un équilibreur de charge HTTP(S) global servant d'interface à votre application multirégionale hébergée par le maillage de services.

    Effectuer un nettoyage

    Pour éviter que les ressources utilisées dans le cadre de ce déploiement soient facturées sur votre compte Google Cloud , supprimez le projet contenant les ressources, ou conservez le projet et supprimez les ressources individuelles.

    Supprimer le projet

    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.

    Supprimer les ressources individuelles

    Si vous souhaitez conserver le projet Google Cloud que vous avez utilisé dans ce déploiement, supprimez les différentes ressources :

    1. Dans Cloud Shell, supprimez les ressources 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. Supprimez les ressources 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. Supprimez les règles :

      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. Supprimez les exportations de service :

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml
      
    5. Supprimez les ressources 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. Supprimez les ressources du gestionnaire de certificats :

      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. Supprimez l'entrée Endpoints DNS :

      gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
      
    8. Supprimez l'adresse IP statique :

      gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
      
    9. Supprimez les clusters GKE Autopilot. Cette étape prend plusieurs minutes.

      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
      

    Étape suivante

    Contributeurs

    Auteurs :

    Autres contributeurs :