Kubernetes

Marcio H
Tecnologia e afins
Published in
11 min readJul 15, 2019

Chegou a hora de falarmos sobre Kubernetes, um sistema de gerenciamento de containers de código aberto que cresceu enormemente em popularidade nos últimos anos.

O Kubernetes, ou K8S (um trocadilho com o nome Kubernetes — k + 8 caracteres + s) ou “kube” (para aqueles que já estão mais íntimos) é um sistema de cluster e orquestração para containers como o Docker, mas que suporta outros sistemas de container, como o Rocket, por exemplo.

Kubernetes é um sistema de código aberto que foi desenvolvido pelo Google para gerenciamento de aplicações em containers através de múltiplos hosts de um cluster. Tem como principal objetivo facilitar a implantação de aplicações baseadas em microsserviços. Ele foi baseado na experiência do Google de muitos anos trabalho com containers, adaptando o para se trabalhar com Docker.

O Kubernetes tem um papel fundamental para gerenciar esses hosts e executar demandas que são recebidas pelo cluster. Muita gente ainda tem dúvida ou faz confusão tentando comparar Docker e Kubernetes, mas a comparação correta seria “Docker Swarm” e Kubernetes, ambas ferramentas de orquestração de cluster. O Kubernetes usa o Docker para criar os containers nos nós do cluster. O trabalho dele aqui é gerenciar, controlar e monitorar o estado desses containers ao longo do cluster.

Com o uso cada vez maior de containers, os problemas de orquestração tornaram-se mais relevantes. Nos últimos anos, vários projetos e empresas tentaram enfrentar o desafio — mas o Kubernetes surgiu como uma plataforma forte e dominante para operar containers.

Algumas vantagens do Kubernetes:

  • Container sempre online: Verifica a saúde da sua aplicação, podendo reiniciar contêineres que falham, substituir contêineres ou matar contêineres que não respondem à sua verificação de saúde.
  • Autoscaling: Obtém métricas e verifica se há necessidade de crescer horizontalmente seus containers (escalar).
  • Descoberta de Serviço: Containers recebem um endereço IP e conseguem enxergar um ao outro através de uma rede virtual.
  • Crescimento Horizontal: Com um simples comando é possível aumentar o número de containers da mesma imagem.
  • Balanceador de Carga: Utiliza load balancer para dividir a carga de requisições recebidas entre os containers.
  • Rollbacks automáticos: Se algo der errado, Kubernetes volta automaticamente a versão anterior da aplicação.
  • Execução em Batch: Permite rodar comandos em batch como containers.
  • Decisões Automáticas: Permite que você especifique quanto de CPU e memória cada container precisa, mas caso necessário, ele pode tomar decisões automáticas referente a gestão desses recursos dos containers.
  • Orquestração de armazenamento: permite que você monte automaticamente um sistema de armazenamento de sua escolha, como armazenamentos locais ou provedores de nuvem pública.

Estrutura do Kubernetes

O Kubernetes coordena um cluster de alta disponibilidade, com máquinas (físicas ou virtuais) que estão conectadas para trabalhar como uma unidade única. Conforme é possível observar na imagem acima, um cluster Kubernetes é composto por um Master e um conjunto de Nodes (ou workers).

O Master é a máquina que controla os nós do Kubernetes. É nela que todas as atribuições de tarefas do cluster se originam. Ela gerencia todas as atividades do cluster, como por exemplo, gerenciar o agendamento de aplicações, manter o estado desejado das aplicações, escalar, efetuar atualizações, etc

O Node — anteriormente conhecido como minion — funciona como um worker dentro do cluster, ou seja, ele recebe ordens do Master e fica responsável pelo funcionamento das aplicações.

Componentes do Kubernetes

O Kubernetes é composto por componentes que são responsáveis por atividades específicas, sendo que alguns desses componentes executam no servidor Master e outros nos Nodes, conforme imagem abaixo:

Componentes que rodam no Master:

  • etcd: é uma base de dados de chave valor (key-value store), altamente disponível, utilizado como armazenamento de apoio do Kubernetes para todos os dados do cluster, como dados de configuração do cluster.
  • API Server: componente que expõe a API do Kubernetes (JSON). Ele é o front-end para o painel de controle do Kubernetes, ele é utilizado para os usuários interagirem com o cluster do Kubernetes.
  • Controller Manager: é o cérebro por trás da orquestração. Ele é responsável por notificar e responder quando nodes, containers ou endpoints estão com alguma falha. Ele monitora os controladores e pode tomar a decisão de criar novos containers em alguns casos.
  • Scheduler: é responsável por distribuir containers em múltiplos Nodes. Ele observa os Pods recém-criados que não têm nenhum nó designado e torna responsável em encontrar o melhor nó para eles serem executados.

Componentes que rodam em cada Node:

  • Kubelet: agente que é executado em cada Node do cluster. Ele se conecta ao Docker e cuida da criação, execução e exclusão de contêineres. Ele é responsável por garantir que o contêiner esteja sendo executado em cada worker conforme o esperado.
  • Container Runtime: é o software responsável pela execução de contêineres. O Kubernetes suporta vários runtimes como o Docker.
  • Kube-Proxy: encaminha o tráfego para os contêineres apropriados com base no endereço IP e no número da porta da solicitação recebida.
Visão geral da Arquitetura e dos Componentes do Kubernetes

Outras ferramentas do Kubernetes:

kubectl: é uma interface de linha de comando (command-line) utilizada para executar comandos no cluster do Kubernetes, como para implantar e gerenciar aplicações no cluster do Kubernetes, consultar informações do cluster ou consultar o status de algum node específico.

minikube: é uma ferramenta usada para configurar uma única instância de Kubernetes em um único setup utilizada para configuração em máquina local.

kubeadm: é uma ferramenta utilizada para configurar o Kubernetes em múltiplos Nodes e que pode ser utilizada para configuração na sua máquina local. Utiliza Virtual Machine para simular essa arquitetura.

O que são PODs?

Ao contrário de outros sistemas que você pode ter usado no passado, o Kubernetes não executa containers diretamente, em vez disso, ele envolve um ou mais containers em uma estrutura de nível mais alto chamada POD. Qualquer container no mesmo POD compartilhará os mesmos recursos e rede local. Os containers podem se comunicar facilmente com outros containers no mesmo agrupamento, como se estivessem na mesma máquina, mantendo um grau de isolamento de outros.

Os PODs são usados ​​como a unidade de replicação no Kubernetes. Se sua aplicação tiver um pico de acessos e uma única instância de um POD não suportar a demanda, o Kubernetes poderá ser configurado para implantar novas réplicas de seu POD no cluster, conforme necessário. Mesmo quando não está sob carga pesada, é padrão ter várias cópias de um POD em execução em um sistema de produção, para permitir o balanceamento de carga e aumentar a sua resistência a falhas.

Os PODs podem conter vários containers, mas você deve se limitar quando possível. Como os PODs são dimensionados para cima e para baixo como uma unidade, todos os containers de um POD devem ser dimensionados juntos, independentemente de suas necessidades individuais. Isso leva a recursos desperdiçados e uma conta cara. Para resolver isso, os PODs devem permanecer o menor possível, geralmente contendo apenas um processo principal e seus containers auxiliares fortemente acoplados.

Os recursos do Kubernetes (como PODs, serviços e deployments) são criados de forma declarativa, fazendo uso de arquivos YAML, dessa forma, você precisa criar um arquivo com a definição e detalhes do seu POD.

Abaixo segue um exemplo de um arquivo pod-definition.yml:

Comando para geração do seu POD:

kubectl create -f pod-definition.yml

Configuração de ReplicaSet

O ReplicaSet é um serviço que garante que um número especificado de réplicas de POD está sendo executado a qualquer momento. Como tal, é frequentemente utilizado para garantir a disponibilidade de um número especificado de Pods idênticos.

Quando uma implantação é adicionada ao cluster, o ReplicaSet aumenta automaticamente o número solicitado de PODs e os monitora. Se um POD “morre”, o ReplicaSet irá recriá-lo automaticamente.

Apesar desse serviço monitorar seus PODs e você não precisar lidar com os PODs manualmente, é recomendável que ao invés de utilizar diretamente o ReplicaSet você utilize o serviço de Deployment, pois ele cria um ReplicaSet a cada execução, simplificando todo o seu processo operacional.

Abaixo segue um exemplo de um arquivo replicaset-definition.yml:

Comando para aplicar a configuração de ReplicaSet nos seus PODs:

kubectl create -f replicaset-definition.yml

Deployment no Kubernetes

Embora os PODs sejam a unidade básica de computação no Kubernetes, eles normalmente não são lançados diretamente em um cluster, como visto no tópico anterior, o ReplicaSet cuida dessa gestão e é criado automaticamente a cada implantação feita da sua aplicação através do Deployment.

Na configuração do Deployment, além das configurações de ReplicaSet, você também precisa definir qual o tipo de implantação que deseja para a sua aplicação: Rolling Update ou Recreate.

  • Recreate: Todos os PODs da sua aplicação são finalizados e na sequencia, novos PODs são criados contendo a nova versão do seu software. Nesse modo você possuí um tempo de down time (indisponibilidade).
  • Rolling Update: É o modo padrão quando não especificado, ele vai finalizando seus PODs um a um e criando novos de forma suave, não ocasionando nenhuma indisponibilidade na sua aplicação.

Abaixo segue um exemplo de um arquivo deployment-definition.yml:

Comando para aplicar sua configuração de Deployment:

kubectl create -f deployment-definition.yml

Comando para aplicar um novo Deployment após sua criação:

kubectl apply -f deployment-definition.yml

Comando para fazer rollback do seu Deployment e voltar a release anterior:

kubectl rollout undo deployment/myapp-deployment

O que é Ingress, NodePort, LoadBalance e ClusterIP?

Usando os conceitos descritos acima, você pode criar um cluster de nós e iniciar implantações de PODs no cluster. Há um último problema a ser resolvido: permitir o tráfego externo para a sua aplicação.

Por padrão, o Kubernetes fornece isolamento entre os PODs e o mundo externo. Se você deseja se comunicar com um serviço em execução em um POD, é necessário abrir um canal para comunicação.

Vamos conhecer abaixo os diferentes tipos de conexões que o Kubernetes fornece para utilização.

Como funciona o ClusterIP

Um ClusterIP service é o serviço Kubernetes padrão, ele oferece um serviço dentro do seu cluster que outros aplicativos que estão dentro dele podem acessar. Nesse serviço não há acesso externo.

Abaixo segue um exemplo de um arquivo clusterIP.yml:

Se você não pode acessar um ClusterIP da Internet, por que estou falando sobre isso? Acontece que você pode acessá-lo usando o proxy:

Comando para aplicar iniciar um Kubernetes Proxy:

kubectl proxy --port=8080

Agora você consegue navegar através da API do Kubernetes e acessar este serviço utilizando o esquema abaixo:

http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/

Utilizando o YML definido anteriormente, a URL ficaria da seguinte forma:

http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/

Existe alguns cenários em que você usaria o Kubernetes Proxy para acessar seus serviços, como para debugar seus serviços, para conectá-los diretamente a sua máquina local (por algum motivo), liberar para tráfego interno (como ferramentas de dashboard), etc.

Como esse método exige que você execute o kubectl como um usuário autenticado, você não deve usá-lo para expor seu serviço à Internet ou para serviços de produção.

Como funciona o NodePort

NodePort service é a maneira mais primitiva de obter tráfego externo diretamente para seu o serviço. Como o nome indica, ele abre uma porta específica em todos os Nós (as VMs) e qualquer tráfego enviado a essa porta é encaminhado para o serviço.

Abaixo segue um exemplo de um arquivo nodePort.yml:

Um serviço NodePort possui duas diferenças em relação ao ClusterIP. Primeiro, o tipo é “NodePort”, segundo que há também uma porta adicional chamada nodePort que especifica qual porta abrir nos nós. Se você não especificar esta porta, ela escolherá uma porta aleatória. Na maioria das vezes, você deve deixar o Kubernetes escolher a porta, pois existem muitas advertências sobre quais portas estão disponíveis para você usar.

Existem algumas desvantagens de utilizar o NodePort:

  • Você só pode ter uma vez serviço por porta.
  • Você só pode usar as portas 30000 a 32767.
  • Se o seu endereço IP do nó / VM for alterado, você precisará gerenciar isso.

Por esses motivos, não recomendo usar esse método na Produção para expor diretamente seu serviço. Se você está executando um serviço que nem sempre precisa estar disponível ou é muito sensível aos custos, esse método pode funcionar para você. Um bom exemplo da utilização desse método seria para um aplicativo de demonstração ou algo temporário.

Como funciona o LoadBalancer

Um LoadBalancer service é a maneira padrão de expor um serviço à Internet. No GKE, isso ativará um Balanceador de Carga de Rede (Network Load Balancer) que fornecerá um único endereço IP que encaminhará todo o tráfego para o seu serviço.

Se você deseja expor diretamente um serviço na internet, este é o método padrão. Todo o tráfego na porta que você especificar será encaminhado para o serviço, não há filtragem, roteamento, etc. Isso significa que você pode enviar quase todo tipo de tráfego para ele, como HTTP, TCP, UDP, gRPC, Websockets ou qualquer outra coisa.

A grande desvantagem é que cada serviço que você expõe com um LoadBalancer terá seu próprio endereço IP e você precisará pagar por um LoadBalancer por serviço exposto, o que pode ficar caro!

Como funciona o Ingress

Ao contrário de todos os exemplos acima, o Ingress não é realmente um tipo de serviço. Em vez disso, fica na frente de vários serviços e atua como um “roteador inteligente” ou ponto de entrada no seu cluster.

Você pode fazer muitas coisas diferentes com um Ingress e existem muitos tipos de controladores do Ingress que possuem recursos diferentes.

O controlador de entrada GKE padrão gerará um HTTP (S) Load Balancer para você. Isso permitirá que você faça o roteamento baseado em caminho e subdomínio para serviços de back-end. Por exemplo, você pode enviar tudo em foo.seudominio.com para o serviço foo e tudo sob o caminho seudominio.com.br/bar/ para o serviço de barras.

O YAML para um objeto Ingress no GKE com um balanceador de carga HTTP L7 pode se parecer com o seguinte:

Abaixo segue um exemplo de um arquivo ingress.yml do GKE, com um balanceador de carga L7 HTTP:

O Ingress é provavelmente a maneira mais poderosa de expor seus serviços, mas também pode ser a mais complicada.

Existem muitos tipos de controladores do Ingress, como do Google Cloud Load Balancer, Nginx, Contour, Istio e muito mais. Também existem plugins para controladores do Ingress, como o gerenciador de certificação, que podem provisionar automaticamente certificados SSL para seus serviços.

O Ingress é o mais útil se você deseja expor vários serviços no mesmo endereço IP e todos serviços utilizando o mesmo protocolo L7 (normalmente HTTP). Você paga apenas por um balanceador de carga se estiver usando a integração nativa do GCP, e como o Ingress é inteligente, você pode obter muitos recursos prontos para uso (como SSL, Auth, Routing etc.)

Caso queira se aprofundar mais:

O que está descrito nesse artigo acima é uma versão super simplificada do Kubernetes, mas deve fornecer os fundamentos necessários para você começar a experimentar (caso queira). Caso você queira mais informações, acesse a documentação oficial do Kubernetes:

https://kubernetes.io/docs/tutorials/kubernetes-basics/

https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0

--

--