Conectividade do Cluster
Conectividade é uma parte central do Kubernetes, mas pode ser desafiador entender exatamente como é o seu funcionamento esperado. Existem 4 problemas distintos em conectividade que devem ser tratados:
- Comunicações contêiner-para-contêiner altamente acopladas: Isso é resolvido
por Pods e comunicações através do
localhost
. - Comunicações pod-para-pod: Esse é o foco primário desse documento.
- Comunicações pod-para-serviço (service): Isso é tratado em Services.
- Comunicações Externas-para-serviços: Isso é tratado em services.
Kubernetes é basicamente o compartilhamento de máquinas entre aplicações. Tradicionalmente, compartilhar máquinas requer a garantia de que duas aplicações não tentem utilizar as mesmas portas. Coordenar a alocação de portas entre múltiplos desenvolvedores é muito dificil de fazer em escala e expõe os usuários a problemas em nível do cluster e fora de seu controle.
A alocação dinâmica de portas traz uma série de complicações para o sistema - toda aplicação deve obter suas portas através de flags de configuração, os servidores de API devem saber como inserir números dinämicos de portas nos blocos de configuração, serviços precisam saber como buscar um ao outro, etc. Ao invés de lidar com isso, o Kubernetes faz de uma maneira diferente.
O modelo de conectividade e rede do Kubernetes
Todo Pod
obtém seu próprio endereço IP. Isso significa que vocë não precisa
criar links explícitos entre os Pods
e vocë quase nunca terá que lidar com o
mapeamento de portas de contêineres para portas do host. Isso cria um modelo simples,
retro-compatível onde os Pods
podem ser tratados muito mais como VMs ou hosts
físicos da perspectiva de alocação de portas, nomes, descobrimento de serviços
(service discovery), balanceamento de carga, configuração de aplicações e migrações.
O Kubernetes impõe os seguintes requisitos fundamentais para qualquer implementação de rede (exceto qualquer política de segmentação intencional):
- pods em um nó podem se comunicar com todos os pods em todos os nós sem usar NAT.
- agentes em um nó (por exemplo o kubelet ou um serviço local) podem se comunicar com todos os Pods naquele nó.
Nota: Para as plataformas que suportam Pods
executando na rede do host (como o Linux):
- pods alocados na rede do host de um nó podem se comunicar com todos os pods em todos os nós sem NAT.
Esse modelo não só é menos complexo, mas é principalmente compatível com o desejo do Kubernetes de permitir a portabilidade com baixo esforço de aplicações de VMs para contêineres. Se a sua aplicação executava anteriormente em uma VM, sua VM possuía um IP e podia se comunicar com outras VMs no seu projeto. Esse é o mesmo modelo básico.
Os endereços de IP no Kubernetes existem no escopo do Pod
- contêineres em um Pod
compartilham o mesmo network namespace - incluíndo seu endereço de IP e MAC.
Isso significa que contêineres que compõem um Pod
podem se comunicar entre eles
através do endereço localhost
e respectivas portas. Isso também significa que
contêineres em um mesmo Pod
devem coordenar a alocação e uso de portas, o que não
difere do modelo de processos rodando dentro de uma mesma VM. Isso é chamado de
modelo "IP-por-pod".
Como isso é implementado é um detalhe do agente de execução de contêiner em uso.
É possível solicitar uma porta no nó que será encaminhada para seu Pod
(chamado
de portas do host), mas isso é uma operação muito específica. Como esse encaminhamento
é implementado é um detalhe do agente de execução do contêiner. O Pod
mesmo
desconhece a existência ou não de portas do host.
Como implementar o modelo de conectividade do Kubernetes
Existe um número de formas de implementar esse modelo de conectividade. Esse documento não é um estudo exaustivo desses vários métodos, mas pode servir como uma introdução de várias tecnologias e serve como um ponto de início.
A conectividade no Kubernetes é fornecida através de plugins de CNIs
As seguintes opções estão organizadas alfabeticamente e não implicam preferência por qualquer solução.
Cuidado: Esta seção tem links para projetos de terceiros que fornecem a funcionalidade exigida pelo Kubernetes. Os autores do projeto Kubernetes não são responsáveis por esses projetos. Esta página obedece as diretrizes de conteúdo do site CNCF, listando os itens em ordem alfabética. Para adicionar um projeto a esta lista, leia o guia de conteúdo antes de enviar sua alteração.
Antrea
O projeto Antrea é uma solução de conectividade para Kubernetes que pretende ser nativa. Ela utiliza o Open vSwitch na camada de conectividade de dados. O Open vSwitch é um switch virtual de alta performance e programável que suporta Linux e Windows. O Open vSwitch permite ao Antrea implementar políticas de rede do Kubernetes (NetworkPolicies) de uma forma muito performática e eficiente.
Graças à característica programável do Open vSwitch, o Antrea consegue implementar uma série de funcionalidades de rede e segurança.
AWS VPC CNI para Kubernetes
O AWS VPC CNI oferece conectividade com o AWS Virtual Private Cloud (VPC) para clusters Kubernetes. Esse plugin oferece alta performance e disponibilidade e baixa latência. Adicionalmente, usuários podem aplicar as melhores práticas de conectividade e segurança existentes no AWS VPC para a construção de clusters Kubernetes. Isso inclui possibilidade de usar o VPC flow logs, políticas de roteamento da VPC e grupos de segurança para isolamento de tráfego.
O uso desse plugin permite aos Pods no Kubernetes ter o mesmo endereço de IP dentro do pod como se eles estivessem dentro da rede do VPC. O CNI (Container Network Interface) aloca um Elastic Networking Interface (ENI) para cada nó do Kubernetes e usa uma faixa de endereços IP secundário de cada ENI para os Pods no nó. O CNI inclui controles para pré alocação dos ENIs e endereços IP para um início mais rápido dos pods e permite clusters com até 2,000 nós.
Adicionalmente, esse CNI pode ser utilizado junto com o Calico para a criação de políticas de rede (NetworkPolicies). O projeto AWS VPC CNI tem código fonte aberto com a documentação no Github.
Azure CNI para o Kubernetes
Azure CNI é um plugin de código fonte aberto que integra os Pods do Kubernetes com uma rede virtual da Azure (também conhecida como VNet) provendo performance de rede similar à de máquinas virtuais no ambiente. Os Pods podem se comunicar com outras VNets e com ambientes on-premises com o uso de funcionalidades da Azure, e também podem ter clientes com origem dessas redes. Os Pods podem acessar serviços da Azure, como armazenamento e SQL, que são protegidos por Service Endpoints e Private Link. Você pode utilizar as políticas de segurança e roteamento para filtrar o tráfico do Pod. O plugin associa IPs da VNet para os Pods utilizando um pool de IPs secundário pré-configurado na interface de rede do nó Kubernetes.
O Azure CNI está disponível nativamente no Azure Kubernetes Service (AKS).
Calico
Calico é uma solução de conectividade e segurança para contêineres, máquinas virtuais e serviços nativos em hosts. O Calico suporta múltiplas camadas de conectividade/dados, como por exemplo: uma camada Linux eBPF nativa, uma camada de conectividade baseada em conceitos padrão do Linux e uma camada baseada no HNS do Windows. O calico provê uma camada completa de conectividade e rede, mas também pode ser usado em conjunto com CNIs de provedores de nuvem para permitir a criação de políticas de rede.
Cilium
Cilium é um software de código fonte aberto para prover conectividade e segurança entre contêineres de aplicação. O Cilium pode lidar com tráfego na camada de aplicação (ex. HTTP) e pode forçar políticas de rede nas camadas L3-L7 usando um modelo de segurança baseado em identidade e desacoplado do endereçamento de redes, podendo inclusive ser utilizado com outros plugins CNI.
Flannel
Flannel é uma camada muito simples de conectividade que satisfaz os requisitos do Kubernetes. Muitas pessoas reportaram sucesso em utilizar o Flannel com o Kubernetes.
Google Compute Engine (GCE)
Para os scripts de configuração do Google Compute Engine, roteamento
avançado é usado para associar
para cada VM uma sub-rede (o padrão é /24
- 254 IPs). Qualquer tráfico direcionado
para aquela sub-rede será roteado diretamente para a VM pela rede do GCE. Isso é
adicional ao IP principal associado à VM, que é mascarado para o acesso à Internet.
Uma brige Linux (chamada cbr0
) é configurada para existir naquela sub-rede, e é
configurada no docker através da opção --bridge
.
O Docker é iniciado com:
DOCKER_OPTS="--bridge=cbr0 --iptables=false --ip-masq=false"
Essa bridge é criada pelo Kubelet (controlada pela opção --network-plugin=kubenet
)
de acordo com a informação .spec.podCIDR
do Nó.
O Docker irá agora alocar IPs do bloco cbr-cidr
. Contêineres podem alcançar
outros contêineres e nós através da interface cbr0
. Esses IPs são todos roteáveis
dentro da rede do projeto do GCE.
O GCE mesmo não sabe nada sobre esses IPs, então não irá mascará-los quando tentarem se comunicar com a internet. Para permitir isso uma regra de IPTables é utilizada para mascarar o tráfego para IPs fora da rede do projeto do GCE (no exemplo abaixo, 10.0.0.0/8):
iptables -t nat -A POSTROUTING ! -d 10.0.0.0/8 -o eth0 -j MASQUERADE
Por fim, o encaminhamento de IP deve ser habilitado no Kernel de forma a processar os pacotes vindos dos contêineres:
sysctl net.ipv4.ip_forward=1
O resultado disso tudo é que Pods
agora podem alcançar outros Pods
e podem também
se comunicar com a Internet.
Kube-router
Kube-router é uma solução construída que visa prover alta performance e simplicidade operacional. Kube-router provê um proxy de serviços baseado no LVS/IPVS, uma solução de comunicação pod-para-pod baseada em encaminhamento de pacotes Linux e sem camadas adicionais, e funcionalidade de políticas de redes baseadas no IPTables/IPSet.
Redes L2 e bridges Linux
Se você tem uma rede L2 "burra", como um switch em um ambiente "bare-metal", você deve conseguir fazer algo similar ao ambiente GCE explicado acima. Note que essas instruções foram testadas casualmente - parece funcionar, mas não foi propriamente testado. Se você conseguir usar essa técnica e aperfeiçoar o processo, por favor nos avise!!
Siga a parte "With Linux Bridge devices" desse tutorial super bacana do Lars Kellogg-Stedman.
Multus (Plugin multi redes)
Multus é um plugin Multi CNI para suportar a funcionalidade multi redes do Kubernetes usando objetos baseados em CRDs.
Multus suporta todos os plugins referência (ex. Flannel, DHCP, Macvlan) que implementam a especificação de CNI e plugins de terceiros (ex. Calico, Weave, Cilium, Contiv). Adicionalmente, Multus suporta cargas de trabalho no Kubernetes que necessitem de funcionalidades como SRIOV, DPDK, OVS-DPDK & VPP.
OVN (Open Virtual Networking)
OVN é uma solução de virtualização de redes de código aberto desenvolvido pela comunidade Open vSwitch. Permite a criação de switches lógicos, roteadores lógicos, listas de acesso, balanceadores de carga e mais, para construir diferences topologias de redes virtuais. Esse projeto possui um plugin específico para o Kubernetes e a documentação em ovn-kubernetes.
Qual é o próximo
Design inicial do modelo de conectividade do Kubernetes e alguns planos futuros estão descritos com maiores detalhes no documento de design de redes.