Da extremidade à malha de vários clusters: implemente aplicações distribuídas globalmente através do GKE Gateway e da Cloud Service Mesh

Last reviewed 2024-06-30 UTC

Este documento mostra como realizar as seguintes tarefas:

Este guia de implementação destina-se a administradores da plataforma. Também se destina a profissionais avançados que executam o Cloud Service Mesh. As instruções também funcionam para o Istio no GKE.

Arquitetura

O diagrama seguinte mostra a topologia de entrada predefinida de uma malha de serviços, ou seja, um balanceador de carga de TCP/UDP externo que expõe os proxies de gateway de entrada num único cluster:

Um balanceador de carga externo encaminha clientes externos para a malha através de proxies de gateway de entrada.

Este guia de implementação usa recursos do Gateway do Google Kubernetes Engine (GKE). Especificamente, usa um gateway de vários clusters para configurar o equilíbrio de carga de várias regiões em frente de vários clusters do Autopilot distribuídos por duas regiões.

Encriptação TLS do cliente, de um balanceador de carga e da malha.

O diagrama anterior mostra como os dados fluem através de cenários de entrada na nuvem e de entrada na malha. Para mais informações, consulte a explicação do diagrama de arquitetura no documento de arquitetura de referência associado.

Objetivos

  • Implemente um par de clusters do GKE Autopilot na mesma frota. Google Cloud
  • Implemente uma malha de serviços na nuvem baseada no Istio na mesma frota.
  • Configure um balanceador de carga através do GKE Gateway para terminar o tráfego HTTPS público.
  • Direcionar o tráfego HTTPS público para aplicações alojadas pelo Cloud Service Mesh que são implementadas em vários clusters e regiões.
  • Implemente a aplicação de exemplo whereami nos dois clusters do Autopilot.

Otimização de custos

Neste documento, usa os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custos com base na sua utilização projetada, use a calculadora de preços.

Os novos Google Cloud utilizadores podem ser elegíveis para uma avaliação gratuita.

Quando terminar as tarefas descritas neste documento, pode evitar a faturação contínua eliminando os recursos que criou. Para mais informações, consulte o artigo Limpe.

Antes de começar

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

    Roles required to select or create a project

    • Select a project: Selecting a project doesn't require a specific IAM role—you can select any project that you've been granted a role on.
    • Create a project: To create a project, you need the Project Creator (roles/resourcemanager.projectCreator), which contains the resourcemanager.projects.create permission. Learn how to grant roles.

    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

    Executa todos os comandos do terminal para esta implementação a partir do Cloud Shell.

  4. Defina o seu Google Cloud projeto predefinido:

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

    Substitua PROJECT_ID pelo ID do projeto que quer usar para esta implementação.

  5. Crie um diretório de trabalho:

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

    Nesta secção, cria clusters do GKE para alojar as aplicações e a infraestrutura de apoio, que cria mais tarde neste guia de implementação.

    1. No Cloud Shell, crie um novo ficheiro kubeconfig. Este passo garante que não cria um conflito com o seu ficheiro kubeconfig (predefinido) existente.

      touch edge2mesh_mr_kubeconfig
      export KUBECONFIG=${WORKDIR}/edge2mesh_mr_kubeconfig
      
    2. Defina as variáveis de ambiente que são usadas quando cria os clusters do GKE e os recursos nos mesmos. Modifique as opções de região predefinidas para se adequarem aos seus objetivos.

      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. Ative as APIs Google Cloud que são usadas ao longo deste guia:

      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. Crie um cluster do GKE Autopilot com nós privados em CLUSTER_1_REGION. Use a flag --async para evitar esperar que o primeiro cluster seja aprovisionado e registado na frota:

      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. Crie e registe um segundo cluster do Autopilot em 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. Certifique-se de que os clusters estão em execução. Pode demorar até 20 minutos até que todos os clusters estejam em execução:

      gcloud container clusters list
      

      O resultado é semelhante ao seguinte:

      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. Reúna as credenciais para CLUSTER_1_NAME.Criou-o de forma assíncrona para poder executar comandos adicionais enquanto o cluster era aprovisionado.CLUSTER_1_NAME

      gcloud container clusters get-credentials ${CLUSTER_1_NAME} \
          --region ${CLUSTER_1_REGION}
      
    8. Para esclarecer os nomes dos contextos do Kubernetes, mude o nome para os nomes dos 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}
      

    Instale uma malha de serviço

    Nesta secção, configura a malha de serviços na nuvem gerida com a API Fleet. A utilização da API Fleet para ativar o Cloud Service Mesh oferece uma abordagem declarativa para aprovisionar uma malha de serviços.

    1. No Cloud Shell, ative o Cloud Service Mesh na frota:

      gcloud container fleet mesh enable
      
    2. Ative a gestão automática do plano de controlo e do plano de dados:

      gcloud container fleet mesh update \
        --management automatic \
        --memberships ${CLUSTER_1_NAME},${CLUSTER_2_NAME}
      
    3. Aguarde cerca de 20 minutos. Em seguida, verifique se o estado do plano de controlo é ACTIVE:

      gcloud container fleet mesh describe
      

      O resultado é semelhante ao seguinte:

      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'
      

    Implemente um balanceador de carga de aplicações externo e crie gateways de entrada

    Nesta secção, implementa um Application Load Balancer externo através do controlador do GKE Gateway e cria gateways de entrada para ambos os clusters. Os recursos gateway e gatewayClass automatizam o aprovisionamento do equilibrador de carga e da verificação de funcionamento do back-end. Para fornecer a terminação TLS no balanceador de carga, crie recursos do Gestor de certificados e anexe-os ao balanceador de carga. Além disso, usa pontos finais para aprovisionar automaticamente um nome DNS público para a aplicação.

    Instale um gateway de entrada em ambos os clusters

    Como prática recomendada de segurança, recomendamos que implemente o gateway de entrada num espaço de nomes diferente do plano de controlo da malha.

    1. No Cloud Shell, crie um namespace asm-ingress dedicado em cada cluster:

      kubectl --context=${CLUSTER_1_NAME} create namespace asm-ingress
      kubectl --context=${CLUSTER_2_NAME} create namespace asm-ingress
      
    2. Adicione uma etiqueta de espaço de nomes aos espaços de nomes 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
      

      O resultado é semelhante ao seguinte:

      namespace/asm-ingress labeled
      

      Etiquetar os espaços de nomes asm-ingress com istio-injection=enabled indica ao Cloud Service Mesh que injete automaticamente proxies Envoy sidecar quando um pod é implementado.

    3. Gere um certificado autoassinado para utilização futura:

      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
      

      O certificado oferece uma camada adicional de encriptação entre o equilibrador de carga e os gateways de entrada da malha de serviços. Também permite a compatibilidade com protocolos baseados em HTTP/2, como o gRPC. As instruções sobre como anexar o certificado autoassinado aos gateways de entrada são fornecidas mais adiante em Crie recursos de endereço IP externo, registo DNS e certificado TLS.

      Para mais informações sobre os requisitos do certificado do gateway de entrada, consulte o artigo Encriptação do equilibrador de carga para os back-ends.

    4. Crie um segredo do Kubernetes em cada cluster para armazenar o certificado autossinado:

      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. Para fazer a integração com o Application Load Balancer externo, crie uma variante do kustomize para configurar os recursos do gateway de entrada:

      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. Aplique a configuração do gateway de entrada a ambos os clusters:

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

    Exponha pods de gateway de entrada ao balanceador de carga através de um serviço em vários clusters

    Nesta secção, exporta os pods do gateway de entrada através de um recurso personalizado.ServiceExport Tem de exportar os pods do gateway de entrada através de um recurso personalizado ServiceExport pelos seguintes motivos:

    1. No Cloud Shell, ative os serviços em vários clusters (MCS) para a frota:

      gcloud container fleet multi-cluster-services enable
      
    2. Conceda ao MCS as autorizações de IAM necessárias ao projeto ou à frota:

      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. Crie o ficheiro YAML ServiceExport:

      cat <<EOF > ${WORKDIR}/svc_export.yaml
      kind: ServiceExport
      apiVersion: net.gke.io/v1
      metadata:
        name: asm-ingressgateway
        namespace: asm-ingress
      EOF
      
    4. Aplique o ficheiro YAML ServiceExport a ambos os clusters:

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

      Se receber a seguinte mensagem de erro, aguarde alguns momentos para que as definições de recursos personalizados (CRDs) do MCS sejam instaladas. Em seguida, volte a executar os comandos para aplicar o ServiceExport ficheiro YAML a ambos os 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
      

    Crie recursos de endereço IP externo, registo de DNS e certificado TLS

    Nesta secção, cria recursos de rede que suportam os recursos de balanceamento de carga que cria mais tarde nesta implementação.

    1. No Cloud Shell, reserve um endereço IP externo estático:

      gcloud compute addresses create mcg-ip --global
      

      Um endereço IP estático é usado pelo recurso GKE Gateway. Permite que o endereço IP permaneça o mesmo, mesmo que o balanceador de carga externo seja recriado.

    2. Obtenha o endereço IP estático e armazene-o como uma variável de ambiente:

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

      Para criar um mapeamento estável e fácil de usar para o endereço IP do gateway, tem de ter um registo DNS público.

      Pode usar qualquer fornecedor de DNS e esquema de automatização que quiser. Esta implementação usa os Endpoints em vez de criar uma zona DNS gerida. O Endpoints fornece um registo de DNS gerido pela Google gratuito para um endereço IP externo.

    3. Execute o seguinte comando para criar um ficheiro YAML denominado 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
      

      O ficheiro dns-spec.yaml define o registo de DNS público no formato frontend.endpoints.PROJECT_ID.cloud.goog, em que PROJECT_ID é o identificador exclusivo do seu projeto.

    4. Implemente o ficheiro dns-spec.yaml para criar a entrada DNS. Este processo demora alguns minutos.

      gcloud endpoints services deploy ${WORKDIR}/dns-spec.yaml
      
    5. Crie um certificado com o Gestor de certificados para o nome da entrada DNS que criou no passo anterior:

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

      É usado um certificado TLS gerido pela Google para terminar os pedidos de clientes recebidos no balanceador de carga.

    6. Crie um mapa de certificados:

      gcloud certificate-manager maps create mcg-cert-map
      

      O equilibrador de carga faz referência ao certificado através da entrada do mapa de certificados que cria no passo seguinte.

    7. Crie uma entrada de mapeamento de certificados para o certificado que criou anteriormente nesta secção:

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

    Crie políticas de serviço de back-end e recursos do balanceador de carga

    Nesta secção, conclui as seguintes tarefas:

    • Crie uma política de segurança do Cloud Armor com regras.
    • Crie uma política que permita ao equilibrador de carga verificar a capacidade de resposta dos pods do gateway de entrada através do ServiceExportficheiro YAML que criou anteriormente.
    • Use a API GKE Gateway para criar um recurso de balanceador de carga.
    • Use o recurso personalizado GatewayClass para definir o tipo de equilibrador de carga específico.
    • Ative o balanceamento de carga de vários clusters para a frota e designe um dos clusters como o cluster de configuração da frota.
    1. No Cloud Shell, crie uma política de segurança do Cloud Armor:

      gcloud compute security-policies create edge-fw-policy \
          --description "Block XSS attacks"
      
    2. Crie uma regra para a política de segurança:

      gcloud compute security-policies rules create 1000 \
          --security-policy edge-fw-policy \
          --expression "evaluatePreconfiguredExpr('xss-stable')" \
          --action "deny-403" \
          --description "XSS attack filtering"
      
    3. Crie um ficheiro YAML para a política de segurança e faça referência ao ServiceExport ficheiro YAML através de um ficheiro YAML ServiceImportcorrespondente:

      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. Aplique a política do Cloud Armor a ambos os 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. Crie um ficheiro YAML personalizado que permita ao balanceador de carga realizar verificações de funcionamento no ponto final de funcionamento do Envoy (porta 15021 no caminho /healthz/ready) dos pods do gateway de entrada em ambos os 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. Aplique o ficheiro YAML personalizado que criou no passo anterior a ambos os 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. Ative o equilíbrio de carga de vários clusters para a frota e designe CLUSTER_1_NAME como o cluster de configuração:

      gcloud container fleet ingress enable \
        --config-membership=${CLUSTER_1_NAME} \
        --location=${CLUSTER_1_REGION}
      
    8. Conceda autorizações de IAM para o controlador de gateway na frota:

      gcloud projects add-iam-policy-binding PROJECT_ID \
          --member "serviceAccount:service-${PROJECT_NUMBER}@gcp-sa-multiclusteringress.iam.gserviceaccount.com" \
          --role "roles/container.admin"
      
    9. Crie o ficheiro YAML do equilibrador de carga através de um recurso personalizado do Gateway que faça referência ao gke-l7-global-external-managed-mc gatewayClass e ao endereço IP estático que criou anteriormente:

      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. Aplique o ficheiro YAML frontend-gateway a ambos os clusters. Apenas o cluster de configuração CLUSTER_1_NAME é autoritário, a menos que designe um cluster de configuração diferente como autoritário:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-gateway.yaml
      
    11. Crie um HTTPRoute ficheiro YAML denominado default-httproute.yaml que instrui o recurso Gateway a enviar pedidos para os gateways de entrada:

      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. Aplique o ficheiro HTTPRoute YAML que criou no passo anterior a ambos os clusters:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/default-httproute.yaml
      
    13. Para fazer redirecionamentos de HTTP para HTTP(S), crie um HTTPRouteficheiro YAML adicional denominado 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. Aplique o ficheiro YAML de redirecionamento a ambos os clusters:HTTPRoute

      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. Inspeccione o recurso Gateway para verificar o progresso da implementação do equilibrador de carga:

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

      A saída mostra as informações que introduziu nesta secção.

    Implemente a aplicação de amostra whereami

    Este guia usa a app whereami como uma aplicação de exemplo para fornecer feedback direto sobre os clusters que estão a responder a pedidos. A secção seguinte configura duas implementações separadas de whereami em ambos os clusters: uma implementação frontend e uma implementação backend.

    A implementação frontend é a primeira carga de trabalho a receber o pedido. Em seguida, chama a implementação backend.

    Este modelo é usado para demonstrar uma arquitetura de aplicação de vários serviços. Os serviços frontend e backend são implementados em ambos os clusters.

    1. No Cloud Shell, crie os namespaces para um whereami frontend e um whereami backend em ambos os clusters e ative a injeção de namespace:

      kubectl --context=${CLUSTER_1_NAME} create ns frontend
      kubectl --context=${CLUSTER_1_NAME} label namespace frontend istio-injection=enabled
      kubectl --context=${CLUSTER_1_NAME} create ns backend
      kubectl --context=${CLUSTER_1_NAME} label namespace backend istio-injection=enabled
      kubectl --context=${CLUSTER_2_NAME} create ns frontend
      kubectl --context=${CLUSTER_2_NAME} label namespace frontend istio-injection=enabled
      kubectl --context=${CLUSTER_2_NAME} create ns backend
      kubectl --context=${CLUSTER_2_NAME} label namespace backend istio-injection=enabled
      
    2. Crie uma variante do kustomize para o 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. Aplique a variante whereami backend a ambos os clusters:

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-backend/variant
      
    4. Crie uma variante do kustomize para o 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. Aplique a variante whereami frontend a ambos os clusters:

      kubectl --context=${CLUSTER_1_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      kubectl --context=${CLUSTER_2_NAME} apply -k ${WORKDIR}/whereami-frontend/variant
      
    6. Crie um ficheiro YAML para encaminhar pedidos para o whereami frontend:VirtualService

      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. Aplique o ficheiro YAML frontend-vs a ambos os clusters:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-vs.yaml
      
    8. Agora que implementou o frontend-vs.yaml em ambos os clusters, tente chamar o ponto final público dos seus clusters:

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

      O resultado é semelhante ao seguinte:

      {
        "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 executar o comando curl algumas vezes, vai ver que as respostas (tanto de frontend como de backend) provêm de regiões diferentes. Na respetiva resposta, o balanceador de carga está a fornecer georouting. Isto significa que o balanceador de carga está a encaminhar pedidos do cliente para o cluster ativo mais próximo, mas os pedidos continuam a chegar aleatoriamente. Quando os pedidos vão ocasionalmente de uma região para outra, aumenta a latência e o custo.

    Na secção seguinte, implementa o equilíbrio de carga de localidade na malha de serviços para manter os pedidos locais.

    Ative e teste o equilíbrio de carga de localidade para o whereami

    Nesta secção, implementa o equilíbrio de carga de localidade na malha de serviços para manter os pedidos locais. Também realiza alguns testes para ver como o whereami processa vários cenários de falha.

    Quando faz um pedido ao serviço whereami frontend, o balanceador de carga envia o pedido para o cluster com a latência mais baixa relativamente ao cliente. Isto significa que os pods de gateway de entrada na malha equilibram os pedidos de carga para os pods whereami frontend em ambos os clusters. Esta secção resolve esse problema ativando o balanceamento de carga de localidade na malha.

    1. No Cloud Shell, crie um ficheiro YAML que ative a comutação por falha regional do balanceamento de carga de localidade para o serviço frontend:DestinationRule

      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
      

      O exemplo de código anterior apenas ativa o encaminhamento local para o serviço frontend. Também precisa de uma configuração adicional que processe o back-end.

    2. Aplique o ficheiro YAML frontend-dr a ambos os clusters:

      kubectl --context=${CLUSTER_1_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      kubectl --context=${CLUSTER_2_NAME} apply -f ${WORKDIR}/frontend-dr.yaml
      
    3. Crie um DestinationRuleficheiro YAML que ative o balanceamento de carga de localidade para a comutação por falha regional para o serviço 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. Aplique o ficheiro YAML backend-dr a ambos os clusters:

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

      Com os dois conjuntos de ficheiros YAML DestinationRule aplicados a ambos os clusters, os pedidos permanecem locais para o cluster para o qual o pedido é encaminhado.

      Para testar a ativação pós-falha do serviço frontend, reduza o número de réplicas para o gateway de entrada no cluster principal.

      Do ponto de vista do equilibrador de carga multirregional, esta ação simula uma falha do cluster. Faz com que esse cluster falhe as verificações de funcionamento do equilibrador de carga. Este exemplo usa o cluster em CLUSTER_1_REGION. Só deve ver respostas do cluster em CLUSTER_2_REGION.

    5. Reduza o número de réplicas para o gateway de entrada no cluster principal para zero e chame o ponto final público para verificar se os pedidos foram transferidos para o outro cluster:

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

      O resultado deve ser semelhante ao seguinte:

      $ 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. Para retomar o encaminhamento de tráfego típico, restaure as réplicas do gateway de entrada para o valor original no cluster:

      kubectl --context=${CLUSTER_1_NAME} -n asm-ingress scale --replicas=3 deployment/asm-ingressgateway
      
    7. Simule uma falha para o serviço backend reduzindo o número de réplicas na região principal para 0:

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

      Verifique se as respostas do serviço frontend provêm da região principal us-central1 através do balanceador de carga e se as respostas do serviço backend provêm da região secundária us-east4.

      O resultado também deve incluir uma resposta para o serviço frontend da região principal (us-central1) e uma resposta para o serviço backend da região secundária (us-east4), conforme esperado.

    8. Restaure as réplicas do serviço de back-end para o valor original para retomar o encaminhamento de tráfego típico:

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

    Agora, tem um balanceador de carga HTTP(S) global que funciona como um front-end para a sua aplicação multirregional alojada na malha de serviços.

    Limpar

    Para evitar incorrer em cobranças na sua Google Cloud conta pelos recursos usados nesta implementação, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.

    Elimine o projeto

    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.

    Elimine os recursos individuais

    Se quiser manter o Google Cloud projeto que usou nesta implementação, elimine os recursos individuais:

    1. No Cloud Shell, elimine os recursos 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. Elimine os recursos do 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. Elimine as políticas:

      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. Elimine as exportações de serviços:

      kubectl --context=${CLUSTER_1_NAME} delete -f ${WORKDIR}/svc_export.yaml
      kubectl --context=${CLUSTER_2_NAME} delete -f ${WORKDIR}/svc_export.yaml
      
    5. Elimine os recursos do 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. Elimine os recursos do 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. Elimine a entrada de DNS dos pontos finais:

      gcloud --project=PROJECT_ID endpoints services delete "frontend.endpoints.PROJECT_ID.cloud.goog" --quiet
      
    8. Elimine o endereço IP estático:

      gcloud --project=PROJECT_ID compute addresses delete mcg-ip --global --quiet
      
    9. Elimine os clusters do GKE Autopilot. Este passo demora vários minutos.

      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
      

    O que se segue?

    Colaboradores

    Autores:

    Outros colaboradores: