Como um pod do Kubernetes obtém um endereço IP?

Observação. trad.: Este artigo, escrito por um engenheiro SRE do LinkedIn, detalha a magia interna do Kubernetes - mais precisamente, a interação de CRI, CNI e kube-apiserver - que acontece quando o próximo pod precisa receber um endereço IP.

Um dos requisitos básicos Modelo de rede Kubernetes é que cada pod deve ter seu próprio endereço IP e qualquer outro pod no cluster deve ser capaz de contatá-lo nesse endereço. Existem muitos “provedores” de rede (Flannel, Calico, Canal, etc.) que ajudam a implementar este modelo de rede.

Quando comecei a trabalhar com o Kubernetes, não estava totalmente claro para mim como exatamente os pods obtinham seus endereços IP. Mesmo compreendendo como funcionavam os componentes individuais, era difícil imaginá-los trabalhando juntos. Por exemplo, eu sabia para que serviam os plug-ins CNI, mas não tinha ideia de como exatamente eles eram chamados. Portanto, decidi escrever este artigo para compartilhar conhecimento sobre os vários componentes de rede e como eles funcionam juntos em um cluster Kubernetes, o que permite que cada pod obtenha seu próprio endereço IP exclusivo.

Existem diferentes maneiras de organizar a rede no Kubernetes, assim como existem diferentes opções de tempo de execução para contêineres. Esta publicação utilizará Flanela para organizar uma rede em um cluster e como um ambiente executável - Contêiner. Também estou supondo que você sabe como funciona a rede entre contêineres, então vou abordar isso brevemente, apenas para contextualizar.

Alguns conceitos básicos

Contêineres e a rede: uma breve visão geral

Existem muitas publicações excelentes na Internet que explicam como os contêineres se comunicam entre si pela rede. Portanto, darei apenas uma visão geral dos conceitos básicos e me limitarei a uma abordagem, que envolve a criação de uma ponte Linux e o encapsulamento de pacotes. Os detalhes são omitidos, uma vez que o próprio tópico da rede de contêineres merece um artigo separado. Links para algumas publicações particularmente esclarecedoras e educacionais serão fornecidos abaixo.

Contêineres em um host

Uma maneira de organizar a comunicação via endereços IP entre contêineres executados no mesmo host envolve a criação de uma ponte Linux. Para isso, são criados dispositivos virtuais em Kubernetes (e Docker) veth (ethernet virtual). Uma extremidade do veth dispositivo se conecta ao namespace de rede do contêiner, a outra ao Ponte Linux na rede hospedeira.

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

Como um pod do Kubernetes obtém um endereço IP?

Contêineres em hosts diferentes

O encapsulamento de pacotes é um método que permite que contêineres em nós diferentes se comuniquem entre si usando endereços IP. Na Flannel a tecnologia é responsável por essa oportunidade. vxlan, que “empacota” o pacote original em um pacote UDP e depois o envia ao seu destino.

Em um cluster Kubernetes, Flannel cria um dispositivo vxlan e atualiza a tabela de rotas em cada nó de acordo. Cada pacote destinado a um contêiner em um host diferente passa pelo dispositivo vxlan e é encapsulado em um pacote UDP. No destino, o pacote aninhado é extraído e encaminhado para o pod desejado.

Como um pod do Kubernetes obtém um endereço IP?
Nota: Esta é apenas uma forma de organizar a comunicação de rede entre contêineres.

O que é CRI?

CRI (interface de tempo de execução do contêiner) é um plugin que permite ao kubelet usar diferentes ambientes de execução de contêineres. A API CRI está integrada em vários tempos de execução, para que os usuários possam escolher o tempo de execução de sua preferência.

O que é CNI?

Projeto CNI Representa especificação para organizar uma solução de rede universal para contêineres Linux. Além disso, inclui plug-ins, responsável por diversas funções ao configurar uma rede de pods. O plugin CNI é um arquivo executável que está em conformidade com a especificação (discutiremos alguns plugins abaixo).

Alocação de sub-redes a nós para atribuição de endereços IP a pods

Como cada pod em um cluster deve ter um endereço IP, é importante garantir que esse endereço seja exclusivo. Isso é conseguido atribuindo a cada nó uma sub-rede exclusiva, a partir da qual os pods desse nó recebem endereços IP.

Controlador IPAM de nó

Quando nodeipam passado como parâmetro de flag --controllers gerenciador de controlador kube, ele aloca uma sub-rede separada (podCIDR) para cada nó do CIDR do cluster (ou seja, o intervalo de endereços IP da rede do cluster). Como esses podCIDRs não se sobrepõem, é possível que cada pod receba um endereço IP exclusivo.

Um nó do Kubernetes recebe um podCIDR quando é inicialmente registrado no cluster. Para alterar o podCIDR dos nós, você precisa cancelar o registro deles e, em seguida, registrá-los novamente, fazendo as alterações apropriadas na configuração da camada de controle do Kubernetes. Você pode exibir o podCIDR de um nó usando o seguinte comando:

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

Kubelet, tempo de execução de contêiner e plug-ins CNI: como tudo funciona

Agendar um pod por nó envolve muitas etapas preparatórias. Nesta seção, focarei apenas naqueles que estão diretamente relacionados à configuração de uma rede de pods.

Agendar um pod para um determinado nó aciona a seguinte cadeia de eventos:

Como um pod do Kubernetes obtém um endereço IP?

Informações: Arquitetura de plug-ins Containerd CRI.

Interação entre o tempo de execução do contêiner e os plug-ins CNI

Cada provedor de rede possui seu próprio plugin CNI. O tempo de execução do contêiner o executa para configurar a rede do pod durante a inicialização. No caso do containerd, o plugin CNI é lançado pelo plugin CRI de contêiner.

Além disso, cada provedor possui seu próprio agente. Ele é instalado em todos os nós do Kubernetes e é responsável pela configuração da rede dos pods. Esse agente está incluído na configuração do CNI ou o cria de forma independente no nó. A configuração ajuda o plugin CRI a definir qual plugin CNI chamar.

A localização da configuração CNI pode ser customizada; por padrão está em /etc/cni/net.d/<config-file>. Os administradores de cluster também são responsáveis ​​por instalar plug-ins CNI em cada nó do cluster. Sua localização também é personalizável; diretório padrão - /opt/cni/bin.

Ao usar o containerd, os caminhos para a configuração do plugin e binários podem ser definidos na seção [plugins.«io.containerd.grpc.v1.cri».cni] в arquivo de configuração do contêiner.

Como estamos usando o Flannel como nosso provedor de rede, vamos falar um pouco sobre como configurá-lo:

  • Flanneld (daemon do Flanel) geralmente é instalado em um cluster como um DaemonSet com install-cni como contêiner de inicialização.
  • Install-cni cria Arquivo de configuração CNI (/etc/cni/net.d/10-flannel.conflist) em cada nó.
  • Flanneld cria um dispositivo vxlan, recupera metadados de rede do servidor API e monitora atualizações de pod. À medida que são criados, ele distribui 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 trabalho do Flannel, recomendo utilizar os links no final do artigo.

Aqui está um diagrama da interação entre o plugin Containerd CRI e os plugins CNI:

Como um pod do Kubernetes obtém um endereço IP?

Como você pode ver acima, o kubelet chama o plugin Containerd CRI para criar o pod, que então chama o plugin CNI para configurar a rede do pod. Ao fazer isso, o plug-in CNI do provedor de rede chama outros plug-ins CNI principais para configurar vários aspectos da rede.

Interação entre plug-ins CNI

Existem vários plug-ins CNI cuja função é ajudar a configurar a comunicação de rede entre contêineres no host. Este artigo discutirá três deles.

Plugin CNI Flanela

Ao usar o Flannel como provedor de rede, o componente Containerd CRI chama Plugin CNI Flanelausando 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 Flannel CNI funciona em conjunto com o Flanneld. Durante a inicialização, o Flanneld recupera o podCIDR e outros detalhes relacionados à rede do servidor API e os salva em um 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 Flannel CNI usa dados de /run/flannel/subnet.env para configurar e chamar o plugin de ponte CNI.

Ponte de plug-in CNI

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"
  }
}

Quando chamado pela primeira vez, ele cria uma ponte Linux com «name»: «cni0», que é indicado na configuração. Em seguida, um par veth é criado para cada pod. Uma extremidade está conectada ao namespace da rede do contêiner, a outra está incluída na ponte Linux na rede host. Ponte de plug-in CNI conecta todos os contêineres host a uma ponte Linux na rede host.

Tendo terminado de configurar o par veth, o plugin Bridge chama o plugin CNI IPAM host-local. O tipo de plug-in IPAM pode ser configurado na configuração CNI que o plug-in CRI usa para chamar o plug-in Flannel CNI.

Plug-ins IPAM CNI locais de host

Ponte de chamadas CNI Plug-in IPAM host-local CNI com a seguinte configuração:

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

Plug-in IPAM local de host (IP Address Mgerenciamento - gerenciamento de endereço IP) retorna o endereço IP do contêiner da sub-rede e armazena o IP alocado 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 este endereço IP está 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

Kube-controller-manager atribui um podCIDR a cada nó. Os pods de cada nó recebem endereços IP do espaço de endereço no intervalo podCIDR alocado. Como os podCIDRs dos nós não se sobrepõem, todos os pods recebem endereços IP exclusivos.

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

Levei algum tempo para compreender todas as sutilezas e nuances de todas essas interações. Espero que esta experiência ajude você a entender melhor como funciona o Kubernetes. Se eu estiver errado sobre alguma coisa, entre em contato comigo em Twitter ou no endereço [email protegido]. Sinta-se à vontade para entrar em contato se desejar discutir aspectos deste artigo ou qualquer outra coisa. Eu adoraria conversar com você!

referências

Contêineres e rede

Como funciona a flanela?

CRI e CNI

PS do tradutor

Leia também em nosso blog:

Fonte: habr.com

Adicionar um comentário