Configurar o balanceamento de carga HTTP(S) externo para o Anthos Service Mesh gerenciado

Visão geral

O Cloud Load Balancing fornece muitos recursos de borda gerenciados na nuvem, incluindo balanceamento de carga anycast global, certificados gerenciados pelo Google, gerenciamento de identidade e acesso e firewall ou SDI da nuvem. O Anthos Service Mesh pode integrar perfeitamente esses recursos de borda no seguinte modelo de entrada de malha. O gateway de nuvem da malha de serviço oferece uma maneira unificada de configurar o gateway de entrada do Anthos Service Mesh com o Cloud Load Balancing simultaneamente por meio da API Kubernetes Gateway.

Diagrama demonstrando o balanceador de carga do Cloud com o Anthos Service Mesh

Em comparação com nosso guia do usuário anterior, Da borda à malha: como expor aplicativos de malha de serviço por meio da Entrada do GKE, com um gateway de nuvem de malha de serviço, esse modelo agora pode ser implantado por um recurso de gateway do Kubernetes que simplifica o processo de implantação do balanceamento de carga na nuvem e hospedado em cluster em conjunto.

Limitações de visualização

As seguintes limitações se aplicam à versão de pré-lançamento desse recurso:

  • Não há suporte para gateways de vários clusters.
  • Os clusters do Autopilot não têm suporte.
  • Somente o balanceador de carga clássico do aplicativo é compatível. O balanceador de carga avançado e o balanceador de carga HTTP(S) interno não são compatíveis.
  • O tráfego entre o balanceador de carga HTTP(S) externo e o gateway de entrada do Anthos Service Mesh é criptografado usando TLS. No entanto, o balanceador de carga HTTP(S) externo não vai verificar o certificado fornecido pelo gateway de entrada do Anthos Service Mesh. Essa limitação se aplica a todos os usuários do balanceador de carga HTTP(S) do Google Cloud.
  • Se o GatewayClasses do Anthos Service Mesh for excluído de um cluster, ele não será reinstalado automaticamente. No entanto, isso não vai afetar a usabilidade do recurso.
  • A lógica de correspondência de rota não segue as especificações da API Gateway e corresponde à ordem do HTTPRoute. Isso mudará em versões futuras para seguir as especificações da API Gateway.

Requisitos

  • Anthos Service Mesh gerenciado instalado em um cluster do Google Kubernetes Engine (GKE) com a versão 1.24 ou mais recente. Outros clusters do GKE Enterprise não são compatíveis.
  • Apenas na versão v1beta1 da API Gateway do Kubernetes.

Pré-requisitos

  • Ativar as APIs a seguir no projeto:

    • compute.googleapis.com
    • container.googleapis.com
    • certificatemanager.googleapis.com
    • serviceusage.googleapis.com
    gcloud services enable \
       compute.googleapis.com \
       container.googleapis.com \
       certificatemanager.googleapis.com \
       serviceusage.googleapis.com
    

Implantar o gateway da nuvem da malha de serviço em uma malha de cluster único

Nesta seção, mostramos como implantar um recurso de gateway do Kubernetes que implanta um balanceador de carga HTTP(S) externo global (clássico) e um gateway de entrada do Anthos Service Mesh.

Ativar a API Gateway com o Anthos Service Mesh gerenciado

  1. Ative a API Gateway no cluster. O cluster do GKE precisa ser da versão 1.24 ou posterior.

  2. Instale o Anthos Service Mesh gerenciado com rapid ou regular como o canal de lançamento.

Implantar o recurso de gateway

Ao implantar o gateway da nuvem da malha de serviço, os recursos do gateway do Kubernetes são usados para implantar o gateway de entrada do Cloud Load Balancing e do Anthos Service Mesh em uma única etapa. Os recursos do gateway do Kubernetes são diferentes dos recursos do gateway do Istio.

Para mais informações sobre as diferenças, consulte Gateways do Kubernetes e gateways do Istio. Cada gateway do Kubernetes tem um GatewayClass que indica o tipo e os recursos inerentes dele. O gateway da nuvem da malha de serviço tem uma GatewayClass que pode implantar o gateway de entrada do Cloud Load Balancing e do Anthos Service Mesh.

  1. Salve o seguinte manifesto GatewayClass em um arquivo chamado l7-gateway-class.yaml:

    apiVersion: gateway.networking.k8s.io/v1beta1
    kind: GatewayClass
    metadata:
      name: asm-l7-gxlb
    spec:
      controllerName: mesh.cloud.google.com/gateway
    
  2. Implante o GatewayClass no cluster:

    kubectl apply -f l7-gateway-class.yaml
    
  3. Verifique se o GatewayClass está presente após a instalação:

    kubectl get gatewayclasses.gateway.networking.k8s.io
    

    A resposta é semelhante a:

    NAME          CONTROLLER
    asm-l7-gxlb   mesh.cloud.google.com/gateway
    gke-l7-rilb   networking.gke.io/gateway
    gke-l7-gxlb   networking.gke.io/gateway
    

    A implantação de todos os recursos pode levar alguns minutos. Se a saída esperada não for exibida, verifique se você atendeu aos pré-requisitos corretamente.

    Você também vai ver o seguinte GatewayClass:

    gke-l7-gxlb   networking.gke.io/gateway
    

    Ele é usado para implantar o balanceador de carga HTTP(S) externo global subjacente do Google Cloud.

  4. Crie um namespace dedicado para o gateway da nuvem da malha de serviço:

    kubectl create namespace istio-ingress
    
  5. Salve o seguinte manifesto de gateway em um arquivo chamado gateway.yaml:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
    
  6. Implante o gateway no cluster no namespace istio-ingress:

    kubectl apply -f gateway.yaml
    
  7. Verifique se os objetos da API Kubernetes Gateway foram criados:

    kubectl get gateways.gateway.networking.k8s.io -n istio-ingress
    

    A resposta é semelhante a:

    NAME                                CLASS         ADDRESS         READY   AGE
    asm-gw-gke-servicemesh-cloud-gw     gke-l7-gxlb   34.111.114.64   True    9m40s
    asm-gw-istio-servicemesh-cloud-gw   istio                                 9m44s
    servicemesh-cloud-gw                asm-l7-gxlb                           9m44s
    

Veja a seguir o que acontecerá quando esse objeto da API Kubernetes Gateway for implantado:

  • Um balanceador de carga HTTP(S) externo é implantado e configurado. Pode levar alguns minutos para aparecer, mas, quando isso acontecer, o gateway indicará o endereço IP e será anotado com os nomes dos recursos do balanceador de carga do Compute Engine que foram criados.
  • Uma implantação de gateway de entrada do Anthos Service Mesh é criada no namespace istio-ingress. Isso cria as instâncias de proxy Envoy que receberão o tráfego do balanceador de carga do Cloud.
  • O balanceador de carga do Cloud vai criptografar e rotear todo o tráfego para o gateway de entrada do Anthos Service Mesh.

Agora você tem a infraestrutura completa necessária para aceitar o tráfego da Internet na sua malha. Observe que essa é a implantação de gateway mais simples possível. Nas seções a seguir, você vai adicionar outras políticas e recursos que vão preparar a produção.

Implantação de apps e roteamento

Para demonstrar todos os recursos, implante um aplicativo no Anthos Service Mesh e receba tráfego da Internet pelo gateway para exemplos.

  1. Identifique o namespace default para ativar a injeção de arquivo secundário.

    kubectl label namespace default istio-injection=enabled istio.io/rev- --overwrite
    
  2. Salve o seguinte manifesto de gateway em um arquivo chamado whereami.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v1
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v1
      template:
        metadata:
          labels:
            app: whereami-v1
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v1"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v1
    spec:
      selector:
        app: whereami-v1
      ports:
      - port: 8080
        targetPort: 8080
    ---
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: whereami-v2
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: whereami-v2
      template:
        metadata:
          labels:
            app: whereami-v2
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1.2.20
            ports:
              - containerPort: 8080
            env:
            - name: METADATA
              value: "whereami-v2"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: whereami-v2
    spec:
      selector:
        app: whereami-v2
      ports:
      - port: 8080
        targetPort: 8080
    

    Esse manifesto cria Service/whereami-v1, Service/whereami-v2, Deployment/whereami-v1 e Deployment/whereami-v2 para o whereami, um aplicativo simples que gera JSON para indicar a identidade e o local dele. Você implantará duas versões diferentes dele.

  3. Crie os serviços e as implantações:

    kubectl apply -f whereami.yaml
    

    Depois que ele estiver em execução, você terá quatro pods whereami em execução no cluster.

  4. Verifique se todos os quatro pods estão em execução:

    kubectl get pods
    

    A resposta é semelhante a:

    whereami-v1-7c76d89d55-qg6vs       2/2     Running   0          28s
    whereami-v1-7c76d89d55-vx9nm       2/2     Running   0          28s
    whereami-v2-67f6b9c987-p9kqm       2/2     Running   0          27s
    whereami-v2-67f6b9c987-qhj76       2/2     Running   0          27s
    
  5. Salve o seguinte manifesto HTTPRoute em um arquivo chamado http-route.yaml:

    kind: HTTPRoute
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: where-route
    spec:
     parentRefs:
     - kind: Gateway
       name: servicemesh-cloud-gw
       namespace: istio-ingress
     hostnames:
     - "where.example.com"
     rules:
     - matches:
       - headers:
         - name: version
           value: v2
       backendRefs:
       - name: whereami-v2
         port: 8080
     - backendRefs:
       - name: whereami-v1
         port: 8080
    
  6. Implante http-route.yaml no cluster:

    kubectl apply -f http-route.yaml
    

    Essa HTTPRoute faz referência à servicemesh-cloud-gw, o que significa que ela vai configurar o gateway da nuvem da malha de serviço para definir o gateway de entrada do Anthos Service Mesh subjacente com essas regras de roteamento. O HTTPRoute executa a mesma função que o VirtualService do Istio, mas usa a API Kubernetes Gateway para isso. Como a API Gateway é uma especificação do OSS com várias implementações subjacentes, ela é a melhor API adequada para definir o roteamento em uma combinação de diferentes balanceadores de carga, como proxies do Anthos Service Mesh e balanceadores de carga do Cloud.

  7. Recuperar o endereço IP do gateway para enviar tráfego ao aplicativo:

    VIP=$(kubectl get gateways.gateway.networking.k8s.io asm-gw-gke-servicemesh-cloud-gw -o=jsonpath="{.status.addresses[0].value}" -n istio-ingress)
    

    A saída é um endereço IP.

    echo $VIP
    
    34.111.61.135
    
  8. Envie tráfego para o endereço IP do gateway para validar se essa configuração funciona corretamente. Envie uma solicitação com o cabeçalho version: v2 e outra sem para determinar se o roteamento é feito corretamente nas duas versões do aplicativo.

    curl ${VIP} -H "host: where.example.com"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v1",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v1-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    
    curl ${VIP} -H "host: where.example.com" -H "version: v2"
    
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "whereami-v2",
      "node_name": "gke-gke1-default-pool-9b3b5b18-hw5z.c.church-243723.internal",
      "pod_name": "whereami-v2-67d9c5d48b-zhr4l",
      "pod_name_emoji": "⚒",
      "project_id": "church-243723",
      "timestamp": "2021-02-08T18:55:01",
      "zone": "us-central1-a"
    }
    

Implantação do gateway de produção

A seção anterior mostrou um exemplo muito simples de gateway da nuvem da malha de serviço. As etapas a seguir são baseadas no exemplo simples para mostrar uma configuração pronta para produção que demonstra as vantagens de delegar algumas das funcionalidades de roteamento de entrada ao balanceador de carga da nuvem.

No exemplo a seguir, você usará o servicemesh-cloud-gw da seção anterior e adicionará os seguintes recursos para criar um Gateway mais seguro e gerenciável:

  • Implante o gateway com um endereço IP estático que será retido mesmo que a infraestrutura subjacente mude.
  • Converta o gateway para receber tráfego HTTPS com um certificado autoassinado.
  1. Criar um endereço IP externo estático. Um IP estático é útil porque a infraestrutura subjacente pode mudar no futuro, mas o endereço IP pode ser mantido.

    gcloud compute addresses create whereami-ip \
        --global \
        --project PROJECT_ID
    
  2. Crie um certificado autoassinado para o domínio where-example-com:

    openssl genrsa -out key.pem 2048
    cat <<EOF >ca.conf
    [req]
    default_bits              = 2048
    req_extensions            = extension_requirements
    distinguished_name        = dn_requirements
    prompt                    = no
    [extension_requirements]
    basicConstraints          = CA:FALSE
    keyUsage                  = nonRepudiation, digitalSignature, keyEncipherment
    subjectAltName            = @sans_list
    [dn_requirements]
    0.organizationName        = example
    commonName                = where.example.com
    [sans_list]
    DNS.1                     = where.example.com
    EOF
    
    openssl req -new -key key.pem \
        -out csr.pem \
        -config ca.conf
    
    openssl x509 -req \
        -signkey key.pem \
        -in csr.pem \
        -out cert.pem \
        -extfile ca.conf \
        -extensions extension_requirements \
        -days 365
    
    gcloud compute ssl-certificates create where-example-com \
        --certificate=cert.pem \
        --private-key=key.pem \
        --global \
        --project PROJECT_ID
    

    Há muitas maneiras de gerar certificados TLS. Eles podem ser gerados manualmente na linha de comando, gerados com certificados gerenciados pelo Google ou internamente pelo sistema de infraestrutura de chave pública (ICP) de uma empresa. Neste exemplo, você gera manualmente um certificado autoassinado. Os certificados autoassinados geralmente não são usados para serviços públicos, mas demonstram esses conceitos com mais facilidade.

    Para mais informações sobre como criar um certificado autoassinado pelo Kubernetes Secret, consulte Proteger um gateway.

  3. Atualize gateway.yaml com o seguinte manifesto:

    kind: Gateway
    apiVersion: gateway.networking.k8s.io/v1beta1
    metadata:
      name: servicemesh-cloud-gw
      namespace: istio-ingress
    spec:
      gatewayClassName: asm-l7-gxlb
      listeners:
      - name: http
        protocol: HTTP
        port: 80
        allowedRoutes:
          namespaces:
            from: All
      - name: https
        protocol: HTTPS
        port: 443
        allowedRoutes:
          namespaces:
            from: All
        tls:
          mode: Terminate
          options:
            networking.gke.io/pre-shared-certs: where-example-com
      addresses:
      - type: NamedAddress
        value: whereami-ip
    
  4. Reimplante o gateway no seu cluster:

    kubectl apply -f gateway.yaml
    
  5. Consiga o endereço IP do IP estático:

    VIP=$(gcloud compute addresses describe whereami-ip --global --format="value(address)")
    
  6. Use curl para acessar o domínio do gateway. Como o DNS não está configurado para esse domínio, use a opção --resolve para instruir o curl a resolver o nome de domínio para o endereço IP do gateway:

    curl https://where.example.com --resolve where.example.com:443:${VIP} --cacert cert.pem -v
    

    Quando concluída, a saída será semelhante a:

    ...
    * TLSv1.2 (OUT), TLS handshake, Client hello (1):
    * TLSv1.2 (IN), TLS handshake, Server hello (2):
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    * TLSv1.2 (IN), TLS handshake, Server key exchange (12):
    * TLSv1.2 (IN), TLS handshake, Server finished (14):
    * TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
    * TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (OUT), TLS handshake, Finished (20):
    * TLSv1.2 (IN), TLS change cipher, Change cipher spec (1):
    * TLSv1.2 (IN), TLS handshake, Finished (20):
    * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305
    * ALPN, server accepted to use h2
    * Server certificate:
    *  subject: O=example; CN=where.example.com
    *  start date: Apr 19 15:54:50 2021 GMT
    *  expire date: Apr 19 15:54:50 2022 GMT
    *  common name: where.example.com (matched)
    *  issuer: O=example; CN=where.example.com
    *  SSL certificate verify ok.
    ...
    {
      "cluster_name": "gke1",
      "host_header": "where.example.com",
      "metadata": "where-v1",
      "node_name": "gke-gw-default-pool-51ccbf30-yya8.c.agmsb-k8s.internal",
      "pod_name": "where-v1-84b47c7f58-tj5mn",
      "pod_name_emoji": "😍",
      "project_id": "agmsb-k8s",
      "timestamp": "2021-04-19T16:30:08",
      "zone": "us-west1-a"
    }
    

A saída detalhada inclui um handshake de TLS bem-sucedido seguido por uma resposta do aplicativo, como a saída a seguir. Isso prova que o TLS está sendo encerrado corretamente no gateway e que o aplicativo está respondendo ao cliente com segurança.

Você implantou a seguinte arquitetura:

Arquitetura ASM

O servicemesh-cloud-gw e o GatewayClass de asm-l7-gxlb abstraíram alguns componentes internos de infraestrutura para simplificar a experiência do usuário. O Cloud Load Balancing está terminando o tráfego TLS usando um certificado interno e também verificando a integridade da camada de proxy de gateway de entrada do Anthos Service Mesh. O whereami-route implantado na Implantação de app e roteamento configura os proxy de gateway de entrada do Anthos Service Mesh para encaminhar o tráfego para o serviço hospedado de malha correto.

A seguir