Please enable JavaScript.
Coggle requires JavaScript to display documents.
Deep Dive Kubernetes (Misc) - Coggle Diagram
Deep Dive Kubernetes (Misc)
Controller Manager
O API Server não faz nada além de armazenar recursos no etcd e notificar os clientes sobre a mudança. O Scheduler apenas atribui um nó ao pod, portanto, você precisa de outros componentes ativos para garantir que o estado real do sistema converge para o estado desejado, conforme especificado nos recursos implantados por meio do API Server. Este trabalho é feito por controllers rodando dentro do Controller Manager.
Atualmente, o processo único do Controller Manager combina vários controllers que executam várias tarefas de reconciliação. eventualmente serão divididos em processos separados. Nesses inclui ReplicationController, Deployment Controller, Node Controller e etc.
Os recursos são descrições do que deve ser executado no cluster, enquanto os controllers são os componentes ativos do Kubernetes que realizam o trabalho real como resultado dos recursos implantados. Logo, há um controller para quase todos os recursos.
Os controllers fazem muitas coisas diferentes, mas todos observam o API Server em busca de alterações nos recursos e realizam operações para cada alteração
Reconciliação
Em geral, os controllers executam um loop de reconciliação, que reconcilia o estado real com o estado desejado (especificado na seção de especificação do recurso) e grava o novo estado real na seção de status do recurso.
Os controllers usam o mecanismo de watch para serem notificados das alterações, mas como o uso de watchs não garante que o controller não perderá um evento, eles também realizam uma operação de re-lista periodicamente para garantir que não tenham perdido nada.
Os controllers nunca conversam diretamente entre si. Eles nem sabem que existem outros controllers. Cada controller se conecta ao API Server e solicita ser notificado quando ocorrer uma alteração
Kubelet
Em poucas palavras, o Kubelet é o componente responsável por tudo que é executado em um nó de worker.
Seu trabalho inicial é registrar o nó em que está sendo executado criando um recurso Node no API Server. Em seguida, ele precisa monitorar continuamente o API Server para Pods que foram escalonados para o nó e iniciar os contêineres do pod.
Ele faz isso dizendo ao tempo de execução do contêiner configurado (que é Docker, CoreOS, CRI, rkt ou qualquer outra coisa) para executar um contêiner de uma imagem de contêiner específica.
O Kubelet monitora constantemente os contêineres em execução e relata seu status, eventos e consumo de recursos para o API Server.
O Kubelet também é o componente que executa as liveness probes do contêiner, reiniciando os contêineres quando as probes falham.
Por fim, ele encerra os contêineres quando o pod é excluído do API Server e notifica o servidor de que o pod foi encerrado.
Embora o Kubelet converse com o API Server do Kubernetes e obtenha os manifestos do pod de lá, ele também pode executar pods com base nos arquivos de manifesto do pod em um diretório local específico. Esse recurso é usado para executar as versões em contêiner dos componentes do Control Plane como pods, como você viu no início do capítulo.
Kubernetes Proxy
Além do Kubelet, cada nó do worker também executa o kube-proxy, cujo objetivo é garantir que os clientes possam se conectar aos services definidos por meio da API do Kubernetes.
O kube-proxy garante que as conexões com o IP e a porta do serviço terminem em um dos pods que suportam esse service (ou outros pontos de extremidade de serviço não pod).
Quando um service é apoiado por mais de um pod, o proxy executa o balanceamento de carga nesses pods.
Iptabels
Para interceptar as conexões destinadas aos IPs de service, o proxy configurou as regras do iptables para redirecionar as conexões para o servidor proxy.
O kube-proxy recebeu esse nome porque era um proxy real, mas a implementação atual, com muito melhor desempenho, usa apenas as regras do iptables para redirecionar pacotes para um pod de back-end selecionado aleatoriamente sem passá-los por um servidor proxy real.
Este modo é chamado de iptables proxy mode.
A principal diferença entre esses dois modos é se os pacotes passam pelo kube-proxy e devem ser tratados no espaço do usuário ou se são tratados apenas pelo Kernel (no espaço do kernel). Isso tem um grande impacto no desempenho.
Iptables não utiliza round-robin para distribuir as requests, ele escolhe de forma aleatória. Então se tiver poucos usuários é comum de ver um desbalanço de requisições.
Services
Quando um Service é criado no API Server, o endereço IP virtual é atribuído a ele imediatamente.
Logo depois, o API Server notifica todos os agentes kube-proxy em execução nos nós do Worker que um novo Service foi criado.
Cada kube-proxy torna esse Service endereçável no nó em que está sendo executado
Ele faz isso configurando algumas regras de iptables, que garantem que cada pacote destinado ao par IP/porta do Service seja interceptado e seu endereço de destino modificado, de modo que o pacote seja redirecionado para um dos pods que suportam o Service.
Além de observar (watch) o API Server quanto a alterações nos Services, o kube-proxy também observa as alterações nos objetos Endpoints.
Fluxo de requisições Pod A (em um nó A) para Pod B (em um nó B)
O destino do pacote (172.30.0.1:80) é definido inicialmente para o IP e a porta do Service
Antes de ser enviado para a rede, o pacote é tratado primeiro pelo kernel do nó A de acordo com as regras do iptables configuradas no nó
O kernel verifica se o pacote corresponde a alguma dessas regras do iptables. Se algum pacote tiver o IP de destino igual a 172.30.0.1 e porta de destino igual a 80, o IP e a porta de destino do pacote devem ser substituídos pelo IP e porta de um pod selecionado aleatoriamente.
O pacote no exemplo corresponde a essa regra e, portanto, seu IP/porta de destino é alterado de forma aleatoriamente para um dos pods B do service B.
HA Control Plane
Para tornar o Kubernetes altamente disponível, você precisa executar vários nós mestres, que executam várias instâncias.
Componentes do Master: etcd, API server, Controller Manager and Scheduler
ETCD CLUSTER
etcd foi projetado como um sistema distribuído, um de seus principais recursos é a capacidade de executar várias instâncias do etcd, portanto, torná-lo altamente disponível não é grande coisa
Você faz isso incluindo a lista de todas as outras instâncias na configuração de cada instância. Por exemplo, ao iniciar uma instância, você especifica os IPs e as portas onde as outras instâncias etcd podem ser alcançadas.
O etcd replicará dados em todas as suas instâncias, portanto, uma falha de um dos nós ao executar um cluster de três máquinas ainda permitirá que o cluster aceite operações de leitura e gravação.
Para aumentar a tolerância a falhas para mais de um único nó, você precisa executar cinco ou sete nós etcd, o que permitiria ao cluster lidar com duas ou três falhas de nós, respectivamente.
API SERVER
Tornar o API Server altamente disponível é ainda mais simples. Como o API Server é (quase completamente) sem estado (todos os dados são armazenados no etcd, mas o API Server os armazena em cache), você pode executar quantos API Servers precisar e eles não precisam estar cientes de cada outro em tudo.
Normalmente, um API Server é colocado em cada instância etcd. Ao fazer isso, as instâncias do etcd não precisam de nenhum tipo de balanceador de carga na frente delas, porque cada instância do API Server fala apenas com a instância local do etcd.
Os API Servers, por outro lado, precisam ser liderados por um balanceador de carga, para que os clientes (kubectl, mas também o Controller Manager, Scheduler e todos os Kubelets) sempre se conectem apenas às instâncias de API Server íntegras.
CONTROLLERS AND THE SCHEDULER
Comparado ao API Server, onde várias réplicas podem ser executadas simultaneamente, executando várias instâncias do Controller Manager ou do Scheduler não é tão simples.
Como os controllers e o Scheduler observam ativamente o estado do cluster e agem quando ele muda, possivelmente modificando ainda mais o estado do cluster, executando várias instâncias de cada um desses componentes resultariam em todos eles executando a mesma ação. Criando conflitos
Por esse motivo, ao executar várias instâncias desses componentes, apenas uma instância pode estar ativa por vez.
Tudo isso é cuidado pelos próprios componentes (isso é controlado com a opção --leader-elect, cujo padrão é true).
Cada componente individual só estará ativo quando for o líder eleito. Apenas o líder executa o trabalho real, enquanto todas as outras instâncias estão de prontidão e esperando que o líder atual falhe. Quando isso acontece, as instâncias restantes elegem um novo líder, que então assume o trabalho.
O Controller Manager e o Scheduler podem ser executados em conjunto com o API Server e etcd, ou podem ser executados em máquinas separadas. Quando colocados, eles podem se comunicar diretamente com o API Server local; caso contrário, eles se conectam aos API Servers por meio do balanceador de carga.
O que acho mais interessante aqui é que esses componentes não precisam conversar diretamente entre si para eleger um líder. O mecanismo de eleição do líder funciona puramente criando um recurso no API Server. E nem é um tipo especial de recurso – o recurso Endpoints (ou ConfigMaps) é usado para conseguir isso (abusado é provavelmente um termo mais apropriado).