Como um pod no Kubernetes recebe um endereço IP

Nota do tradutor.: este artigo, escrito por um engenheiro de SRE do LinkedIn, detalha a 'magia interna' no Kubernetes – mais especificamente, a interação entre CRI, CNI e kube-apiserver, e o que acontece quando um pod precisa receber um endereço IP.

Um dos requisitos básicos do modelo de rede do Kubernetes é que cada pod deve ter seu próprio endereço IP, e qualquer outro pod no cluster deve ser capaz de se comunicar com ele por esse endereço. Existem muitos provedores de rede (Flannel, Calico, Canal etc.) que ajudam a implementar esse modelo de rede.

Quando comecei a trabalhar com Kubernetes, não estava claro para mim como os pods obtêm seus endereços IP. Mesmo entendendo como funcionam os componentes individuais, era difícil imaginar como eles trabalham juntos. Por exemplo, eu sabia para que serviam os plugins CNI, mas não tinha ideia de como eles eram invocados. Então decidi escrever este artigo para compartilhar conhecimentos sobre os vários componentes de rede e como eles colaboram no cluster Kubernetes para permitir que cada pod receba seu endereço IP único.

Existem várias maneiras de organizar a interação de rede no Kubernetes – assim como existem várias opções de ambientes de execução (runtime) para contêineres. Neste artigo, será utilizado Flannel para organizar a rede no cluster, e como ambiente de execução – Containerd. Também parto da suposição de que você entende como funciona a interação de rede entre contêineres, portanto, apenas abordarei brevemente, exclusivamente para o contexto.

Alguns conceitos básicos

Contêineres e rede: uma visão geral

Na internet, há muitas publicações excelentes que explicam como os contêineres se conectam entre si pela rede. Portanto, farei apenas uma visão geral dos conceitos principais e limitarei-me a uma abordagem que envolve a criação de uma ponte Linux e o encapsulamento de pacotes. Os detalhes são omitidos, pois o tema da interação de rede entre contêineres merece um artigo separado. Links para algumas publicações especialmente informativas e educativas serão fornecidos abaixo.

Contêineres em um único host

Uma das maneiras de organizar a comunicação por endereços IP entre contêineres que estão rodando no mesmo host é através da criação de uma ponte Linux. Para isso, no Kubernetes (e Docker) são criados dispositivos virtuais veth (ethernet virtual). Uma extremidade do dispositivo veth está conectada ao espaço de nomes de rede do contêiner, e a outra está conectada ao ponte Linux na rede do host.

Todos os contêineres em um mesmo host têm uma extremidade da veth conectada à ponte, através da qual eles podem se comunicar entre si por endereços IP. A ponte Linux também possui um endereço IP e atua como um gateway para o tráfego de saída (egress) dos pods, destinado a outros nós.

Como um pod no Kubernetes recebe um endereço IP

Contêineres em hosts diferentes

A encapsulação de pacotes é uma das maneiras que permite que contêineres em nós diferentes se comuniquem entre si por endereços IP. No Flannel, essa funcionalidade é gerenciada pela tecnologia vxlan, que "embala" o pacote original em um pacote UDP e o envia ao destino.

No cluster Kubernetes, o Flannel cria um dispositivo vxlan e complementa a tabela de rotas em cada um dos nós. Cada pacote destinado a um contêiner em outro host passa pelo dispositivo vxlan e é encapsulado em um pacote UDP. No destino, o pacote encapsulado é extraído e redirecionado para o pod desejado.

Como um pod no Kubernetes recebe um endereço IP
Nota: Este é apenas um dos modos de organizar a interação de rede entre contêineres.

O que é CRI?

CRI (Container Runtime Interface) é um plugin que permite que o kubelet utilize diferentes ambientes de execução de contêineres. A API CRI está embutida em vários ambientes de execução, permitindo que os usuários escolham o runtime de sua preferência.

O que é CNI?

O projeto CNI representa uma especificação para a implementação de uma solução de rede universal para contêineres Linux. Além disso, inclui plugins, responsáveis por diversas funções na configuração da rede do pod. Um plugin CNI é um executável que está de acordo com a especificação (alguns plugins serão discutidos abaixo).

Atribuição de sub-redes aos nós para a alocação de endereços IP aos pods

Como cada pod do cluster deve ter um endereço IP, é importante garantir que esse endereço seja único. Isso é alcançado pela atribuição de uma sub-rede exclusiva a cada nó, a partir da qual então os endereços IP são alocados aos pods nesse nó.

O controlador IPAM do nó

Quando nodeipam é passado como um parâmetro de flag --controllers kube-controller-manager, ele atribui a cada nó uma sub-rede separada (podCIDR) do CIDR do cluster (ou seja, um intervalo de endereços IP para a rede do cluster). Como esses podCIDRs não se sobrepõem, é possível atribuir a cada pod um endereço IP único.

O nó Kubernetes recebe um podCIDR no momento de seu registro inicial no cluster. Para alterar o podCIDR dos nós, é necessário desregistrá-los e, em seguida, registrá-los novamente, fazendo as alterações necessárias na configuração da camada de gerenciamento do Kubernetes. O podCIDR de um nó pode ser exibido com o seguinte comando:

$ kubectl get no  -o json | jq '.spec.podCIDR'
10.244.0.0/24

Kubelet, ambiente de execução de contêiner e plugins CNI: como tudo isso funciona

O agendamento de um pod em um nó está relacionado à execução de várias etapas preparatórias. Nesta seção, focarei apenas naquelas que estão diretamente ligadas à configuração da rede do pod.

O agendamento de um pod em um determinado nó inicia a seguinte cadeia de eventos:

Como um pod no Kubernetes recebe um endereço IP

Ajuda: Arquitetura dos plugins CRI do Containerd.

Interação entre o ambiente de execução de contêineres e os plugins CNI

Cada provedor de rede tem seu próprio plugin CNI. O ambiente de execução do contêiner o chama para configurar a rede para o pod durante seu início. No caso do containerd, a execução do plugin CNI é feita pelo plugin Containerd CRI.

Cada provedor também possui seu próprio agente. Ele é instalado em todos os nós do Kubernetes e é responsável pela configuração da rede dos pods. Este agente vem com a configuração do CNI ou cria-a sozinho no nó. A configuração ajuda o plugin CRI a determinar qual plugin CNI chamar.

O local do arquivo de configuração do CNI pode ser configurado; por padrão, ele fica em /etc/cni/net.d/<config-file>. Os administradores do cluster também são responsáveis pela instalação dos plugins CNI em cada nó do cluster. A localização deles também é configurável; o diretório padrão é /opt/cni/bin.

Ao usar o containerd, os caminhos para a configuração e os binários do plugin podem ser especificados na seção [plugins."io.containerd.grpc.v1.cri".cni] em do arquivo de configuração do containerd.

Como estamos usando o Flannel como provedor de rede, vamos falar um pouco sobre sua configuração:

  • Flanneld (o daemon do Flannel) geralmente é instalado no cluster como um DaemonSet com install-cni como um init-container.
  • Install-cni cria um arquivo de configuração CNI (/etc/cni/net.d/10-flannel.conflist) em cada nó.
  • Flanneld cria o dispositivo vxlan, extrai os metadados de rede da API do servidor e monitora as atualizações dos pods. À medida que eles são criados, ele dissemina rotas para todos os pods em todo o cluster.
  • Essas rotas permitem que os pods se comuniquem entre si por meio de endereços IP.

Para informações mais detalhadas sobre o funcionamento do Flannel, recomendo consultar os links no final do artigo.

Aqui está o esquema de interação entre o plugin Containerd CRI e os plugins CNI:

Como um pod no Kubernetes recebe um endereço IP

Como mostrado acima, o kubelet chama o plugin Containerd CRI para criar um pod, e este chama o plugin CNI para configurar a rede do pod. O plugin CNI do provedor de rede, por sua vez, chama outros plugins base CNI para configurar vários aspectos da rede.

Interação entre plugins CNI

Existem vários plugins CNI, cuja função é ajudar a configurar a comunicação de rede entre os contêineres no host. Este artigo abordará três deles.

Plugin CNI Flannel

Ao usar o Flannel como provedor de rede, o componente Containerd CRI chama Plugin CNI Flannel, usando o arquivo de configuração CNI /etc/cni/net.d/10-flannel.conflist.

$ cat /etc/cni/net.d/10-flannel.conflist
{
  "name": "cni0",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
         "ipMasq": false,
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    }
  ]
}

O plugin CNI Flannel opera em conjunto com o Flanneld. Durante a inicialização, o Flanneld extrai o podCIDR e outros detalhes relacionados à rede da API do servidor e os salva no arquivo /run/flannel/subnet.env.

FLANNEL_NETWORK=10.244.0.0/16 
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450 
FLANNEL_IPMASQ=false

O plugin CNI Flannel utiliza os dados de /run/flannel/subnet.env para configurar e invocar o plugin CNI bridge.

Plugin CNI Bridge

Este plugin é chamado com a seguinte configuração:

{
  "name": "cni0",
  "type": "bridge",
  "mtu": 1450,
  "ipMasq": false,
  "isGateway": true,
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24"
  }
}

Na primeira chamada, ele cria uma bridge Linux com "name": "cni0", conforme especificado na configuração. Em seguida, uma par de veth é criada para cada pod. Uma ponta se conecta ao espaço de nomes de rede do contêiner, e a outra se conecta à bridge Linux na rede do host. Plugin CNI Bridge conecta todos os contêineres do host à bridge Linux na rede do host.

Após finalizar a configuração do par de veth, o plugin Bridge chama o plugin IPAM local do host (host-local). O tipo de plugin IPAM pode ser configurado no arquivo de configuração CNI que o plugin CRI utiliza para invocar o plugin CNI Flannel.

Plugins IPAM locais do host CNI

Bridge CNI chama plugin IPAM local do host CNI com a seguinte configuração:

{
  "name": "cni0",
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24",
    "dataDir": "/var/lib/cni/networks"
  }
}

Plugin IPAM host-local (IP Aendereço Mgestão — gerenciamento de endereços IP) retorna o endereço IP para o contêiner da sub-rede e armazena o IP atribuído no host no diretório especificado na seção dataDir — /var/lib/cni/networks/<network-name=cni0>/<ip>. Este arquivo contém o ID do contêiner ao qual o endereço IP foi atribuído.

Ao chamar o plugin IPAM host-local, ele retorna os seguintes dados:

{
  "ip4": {
    "ip": "10.244.4.2",
    "gateway": "10.244.4.3"
  },
  "dns": {}
}

Resumo

O kube-controller-manager atribui podCIDR a cada nó. Os pods de cada nó obtêm endereços IP do espaço de endereços dentro da faixa de podCIDR designada. Como os podCIDRs dos nós não se sobrepõem, todos os pods recebem endereços IP únicos.

O administrador do cluster Kubernetes configura e instala o kubelet, o ambiente de execução de contêineres, o agente do provedor de rede e copia os plugins CNI em cada nó. Durante a inicialização, o agente do provedor de rede gera a configuração CNI. Quando um pod é agendado em um nó, o kubelet chama o plugin CRI para criá-lo. Em seguida, se o containerd estiver em uso, o plugin Containerd CRI chama o plugin CNI especificado na configuração CNI para configurar a rede do pod. Como resultado, o pod recebe um endereço IP.

Levei algum tempo para entender todas as sutilezas e nuances dessas interações. Espero que a experiência adquirida também ajude você a entender melhor como o Kubernetes funciona. Se eu cometer algum erro, por favor, entre em contato comigo no Twitter ou em hello@ronaknathani.com. Sinta-se à vontade para entrar em contato se quiser discutir aspectos deste artigo ou qualquer outra coisa. Ficarei feliz em conversar com você!

Links

Contêineres e rede

Como funciona o Flannel

CRI e CNI

P.S. do tradutor

Confira também em nosso blog:

Fonte: habr.com

Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS 🔥 Compre hospedagem confiável para sites com proteção contra DDoS, servidores VPS VDS | ProHoster