Visão geral da rede

Nesta página, você terá 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 começando a usar 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, clientes externos e Services se comunicam, em vez de pensar em como seus hosts ou VMs estão conectados.

A avançada rede definida por software (SDN, na sigla em inglês) do Kubernetes permite o roteamento e o encaminhamento de pacotes para pods, Services e nós em diferentes zonas no mesmo cluster regional. O Kubernetes e o GCP também configuram dinamicamente regras de filtragem de IP, tabelas de roteamento e regras de firewall em cada nó, dependendo do modelo declarativo das implantações do Kubernetes e da configuração do cluster no GCP.

Pré-requisitos

Nesta página, é usada a terminologia relacionada a camadas de transporte, Internet e aplicativo do conjunto de protocolo da Internet, incluindo HTTP e DNS (todos os links em inglês), mas você não precisa ser especialista nesses tópicos.

Além disso, é possível achar este conteúdo mais fácil de entender se você tiver um conhecimento básico dos utilitários e conceitos de gerenciamento de rede do Linux, como roteamento e regras de iptables.

O modelo de rede do Kubernetes depende muito de endereços IP. Services, 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 durante a leitura:

  • ClusterIP: o endereço IP atribuído a um Service. Em outros documentos, pode ser chamado de "IP do cluster". Esse endereço é estável durante a vida útil do Service, conforme discutido na seção "Services" 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, você aprenderá sobre a rede em um cluster do Kubernetes, no que se refere a pods, alocação de IP e Services.

Alocação de IP

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

  • 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ó oferece conectividade a partir de componentes de controle, como kube-proxy e kubelet, ao servidor da API Kubernetes. Esse IP é a conexão do nó com o restante do cluster.
  • Cada nó tem um pool de endereços IP a que o GKE atribui pods em execução nesse nó (por padrão, um bloco CIDR /24[em inglês]). Se preferir, especifique o intervalo de IPs ao criar o cluster. O recurso de intervalo flexível CIDR de pod permite reduzir o tamanho do intervalo de IPs de pod para nós em um determinado pool de nós.

  • Cada pod tem um único endereço IP atribuído a partir do intervalo CIDR de pod do respectivo nó. Esse endereço IP é compartilhado por todos os contêineres em execução no pod e os conecta a outros pods em execução no cluster.

  • Cada Service tem um endereço IP, denominado ClusterIP, atribuído com base na rede VPC do cluster. Se preferir, é possível personalizar a rede VPC ao criar o cluster.

Para mais informações, acesse Como criar clusters nativos de VPC usando IPs de 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 pool 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 programa um pod para ser executado em um nó, ele cria um namespace de rede (em inglês) para o pod no kernel Linux do nó. Esse namespace 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 do 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 está conectado por meio do pod à interface de rede física do nó, 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 a CNI do GKE, uma extremidade do par veth será anexada ao pod no respectivo namespace e a outra será conectada ao dispositivo ponte do Linux cbr0. Nesse caso, o comando a seguir mostra os vários endereços MAC de pods anexados a cbr0:

    arp -n
    

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

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

    arp -n
    

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

    brctl show
    

As regras de 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 Services.

Services

No Kubernetes, é possível atribuir pares arbitrários de chave-valor 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 Service tem portas e um endereço IP estáveis e fornece balanceamento de carga entre o conjunto de pods com rótulos correspondentes a todos os definidos no seletor de rótulos (em inglês) durante a criação do Service.

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

Diagrama de dois Services separados, conforme descrito no parágrafo anterior

O Kubernetes atribui um endereço IP estável e confiável a cada Service recém-criado, o ClusterIP (em inglês), do pool de endereços IP de Service disponíveis no cluster. O Kubernetes também atribui um nome de host ao ClusterIP. Para isso, ele adiciona uma entrada DNS (em inglês). 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 do modo 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 os) nós.

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

Ao configurar um Service, é possível remapear a porta de detecção de atividade dele definindo valores para port e targetPort.

  • port é onde os clientes chegam ao aplicativo.
  • targetPort é a porta na qual o aplicativo está realmente detectando tráfego no pod.

kube-proxy adiciona e remove regras iptables no nó para gerenciar esse remapeamento de porta.

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 Service 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 e 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 detalhes sobre pods individuais ou contêineres dentro deles.

Diagrama ilustrando um cliente se conectando a um Service 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 Services para fornecer endereços IP estáveis a aplicativos em execução nos pods. Por padrão, os pods não expõem um endereço IP externo porque kube-proxy gerencia todo o tráfego em cada nó. Os pods e os respectivos contêineres podem se comunicar livremente, mas as conexões fora do cluster não podem acessar o Service. 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 Service 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 de nuvem privada virtual (VPC, na sigla em inglês) 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 de dentro 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 Ingress em vez de uma regra de encaminhamento para rotear o tráfego para um nó do Kubernetes.

Quando o tráfego chega a um nó do Kubernetes, ele é tratado da mesma maneira, qualquer que seja do 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ó o encaminha 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 de iptables que 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 você quiser evitar os saltos extras, especifique que o tráfego precisa ir a um pod localizado no mesmo nó que inicialmente recebe o tráfego.

Para fazer isso, defina externalTrafficPolicy como Local no manifesto de Service:

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 somente para nós que têm um pod íntegro pertencente ao Service. 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 o Service precisar estar acessível fora do cluster e fora da rede VPC, configure-o como um LoadBalancer (em inglês). Basta definir o campo type como LoadBalancer ao definir o Service. O GKE provisiona um balanceador de carga de rede na frente do Service. 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 chega ao nó, o nó usa a tabela NAT iptables para escolher um pod. kube-proxy gerencia as regras de 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 Service 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 alcança determinado nó, esse nó usa a tabela NAT iptables para escolher um pod, mesmo se o pod estiver em um nó diferente. kube-proxy gerencia as regras de iptables no nó.

Para mais informações sobre balanceadores de carga internos, acesse 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 Ingress permite mapear nomes de host e caminhos de URL em Services no cluster. Ao usar um balanceador de carga HTTP(S), configure o Service para usar um NodePort (em inglês) e um ClusterIP. Quando o tráfego acessa o Service no IP de um nó no NodePort, o GKE roteia o tráfego para um pod íntegro do Service. Especifique um NodePort ou permita 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 chega ao nó, o nó usa a tabela NAT iptables para escolher um pod. kube-proxy gerencia as regras de iptables no nó.

Esta definição Ingress encaminha o tráfego de demo.example.com para um Service chamado frontend na porta 80 e demo-backend.example.com para um Service chamado 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 a combinação NodeIP:NodePort desse nó. O nó usa a tabela NAT iptables para escolher um pod. kube-proxy gerencia as regras de iptables no nó.

Como limitar a conectividade com pods e Services

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

Para limitar o acesso entre os pods, use 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 Service usar um balanceador de carga externo, ele poderá ser acessado pelo tráfego de qualquer endereço IP externo por padrão. Para restringir quais intervalos de endereços IP podem acessar os endpoints no cluster, configure a opção loadBalancerSourceRanges ao configurar o Service. É possível especificar vários intervalos e atualizar a configuração de um Service em execução a qualquer momento. A instância kube-proxy em execução em cada nó configura as regras de iptables para negar todo o tráfego que não corresponde ao loadBalancerSourceRanges especificado. Nenhuma regra de firewall VPC é criada.

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

Se o Service usar o Balanceador de carga HTTP(S), utilize uma Política de segurança do Google Cloud Armor para limitar quais endereços IP externos podem acessar o Service e quais respostas retornar quando o acesso for negado por causa dessa política. Configure o Stackdriver Logging para registrar informações sobre essas interações.

Se uma política de segurança do Google Cloud Armor não for refinada o suficiente, ative o Cloud Identity-Aware Proxy nos seus endpoints para implementar autenticação e autorização de usuário para seu aplicativo. Acesse o tutorial detalhado para configurar o Cloud IAP para mais informações.

A seguir

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

Enviar comentários sobre…

Documentação do Kubernetes Engine