Kubernetes

Gabriel Parracho | Guilherme Santiago | Leandro Marinho

Introdução ao Kubernetes

Conceitos Básicos

Primeiramente, é necessário pontuar alguns conceitos que serão utilizados com frequência durante o desenvolvimento deste trabalho. O primeiro deles é o Container, que é uma tecnologia muito utilizada ultimamente e que mudou a forma como se estrutura a arquitetura das infraestruturas de computação. Este termo se refere a uma forma de virtualização de máquina a nível de sistema operacional, onde há o empacotamento de uma aplicação e suas devidas dependências e configurações, tornando a aplicação passível de rodar em diferentes ambientes de computação. Outro conceito que será bastante utilizado é o de Nó (Node). No contexto deste trabalho ele consiste numa unidade de processamento e memória, podendo ser uma máquina virtual ou física, e é onde os containers são utilizados. Um nó pode conter zero, um ou mais containers. Um termo que será muito utilizado e que possui um significado específico nesse contexto é o objeto. Um objeto no Kubernetes é basicamente tudo que criado e gerenciado dentro do mesmo e são definidos através de um arquivo YAML, que é uma linguagem de serialização de dados legível para seres humanos. Por último, tem-se o Cluster que é o conjunto de nós que trabalham em conjunto para executar uma ou mais tarefas de forma coordenada.

Kubernetes

O Kubernetes é uma plataforma open-source para orquestração, automação e gerenciamento de ambientes conteinerizados, nos últimos anos com a transição de ambientes monolíticos para micro-serviços o Kubernetes, também conhecido como K8s, tem sido cada vez mais utilizado por grandes empresas do mercado e com isso criando uma grande e forte comunidade. Os principais objetivos desta ferramenta são: gerenciar dinamicamente os containers presentes em diferentes máquinas; criar e manter aplicações escaláveis, realizáveis e de auto-gerenciamento; oferecer diversas ferramentas para o controle automático dos containers. O kubernetes trabalha de forma declarativa, onde é definido um estado para a aplicação e a ferramenta funciona de modo a manter a aplicação nesse estado determinado.

Componentes do Kubernetes

Apresentado o que é o Kubernetes e os seus objetivos, agora é necessário conhecer a sua arquitetura e seus componentes. Num cluster de Kubernetes os componentes são agrupados em dois grupos, o Control Plane e os Worker Nodes. O control plane é uma coleção de componentes que são responsáveis por gerenciar o cluster de forma global, esses componentes não precisam necessariamente rodar todos em um só nó, eles podem se espalhar pelo cluster, porém uma boa prática é agrupá-los em um único nó dedicado conhecido como controller machine. Os componentes do control plane são:

Worker node são as máquinas(nós) que rodam os containers e a sua quantidade pode ser qualquer dentro do cluster. Assim como o control plane esse nó possui diversos componentes que são responsáveis por gerenciar os containers e os mesmos se comunicam com control plane via API. Os componentes dos nodes são:

Agora com toda a arquitetura dos componentes apresentados, segue uma imagem do design da mesma.

Na figura 1, fica evidente que o kube-api-server se comunica com todos os outros componentes, por isso ele é o principal componente para o gerenciamento interno do cluster.

Pods

Os pods são o agrupamento de um ou mais containers que compartilham entre si recursos de armazenamento e de network. Basicamente num cluster de Kubernetes a menor unidade de computação a serem criados e gerenciados são os pods. Os pods são objetos do Kubernetes e portanto são definidos através de um arquivo YAML.

Na figura 2, tem-se um exemplo básico da definição de um Pod. Na primeira linha tem a versão da API do Kubernetes que está sendo utilizada, na segunda linha é dito o tipo de objeto que está sendo criado ou gerenciado, no caso um Pod, na terceira linha se tem os metadados, que são dados sobre os dados, e por último vêm as especificações do próprio Pod, como no exemplo o nome do container a ser utilizado e sua imagem. O exemplo dessa figura é um caso bem simples, um Pod de uma aplicação real pode conter mais especificações e de mais complexidades, algumas delas serão abordadas nesse artigo.

Configuração de aplicação

Application configuration é outro objeto do Kubernetes que é utilizado para passar dados dinamicamente para um container que está rodando para controlar ou alterar seu comportamento. Há dois tipos disso:

Gerenciando recursos do container

Os containers utilizam recursos computacionais dos nós os quais estão alocados, portanto é necessário gerenciar-los para que não haja desperdício ou a falta de tal e para isso, no Kubernetes, existem duas especificações que são capazes de realizar essa tarefa, são elas:

Gerenciando a saúde do container

Num cluster de Kubernetes, os containers são os responsáveis por realizar as tarefas e aplicações, portanto é necessário que eles estejam sempre em funcionamento e saudáveis, e para isso existem diversas funções nessa ferramenta. Mas o que determina a saúde de um container? Isso varia da aplicação a qual o container está realizando, portanto depende de quem a está administrando. Porém o Kubernetes possui umas especificações dentro do pod para ajudar nessa tarefa. Com o liveness probe é possível, por exemplo, passar uma lista de comandos, que serão executados no container e caso eles sejam sucedidos é considerado saudável e caso contrário, não saudável. O startup probe é bem similar com o anterior, porém esse é rodado durante o processo de iniciação do container e só, enquanto o liveness probe é rodado dado uma escala determinada pelo administrador do cluster. No Kubernetes existe também uma outra especificação que reinicia o container assim que ele é dado como não saudável, ela é conhecida como restart policy (política de reiniciamento) com o valor de on failure (ao falhar).

Multi-Container Pods

Como dito anteriormente, no começo deste módulo, os pods são o agrupamento de um ou mais containers que compartilham recurso e network entre si, porém até agora os pods mostrados continha apenas um container, então agora será abordado como ocorre a interação entre os containers dentro de um mesmo pod. Os containers compartilham dos mesmos namespaces e se comunicam entre si em qualquer porta, mesmo que a porta não esteja exposta ao cluster. Compartilham também os volumes de armazenamento, ou seja, um container pode acessar um arquivo salvo em disco de outro container. É possível ter containers que são usados, somente, para executar algumas tarefas durante a inicialização do pod e assim que realizam sua função são terminados e o container principal começa a rodar, esses containers são conhecidos como initi containers e pode se ter diversos dentro de um mesmo pod.

Alocação de Pods

Os pods sem estarem alocados em um nó não são capazes de fazer nada, portanto a tarefa de alocação de nós, conhecida como scheduling, é fundamental para o funcionamento geral do cluster. Como dito anteriormente, o componente responsável por essa tarefa é o Scheduler, presente no control plane. O Scheduler leva em consideração ao alocar um pod em um nó a requisição ou limitação de recurso que o mesmo utiliza, pois caso o nó não tenha capacidade computacional conforme o pod pede, o pod não será alocado nesse mesmo e sim em outro que possua. Outra coisa que ele leva em conta são as configurações de nó feitas com node labels, que são rótulos associados aos nós do tipo chave:valor. Esses rótulos podem ser definidos também a nível de nó, e é a combinação de ter os mesmos rótulos e valores presente no pod e no nó que faz com que o scheduler faça a alocação. Os rótulos a nível de pod são feitos através de um nodeSelector, que se combina com os node labels, e ou um nodeName que se refere a alocação de um nó com um nome específico.

Deployments

Como dito anteriormente, o Kubernetes é capaz de definir um estado para aplicação manter esse estado. É com o deployment que isso é possível, ele é um objeto Kubernetes responsável por definir e manter o estado tendo que criar, deletar e substituir pods que forem necessários para alcançar tal objetivo. Para manter o estado desejado o deployment conta com três componentes:

Com o Rolling Updates é possível fazer uma atualização no cluster de forma gradual, essa feature muda os pods do deployment a uma taxa controlada e lentamente trocando um pod por outro. E com o RollBack é possível voltar uma versão de deployment, isso é muito útil quando há um erro ou falha de segurança durante uma atualização e há versões anteriores funcionando perfeitamente. Algumas aplicações clássicas do deployment são: a possibilidade de escalar a aplicação tanto para cima quanto para baixo, alterando o número de réplicas dos pods e utilizar o rolling updates para atualizar uma nova versão de software.

Network e Services

Network

Network é uma parte central para a comunicação entre os diferentes componentes e serviços que compõem um cluster. Ela é a base para a comunicação entre os Pods, serviços externos e usuários finais. Neste tópico, existem 4 problemas principais a serem resolvidos:

- Comunicações altamente acopladas entre contêineres: isso é resolvido por meio de Pods e comunicações locais.
- Comunicações de Pod para Pod: tratado por Network.
- Comunicações de Pod para Serviço: tratado por Services.
- Comunicações externas para Serviço: tratado por Services.

O modelo de network é baseado no tempo de execução de um container em cada nó, e para isso, utilizam os CNI (Container Network Interface) plugins.

CNI Plugins

Os CNI Plugins são especificações padrões do ecossistema de kubernetes que definem um conjunto de plugins para gerenciar a configuração de rede dos contêineres em um cluster. São eles os responsáveis por configurar e gerenciar o network entre contêineres no ambiente e por tarefas como:

- Criação de interfaces de rede
- Atribuição de endereços IP
- Configuração de rotas e regras de firewall
- Integração com soluções de rede

Dentre os vários plugins disponíveis, podemos destacar os seguintes:

Flannel: O Flannel é uma solução de rede popular para Kubernetes, que usa a sobreposição (overlay) de rede para conectar os pods. Ele atribui um endereço IP único a cada pod e encapsula o tráfego em pacotes IP que são roteados entre os nós do cluster.
Calico: Fornece um plano de controle distribuído que atribui políticas de rede aos pods e fornece recursos avançados, como isolamento de rede baseado em políticas, segmentação e roteamento avançado.
Weave: Solução de rede que oferece conectividade entre pods em um cluster Kubernetes. Ele usa um plano de controle centralizado e cria uma rede sobreposta que permite que os pods se comuniquem entre si usando endereços IP virtuais.

Podemos observar que cada plugin tem suas características específicas, próprias para cada caso de uso, mas sempre seguindo o padrão CNI, para garantir a interoperabilidade entre a rede de clusters em um ambiente Kubernete.

Kubernetes DNS

Kubernetes DNS é um outro serviço que, assim como o DNS, fornece resolução de nomes para os componentes dentro de um cluster, permitindo que recursos, tais como Pods e Services, sejam acessados por meio desses nomes ao invés do endereço IP. Sua implementação é dada através de um servidor DNS interno, executado em cada nó do cluster. Para fornecer a resolução de um nome, segue a seguinte convenção de nomenclatura:

- Nomes de Serviço: Cada serviço Kubernetes recebe um nome no formato (nome-do-servico).(namespace).svc.cluster.local. Ao fazer uma consulta DNS para esse nome, o Kubernetes DNS retorna os endereços IP dos pods que fazem parte desse serviço.
- Nomes de Pod: Os pods também recebem nomes no formato (nome-do-pod).(namespace).pod.cluster.local. Esses nomes são automaticamente registrados no Kubernetes DNS e resolvem para o endereço IP do pod correspondente.

Com isso, os componentes de um mesmo cluster podem se referir por meio de seus service names, ao invés de endereços IP que mudam dinamicamente.

Políticas de Network

As políticas de Network são usadas para definirem regras e restrições sob a comunicação de network entre os vários componentes de um mesmo cluster. Com elas, é possível ter uma garantia de controle, segurança, isolamento e fluxo do tráfego em um Kubernetes. As principais políticas de Network são:

- Políticas de Rede: Implementadas usando a API de NetworkPolicy. Definem regras de tráfego com base em rótulos (labels) aplicados a pods e serviços.
- Segmentação de Rede: Permite isolar grupos de pods em redes virtuais separadas. Dessa forma, é possível restringir a comunicação entre diferentes segmentos de rede, mesmo quando eles estão no mesmo cluster Kubernetes.
- Restrições de Tráfego: Usada para restringir o tráfego de entrada ou saída de pods ou serviços. É possível definir regras que permitem ou bloqueiam conexões com base em endereços IP de origem ou destino, portas de serviço, protocolos de rede e outras características.
- Criptografia e Autenticação: Podem ser aplicadas para garantir a segurança da comunicação de rede no Kubernetes. Isso inclui o uso de TLS (Transport Layer Security) para criptografar o tráfego de rede, autenticação baseada em certificados e controle de acesso a recursos de rede usando políticas de autorização.
- Proxies e Balanceadores de Carga: Essas soluções podem ser usadas para rotear o tráfego de rede entre os serviços, fornecer recursos avançados de balanceamento de carga e gerenciar o tráfego externo para o cluster.

Services

Os Services são uma abstração que ajudam a expor grupos de Pods em uma rede. Eles abstraem a complexidade de encontrar e acompanhar os endereços IP dos Pods individuais, ao invés de se preocupar com IPs dinâmicos, os serviços podem ser referenciados pelos seus nomes e o Kubernetes irá rotear para o Pod correto.

Service Types

Os Service Types são:

1.Cluster IP: Cria um endereço IP interno que só pode ser acessado de dentro do cluster.
2.NodePort: Atribui uma porta estática e encaminha o tráfego para o serviço, permitindo que o serviço seja acessível externamente usando o IP e a porta.
3.LoadBalancer: Provisiona um balanceador de carga externo (depende que a plataforma de nuvem suporte load balancing) e atribui um IP externo ao serviço. O tráfego é distribuído pelo balanceador de carga para os pods e é útil para expor o serviço para o exterior.
4.ExternalName: Mapeia o serviço para um nome externo, útil para o serviço ser acessível por um nome de domínio externo.

Service DNS

O Service DNS atribui nomes aos serviços dentro do cluster, permitindo que as aplicações que também estão nele sejam facilmente acessadas. Ao invés de usar endereços IP, é possível fazer a comunicação utilizando os nomes DNS.

Ingress

O Ingress é um recurso que gerencia acesso externo a serviços dentro do cluster. Ele age como um controlador de tráfego, roteando as solicitações baseando-se nas regras de roteamento configuradas. Essas funções são obtidas somente quando se instala um ou mais Ingress controllers, para implementar e gerenciar o Ingress.

Como criar um cluster de Kubernetes

Para a criação de um cluster de Kubernetes será utilizado uma ferramenta que facilita o processo, o Kubeadm. Serão criados três servidores em nuvem, gerados pela plataforma Cloud Guru, um será responsável pelo control plane e os outros dois funcionarão como workers nodes.

O primeiro passo será alterar os hostnames dos servidores para que seja simples identificá-los, para isto será utilizado o comando “hostnamectl set-hostname”.


Este procedimento foi realizado nos três servidores, onde os outros dois foram nomeados como k8s-worker1 e k8s-worker2.
Em seguida é necessário criar um arquivo de mapeamento entre os servidores no diretório hosts de todos eles, para que seja possível a comunicação entre eles.

Os próximos passos consistem em instalar o container runtime, que nesse caso será o conteinerd, o kubeadm, o kubelet e o kubectl, este último é uma ferramenta de linha de comando que é utilizada para gerenciar o cluster. Essas etapas são muito verbosas, portanto será colocada toda a lista de comandos necessários para realizá-las com comentário.


Agora com os arquivos de comunicação nos três servidores e o containerd e kubernetes instalados neles, o próximo passo é inicializar o cluster. Esta etapa só é necessária realizar no control plane, visto que ele é nó responsável por gerenciar o cluster.
Para inicialização do cluster será utilizado o kubeadm, com o seguinte comando: sudo kubeadm init
sudo kubeadm init -pod-network-cidr xxx.xxx.xx/xx --kubernetes-version x.x.x.
A primeira flag se refere ao alcance de endereços IP presentes no cluster e a segunda sobre a versão do kubernetes a ser utilizada.

Com o cluster inicializado, é necessário configurar o arquivo kubeconfig responsável por autenticar o cluster e permitir a comunicação entre usuário e cluster através do kubectl. Para essa etapa serão utilizados os três comandos a seguir:

-mkdir -p $HOME/.kube
-sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
-sudo chown $(id -u):$(id -g) $HOME/.kube/config

Na figura 16, percebe-se que ao utilizar o comando kubectl get nodes é retornado apenas o control plane e que ele não está pronto e isso se dá ao fato da falta de configuração dos plugins de network, responsável pela comunicação entre os nós. Portanto a próxima etapa será a instalação desse plugin, nesse caso será utilizado o Calico plugin, com o seguinte comando:

kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml

Por fim, precisa-se juntar os workers nodes ao cluster e para isto é utilizado o comando join. No control plane será criado um token de identificação que os workers nodes utilizarão para dar join no cluster. Os comandos a serem utilizados são:

- kubeadm token create –print-join-command (No control plane)
- sudo kubeadm join (retorno do comando de cima) (Nos workers nodes)



Após todas essas etapas, tem-se um cluster de kubernetes pronto para ser utilizado, é possível verificar a criação utilizando o comando kubectl get nodes no control plane.

Bibliografia

Site oficial do Kubernetes: https://kubernetes.io/
Documentação do Kubernetes: https://kubernetes.io/docs/home/
Curso gratuito no Udacity: https://www.udacity.com/course/scalable-microservices-with-kubernetes--ud615
Documentação do Docker: https://docs.docker.com/
Kubernetes no GitHub: https://github.com/kubernetes/kubernetes
Blog do Kubernetes: Kubernetes Blog
Kubernetes Container Runtimes | Airplane
https://containerd.io/docs/
Certified Kubernetes Administrator (CKA) | A Cloud Guru