Visão geral da rede

Nesta página, fornecemos uma visão geral dos principais aspectos da rede do Google Kubernetes Engine. Estas informações são úteis para aqueles que estão apenas dando os primeiros passos com o Kubernetes, bem como operadores de cluster ou desenvolvedores de aplicativos experientes que precisam de mais conhecimento sobre a rede do Kubernetes para melhor projetar aplicativos ou configurar cargas de trabalho do Kubernetes.

O Kubernetes permite que você defina de forma declarativa como seus aplicativos são implantados, como os aplicativos se comunicam entre si e com o plano de controle do Kubernetes e como os clientes podem alcançar seus aplicativos. Esta página também contém informações sobre como o GKE configura os serviços do Google Cloud Platform, em que ele é relevante para a rede.

Quando você usa o Kubernetes para orquestrar seus aplicativos, é importante mudar a maneira como você pensa sobre o design de rede de seus aplicativos e os hosts dele. Com o Kubernetes, você pensa em como os pods, serviços e clientes externos se comunicam, em vez de pensar em como seus hosts ou VMs estão conectados.

O Kubernetes, junto com o GCP, configura dinamicamente as regras de filtragem de IP, as tabelas de encaminhamento e as regras de firewall em cada nó, dependendo do modelo declarativo das implantações do Kubernetes e da configuração do cluster no GCP. Não faça alterações manuais nos nós, porque elas serão substituídas pelo GKE e seu cluster poderá não funcionar corretamente. O único motivo para acessar um nó diretamente é depurar problemas na sua configuração.

Pré-requisitos

Nesta página, é usada a terminologia relacionada às camadas de transporte, Internet e aplicativo do conjunto de protocolos da Internet, incluindo HTTP e DNS. No entanto, você não precisa ser um especialista nesses tópicos.

Além disso, este conteúdo pode ser mais fácil de entender se você tiver uma compreensão básica dos conceitos e utilitários de gerenciamento de rede Linux, como regras iptables e roteamento.

O modelo de rede do Kubernetes depende muito de endereços IP. Serviços, pods, contêineres e nós se comunicam usando endereços IP e portas. O Kubernetes fornece diferentes tipos de balanceamento de carga para direcionar o tráfego para os pods corretos. Todos esses mecanismos são descritos com mais detalhes posteriormente neste tópico. Tenha os seguintes termos em mente ao ler:

  • ClusterIP: o endereço IP atribuído a um serviço. Em outros documentos, pode ser chamado de "IP do cluster". Esse endereço é estável durante a vida útil do serviço, conforme discutido na seção Serviços deste tópico.
  • IP do pod: o endereço IP atribuído a um determinado pod. Ele é temporário, conforme discutido na seção Pods deste tópico.
  • IP do nó: o endereço IP atribuído a um determinado nó.

Rede dentro do cluster

Nesta seção, discutimos a rede dentro de um cluster do Kubernetes, no que se refere à alocação de IP, pods e serviços.

Alocação de IP

O Kubernetes usa vários intervalos de IP para atribuir endereços IP a nós, pods e serviços.

  • Cada nó tem um endereço IP atribuído a partir da rede de nuvem privada virtual (VPC, na sigla em inglês) do cluster. Esse IP de nó fornece conectividade de componentes de controle, como o kube-proxy e o kubelet para o servidor da API Kubernetes.
  • Cada pod tem um endereço IP atribuído a partir de um intervalo de 256 endereços IP, um bloco /24 CIDR. Opcionalmente, é possível especificar esse intervalo ao criar o cluster.
  • Cada serviço tem um endereço IP, denominado ClusterIP, atribuído a partir da rede VPC do cluster. Opcionalmente, é possível personalizar a rede VPC ao criar o cluster.

Para ver mais informações, acesse Como criar clusters nativos de VPC usando IPs do alias.

Pods

No Kubernetes, um pod é a unidade implantável mais básica dentro de um cluster do Kubernetes. Um pod executa um ou mais contêineres. Zero ou mais pods são executados em um nó. Cada nó no cluster faz parte de um conjunto de nós. No GKE, esses nós são máquinas virtuais, cada uma sendo executada como uma instância no Compute Engine.

Os pods também podem ser anexados a volumes de armazenamento externos e outros recursos personalizados. Este diagrama mostra um único nó executando dois pods, cada um anexado a dois volumes.

Diagrama mostrando um único nó executando dois pods, conforme descrito no parágrafo acima

Quando o Kubernetes agenda um pod para ser executado em um nó, ele cria um namespace de rede para o pod no kernel Linux do nó. Esse namespace de rede conecta a interface de rede física do nó, como eth0, com o pod usando uma interface de rede virtual, para que os pacotes possam fluir de e para o pod. A interface de rede virtual associada no namespace de rede raiz do nó se conecta a uma ponte do Linux que permite a comunicação entre pods no mesmo nó. Um pod também pode enviar pacotes fora do nó usando a mesma interface virtual.

O Kubernetes atribui um endereço IP (o IP do pod) à interface de rede virtual no namespace de rede do pod a partir de um intervalo de endereços reservado para pods no nó. Esse intervalo de endereços é um subconjunto do intervalo de endereços IP atribuído ao cluster para pods, que você pode configurar ao criar um cluster.

Um contêiner em execução em um pod usa o namespace de rede do pod. Do ponto de vista do contêiner, o pod parece ser uma máquina física com uma interface de rede. Todos os contêineres no pod veem essa mesma interface de rede. O localhost de cada contêiner é conectado à interface de rede física do nó por meio do pod, como eth0.

Observe que essa conectividade varia muito se você usa a CNI nativa do GKE ou se escolhe usar a implementação da Calico habilitando a Política de rede ao criar o cluster.

  • Se você usar o CNI do GKE, uma extremidade do par veth é anexada ao pod em seu namespace e a outra é conectada ao dispositivo de ponte do Linux cbr0. Nesse caso, o comando a seguir mostra os vários endereços MAC dos pods anexados ao cbr0:

    arp -n
    

    Além disso, invocar o seguinte no contêiner da caixa de ferramentas mostra a extremidade do namespace raiz de cada par veth anexado ao cbr0:

    brctl show cbr0
    
  • Se a política de rede estiver ativada, uma extremidade do par veth é anexada ao pod e a outra ao eth0. Nesse caso, o comando a seguir mostra os vários endereços MAC dos pods conectados a diferentes dispositivos veth.

    arp -n
    

    Além disso, invocar o seguinte no contêiner da caixa de ferramentas mostra que não há um dispositivo de ponte do Linux chamado cbr0:

    brctl show
    

As regras do iptables que facilitam o encaminhamento dentro do cluster variam de um cenário para outro. É importante ter essa distinção em mente durante a solução detalhada de problemas relacionados à conectividade.

Por padrão, cada pod tem acesso não filtrado a todos os outros pods em execução em todos os nós do cluster, mas é possível limitar o acesso entre os pods. O Kubernetes regularmente derruba e recria os pods. Isso acontece quando um pool de nós é atualizado, ao alterar a configuração declarativa do pod ou ao alterar a imagem de um contêiner ou quando um nó fica indisponível. Portanto, o endereço IP de um pod é um detalhe de implementação e não é recomendável confiar neles. O Kubernetes fornece endereços IP estáveis usando serviços.

Serviços

No Kubernetes, você pode atribuir pares arbitrários de valores-chave denominados rótulos a qualquer recurso do Kubernetes. O Kubernetes usa rótulos para agrupar vários pods relacionados em uma unidade lógica denominada serviço. Um serviço tem um endereço IP e portas estáveis e fornece balanceamento de carga entre o conjunto de pods de que os rótulos correspondem a todos os rótulos que você define no seletor de rótulo ao criar o serviço.

O diagrama a seguir mostra dois serviços separados, cada um composto por vários pods. Cada um dos pods no diagrama tem o rótulo app=demo, mas seus outros rótulos são diferentes. O "front-end” de serviço corresponde a todos os pods com app=demo e component=frontend, enquanto os “usuários” de serviço correspondem a todos os pods com app=demo e component=users. O pod cliente não corresponde exatamente ao seletor de serviço, portanto não faz parte de nenhum dos serviços. No entanto, o pod cliente pode se comunicar com qualquer um dos serviços porque é executado no mesmo cluster.

Diagrama de dois serviços separados, conforme descrito no parágrafo anterior

O Kubernetes atribui um endereço IP estável e confiável a cada serviço recém-criado (o ClusterIP) do pool de endereços IP de serviço disponíveis no cluster. O Kubernetes também atribui um nome de host ao ClusterIP adicionando uma entrada DNS. O ClusterIP e o nome do host são exclusivos dentro do cluster e não são alterados durante todo o ciclo de vida do serviço. O Kubernetes apenas libera o ClusterIP e o nome do host se o serviço for excluído da configuração do cluster. Para alcançar um pod íntegro, execute seu aplicativo usando o ClusterIP ou o nome do host do serviço.

À primeira vista, um serviço pode parecer um ponto único de falha para seus aplicativos. No entanto, o Kubernetes distribui o tráfego da forma mais uniforme possível em todo o conjunto de pods, sendo executado em muitos nós, para que um cluster possa resistir a uma interrupção que afeta um ou mais (mas não todos) nós.

A conectividade entre pods e serviços é gerenciada pelo Kubernetes usando o componente kube-proxy, que é executado em cada nó. O kube-proxy, que não é um proxy alinhado e sim um controlador de balanceamento de carga baseado em saída, observa o servidor da API do Kubernetes e mapeia continuamente o ClusterIP para pods íntegros, adicionando e removendo regras NAT de destino (DNAT, na sigla em inglês) ao subsistema iptables do nó. Quando um contêiner em execução em um pod envia tráfego para o ClusterIP de um serviço, o nó seleciona um pod aleatoriamente e direciona o tráfego para esse pod.

Quando você configura um serviço, é possível, opcionalmente, remapear sua porta de escuta definindo valores para port e targetPort.

  • port é o local em que os clientes alcançam o aplicativo.
  • targetPort é a porta em que o aplicativo está realmente escutando o tráfego dentro do pod.

O kube-proxy gerencia esse remapeamento de porta adicionando e removendo regras iptables no nó.

Este diagrama ilustra o fluxo de tráfego de um pod cliente para um pod servidor em um nó diferente. O cliente se conecta ao serviço em 172.16.12.100:80. O servidor da API Kubernetes mantém uma lista de pods que executam o aplicativo. O processo kube-proxy em cada nó usa essa lista para criar uma regra iptables para direcionar o tráfego para um pod apropriado (como 10.255.255.202:8080). O pod cliente não precisa estar ciente da topologia do cluster ou de quaisquer detalhes sobre pods individuais ou contêineres dentro deles.

Diagrama ilustrando um cliente se conectando a um serviço e sendo encaminhado para um pod, conforme descrito no parágrafo anterior

Rede fora do cluster

Esta seção explica como o tráfego de fora do cluster alcança os aplicativos em execução em um cluster do Kubernetes. Essas informações são importantes ao projetar aplicativos e cargas de trabalho do seu cluster.

Você já leu sobre como o Kubernetes usa os serviços para fornecer endereços IP estáveis para aplicativos em execução nos pods. Por padrão, os pods não expõem um endereço IP externo, porque o kube-proxy gerencia todo o tráfego em cada nó. Os pods e seus contêineres podem se comunicar livremente, mas as conexões fora do cluster não podem acessar o serviço. Por exemplo, na ilustração anterior, os clientes fora do cluster não podem acessar o serviço de front-end por meio do ClusterIP.

O GKE fornece três tipos diferentes de balanceadores de carga para controlar o acesso e distribuir o tráfego de entrada no seu cluster da forma mais uniforme possível. É possível configurar um serviço para usar vários tipos de balanceadores de carga simultaneamente.

  • Balanceadores de carga externos gerenciam o tráfego proveniente de fora do cluster e de fora da sua rede VPC do GCP. Eles usam regras de encaminhamento associadas à rede do GCP para encaminhar o tráfego para um nó do Kubernetes.
  • Balanceadores de carga internos gerenciam o tráfego proveniente da mesma rede VPC. Como os balanceadores de carga externos, eles usam regras de encaminhamento associadas à rede do GCP para encaminhar o tráfego para um nó do Kubernetes.
  • Balanceadores de carga HTTP(S) são balanceadores de carga externos especializados, usados para tráfego HTTP(S). Eles usam um recurso de Entrada em vez de uma regra de encaminhamento para encaminhar o tráfego para um nó do Kubernetes.

Quando o tráfego alcança um nó do Kubernetes, ele é tratado da mesma maneira, qualquer que seja o tipo de balanceador de carga. O balanceador de carga não sabe quais nós do cluster estão executando os pods do respectivo serviço. Em vez disso, ele balanceia o tráfego em todos os nós do cluster, mesmo aqueles que não executam um pod relevante. Em um cluster regional, a carga é distribuída por todos os nós de todas as zonas da região do cluster. Quando o tráfego é encaminhado para um nó, o nó encaminha o tráfego para um pod, que pode estar em execução no mesmo nó ou em um nó diferente. O nó encaminha o tráfego para um Pod escolhido aleatoriamente usando as regras iptables que o kube-proxy gerencia no nó.

No diagrama a seguir, o balanceador de carga de rede direciona o tráfego para o nó do meio, e o tráfego é redirecionado para um Pod no primeiro nó.

Diagrama mostrando o tráfego sendo roteado de um nó para um pod em outro nó, conforme descrito no parágrafo anterior

Quando um balanceador de carga envia tráfego para um nó, o tráfego pode ser encaminhado para um pod em um nó diferente. Isso requer saltos de rede adicionais. Se quiser evitar os saltos adicionais, é possível especificar que o tráfego precisa ir a um pod que esteja no mesmo nó que inicialmente recebe o tráfego.

Para especificar que o tráfego precisa ir a um pod no mesmo nó, defina externalTrafficPolicy como Local em seu manifesto de serviço:

apiVersion: v1
kind: Service
metadata:
  name: my-lb-service
spec:
  type: LoadBalancer
  externalTrafficPolicy: Local
  selector:
    app: demo
    component: users
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080

Quando você define externalTrafficPolicy como Local, o balanceador de carga envia tráfego apenas para nós que têm um pod íntegro que pertença ao serviço. O balanceador de carga usa uma verificação de integridade para determinar quais nós têm os pods apropriados.

Balanceador de carga externo

Se for necessário que o serviço possa ser acessado de fora do cluster e de fora da rede VPC, configure-o como um LoadBalancer. Para isso, configure o campo type do serviço como LoadBalancer ao defini-lo. O GKE provisiona um balanceador de carga de rede na frente do serviço. O balanceador de carga de rede está ciente de todos os nós no cluster e configura as regras de firewall da rede VPC para permitir conexões com o serviço fora da rede VPC usando o endereço IP externo do serviço. É possível atribuir um endereço IP externo estático ao serviço. Acesse Como configurar nomes de domínio com endereços IP estáticos para mais informações.

Detalhes técnicos

Ao usar o balanceador de carga externo, o tráfego que chega é inicialmente encaminhado para um nó usando uma regra de encaminhamento associada à rede do GCP. Depois que o tráfego atinge o nó, o nó usa sua tabela NAT iptables para escolher um pod. O kube-proxy gerencia as regras iptables no nó.

Balanceador de carga interno

Para o tráfego que precisa alcançar seu cluster de dentro da mesma rede VPC, configure seu serviço para provisionar um balanceador de carga interno. O balanceador de carga interno escolhe um endereço IP da sub-rede VPC do cluster em vez de um endereço IP externo. Aplicativos ou serviços na rede VPC podem usar esse endereço IP para se comunicar com os serviços dentro do cluster.

Detalhes técnicos

A funcionalidade de balanceamento de carga interno é fornecida pelo GCP. Quando o tráfego atinge um determinado nó, esse nó usa a respectiva tabela NAT iptables para escolher um pod, mesmo se o pod estiver em um nó diferente. O kube-proxy gerencia as regras iptables no nó.

Para mais informações sobre balanceadores de carga internos, visite a documentação do balanceador de carga interno.

Balanceador de carga de HTTP(S)

Muitos aplicativos, como APIs de serviço da Web RESTful, se comunicam usando HTTP(S). Você pode permitir que clientes externos à sua rede VPC acessem esse tipo de aplicativo usando um recurso Ingress do Kubernetes. Um recurso Entrada permite mapear nomes de host e caminhos de URL para serviços no cluster. Ao usar um balanceador de carga HTTP(S), você precisa configurar o serviço para usar um NodePort e um ClusterIP. Quando o tráfego acessa o serviço no IP de um nó no NodePort, o GKE encaminha o tráfego para um pod íntegro do serviço. É possível especificar um NodePort ou permitir que o GKE atribua uma porta aleatória não utilizada.

Quando você cria o recurso Ingress, o GKE provisiona um balanceador de carga HTTP(S) no projeto do GCP. O balanceador de carga envia uma solicitação para o endereço IP de um nó no NodePort. Depois que a solicitação atinge o nó, o nó usa sua tabela NAT iptables para escolher um pod. O kube-proxy gerencia as regras iptables no nó.

Essa definição da Entrada encaminha o tráfego para demo.example.com até um serviço denominado frontend na porta 80, e demo-backend.example.com até um serviço denominado users na porta 8080.

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: demo
spec:
  rules:
  - host: demo.example.com
    http:
      paths:
      - backend:
          serviceName: frontend
          servicePort: 80
  - host: demo-backend.example.com
    http:
      paths:
      - backend:
          serviceName: users
          servicePort: 8080

Acesse Ingress no Google Cloud Platform para mais informações.

Detalhes técnicos

Quando você cria um objeto de entrada, o controlador do GKE Ingress configura um balanceador de carga HTTP(S) do GCP de acordo com as regras no manifesto da entrada e nos manifestos do serviço associados. O cliente envia uma solicitação ao balanceador de carga HTTP(S). O balanceador de carga é um proxy real. Ele escolhe um nó e encaminha a solicitação para essa combinação NodeIP:NodePort do nó. O nó usa sua tabela NAT iptables para escolher um pod. O kube-proxy gerencia as regras iptables no nó.

Como limitar a conectividade com pods e serviços

Por padrão, todos os pods em execução no mesmo cluster podem se comunicar livremente. No entanto, você pode limitar a conectividade dentro de um cluster de maneiras diferentes, dependendo das necessidades.

Como limitar o acesso entre pods

Você pode limitar o acesso entre os pods usando uma política de rede. Com as definições de política de rede, é possível restringir a entrada e a saída de pods com base em uma combinação arbitrária de rótulos, intervalos de IP e números de porta. Por padrão, não há política de rede, portanto, todo o tráfego entre os pods no cluster é permitido. Assim que você cria a primeira política de rede em um namespace, o restante do tráfego é negado.

Acesse Políticas de rede para mais detalhes sobre como especificar a política em si.

Depois de criar uma política de rede, você precisa ativá-la explicitamente para o cluster. Acesse Como configurar políticas de rede para aplicativos para mais informações.

Como limitar o acesso a um balanceador de carga externo

Se seu serviço usar um balanceador de carga externo, o tráfego de qualquer endereço IP externo poderá acessar seu serviço por padrão. Para restringir quais intervalos de endereços IP podem acessar os pontos de extremidade no seu cluster, configure a opção loadBalancerSourceRanges ao configurar o serviço. É possível especificar vários intervalos e atualizar a configuração de um serviço em execução a qualquer momento. A instância kube-proxy em execução em cada nó configura as regras iptables desse nó para negar todo tráfego que não corresponda ao loadBalancerSourceRanges especificado. Nenhuma regra de firewall VPC é criada.

Como limitar o acesso a um balanceador de carga HTTP(S)

Se o serviço usar o balanceador de carga HTTP(S), será possível usar uma política de segurança do Cloud Armor para limitar quais endereços IP externos podem acessar seu serviço, bem como quais respostas retornar quando o acesso for negado por causa da política de segurança. Você pode configurar o Stackdriver Logging para registrar informações sobre essas interações.

Se uma política de segurança do Cloud Armor não for suficientemente refinada, você poderá ativar o Cloud Identity-Aware Proxy nos pontos de extremidade para implantar a autenticação e a autorização baseadas no usuário para seu aplicativo. Acesse o tutorial detalhado para configurar o Cloud IAP para mais informações.

Próximas etapas

Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…

Documentação do Kubernetes Engine