Criar um balanceador de carga interno em redes VPC

Nesta página, explicamos como criar um balanceador de carga de rede de passagem interna no Google Kubernetes Engine (GKE) entre redes VPC.

Antes de ler este documento, confira se você conhece os seguintes conceitos:

Antes de começar

Antes de começar, verifique se você realizou as tarefas a seguir:

  • Ative a API Google Kubernetes Engine.
  • Ativar a API Google Kubernetes Engine
  • Para usar a Google Cloud CLI nesta tarefa, instale e inicialize a CLI gcloud. Se você instalou a CLI gcloud anteriormente, instale a versão mais recente executando o comando gcloud components update. Talvez as versões anteriores da CLI gcloud não sejam compatíveis com a execução dos comandos neste documento.

Criar um balanceador de carga interno com o Private Service Connect

Como produtor de serviço, é possível usar anexos de serviço para disponibilizar seus serviços aos consumidores de serviço em outras redes VPC usando o Private Service Connect. É possível criar, gerenciar e excluir anexos de serviço usando um recurso personalizado ServiceAttachment. O controlador do Private Service Connect do GKE monitora o recurso ServiceAttachment e cria, atualiza ou exclui automaticamente um recurso ServiceAttachment correspondente no Compute Engine.

Requisitos e limitações

  • Limitações se aplicam ao Private Service Connect.
  • É possível criar um anexo de serviço nas versões 1.21.4-gke.300 e posteriores do GKE.
  • O cluster precisa ter o complemento HttpLoadBalancing ativado. Os novos clusters do GKE têm o complemento HttpLoadBalancing ativado por padrão.
  • Não é possível usar a mesma sub-rede em várias configurações de anexos do serviço.
  • Você precisa criar um serviço do GKE que usa um balanceador de carga de rede de passagem interna.
  • O serviço do GKE precisa usar apenas um protocolo. Os serviços do GKE com protocolo misto não são compatíveis.
  • Não é possível especificar uma sub-rede em um projeto diferente (VPC compartilhada) para versões do GKE anteriores a 1.22.4-gke.100. Para a VPC compartilhada, verifique se todos os requisitos da VPC compartilhada foram atendidos.
  • Depois de criar um anexo de serviço, não é possível atualizar o balanceador de carga interno. Para mudar as configurações do balanceador de carga, exclua e recrie o anexo de serviço.

Compatibilidade de versão de IP para serviços e sub-redes NAT

Quando você cria um recurso ServiceAttachment, o controlador do Private Service Connect do GKE cria um único anexo de serviço do Compute Engine associado a uma regra de encaminhamento do produtor. A regra de encaminhamento do produtor usa um endereço IPv4 ou IPv6. A tabela a seguir mostra como o controlador seleciona a regra de encaminhamento com base na configuração da família de IP (campo spec.ipFamilies) do serviço do Kubernetes referenciado e nos tipos de pilha de todas as sub-redes especificadas no campo spec.natSubnets:

Serviço do Kubernetes (regras de encaminhamento) Tipos de pilha de sub-redes no campo natSubnets Regra de encaminhamento de anexo de serviço do Compute Engine Observações
IPv4 de pilha única IPV4_ONLY, IPV4_IPV6 ou ambos Endereço IPv4 Compatível.
Contém qualquer sub-rede IPV6_ONLY Nenhum (erro) Erro de configuração. Todas as sub-redes NAT precisam ser compatíveis com endereços IPv4.
Pilha dupla (endereços IPv4 e IPv6) IPV4_ONLY, IPV4_IPV6 ou ambos (sem sub-rede IPV6_ONLY) Endereço IPv4 Compatível. Usa a regra de encaminhamento IPv4. Um anexo de serviço IPv4 pode aceitar conexões de endpoints de consumidor IPv4 e IPv6.
IPV6_ONLY ou uma combinação de IPV6_ONLY e IPV4_IPV6 (sem sub-rede IPV4_ONLY) Endereço IPv6 Compatível. Usa a regra de encaminhamento IPv6 porque uma sub-rede IPV6_ONLY está presente. Um anexo de serviço IPv6 aceita conexões apenas de endpoints de consumidor IPv6.
Contém as sub-redes IPV4_ONLY e IPV6_ONLY Nenhum (erro) Erro de configuração. Todas as sub-redes NAT precisam compartilhar uma versão de IP comum.
IPv6 de pilha única IPV6_ONLY, IPV4_IPV6 ou ambos Endereço IPv6 Compatível.
Contém qualquer sub-rede IPV4_ONLY Nenhum (erro) Erro de configuração. Todas as sub-redes NAT precisam ser compatíveis com endereços IPv6.

Para mais informações sobre como os endpoints do consumidor se conectam a anexos de serviço IPv4 e IPv6, consulte Conversão de versão de IP.

Criar um ServiceAttachment

  1. Crie uma sub-rede.

    É necessário criar uma nova sub-rede para cada ServiceAttachment.

    gcloud compute networks subnets create SUBNET_NAME \
        --project PROJECT_ID \
        --network NETWORK_NAME \
        --region REGION \
        --range SUBNET_RANGE \
        --purpose PRIVATE_SERVICE_CONNECT
    

    Substitua:

    • SUBNET_NAME: o nome da nova sub-rede; Nas versões 1.22.4-gke.100 e posteriores do GKE, é possível especificar uma sub-rede em um projeto diferente usando o URL de recurso totalmente qualificado para esse campo. Você pode conseguir o URL do recurso totalmente qualificado usando o comando gcloud compute networks subnets describe.
    • PROJECT_ID: ID do seu projeto do Google Cloud.
    • NETWORK_NAME: o nome da rede VPC da sub-rede;
    • REGION: a região da nova sub-rede. Use a mesma região do serviço criado;
    • SUBNET_RANGE: o intervalo de endereços IPv4 a ser usado para a sub-rede.

    Para criar uma sub-rede do Private Service Connect de pilha dupla ou somente IPv6, inclua as flags --stack-type=IPV4_IPV6 e --ipv6-access-type=INTERNAL ou as flags --stack-type=IPV6_ONLY e --ipv6-access-type=INTERNAL (omita a flag --range ao usar o tipo de pilha IPV6_ONLY). Verifique se o tipo de pilha de sub-rede é compatível com a família de IPs do Serviço, conforme descrito em Compatibilidade de versão de IP para Serviços e sub-redes NAT.

  2. Implante uma carga de trabalho.

    No manifesto a seguir, veja uma implantação que executa uma imagem de amostra do contêiner de aplicativo da Web. Salve o manifesto como my-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: psc-ilb
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: psc-ilb
      template:
        metadata:
          labels:
            app: psc-ilb
        spec:
          containers:
          - name: whereami
            image: us-docker.pkg.dev/google-samples/containers/gke/whereami:v1
            ports:
              - name: http
                containerPort: 8080
            readinessProbe:
              httpGet:
                path: /healthz
                port: 8080
                scheme: HTTP
              initialDelaySeconds: 5
              timeoutSeconds: 1
    
  3. Aplique o manifesto ao cluster:

    kubectl apply -f my-deployment.yaml
    
  4. Crie um serviço O manifesto a seguir descreve um serviço que cria um balanceador de carga de rede de passagem interna na porta TCP 8080. Salve o manifesto como my-service.yaml:

     apiVersion: v1
     kind: Service
     metadata:
       name: SERVICE_NAME
       annotations:
         networking.gke.io/load-balancer-type: "Internal"
     spec:
       type: LoadBalancer
       selector:
         app: psc-ilb
       ports:
       - port: 80
         targetPort: 8080
         protocol: TCP
    

    Substitua:

    • SERVICE_NAME: o nome do novo serviço;
  5. Aplique o manifesto ao cluster:

    kubectl apply -f my-service.yaml
    
  6. Criar ServiceAttachment.

    O manifesto a seguir descreve um ServiceAttachment que expõe o serviço criado para os consumidores de serviço. Salve o manifesto como my-psc.yaml:

    apiVersion: networking.gke.io/v1
    kind: ServiceAttachment
    metadata:
     name: SERVICE_ATTACHMENT_NAME
     namespace: default
    spec:
     connectionPreference: ACCEPT_AUTOMATIC
     natSubnets:
     - SUBNET_NAME
     proxyProtocol: false
     reconcileConnections: false  # set to true to enable connection reconciliation
     resourceRef:
       kind: Service
       name: SERVICE_NAME
    

    Substitua:

    • SERVICE_ATTACHMENT_NAME: o nome do novo anexo de serviço.
    • SUBNET_NAME: o nome da nova sub-rede. Nas versões 1.22.4-gke.100 e posteriores do GKE, é possível especificar uma sub-rede em um projeto diferente usando o URL de recurso totalmente qualificado para esse campo. Você pode conseguir o URL do recurso totalmente qualificado usando o comando gcloud compute networks subnets describe. Para uma configuração de VPC compartilhada, use o seguinte formato: projects/HOST_PROJECT_ID/regions/COMPUTE_REGION/subnetworks/SUBNET_NAME.

    Para saber mais sobre os campos de manifesto, consulte os campos de anexo de serviço.

  7. Aplique o manifesto ao cluster:

    kubectl apply -f my-psc.yaml
    
  8. Verifique se o controlador do Private Service Connect criou o anexo de serviço:

    gcloud compute service-attachments list
    

    A saída mostra um anexo de serviço com um nome gerado automaticamente:

    NAME        REGION       PRODUCER_FORWARDING_RULE          CONNECTION_PREFERENCE
    k8s1-sa-... REGION_NAME  a3fea439c870148bdba5e59c9ea9451a  ACCEPT_AUTOMATIC
    

Veja uma ServiceAttachment

Para visualizar os detalhes de uma ServiceAttachment, use o seguinte comando:

kubectl describe serviceattachment SERVICE_ATTACHMENT_NAME

O resultado será assim:

Name:        <sa-name>
Namespace:    default
Labels:       <none>
Annotations:  <none>
API Version:  networking.gke.io/v1beta1
Kind:         ServiceAttachment
Metadata:
  ...
Status:
  Forwarding Rule URL:      https://www.googleapis.com/compute/beta/projects/<project>/regions/<region>/forwardingRules/<fr-name>
  Last Modified Timestamp:  2021-07-08T01:32:39Z
  Service Attachment URL:   https://www.googleapis.com/compute/beta/projects/<projects>/regions/<region>/serviceAttachments/<gce-service-attachment-name>
Events:                     <none>

Consumir um ServiceAttachment

Para consumir o serviço de outro projeto, siga estas etapas:

  1. Consiga o URL do ServiceAttachment:

    kubectl get serviceattachment SERVICE_ATTACHMENT_NAME -o=jsonpath="{.status.serviceAttachmentURL}"
    

    O resultado será assim:

      serviceAttachmentURL: https://www.googleapis.com/compute/alpha/projects/<project>/region/<region>/serviceAttachments/k8s1-...my-sa
    
  2. Crie um endpoint do Private Service Connect usando o URL do ServiceAttachment.

  3. Verifique se é possível se conectar ao serviço implantado no projeto do produtor usando um comando curl de uma VM no projeto do consumidor:

    curl PSC_IP_ADDRESS
    

    Substitua PSC_IP_ADDRESS pelo endereço IP da regra de encaminhamento no projeto do consumidor.

    O resultado será assim:

    {
      "cluster_name":"cluster",
      "host_header":"10.128.15.200",
      "node_name":"gke-psc-default-pool-be9b6e0e-dvxg.c.gke_project.internal",
      "pod_name":"foo-7bf648dcfd-l5jf8",
      "pod_name_emoji":"👚",
      "project_id":"gke_project",
      "timestamp":"2021-06-29T21:32:03",
      "zone":"ZONE_NAME"
    }
    

Atualizar um ServiceAttachment

É possível atualizar um ServiceAttachment usando as seguintes etapas:

  1. Edite o manifesto ServiceAttachment em my-psc.yaml:

    apiVersion: networking.gke.io/v1
    kind: ServiceAttachment
    metadata:
      name: my-sa
      namespace: default
    spec:
      connectionPreference: ACCEPT_AUTOMATIC
      natSubnets:
      - my-nat-subnet
      proxyProtocol: false
      resourceRef:
        kind: Service
        name: ilb-service
    
  2. Aplique o manifesto ao cluster:

    kubectl apply -f my-psc.yaml
    

Excluir um ServiceAttachment

Não é possível excluir um balanceador de carga de rede de passagem interna conectado a um anexo de serviço. É necessário excluir o anexo de serviço e o serviço do GKE separadamente.

  1. Exclua o anexo de serviço:

    kubectl delete serviceattachment SERVICE_ATTACHMENT_NAME --wait=false
    

    Esse comando marca o anexo de serviço para exclusão, mas o recurso continua a existir. Também é possível aguardar a conclusão da exclusão omitindo a sinalização --wait.

  2. Exclua o serviço:

    kubectl delete svc SERVICE_NAME
    
  3. Exclua a sub-rede:

    gcloud compute networks subnets delete SUBNET_NAME
    

ServiceAttachment campos

O ServiceAttachment tem os seguintes campos:

  • connectionPreference: a preferência de conexão que determina como os clientes se conectam ao serviço. É possível usar a aprovação automática do projeto usando ACCEPT_AUTOMATIC ou a aprovação explícita do projeto usando ACCEPT_MANUAL. Para mais informações, consulte Como publicar serviços usando o Private Service Connect.
  • natSubnets: uma lista de nomes de recurso de sub-rede a serem usados para o anexo de serviço.
  • proxyProtocol: quando definido como verdadeiro, o IP de origem do consumidor e o ID da conexão do Private Service Connect estão disponíveis nas solicitações. Esse campo é opcional e o padrão será falso se não for fornecido.
  • reconcileConnections (pré-lançamento): quando definido como verdadeiro, as alterações nas listas de aceitação ou rejeição do consumidor de serviço encerram automaticamente as conexões não autorizadas. Quando definido como false, as mudanças afetam apenas as novas conexões. Esse campo é opcional e o padrão é falso. Este campo é compatível com a versão 1.36.0-gke.2459000 e posteriores do GKE.
  • consumerAllowList: a lista de projetos de consumidor que têm permissão para se conectar ao ServiceAttachment. Este campo só pode ser usado quando connectionPreference é ACCEPT_MANUAL. Para mais informações sobre esse campo, consulte Como publicar serviços usando o Private Service Connect.
    • project: o ID do projeto ou número do projeto do consumidor.
    • connectionLimit: o limite de conexão do projeto do consumidor. Este campo é opcional.
    • forceSendFields: os nomes de campo a serem enviados para incluir nas solicitações de API. Este campo é opcional.
    • nullFields: os nomes de campo a serem incluídos nas solicitações de API com um valor nulo. Este campo é opcional.
  • consumerRejectList: a lista de IDs de projeto ou números de consumidores que não têm permissão para se conectar a ServiceAttachment. Este campo só pode ser usado quando connectionPreference é ACCEPT_MANUAL. Para mais informações sobre esse campo, consulte Como publicar serviços usando o Private Service Connect.
  • resourceRef: uma referência ao recurso do Kubernetes.

    • kind: o tipo do recurso do Kubernetes. Você precisa usar Service.
    • name: o nome do recurso do Kubernetes que precisa estar no mesmo namespace que o balanceador de carga de rede de passagem interna.

Solução de problemas

É possível ver as mensagens de erro usando o seguinte comando:

kubectl get events -n NAMESPACE

Substitua NAMESPACE pelo namespace do balanceador de carga de rede de passagem interna.

Erro ao excluir o balanceador de carga de rede de passagem interna

Se você tentar excluir um balanceador de carga de rede de passagem interna que está sendo usado por um anexo de serviço, ocorrerá uma mensagem de erro semelhante à mensagem a seguir. É preciso excluir o ServiceAttachment antes de excluir o balanceador de carga de rede de passagem interna.

Error syncing load balancer: failed to ensure load balancer: googleapi:
Error 400: The forwarding_rule resource '<fwd-rule-URL>' is already being used
by '<svc-attachment-URL>', resourceInUseByAnotherResource.

Erro ao ativar o acesso global

Talvez você encontre um erro ao ativar o acesso global para um balanceador de carga de rede de passagem interna que usa um anexo de serviço do Private Service Connect.

Sintoma:

Quando você ativa o acesso global atualizando o manifesto do serviço do GKE e definindo a anotação networking.gke.io/internal-load-balancer-allow-global-access: "true", a atualização falha ao aplicar o manifesto. A seguinte mensagem de erro é exibida ao executar o comando kubectl get events:

Error syncing load balancer: failed to ensure load balancer: googleapi: Error 400: The forwarding_rule resource '...' is already being used by '...', resourceInUseByAnotherResource

Motivo:

Esse erro ocorre porque o plano de controle do GKE tenta recriar a regra de encaminhamento do balanceador de carga para ativar o acesso global. No entanto, como a regra de encaminhamento está em uso por um ServiceAttachment, ela não pode ser excluída e recriada, o que resulta no erro.

Alternativa:

Para ativar o acesso global no balanceador de carga e minimizar o tempo de inatividade, atualize as configurações de serviço do GKE e atualize manualmente a regra de encaminhamento:

  1. Atualize o manifesto do serviço do GKE: atualize o manifesto do serviço do GKE para incluir a anotação networking.gke.io/internal-load-balancer-allow-global-access: "true".

  2. Ative manualmente o acesso global na regra de encaminhamento: siga as etapas em Ativar o acesso global para atualizar a regra de encaminhamento do balanceador de carga usando o console doGoogle Cloud , a Google Cloud CLI ou a API Compute Engine.

Campo ReconcileConnections não sincronizado

Se você ativou manualmente o campo ReconcileConnections no recurso ServiceAttachment do Compute Engine, mas omitiu o campo do manifesto do Kubernetes, o campo será padronizado como false. O controlador do GKE não substitui o valor do campo.

Sintoma:

O recurso ServiceAttachment do Kubernetes tem a anotação networking.gke.io/unsynced-field: ReconcileConnections. Ao executar o comando kubectl get events, você verá um evento de aviso semelhante ao seguinte:

Field "ReconcileConnections" is not specified in the ServiceAttachment CR but has a value in GCE. The controller will not overwrite this field until it is explicitly set in the CR.

Alternativa:

Para resolver esse aviso e sincronizar os valores, execute uma das seguintes ações:

  • Atualize o recurso ServiceAttachment do GKE: atualize o manifesto ServiceAttachment do GKE para incluir reconcileConnections: true (ou false se quiser desativá-lo).
  • Atualize o recurso ServiceAttachment do Compute Engine: defina manualmente o campo reconcileConnections como false.

A seguir