Como configurar o balanceamento de carga HTTP(S) com a entrada

Neste tutorial, mostramos como executar um aplicativo da Web por trás de um balanceador de carga HTTP(S) externo configurando o recurso de entrada.

Segundo plano

O Google Kubernetes Engine (GKE) oferece suporte integrado a dois tipos de Cloud Load Balancing para um aplicativo acessível ao público:

  • Quando você especifica type:LoadBalancer no manifesto do recurso, o GKE cria um Serviço do tipo LoadBalancer. O GKE faz chamadas apropriadas à API do Google Cloud para criar um balanceador de carga de rede externo ou um balanceador de carga TCP/UDP interno. O GKE cria um balanceador de carga TCP/UDP interno quando você adiciona a anotação cloud.google.com/load-balancer-type: "Internal". Caso contrário, o GKE criará um balanceador de carga de rede externo.

    É possível usar um desses tipos de balanceador de carga para o tráfego HTTP(S), mas eles operam nas camadas OSI 3/4 e não reconhecem conexões HTTP ou respostas e solicitações HTTP individuais. Outra característica importante é que as solicitações não são encaminhadas por proxy ao destino.

  • Ao especificar kind:Ingress no manifesto do recurso, você instrui o GKE a criar um recurso de entrada. Ao incluir anotações e oferecer suporte a cargas de trabalho e Serviços, você consegue criar um controlador de Entrada personalizado. Caso contrário, o GKE faz chamadas apropriadas à API do Google Cloud para criar um balanceador de carga HTTP(S) externo. As regras de host e as correspondências de caminho do mapa de URLs do balanceador de carga se referem a um ou mais serviços de back-end, onde cada serviço corresponde a um Serviço do GKE do tipo NodePort, conforme mencionado no Ingress. Os back-ends para cada serviço de back-end são grupos de instâncias ou de endpoints de rede (NEGs, na sigla em inglês). Os NEGs são criados quando você define o balanceamento de carga nativo de contêiner como parte da configuração da Entrada. Para cada serviço de back-end, o GKE cria uma verificação de integridade do Google Cloud com base nas configurações de sondagem de prontidão da carga de trabalho referenciada pelo Serviço do GKE correspondente.

    Se você estiver expondo um serviço HTTP(S) hospedado no GKE, o HTTP(S) é o método recomendado para balanceamento de carga.

Objetivos

  • Crie um cluster do GKE.
  • Implante o aplicativo da Web de amostra no cluster.
  • Exponha o aplicativo de amostra à Internet por trás de um balanceador de carga HTTP(S) externo.

Antes de começar

Siga estas etapas para ativar a API do Kubernetes Engine:
  1. Acesse a página do Kubernetes Engine no Console do Google Cloud.
  2. Crie ou selecione um projeto.
  3. Aguarde a ativação da API e dos serviços relacionados. Isso pode levar alguns minutos.
  4. Verifique se o faturamento está ativado para seu projeto na nuvem. Saiba como confirmar se o faturamento está ativado para o projeto.

Instale as ferramentas de linha de comando a seguir usadas neste tutorial:

  • gcloud é usado para criar e excluir clusters do Kubernetes Engine. gcloud está incluído no SDK do Google Cloud.
  • O kubectl é usado para gerenciar o Kubernetes, o sistema de orquestração de cluster usado pelo Kubernetes Engine. É possível instalar kubectl usando gcloud:
    gcloud components install kubectl

Clone o código de amostra do GitHub:

git clone https://github.com/GoogleCloudPlatform/kubernetes-engine-samples
cd kubernetes-engine-samples/load-balancing

Definir padrões para a ferramenta de linha de comando gcloud

Para poupar tempo, em vez de digitar o ID do projeto e as opções de zona do Compute Engine na ferramenta de linha de comando gcloud, defina os padrões:
gcloud config set project project-id
gcloud config set compute/zone compute-zone

Criar um cluster de contêiner

Crie um cluster de contêiner chamado loadbalancedcluster executando:

gcloud container clusters create loadbalancedcluster

Como implantar um aplicativo da Web

No manifesto a seguir, você encontra uma implantação que executa a imagem do contêiner do aplicativo da Web de amostra em um servidor HTTP na porta 8080:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: default
spec:
  selector:
    matchLabels:
      run: web
  template:
    metadata:
      labels:
        run: web
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:1.0
        imagePullPolicy: IfNotPresent
        name: web
        ports:
        - containerPort: 8080
          protocol: TCP

Aplique o recurso ao cluster:

kubectl apply -f web-deployment.yaml

Como expor a implantação dentro do cluster

O manifesto a seguir descreve um Serviço que torna a implantação web acessível no cluster de contêiner:

apiVersion: v1
kind: Service
metadata:
  name: web
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web
  type: NodePort
  1. Aplique o recurso ao cluster:

    kubectl apply -f web-service.yaml
    

    Quando você cria um serviço do tipo NodePort com esse comando, o GKE o disponibiliza em um número de porta alto selecionado aleatoriamente (por exemplo, 32640) em todos os nós do cluster.

  2. Verifique se o serviço foi criado e se uma porta do nó está alocada:

    kubectl get service web
    
    Saída:
    NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
    web       NodePort   10.35.245.219   <none>        8080:32640/TCP   5m
    

    Na saída de exemplo, a porta do nó para o serviço do web é 32640. Além disso, não há IP externo alocado para esse Serviço. Como os nós do GKE não podem ser acessados externamente por padrão, criar esse serviço não faz com que o aplicativo possa ser acessado pela Internet.

Para que o aplicativo de servidor da Web HTTP(S) possa ser acessado publicamente, crie um recurso de entrada.

Como criar um recurso de entrada

A entrada é um recurso do Kubernetes que encapsula um conjunto de regras e configurações para encaminhar tráfego HTTP(S) externo aos serviços internos.

No GKE, o Ingress é implementado usando o Cloud Load Balancing. Quando você cria uma entrada no cluster, o GKE cria um balanceador de carga HTTP(S) e o configura para encaminhar tráfego para o aplicativo.

O Kubernetes Ingress é um recurso Beta. Isso significa que a forma como você descreve o objeto dele está sujeita a alterações, mas os balanceadores de carga do Cloud provisionados pelo GKE para implementar o Ingress estão prontos para produção.

O manifesto a seguir descreve um recurso de entrada que direciona o tráfego para seu serviço web:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: basic-ingress
spec:
  backend:
    serviceName: web
    servicePort: 8080

Aplique o recurso ao cluster:

kubectl apply -f basic-ingress.yaml

Depois que você implantar esse manifesto, o Kubernetes criará um recurso de entrada no cluster. O controlador de entrada do GKE cria e configura um balanceador de carga HTTP(S) de acordo com as informações na entrada, roteando todo o tráfego HTTP externo (na porta 80) para o serviço NodePort web que você expôs.

Visitar seu aplicativo

Para descobrir o endereço IP externo do balanceador de carga que disponibiliza o aplicativo, execute:

kubectl get ingress basic-ingress
Saída:
NAME            HOSTS     ADDRESS         PORTS     AGE
basic-ingress   *         203.0.113.12    80        2m

Abra o endereço IP externo do aplicativo em um navegador e veja uma resposta HTTP de texto simples como esta:

Hello, world!
Version: 1.0.0
Hostname: web-6498765b79-fq5q5

Acesse Balanceamento de carga no Console do Cloud e verifique os recursos de rede criados pelo controlador da entrada do GKE.

(Opcional) Como configurar um endereço IP estático

Quando você publica um servidor da Web em um nome de domínio, precisa que o endereço IP externo de um aplicativo seja um IP estático que não seja alterado.

Por padrão, o GKE aloca endereços IP externos temporários de aplicativos HTTP expostos por meio de um Ingress. Endereços temporários estão sujeitos a alterações. Se você planeja executar seu aplicativo por muito tempo, use um endereço IP externo estático.

Depois de configurar um IP estático para o recurso de entrada, a exclusão da entrada não exclui o endereço IP estático associado a ela. Certifique-se de limpar os endereços IP estáticos configurados quando não planejar usá-los novamente.

Para configurar um endereço IP estático, conclua as etapas a seguir:

  1. Reserve um endereço IP externo estático nomeado web-static-ip.

    gcloud

    gcloud compute addresses create web-static-ip --global
    

    Config Connector

    Observação: esta etapa requer o Config Connector. Siga estas instruções para instalar o Config Connector no cluster.

    apiVersion: compute.cnrm.cloud.google.com/v1beta1
    kind: ComputeAddress
    metadata:
      name: web-static-ip
    spec:
      location: global
    Para implantar esse manifesto, faça o download dele para sua máquina como compute-address.yaml e execute:
    kubectl apply -f compute-address.yaml

  2. O manifesto basic-ingress-static.yaml adiciona uma anotação à entrada para usar o recurso de IP estático chamado web-static-ip:

    apiVersion: networking.k8s.io/v1beta1
    kind: Ingress
    metadata:
      name: basic-ingress
      annotations:
        kubernetes.io/ingress.global-static-ip-name: "web-static-ip"
    spec:
      backend:
        serviceName: web
        servicePort: 8080
    

    Veja o manifesto:

    cat basic-ingress-static.yaml
    
  3. Aplique o recurso ao cluster:

    kubectl apply -f basic-ingress-static.yaml
    
  4. Verifique o endereço IP externo:

    kubectl get ingress basic-ingress
    

    Aguarde até que o endereço IP do seu aplicativo seja alterado para usar o endereço IP reservado do recurso web-static-ip.

    A atualização do recurso de entrada atual, a reconfiguração do balanceador de carga e a propagação das regras de balanceamento de carga em todo o mundo podem demorar alguns minutos. Após a conclusão da operação, o GKE libera o endereço IP temporário anteriormente alocado ao aplicativo.

(Opcional) Como processar vários aplicativos em um balanceador de carga

Execute vários serviços em um único balanceador de carga e IP público configurando regras de encaminhamento na entrada. Com a hospedagem de vários serviços na mesma entrada, você evita a criação de mais balanceadores de carga, que são recursos faturáveis, para cada serviço publicado na Internet.

O manifesto a seguir descreve uma implantação com a versão 2.0 do mesmo aplicativo da Web:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web2
  namespace: default
spec:
  selector:
    matchLabels:
      run: web2
  template:
    metadata:
      labels:
        run: web2
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:2.0
        imagePullPolicy: IfNotPresent
        name: web2
        ports:
        - containerPort: 8080
          protocol: TCP

Aplique o recurso ao cluster:

kubectl apply -f web-deployment-v2.yaml

O manifesto a seguir descreve um serviço que expõe web2 internamente ao cluster em um serviço NodePort chamado web2:

apiVersion: v1
kind: Service
metadata:
  name: web2
  namespace: default
spec:
  ports:
  - port: 8080
    protocol: TCP
    targetPort: 8080
  selector:
    run: web2
  type: NodePort

Aplique o recurso ao cluster:

kubectl apply -f web-service-v2.yaml

O manifesto a seguir descreve um recurso de entrada que:

  • roteia as solicitações com o caminho começando com /v2/ para o serviço web2
  • encaminha todas as outras solicitações para o serviço web
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: fanout-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: web
          servicePort: 8080
      - path: /v2/*
        backend:
          serviceName: web2
          servicePort: 8080

Aplique o recurso ao cluster:

kubectl create -f fanout-ingress.yaml

Depois que a entrada for implantada, execute kubectl get ingress fanout-ingress para descobrir o endereço IP público do cluster.

Em seguida, acesse o endereço IP para ver se os dois aplicativos podem ser acessados no mesmo balanceador de carga:

  • Acesse http://<IP_ADDRESS>/ e observe que a resposta contém Version: 1.0.0 (já que a solicitação é encaminhada para o serviço web)
  • Acesse http://<IP_ADDRESS>/v2/ e observe que a resposta contém Version: 2.0.0 (já que a solicitação é encaminhada para o serviço web2)

O único caractere curinga aceito no campo path de uma entrada é *. O caractere * precisa vir depois de uma barra (/) e ser o último caractere no padrão. Por exemplo, /*, /foo/* e /foo/bar/* são padrões válidos, ao contrário de *, /foo/bar* e /foo/*/bar.

Um padrão mais específico tem precedência sobre um menos específico. Se você tiver os padrões /foo/* e /foo/bar/*, /foo/bar/bat será usado na correspondência com /foo/bar/*.

Para mais informações sobre limitações de caminho e correspondência de padrões, consulte a documentação dos mapas de URL.

(Opcional) Como monitorar a disponibilidade e a latência do serviço

As verificações de tempo de atividade do Google Cloud realizam o monitoramento de aplicativos do Blackbox do ponto de vista do usuário, determinando a latência e a disponibilidade de vários IPs externos para o endereço IP do balanceador de carga. Em comparação, as verificações de integridade do Google Cloud realizam uma verificação interna em relação aos IPs do pod, determinando a disponibilidade no nível da instância. As verificações são complementares e fornecem uma visão holística da integridade do aplicativo.

É possível criar uma verificação de tempo de atividade usando o Console do Google Cloud, a API Cloud Monitoring ou as bibliotecas de cliente do Cloud Monitoring. Para mais informações, consulte Como gerenciar verificações de tempo de atividade. Se você quiser criar uma verificação de tempo de atividade usando o Console do Google Cloud, faça o seguinte:

  1. No Console do Google Cloud, selecione Monitoramento ou clique no botão a seguir:

    Acessar Monitoring

  2. No painel de navegação Monitoramento, selecione Verificações de tempo de atividade e clique em Criar verificação de tempo de atividade.

  3. Para o destino da verificação de tempo de atividade, defina os seguintes campos:

    • Selecione o tipo de protocolo como TCP.
    • Em Tipo de recurso, selecione URL.
    • Em Nome do host, insira o endereço IP do balanceador de carga.
    • Digite o número da porta do balanceador de carga no campo Porta.

    Para ter acesso à documentação completa de todos os campos em uma verificação de tempo de atividade, consulte Como criar uma verificação de tempo de atividade.

Para monitorar uma verificação de tempo de atividade, você pode criar uma política de alertas ou ver o painel de verificação de tempo de atividade. Uma política de alertas pode notificar você por e-mail ou por meio de um canal diferente se a verificação de tempo de atividade falhar. Para informações gerais sobre políticas de alertas, consulte Introdução a alertas.

Comentários

Por padrão, a entrada executa uma verificação de integridade periódica. Para fazer isso, realiza uma solicitação GET no caminho / para determinar a integridade do aplicativo. A resposta esperada é HTTP 200. Se você quiser verificar um caminho diferente ou esperar um código de resposta diferente, poderá usar um caminho de verificação de integridade personalizado.

A entrada é compatível com casos de uso mais avançados, como os abaixo:

  • Hospedagem virtual baseada em nome: use a Entrada para reaproveitar o balanceador de carga em vários nomes de domínio, subdomínios e para expor diversos serviços em um único endereço IP e balanceador de carga. Confira os exemplos de fanout simples e hospedagem virtual baseada em nome para saber como configurar a entrada para essas tarefas.

  • Encerramento HTTPS: é possível configurar a entrada para encerrar o tráfego HTTPS usando o Cloud Load Balancer.

Quando uma entrada é excluída, os recursos associados são limpos automaticamente pelo controlador de entrada do GKE, com exceção dos endereços IP estáticos reservados.

Limpeza

Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

  1. Excluir as regras de encaminhamento criadas manualmente e os proxies de destino que fazem referência à entrada:

    Um proxy de destino pendente que faz referência a um mapa de URLs gerenciado do controlador de entrada do GKE faz com que a exclusão da entrada falhe nas versões 1.15.4-gke.22+ do GKE. Inspecione o recurso de entrada para encontrar um evento com uma mensagem de erro semelhante a esta:

     Error during GC: error running load balancer garbage collection routine: googleapi: Error 400: The url_map resource 'projects/project-id/global/urlMaps/k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82' is already being used by 'projects/project-id/global/targetHttpsProxies/k8s2-um-tlw9rhgp-default-my82-target-proxy', resourceInUseByAnotherResource
     

    No exemplo da mensagem de erro acima, k8s2-um-tlw9rhgp-default-my82-target-proxy é um proxy HTTPS de destino criado manualmente que ainda faz referência ao mapa de URL k8s2-um-tlw9rhgp-default-my-ingress-9ifnni82 que foi criado e gerenciado pelo controlador de entrada.

    Esses recursos de front-end criados manualmente (regra de encaminhamento e proxy de destino) precisam ser excluídos antes de continuar com a exclusão da Entrada.

  2. Exclua a Entrada: com essa etapa, o endereço IP externo temporário e os recursos de balanceamento de carga associados ao aplicativo são desalocados:

    kubectl delete ingress basic-ingress

    Se você seguiu a etapa opcional para criar uma Entrada para rotear solicitações por caminho, exclua a Entrada:

    kubectl delete ingress fanout-ingress

  3. Exclua o endereço IP estático: conclua esta etapa somente se tiver seguido a etapa opcional para criar um endereço IP estático.

    • Se você seguiu a "Opção 1" para converter um endereço IP temporário atual em IP estático, acesse o Console do Cloud para excluir o endereço IP estático.

    • Se você seguiu a "Opção 2" para criar um novo endereço IP estático, execute o comando a seguir para excluir o endereço IP estático:

      gcloud compute addresses delete web-static-ip --global
  4. Exclua o cluster: nessa etapa, são excluídos os nós de computação do cluster de contêiner e outros recursos, como as implantações:

    gcloud container clusters delete loadbalancedcluster

A seguir