Capítulo 9: Oracle Kubernetes Engine (OKE)
9.3 Arquitetura do Kubernetes
O Kubernetes é composto por diversos componentes distribuídos e independentes, cada um com sua própria responsabilidade. A maioria deles foi desenvolvida na linguagem de programação Go e muitos fazem parte da Cloud Native Computing Foundation (CNCF).
Para que um cluster Kubernetes funcione corretamente, é necessário instalar e configurar todos esses componentes que serão detalhados a seguir.

Além de detalhar os componentes, será apresentada a arquitetura geral do Kubernetes e a forma como esses componentes interagem entre si.
Para facilitar a identificação, a equipe de desenvolvimento do Kubernetes utiliza o prefixo kube na maioria dos componentes e utilitários que fazem parte do projeto. A exceção a essa convenção são duas dependências externas: o Container Runtime e o etcd.
NOTA
Aqui, são apresentados alguns termos e objetos do Kubernetes, como Pods, Services e Deployments. Não se preocupe, pois os detalhes de cada um deles e o seu funcionamento serão explorados na seção 8.5 Objetos Kubernetes.
9.3.1 Master Nodes e Worker Nodes
Um cluster Kubernetes típico é composto por várias máquinas, que podem ser físicas, virtuais ou uma combinação de ambas, conhecidas como Nodes. Esses nodes são organizados em dois grupos principais:
NOTA
É importante ressaltar que, embora seja possível executar todos os componentes do Kubernetes em uma única máquina, essa configuração não oferece tolerância a falhas. A abordagem recomendada é ter pelo menos duas máquinas configuradas como Master Nodes e outras duas como Worker Nodes. Essa configuração proporciona maior resiliência e disponibilidade.
NOTA
As máquinas do Master Nodes deve ser Linux. Já as máquinas dos Worker Nodes podem ser Linux ou Windows.

Control Plane ou Master Nodes
Esse grupo de máquinas supervisiona e envia tarefas para os Worker Nodes. Ou seja, elas são responsáveis por manter o "estado desejado do cluster".
Toda a inteligência do Kubernetes está concentrada nos Master Nodes, e cada cluster deve ter pelo menos uma máquina designada para desempenhar essa função.
Há uma coleção de serviços que operam continuamente em cada Master Nodes, responsáveis por manter o estado do cluster, incluindo:
NOTA
A documentação de todos os componentes do Kubernetes está disponível no link "Core Components".
kube-apiserver
O kube-apiserver é o frontend do Kubernetes, atuando como o "ponto de administração" que permite aos usuários enviar comandos e consultar informações sobre o cluster.
Esse componente expõe uma API RESTful via HTTPS, que, por padrão, "escuta" as requisições na porta 6443/TCP. Essa API permite que os usuários gerenciem, monitorem e obtenham informações sobre todo o cluster, através do utilitário de linha de comando kubectl.

NOTA
Devido ao fato de o kube-apiserver ser uma API RESTful, é possível interagir com ele utilizando até mesmo o utilitário de linha de comando curl. No entanto, é mais prático e fácil realizar essas interações através do kubectl.
Uma outra função desse componente, é realizar cosultas periódicas ao banco de dados etcd.
etcd
Todos os comandos enviados pelo kube-apiserver, especialmente aqueles que alteram o "estado do cluster", são persistidos ou atualizados em um banco de dados chave/valor distribuído nos Master Nodes conhecido como etcd.
A principal função do etcd é armazenar de maneira persistente todas as alterações que foram enviadas ao kube-apiserver. O Kubernetes consulta periodicamente o etcd para verificar se o "estado do cluster" está em conformidade com os dados ali armazenados.

Outro ponto importante é que nenhum componente pode ler ou escrever no etcd sem passar pelo kube-apiserver.
O etcd não é um componente do projeto Kubernetes, mas é um projeto independente que também faz parte da Cloud Native Computing Foundation (CNCF).
NOTA
Existe um playground online acessível pelo link http://play.etcd.io/play, que permite aprender e gerenciar clusters com o etcd.
kube-scheduler
A principal função do kube-scheduler é monitorar periodicamente o kube-apiserver em busca de novos Pods que precisam ser criados. Com base nas informações disponíveis, o kube-scheduler seleciona um ou mais Worker Nodes adequados para a execução desses Pods, garantindo que os requisitos de recursos e restrições de afinidade sejam atendidos.

NOTA
Uma explicação mais detalhada sobre objetos do Kubernetes será apresentada no capítulo 8.4 Objetos Kubernetes. Por enquanto, é importante compreender que um Pod é um objeto do Kubernetes utilizado para definir uma unidade de execução que pode conter um ou mais contêineres.
Um Pod recém-criado não possui um Worker Node designado para sua execução. Chamamos de "Unschedule Pod" o Pod que não possui um Worker Node elegível para execução, e seu status fica como "Pending". Já o termo "Schedule" refere-se ao processo de atribuição do Pod a um Worker Node capaz de realizar a sua execução. Em outras palavras, quando um Pod é "scheduled", isso significa que ele foi atribuído a um Worker Node específico que é capaz de executá-lo.
Além disso, o kube-scheduler desempenha outras funções importantes, como a verificação de regras de afinidade e antiafinidade, a checagem da disponibilidade de portas de rede e a validação dos recursos de CPU e memória.
NOTA
O processo de Scheduling do Kubernetes é bem mais complexo do que foi descrito aqui. Para maiores detalhes, consulte o "Scheduling, Preemption and Eviction".
kube-controller-manager
O kube-controller-manager, também conhecido como controller, é responsável por executar o "loop de reconciliação" (reconciliation loop), que tem como objetivo manter o "estado do cluster" em sincronia com as informações armazenadas no etcd.
Por exemplo, quando solicitado, o Kubernetes é capaz de manter um número específico de Pods distribuídos entre os diferentes Worker Nodes. Se, por qualquer motivo, o número total de Pods ativos divergir do número de Pods registrados no etcd, o "loop de reconciliação" garantirá que os Pods ausentes sejam criados e iniciados. Vale ressaltar que essa verificação é um processo contínuo, o que justifica o uso da palavra "loop" para descrever sua funcionalidade.

Há diferentes controller que fazem parte do "loop de reconciliação" e cada um deles é responsável por gerenciar e cuidar de um tipo específico de objeto Kubernetes. Alguns deles são:
- Replication Controller
- Deployment Controller
- Job Controller
- Namespace Controller
OCI Cloud Controller Manager (CCM)
O OCI Cloud Controller Manager (oci-cloud-controller-manager), é a implementação do cloud-controller-manager responsável por conectar o Kubernetes às APIs do OCI.
NOTA
O oci-cloud-controller-manager é um projeto de código aberto mantido pela Oracle. O código-fonte da implementação pode ser acessado por meio do link https://github.com/oracle/oci-cloud-controller-manager.
Uma das funcionalidades do oci-cloud-controller-manager é a criação de Load Balance no OCI por meio do do objeto Service.

Compute Nodes ou Worker Nodes
Em resumo, os Worker Nodes têm a função de executar aplicações contêinerizadas, ou, mais precisamente, executar Pods.
Existem, basicamente, três componentes do cluster Kubernetes que são executados nos Worker Nodes e são responsáveis pela execução dos Pods. São eles:
Container Runtime
O Container Runtime é o software responsável pela criação, execução e gerenciamento de contêineres nos Worker Nodes. É necessário instalar um Container Runtime em cada Worker Node para que os Pods possam ser criados e executados.
Existem diferentes Container Runtime suportados e disponíveis para instalação, incluindo:

O Docker Engine foi, por muito tempo, o Container Runtime padrão para a execução de contêineres no Kubernetes. No entanto, em dezembro de 2020, com o lançamento da versão 1.20, o projeto Kubernetes anunciou a descontinuação do suporte ao Docker Engine como runtime de contêineres. Na versão 1.24, o suporte ao Docker Engine foi completamente removido.
Essa decisão foi motivada para permitir a adoção de outros runtimes de contêiner, como containerd, CRI-O, além de qualquer outro que siga as definições do Container Runtime Interface (CRI).
Isso não significa que imagens de contêineres Docker não são compatíveis com o Kubernetes. Todas as imagens que seguem a especificação da Open Container Initiative, são totalmente suportadas no Kubernetes, incluindo as imagens Docker.
Atualmente, é comum ter instalações do containerd ou CRI-O sendo utilizados como runtimes de contêiner. Por exemplo, o Oracle Kubernetes Engine (OKE) utiliza o containerd como seu runtime padrão.
NOTA
Consulte o artigo "Don't Panic: Kubernetes and Docker" que aborda a remoção do Docker Engine como um runtime de contêiner suportado diretamente pelo Kubernetes.
kubelet
O kubelet, componente principal do Worker Node, é responsável por realizar consultas regulares ao kube-apiserver, buscando informações sobre os Pods a serem criados ou removidos. Após obter essas informações, o kubelet interage diretamente com o Container Runtime no Worker Node para a criação ou exclusão efetiva dos Pods.

Mais especificamente, o kubelet obtém e processa o chamado PodSpec, que é um conjunto de informações que define as instruções de criação e o comportamento desejado do Pod. O PodSpec inclui detalhes como a imagem do contêiner a ser utilizada, as configurações de rede, as variáveis de ambiente, os recursos solicitados (como CPU e memória) e as políticas de restart. Com base nessas informações, o kubelet gerencia a execução do Pod no Worker Node, garantindo que ele atenda ao "estado desejado" especificado.
kube-proxy
Em cada Worker Node, há uma instância em execução do kube-proxy, que funciona como um proxy de rede, garantindo a conectividade interna e externa. É o kube-proxy que torna os Pods acessíveis na rede por meio do objeto Service.

Assim como o kubelet, o kube-proxy também interage regularmente com o kube-apiserver.
9.3.2 Addons
Addons são ferramentas que estendem as funcionalidades do Kubernetes.
Alguns Addons são essenciais para o funcionamento adequado do cluster, enquanto outros são opcionais.
NOTA
Para uma lista mais completa sobre os Addons disponíveis, consulte o link "Installing Addons".
Alguns exemplos de Addons essenciais incluem:
- CoreDNS
- O CoreDNS é um servidor DNS mais simples em comparação com servidores mais completos, como o BIND. Ele foi projetado para ser utilizado como o servidor DNS padrão no Kubernetes, desempenhando a função de resolver nomes de Services e Pods dentro do cluster. No entanto, ele também pode ser configurado para atuar como um servidor DNS recursivo, permitindo a resolução de nomes externos.

-
CNI plugin for pod networking
-
CNI (Container Network Interface) é uma especificação e um conjunto de padrões que define uma interface para a configuração de redes em ambientes de contêineres. As implementações CNI mais utilizados no OKE são:
-
- O plug-in CNI Flannel fornece uma rede para os Pods sem utilizar os endereços IP disponíveis de uma sub-rede do OCI. A rede disponibilizada pelo CNI Flannel é frequentemente chamada de "rede de sobreposição", pois consiste em uma rede IP que existe somente dentro do cluster, mais especificamente, nos Worker Nodes.
-
- O plugin OCI VCN-Native Pod Networking CNI, aloca endereços IP de uma sub-rede do OCI diretamente para os Pods. Isso permite que os Pods se comuniquem entre si de forma direta, sem a necessidade de utilizar um Service. Com essa abordagem, os Pods se tornam roteáveis, assim como qualquer outro recurso que utilize um endereço IP, facilitando a comunicação e a integração dentro do ambiente de rede.
-

Alguns exemplos de Addons opcionais incluem:
-
- O Kubernetes Dashboard é uma aplicação Web projetada para administrar, monitorar e gerenciar Pods, Services, Deployments e outros componentes, além de fornecer uma visão geral do próprio cluster Kubernetes.
-
- O Kubernetes Autoscaler é um addon que ajusta automaticamente a capacidade de um cluster Kubernetes com base na demanda de recursos. Ele opera em duas frentes principais: o HPA (Horizontal Pod Autoscaler), que tem como objetivo escalar horizontalmente, ou seja, aumentar ou diminuir o número de réplicas de um Pod, e o VPA (Vertical Pod Autoscaler), que modifica a quantidade de recursos, como CPU e memória, alocados para um Pod.
-
- É um componente desenvolvido pela Oracle que permite gerenciar o tráfego de entrada (ingress) para aplicações em execução em um cluster Kubernetes que está hospedado no OCI. Ele fornece uma maneira de expor serviços de aplicações para o mundo externo, permitindo que os usuários acessem essas aplicações através de URLs e domínios.
-
- É um addon que permite expor um número de GPUs NVIDIA para utilização em cada Worker Node.
9.3.3 Como o Kubernetes Funciona do Início ao Fim (resumo)
-
Você configura um cluster Kubernetes – ele é composto de Master Nodes e Worker Nodes.
-
Você define sua aplicação usando arquivos YAML – normalmente com Deployment, Service, ConfigMap, etc.
-
Você aplica o YAML usando o comando
kubectl apply -f. A solicitação vai para o API Server nos Master Nodes. -
O Kubernetes verifica a solicitação para decidir o que fazer:
a. Criar um novo objeto como um Pod ou Deployment?
b. Atualizar ou excluir um objeto existente?
c. Acionar um controlador para executar alguma ação? etc. -
O API Server armazena a especificação do objeto no etcd, o banco de dados do cluster.
-
O controlador apropriado vê a nova especificação – como um controlador ReplicaSet monitorando novos Deployments.
-
O controlador cria os recursos necessários – por exemplo, dizendo ao scheduler para posicionar novos Pods.
-
O scheduler escolhe um nó adequado para cada Pod – com base na disponibilidade de recursos e regras de agendamento.
-
A especificação do Pod é enviada para o Kubelet do nó – ele solicita ao runtime do contêiner que inicie o contêiner.
-
O runtime do contêiner faz o pull da imagem, cria o contêiner e o executa dentro do Pod.
-
O plugin CNI atribui uma identidade de rede – o Pod recebe um endereço IP e se junta à rede do cluster.
-
O kube-proxy configura regras de roteamento – permitindo que os Services encaminhem tráfego para Pods saudáveis.
-
O Kubelet relata o status dos Pods de volta ao API Server – usado para rastrear prontidão e saúde.
-
Se um Pod falhar ou for excluído, o controlador percebe e o recria – mantendo o sistema sincronizado.
-
Esse loop inteiro continua funcionando – o Kubernetes observa constantemente e reconcilia para corresponder ao estado desejado.
9.3.4 Conclusão
Neste capítulo, foi apresentada uma visão geral do funcionamento e da arquitetura de um cluster Kubernetes. Foram explorados os diversos componentes de software que o compõem, destacando suas funções e a maneira como interagem entre si para formar o ecossistema do Kubernetes. Compreender a totalidade do sistema é fundamental não apenas para entender como o Kubernetes opera, mas também para auxiliar na identificação e resolução de problemas que possam surgir.