Da borda à malha: expor aplicativos de malha de serviço via gateway do GKE

Last reviewed 2024-01-31 UTC

Nesta implantação, você verá como combinar o Anthos Service Mesh com o Cloud Load Balancing para expor aplicativos em uma malha de serviço aos clientes da Internet.

É possível expor um aplicativo aos clientes de várias maneiras, dependendo de onde o cliente está. Nesta implantação, mostramos como expor um aplicativo aos clientes combinando o Cloud Load Balancing com o Anthos Service Mesh para integrar balanceadores de carga a uma malha de serviço. Esta implantação é destinada a profissionais avançados que executam o Anthos Service Mesh. No entanto, ela também funciona para Istio no Google Kubernetes Engine.

Arquitetura

O diagrama a seguir mostra como usar gateways de entrada da malha para integrar balanceadores de carga a uma malha de serviço:

Um balanceador de carga externo encaminha os clientes externos para a malha por meio de proxies de gateway de entrada.

A entrada do Cloud age como o gateway do tráfego externo para a malha por meio da rede VPC.

Na topologia do diagrama anterior, a camada de entrada na nuvem, que é programada pelo gateway do GKE, origina o tráfego de fora da malha de serviço e direciona esse tráfego para a camada de entrada na malha. Em seguida, a camada de entrada da malha direciona o tráfego para os back-ends de aplicativos hospedados na malha.

A entrada do Cloud verifica a integridade da entrada da malha. Por sua vez, a entrada da malha verifica a integridade dos back-ends do aplicativo.

A topologia anterior tem as seguintes considerações:

  • Entrada na nuvem: nesta arquitetura de referência, você configura o balanceador de carga do Google Cloud pelo gateway do GKE para verificar a integridade dos proxies de entrada na malha nas portas de verificação de integridade expostas.
  • Entrada da malha: no aplicativo de malha, você realiza verificações de integridade diretamente nos back-ends a fim de executar o balanceamento de carga e o gerenciamento de tráfego localmente.

A segurança é implementada usando certificados gerenciados fora da malha e certificados internos dentro da malha.

O diagrama anterior ilustra a criptografia HTTPS do cliente para o balanceador de carga do Google Cloud, do balanceador de carga para o proxy de entrada da malha e do proxy de entrada para o proxy sidecar.

Objetivos

  • Implantar um cluster do Google Kubernetes Engine (GKE) no Google Cloud.
  • Implantar o Anthos Service Mesh baseado no Istio no cluster do GKE.
  • Configurar o gateway do GKE para encerrar o tráfego HTTPS público e direcionar esse tráfego para aplicativos hospedados por malha de serviço.
  • Implantar o aplicativo Online Boutique no cluster do GKE que você expõe aos clientes na Internet.

Otimização de custos

Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:

Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços. Novos usuários do Google Cloud podem estar qualificados para uma avaliação gratuita.

Ao concluir as tarefas descritas neste documento, é possível evitar o faturamento contínuo excluindo os recursos criados. Saiba mais em Limpeza.

Antes de começar

  1. No console do Google Cloud, na página do seletor de projetos, selecione ou crie um projeto do Google Cloud.

    Acessar o seletor de projetos

  2. Verifique se a cobrança está ativada para o seu projeto do Google Cloud.

  3. No Console do Google Cloud, ative o Cloud Shell.

    Ativar o Cloud Shell

    Todos os comandos de terminal desta implantação são executados a partir do Cloud Shell.

  4. Faça upgrade para a versão mais recente do Google Cloud CLI:

    gcloud components update
    
  5. Defina seu projeto padrão do Google Cloud:

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

    Substitua PROJECT pelo ID do projeto que quer usar nesta implantação.

  6. Crie um diretório de trabalho:

    mkdir -p ${HOME}/edge-to-mesh
    cd ${HOME}/edge-to-mesh
    export WORKDIR=`pwd`
    

    Depois de concluir a implantação, exclua o diretório de trabalho.

Criar clusters do GKE

Os recursos descritos nesta implantação exigem uma versão de cluster do GKE 1.16 ou mais recente.

  1. No Cloud Shell, crie um novo arquivo kubeconfig. Esta etapa garante que você não crie conflitos com seu arquivo kubeconfig (padrão) atual.

    touch edge2mesh_kubeconfig
    export KUBECONFIG=${WORKDIR}/edge2mesh_kubeconfig
    
  2. Defina as variáveis de ambiente no cluster do GKE:

    export CLUSTER_NAME=edge-to-mesh
    export CLUSTER_LOCATION=us-central1
    
  3. Ative a API Google Kubernetes Engine:

    gcloud services enable container.googleapis.com
    
  4. Crie um cluster do GKE Autopilot:

    gcloud container --project ${PROJECT} clusters create-auto
    ${CLUSTER_NAME} --region ${CLUSTER_LOCATION} --release-channel rapid
    
  5. Certifique-se de que o cluster está em execução:

    gcloud container clusters list
    

    O resultado será assim:

    NAME          LOCATION    MASTER_VERSION    MASTER_IP      MACHINE_TYPE   NODE_VERSION      NUM_NODES  STATUS
    edge-to-mesh  us-central1  1.27.3-gke.1700   34.122.84.52  e2-medium  1.27.3-gke.1700   3          RUNNING
    

Instalar uma malha de serviço

Nesta seção, você configurará o Anthos Service Mesh gerenciado com a API de frota.

  1. No Cloud Shell, ative as APIs necessárias:

    gcloud services enable mesh.googleapis.com
    
  2. Ative o Anthos Service Mesh na frota:

    gcloud container fleet mesh enable
    
  3. Registre o cluster na frota:

    gcloud container fleet memberships register ${CLUSTER_NAME} \
      --gke-cluster ${CLUSTER_LOCATION}/${CLUSTER_NAME
    
  4. Aplique o rótulo mesh_id ao cluster edge-to-mesh:

    gcloud container clusters update ${CLUSTER_NAME} --project ${PROJECT} --region ${CLUSTER_LOCATION} --update-labels mesh_id=proj-${PROJECT_NUMBER}
    
  5. Ative o gerenciamento automático do plano de controle e o plano de dados gerenciado:

    gcloud container fleet mesh update \
      --management automatic \
      --memberships ${CLUSTER_NAME}
    
  6. Após alguns minutos, verifique se o status no plano de controle é ACTIVE:

    gcloud container fleet mesh describe
    

    O resultado será assim:

    ...
    membershipSpecs:
      projects/892585880385/locations/us-central1/memberships/edge-to-mesh:
        mesh:
          management: MANAGEMENT_AUTOMATIC
    membershipStates:
      projects/892585880385/locations/us-central1/memberships/edge-to-mesh:
        servicemesh:
          controlPlaneManagement:
            details:
            - code: REVISION_READY
              details: 'Ready: asm-managed-rapid'
            state: ACTIVE
          dataPlaneManagement:
            details:
            - code: OK
              details: Service is running.
            state: ACTIVE
        state:
          code: OK
          description: 'Revision(s) ready for use: asm-managed-rapid.'
          updateTime: '2023-08-04T02:54:39.495937877Z'
    name: projects/e2m-doc-01/locations/global/features/servicemesh
    resourceState:
      state: ACTIVE
    ...
    

Implantar o gateway do GKE

Nas etapas a seguir, implante o balanceador de carga de aplicativo externo pelo GKE Gateway Controller. O recurso de gateway do GKE automatiza o provisionamento do balanceador de carga e da verificação de integridade do back-end. Além disso, é possível usar o Gerenciador de certificados para provisionar e gerenciar um certificado TLS e o Endpoints para provisionar automaticamente um nome DNS público para o aplicativo.

Instalar um gateway de entrada da malha de serviço

Como prática recomendada de segurança, recomendamos que você implante o gateway de entrada em um namespace diferente do plano de controle.

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

    kubectl create namespace asm-ingress
    
  2. Adicione um rótulo ao namespace asm-ingress:

    kubectl label namespace asm-ingress istio-injection=enabled
    

    A saída será assim:

    namespace/asm-ingress labeled
    

    Rotular o namespace asm-ingress com istio-injection=enabled instrui o Anthos Service Mesh a injetar automaticamente os proxies sidecar do Envoy quando um aplicativo é implantado.

  3. Crie um certificado autoassinado usado pelo gateway de entrada para encerrar conexões TLS entre o balanceador de carga do Google Cloud (a ser configurado posteriormente pelo GKE Gateway Controller) e o gateway de entrada e armazene esse certificado como um secret do Kubernetes:

    openssl req -new -newkey rsa:4096 -days 365 -nodes -x509 \
     -subj "/CN=frontend.endpoints.${PROJECT}.cloud.goog/O=Edge2Mesh Inc" \
     -keyout frontend.endpoints.${PROJECT}.cloud.goog.key \
     -out frontend.endpoints.${PROJECT}.cloud.goog.crt
    
    kubectl -n asm-ingress create secret tls edge2mesh-credential \
     --key=frontend.endpoints.${PROJECT}.cloud.goog.key \
     --cert=frontend.endpoints.${PROJECT}.cloud.goog.crt
    

    Para mais detalhes sobre os requisitos do certificado do gateway de entrada, consulte o guia de considerações do protocolo de back-end seguro.

  4. Execute os seguintes comandos para criar o YAML do recurso 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
    spec:
      ports:
      - name: status-port
        port: 15021
        protocol: TCP
        targetPort: 15021
      - name: http
        port: 80
        targetPort: 8080
      - 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
    spec:
      servers:
      - port:
          number: 443
          name: https
          protocol: HTTPS
        hosts:
        - "*" # IMPORTANT: Must use wildcard here when using SSL, see note below
        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
    
  5. Aplique as CRDs do gateway de entrada:

    kubectl apply -k ${WORKDIR}/asm-ig/variant
    
  6. Verifique se todas as implantações estão funcionando:

    kubectl wait --for=condition=available --timeout=600s deployment --all -n asm-ingress
    

    O resultado será assim:

    deployment.apps/asm-ingressgateway condition met
    

Aplicar uma verificação de integridade do gateway de entrada da malha de serviço

Ao integrar um gateway de entrada da malha de serviço a um balanceador de carga de aplicativo do Google Cloud, o balanceador de carga de aplicativo precisa estar configurado para executar verificações de integridade nos pods do gateway de entrada. A CRD HealthCheckPolicy fornece uma API para configurar essa verificação de integridade.

  1. No Cloud Shell, crie o arquivo HealthCheckPolicy.yaml:

    cat <<EOF >${WORKDIR}/ingress-gateway-healthcheck.yaml
    apiVersion: networking.gke.io/v1
    kind: HealthCheckPolicy
    metadata:
      name: ingress-gateway-healthcheck
      namespace: asm-ingress
    spec:
      default:
        checkIntervalSec: 20
        timeoutSec: 5
        #healthyThreshold: HEALTHY_THRESHOLD
        #unhealthyThreshold: UNHEALTHY_THRESHOLD
        logConfig:
          enabled: True
        config:
          type: HTTP
          httpHealthCheck:
            #portSpecification: USE_NAMED_PORT
            port: 15021
            portName: status-port
            #host: HOST
            requestPath: /healthz/ready
            #response: RESPONSE
            #proxyHeader: PROXY_HEADER
        #requestPath: /healthz/ready
        #port: 15021
      targetRef:
        group: ""
        kind: Service
        name: asm-ingressgateway
    EOF
    
  2. Aplique o HealthCheckPolicy:

    kubectl apply -f ${WORKDIR}/ingress-gateway-healthcheck.yaml
    

Definir políticas de segurança

O Google Cloud Armor fornece proteção contra DDoS e políticas de segurança personalizáveis que podem ser anexadas a um balanceador de carga por meio de recursos de Entrada. Nas etapas a seguir, você criará uma política de segurança que usa regras pré-configuradas para bloquear ataques de scripting em vários locais (XSS). Essa regra ajuda a bloquear o tráfego que corresponde a assinaturas de ataque conhecidas, mas permite qualquer outro tráfego. Seu ambiente pode usar regras diferentes dependendo da carga de trabalho.

  1. No Cloud Shell, crie uma política de segurança chamada edge-fw-policy:

    gcloud compute security-policies create edge-fw-policy \
      --description "Block XSS attacks"
    
  2. Crie uma regra de política de segurança que use os filtros XSS pré-configurados:

    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 o arquivo GCPBackendPolicy.yaml para anexar ao serviço do gateway de entrada:

    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: ""
        kind: Service
        name: asm-ingressgateway
    EOF
    
  4. Aplique o arquivo GCPBackendPolicy.yaml:

    kubectl apply -f ${WORKDIR}/cloud-armor-backendpolicy.yaml
    

Configurar o endereçamento IP e o DNS

  1. No Cloud Shell, crie um endereço IP estático global para o balanceador de carga do Google Cloud:

    gcloud compute addresses create e2m-gclb-ip --global
    

    Esse endereço IP estático é usado pelo recurso do gateway do GKE e permite que o endereço IP permaneça igual, mesmo que o balanceador de carga externo seja alterado.

  2. Consiga o endereço IP estático:

    export GCLB_IP=$(gcloud compute addresses describe e2m-gclb-ip
    --global --format "value(address)")
    echo ${GCLB_IP}
    

    Para criar um mapeamento estável e legível para o endereço IP estático do balanceador de carga de aplicativo, é necessário ter um registro DNS público. Use o provedor de DNS e a automação que quiser. Nesta implantação, usamos o Endpoints em vez de criar uma zona de DNS gerenciada. O Endpoints fornece gratuitamente um registro DNS gerenciado pelo Google para um endereço IP público.

  3. Execute o seguinte comando para criar o arquivo de especificação YAML chamado 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}.cloud.goog"
    x-google-endpoints:
    - name: "frontend.endpoints.${PROJECT}.cloud.goog"
      target: "${GCLB_IP}"
    EOF
    

    A especificação YAML define o registro DNS público no formato frontend.endpoints.${PROJECT}.cloud.goog, em que ${PROJECT} é o identificador exclusivo do projeto.

  4. Implante o arquivo dn