Nota perev. : Este artigo continua a série de materiais sobre o dispositivo básico de redes no Kubernetes, que é descrito de forma acessível e com ilustrações ilustrativas (no entanto, praticamente ainda não havia ilustrações nesta parte do concreto). Traduzindo as duas partes anteriores desta série, as combinamos em uma publicação , que falou sobre o modelo de rede do K8s (interação entre nós e entre nós) e redes de sobreposição. Sua leitura preliminar é desejável (recomendada pelo próprio autor). A continuação é dedicada aos serviços Kubernetes e ao processamento do tráfego de saída e entrada.
NB : Para conveniência do autor, o texto do autor é complementado com links (principalmente para a documentação oficial dos K8s).
Dinâmica de cluster
Devido à natureza dinâmica e em constante mudança do Kubernetes e dos sistemas distribuídos em geral, os pods (e, como resultado, seus endereços IP) também estão mudando constantemente. Os motivos para isso variam de atualizações recebidas para atingir o estado e eventos desejados que levam ao dimensionamento, até falhas imprevistas de um pod ou nó. Portanto, os endereços IP do pod não podem ser usados diretamente para comunicação.
O
serviço no Kubernetes entra em jogo - um IP virtual com um grupo de endereços IP de pod que são usados como terminais e identificados por meio de
seletores de etiquetas . Esse serviço funciona como um balanceador de carga virtual, cujo endereço IP permanece constante e, ao mesmo tempo, os endereços IP do pod apresentado por ele podem mudar constantemente.
Seletor de etiquetas no objeto Serviço no KubernetesPor trás de toda a implementação desse IP virtual estão as regras do iptables (as versões mais recentes do Kubernetes também têm
a capacidade de usar o IPVS, mas este é um tópico para outra discussão), que são controladas por um componente do
Kubernetes chamado
kube-proxy . No entanto, esse nome é enganoso nas realidades de hoje. O proxy Kube foi realmente usado como proxy nos dias anteriores ao lançamento do Kubernetes v1.0, mas isso levou a um grande consumo de recursos e freios devido às operações constantes de cópia entre o espaço do kernel e o espaço do usuário. Agora é apenas um controlador - como muitos outros controladores no Kubernetes. Ele monitora o servidor da API em busca de alterações nos pontos de extremidade e atualiza as regras do iptables de acordo.
De acordo com essas regras do iptables, se o pacote for destinado ao endereço IP do serviço, será feita uma tradução de endereço de rede de destino (DNAT): isso significa que seu endereço IP será alterado do IP do serviço para um dos pontos de extremidade, ou seja, um dos endereços IP do pod, que o iptables seleciona aleatoriamente. Isso garante que a carga seja distribuída igualmente entre os pods.
DNAT em iptablesNo caso desse DNAT, as informações necessárias são armazenadas no
conntrack - a tabela de contabilidade de conexões no Linux (ele armazena traduções de cinco pares feitas pelo iptables:
protocol
,
srcIP
,
srcPort
,
dstIP
,
dstPort
). Tudo é organizado de tal maneira que, quando uma resposta é retornada, uma operação DNAT reversa (un-DNAT) pode ocorrer, ou seja, Substituindo a origem IP do IP do Pod para o IP do Serviço. Graças a esse cliente, não há absolutamente nenhuma necessidade de saber como trabalhar com pacotes nos bastidores.
Entradas de cinco pares (cinco tuplas) na tabela conntrackPortanto, usando os serviços do Kubernetes, podemos trabalhar com as mesmas portas sem nenhum conflito (porque é possível a atribuição de portas aos pontos finais). Isso facilita a descoberta de serviços. Basta usar o DNS interno e codificar permanentemente o host dos serviços. Você pode até usar as variáveis pré-configuradas do Kubernetes com a porta do host e de serviço.
Dica : ao escolher o segundo caminho, você salva muitas chamadas DNS desnecessárias!
Tráfego de saída
Os serviços Kubernetes descritos acima operam em um cluster. Na prática, os aplicativos geralmente precisam acessar alguns sites / API externos.
Em geral, os hosts podem ter endereços IP privados e públicos. Para acessar a Internet, é fornecido um NAT individual para esses endereços IP públicos e privados - isso é especialmente verdadeiro para ambientes em nuvem.
Para interação normal do host com o endereço IP externo, o IP de origem muda do IP do host privado para o IP público para pacotes de saída e para pacotes de entrada - na direção oposta. No entanto, nos casos em que a conexão com o IP externo é iniciada pelo pod, o endereço IP de origem é o IP do Pod, que o mecanismo NAT do provedor de nuvem não conhece. Portanto, ele simplesmente descartará pacotes com endereços IP de origem diferentes dos endereços IP do host.
E aqui, você adivinhou, precisaremos de iptables ainda mais! Desta vez, as regras, que também são adicionadas pelo kube-proxy, são executadas pelo SNAT (Source Network Address Translation), também conhecido como
IP MASQUERADE (mascarado). Em vez de informar o endereço IP de origem, o kernel é instruído a usar a interface IP da qual o pacote chega. No conntrack, também é exibido um registro para executar mais a operação reversa (un-SNAT) na resposta.
Tráfego de entrada
Até agora, estava tudo bem. Os pods podem se comunicar entre si e com a Internet. No entanto, ainda não temos o principal - atendendo ao tráfego do usuário. Atualmente, existem duas maneiras de implementá-lo:
1. NodePort / Cloud Load Balancer (nível L4: IP e porta)
Definir o
NodePort
como o tipo de serviço atribuirá o serviço
NodePort
no intervalo de 30.000 a
NodePort
. Este
nodePort
aberto em todos os nós, mesmo quando nenhum pod está sendo executado no nó. O tráfego de entrada neste
NodePort
direcionado para um dos pods (que podem até aparecer em outro nó!). Novamente, usando o iptables.
O tipo de serviço
LoadBalancer
em ambientes em nuvem cria um balanceador de carga em nuvem (por exemplo, ELB) na frente de todos os nós, trabalhando ainda mais com o mesmo
NodePort
.
2. Ingresso (nível L7: HTTP / TCP)
Muitas outras implementações também executam mapeamento de host / caminho HTTP com back-end correspondentes - por exemplo, nginx, traefik, HAProxy, etc. Com eles, o LoadBalancer e o NodePort tornam-se novamente o ponto de entrada para o tráfego, mas há a vantagem aqui de que precisamos de apenas um Ingress para atender ao tráfego de todos os serviços, em vez de vários NodePort / LoadBalancers.
Políticas de rede
As políticas de rede podem ser consideradas como grupos de segurança / ACLs para pods.
NetworkPolicy
regras
NetworkPolicy
permitem / negam tráfego entre os pods. Sua implementação exata depende da camada de rede / CNI, mas a maioria simplesmente usa iptables.
...
Isso é tudo. Nas
parcelas anteriores, aprendemos o básico da rede no Kubernetes e como as sobreposições funcionam. Agora sabemos como a abstração de serviço ajuda em um cluster dinâmico e torna a descoberta de serviços realmente simples. Também examinamos como o tráfego de saída / entrada flui e quais políticas de rede podem ser úteis para proteger um cluster.
PS do tradutor
Leia também em nosso blog: