Balanceamento de carga HTTP(s) por meio da Entrada

No Google Kubernetes Engine (GKE), um objeto de entrada define regras para rotear tráfego de HTTP(S) externo para aplicativos executados em um cluster. Um objeto de entrada está associado a um ou mais objetos de serviço, e cada um deles está associado a um conjunto de pods.

Ao criar um objeto de entrada, o controlador de entrada do GKE (em inglês) gera um balanceador de carga HTTP(S) do Google Cloud e o configura de acordo com as informações na entrada e nos respectivos serviços associados.

Para saber como configurar o balanceamento de carga HTTP, consulte Como configurar o balanceamento de carga por meio da Entrada.

Recursos do balanceamento de carga HTTP(S)

O balanceamento de carga HTTP(S), configurado pela Entrada, inclui os seguintes recursos:

Configuração flexível para serviços
Uma Entrada define como o tráfego chega aos seus serviços e como ele é roteado para seu aplicativo. Além disso, uma Entrada pode fornecer um único endereço IP para vários serviços no cluster.
Integração com serviços de rede do Google Cloud
Uma entrada pode configurar recursos do Google Cloud, como certificados SSL gerenciados pelo Google (Beta), Google Cloud Armor, Cloud CDN e Cloud Identity-Aware Proxy.
Suporte para vários certificados TLS
Uma Entrada pode especificar o uso de vários certificados TLS para o encerramento da solicitação.

Para saber mais sobre esses recursos, consulte os Conceitos de balanceamento de carga HTTP(S).

Opções para fornecer certificados SSL

Existem três maneiras de fornecer certificados SSL para um balanceador de carga HTTPS:

Certificados gerenciados pelo Google
Os certificados SSL gerenciados pelo Google são provisionados, implantados, renovados e gerenciados para seus domínios. Os certificados gerenciados não oferecem suporte a domínios com caractere curinga ou a vários nomes alternativos do assunto (SANs, na sigla em inglês).
Certificados autogerenciados compartilhados com o Google Cloud
É possível provisionar seu próprio certificado SSL e criar um recurso de certificado em seu projeto do Google Cloud. Em seguida, liste o recurso de certificado em uma anotação em uma Entrada para criar um balanceador de carga HTTP(S) que use o certificado. Consulte as instruções para certificados pré-compartilhados para mais informações.
Certificados autogerenciados como recursos de secret
É possível provisionar seu próprio certificado SSL e criar um Secret para mantê-lo. Em seguida, consulte o secret em uma especificação da Entrada para criar um balanceador de carga HTTP(S) que use o certificado. Para mais informações, consulte as instruções para usar certificados em secrets.

Limitações

  • O tamanho total do namespace e o nome de uma entrada não pode exceder 40 caracteres. O não cumprimento desta diretriz pode fazer com que o controlador de entrada GKE atue de forma anormal. Para mais informações, consulte este problema.

  • O número máximo de regras para um mapa de URL é 50. Isso significa que é possível especificar no máximo 50 regras em uma Entrada.

  • Se você usar o controlador de entrada do GKE, seu cluster poderá ter no máximo 1000 nós.

  • Para que o controlador de entrada do GKE use os readinessProbes como verificação de integridade, os pods de uma entrada precisam existir no momento da criação dela. Se as réplicas forem dimensionadas para 0, a verificação de integridade padrão será aplicada. Para mais informações, veja esses comentários sobre o problema.

  • As alterações no readinessProbe de um Pod não afetam a entrada após a criação.

  • O balanceador de carga HTTPS encerra o TLS em locais que são distribuídos globalmente, de modo a minimizar a latência entre os clientes e o balanceador de carga. Se você precisar de controle geográfico sobre onde o TLS é encerrado, use um controlador de entrada personalizado (em inglês) e um balanceador de carga de rede do GCP e encerre o TLS em back-ends localizados em regiões apropriadas para suas necessidades.

Vários serviços de back-end

Um balanceador de carga HTTP(S) fornece um endereço IP estável para rotear solicitações para diversos serviços de back-end.

Por exemplo, é possível configurar o balanceador de carga para encaminhar solicitações para diferentes serviços de back-end dependendo do caminho do URL. As solicitações enviadas para "your-store.example" podem ser encaminhadas para um serviço de back-end que exibe itens com preço integral. Já as enviadas para "your-store.example/discounted" podem ser encaminhadas para um serviço de back-end que exibe itens com desconto.

Também é possível configurar o balanceador de carga para encaminhar solicitações de acordo com o nome do host. As solicitações enviadas para your-store.example poderiam ir para um serviço de back-end e as enviadas para your-experimental-store.example para outro.

Para criar e configurar um balanceador de carga HTTP(S), crie um objeto Entrada do Kubernetes em um cluster do GKE. O objeto Entrada precisa estar associado a um ou mais objetos de serviço, e cada um deles associado a um conjunto de pods.

Veja aqui o manifesto de uma Entrada.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

Quando você cria a Entrada, o controlador de entrada do GKE cria e configura um balanceador de carga HTTP(S) de acordo com as informações na Entrada e nos serviços associados. Além disso, o balanceador de carga recebe um endereço IP estável que pode ser associado a um nome de domínio.

No exemplo anterior, imagine que você associou o endereço IP do balanceador de carga ao nome de domínio your-store.example. Quando um cliente envia uma solicitação para "your-store.example", ela é roteada para um serviço do Kubernetes chamado my-products na porta 60000. E quando um cliente envia uma solicitação para your-store.example/discounted, essa é roteada para um serviço do Kubernetes chamado my-discounted-products na porta 80.

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 * 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.

O manifesto do serviço my-products ficaria da seguinte maneira:

apiVersion: v1
kind: Service
metadata:
  name: my-products
spec:
  type: NodePort
  selector:
    app: products
    department: sales
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50000

No manifesto do serviço, observe que type é NodePort. Esse é o tipo necessário para uma Entrada usada para configurar um balanceador de carga HTTP(S).

No manifesto do serviço, o campo selector diz que qualquer pod que tenha os rótulos app: products e department: sales é membro deste serviço.

Quando uma solicitação chega ao serviço na porta 60000, ela é roteada para um dos pods de membro na porta TCP 50000.

Cada pod de membro precisa ter um contêiner escutando a porta TCP 50000.

O manifesto do serviço my-discounted-products ficaria da seguinte maneira:

apiVersion: v1
kind: Service
metadata:
  name: my-discounted-products
spec:
  type: NodePort
  selector:
    app: discounted-products
    department: sales
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

No manifesto do serviço, o campo selector diz que qualquer pod que tenha os rótulos app: discounted-products e department: sales é membro deste serviço.

Quando uma solicitação chega ao serviço na porta 80, ela é roteada para um dos pods de membro na porta TCP 8080.

Todo pod membro precisa ter um contêiner escutando a porta TCP 8080.

Back-end padrão

Especifique um back-end padrão fornecendo um campo backend no manifesto da entrada. As solicitações que não corresponderem aos caminhos no campo rules serão enviadas ao serviço e à porta especificada no campo backend. Por exemplo, na entrada a seguir, todas as solicitações que não correspondem / ou /discounted foram enviadas para um serviço chamado my-products na porta 60001.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
spec:
  backend:
    serviceName: my-products
    servicePort: 60001
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-products
          servicePort: 60000
      - path: /discounted
        backend:
          serviceName: my-discounted-products
          servicePort: 80

Se você não especificar um back-end padrão, o GKE fornecerá um back-end padrão que retorna 404.

Verificações de integridade

Um serviço exposto por meio de uma Entrada precisa responder a verificações de integridade do balanceador de carga. Qualquer contêiner que seja o destino final do tráfego com carga balanceada precisa seguir um destes procedimentos para indicar que está íntegro:

  • Veicular uma resposta com o status HTTP 200 para solicitações GET no caminho /.

  • Configurar uma sondagem de preparo do HTTP. Exibir uma resposta com o status HTTP 200 para solicitações GET no path especificado pela sondagem de preparo. O serviço exposto por meio de uma entrada precisa apontar para a mesma porta de contêiner em que a sondagem está ativada.

    Por exemplo, imagine que um contêiner especifica a seguinte sondagem de preparo:

    ...
    readinessProbe:
      httpGet:
        path: /healthy
    

    Em seguida, se o gerenciador do caminho /healthy do contêiner retornar um status HTTP 200, o balanceador de carga considerará o contêiner como ativo e íntegro.

Serviço do Kubernetes em comparação com o serviço de back-end do Google Cloud

Um serviço (em inglês) do Kubernetes e um serviço de back-end do Google Cloud são coisas diferentes. Existe uma forte relação entre os dois, mas o relacionamento não é necessariamente de um para um. O controlador de entrada do GKE cria um serviço de back-end do Google Cloud para cada par (serviceName, servicePort) em um manifesto de entrada. Dessa forma, é possível que um objeto de serviço do Kubernetes esteja relacionado a vários serviços de back-end do Google Cloud.

Suporte para recursos do Google Cloud

É possível usar um BackendConfig para configurar um balanceador de carga HTTP(S) para usar recursos como Google Cloud Armor, Cloud CDN e IAP.

O BackendConfig é um recurso personalizado que contém informações de configuração dos recursos do Google Cloud.

O manifesto de entrada se refere a um serviço, e o manifesto de serviço se refere a um BackendConfig com uma anotação beta.cloud.google.com/backend-config.

...
kind: Ingress
...
spec:
  rules:
  - http:
      paths:
      - path: /
        backend:
          serviceName: my-service
          servicePort: 80
...

kind: Service
metadata:
  name: my-service
  ...
  annotations:
    beta.cloud.google.com/backend-config: '{"ports": {"80":"my-backend-config"}}'
spec:
  type: NodePort
  ...
 

Suporte para WebSocket

O protocolo WebSocket funciona idealmente com o balanceamento de carga HTTP(S). Nenhuma configuração é necessária.

Se você pretende usar o protocolo WebSocket, use um valor de tempo limite maior que o padrão de 30 segundos. Para definir o valor de tempo limite para um serviço de back-end configurado por meio da Entrada, crie um objeto BackendConfig e use a anotação beta.cloud.google.com/backend-config no manifesto do serviço.

Para mais informações, consulte Como configurar um serviço de back-end por meio da Entrada.

Endereços IP estáticos para balanceadores de carga HTTP(S)

Ao criar um objeto Entrada, você recebe um endereço IP externo estável que os clientes podem usar para acessar seus serviços e, por sua vez, os contêineres em execução. O endereço IP é estável porque ele dura por toda a vida útil do objeto Entrada. Se você excluir a Entrada e criar uma nova no mesmo arquivo de manifesto, pode ser que não receba o mesmo endereço IP externo.

Caso queira um endereço IP permanente que se mantenha o mesmo depois de excluir a Entrada e criar uma nova, reserve um endereço IP externo estático global. Em seguida, no manifesto da entrada, inclua uma anotação que forneça o nome do endereço IP estático reservado.

Por exemplo, suponha que você tenha reservado um endereço IP externo estático global chamado my-static-address. No manifesto da Entrada, inclua uma anotação kubernetes.io/ingress.global-static-ip-name, conforme mostrado aqui:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.global-static-ip-name: my-static-address

Para ver mais informações sobre como criar um endereço IP externo estático para uma entrada, consulte Como configurar um endereço IP estático.

Como configurar o HTTPS (TLS) entre o cliente e o balanceador de carga

Um balanceador de carga HTTP(S) atua como um proxy entre seus clientes e o aplicativo. Se você quiser aceitar solicitações HTTPS dos seus clientes, o balanceador de carga precisará ter um certificado para provar sua identidade a eles. Além disso, ele precisa ter uma chave privada para concluir o handshake HTTPS.

Quando o balanceador de carga aceita uma solicitação HTTPS de um cliente, o tráfego entre o cliente e o balanceador de carga é criptografado usando TLS. No entanto, o balanceador de carga encerra a criptografia TLS e encaminha a solicitação sem criptografia para o aplicativo. Para informações sobre como criptografar o tráfego entre o balanceador de carga e o aplicativo, consulte HTTPS entre o balanceador de carga e seu aplicativo.

É possível usar certificados SSL gerenciados pelo Google (Beta) ou usar certificados gerenciados por você mesmo. Para mais informações sobre como criar uma entrada que use certificados gerenciados pelo Google, consulte Como usar certificados SSL gerenciados pelo Google (Beta).

Para fornecer um balanceador de carga HTTP(S) com um certificado e uma chave que você mesmo criou, crie um secret do Kubernetes. O secret contém o certificado e a chave. Para usar um secret, adicione o nome dele no campo tls do seu manifesto de entrada, como mostrado no exemplo a seguir:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
spec:
  tls:
  - secretName: my-secret
  rules:
  - http:
      paths:
      - path: /*
        backend:
          serviceName: my-metrics
          servicePort: 60000

As alterações nos secrets são coletadas periodicamente. Por isso, se você modificar os dados do secret, levará no máximo 10 minutos para que essas alterações sejam aplicadas ao balanceador de carga.

Para mais informações sobre o uso de chaves secretas para fornecer certificados ao balanceador de carga, consulte Como usar vários certificados SSL no balanceamento de carga HTTP(S) por meio da Entrada.

Como desativar o HTTP

Se quiser que todo o tráfego entre o cliente e o balanceador de carga HTTP(S) use HTTPS, é possível desativar o HTTP incluindo a anotação kubernetes.io/ingress.allow-http no seu manifesto da entrada. Defina o valor da anotação como "false".

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: my-ingress-2
  annotations:
    kubernetes.io/ingress.allow-http: "false"
spec:
  tls:
  - secretName: my-secret
  ...

Certificados pré-compartilhados para balanceadores de carga

Como alternativa ao uso das chaves secretas do Kubernetes para fornecer certificados ao balanceador de carga para o encerramento do HTTP(S), é possível usar os certificados enviados anteriormente ao projeto do GCP. Para mais informações, consulte Como usar certificados pré-compartilhados e Como usar vários certificados SSL no balanceamento de carga HTTP(S) com a Entrada.

HTTPS (TLS) entre o balanceador de carga e o aplicativo

Um balanceador de carga HTTP(S) atua como um proxy entre seus clientes e o aplicativo. Os clientes podem usar HTTP ou HTTPS para a comunicação com o proxy do balanceador de carga. Porém, a conexão entre o proxy do balanceador de carga e o aplicativo usa o HTTP por padrão. Se o aplicativo em execução em um pod do GKE for capaz de receber solicitações HTTPS, configure o balanceador de carga para usar HTTPS quando encaminhar solicitações para o aplicativo.

Para configurar o protocolo usado entre o balanceador de carga e o aplicativo, use a anotação cloud.google.com/app-protocols no manifesto de serviço.

O manifesto do serviço a seguir especifica duas portas. A anotação diz que quando um balanceador de carga HTTP(S) segmenta a porta 80 do Serviço, ele deve usar HTTP. E quando o balanceador de carga segmenta a porta 443 do serviço, ele deve usar HTTPS.

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-https-port
    port: 443
    targetPort: 8443
  - name: my-http-port
    port: 80
    targetPort: 50001

A anotação cloud.google.com/app-protocols tem a mesma finalidade que a anotação service.alpha.kubernetes.io/app-protocols mais antiga. Os nomes das anotações antigas e novas podem coexistir, conforme mostrado no seguinte manifesto de serviço. Quando as duas anotações aparecem no mesmo manifesto de serviço, service.alpha.kubernetes.io/app-protocols tem precedência.

apiVersion: v1
kind: Service
metadata:
  name: my-service-3
  annotations:
    cloud.google.com/app-protocols: '{"my-https-port":"HTTPS","my-http-port":"HTTP"}'
    service.alpha.kubernetes.io/app-protocols: '{"my-first-port":"HTTPS","my-second-port":"HTTP"}'
spec:
  type: NodePort
  selector:
    app: metrics
    department: sales
  ports:
  - name: my-first-port
    port: 443
    targetPort: 8443
  - name: my-second-port
    port: 80
    targetPort: 50001

Como usar vários certificados TLS

Suponha que você queira que um balanceador de carga HTTP(S) atenda ao conteúdo de dois nomes de host: your-store.example e your-experimental-store.example. Além disso, você quer que o balanceador de carga use um certificado para your-store.example e outro para your-experimental-store.example.

É possível especificar vários certificados em um manifesto de entrada. O balanceador de carga escolherá um certificado se o nome comum (CN, na sigla em inglês) no certificado corresponder ao nome do host usado na solicitação. Para informações detalhadas sobre como configurar vários certificados, consulte Como usar vários certificados SSL no balanceamento de carga HTTP(S) com a Entrada.

A seguir