Este é o terceiro artigo da série sobre Kubernetes e hoje falaremos sobre outro conceito fundamental para que seja possível ao Kubernetes realizar a orquestração dos containers – Pods. Se você está chegando agora para a acompanhar a série, antes de seguir com a leitura deste texto, recomendo fortemente (por uma questão de continuidade e alinhamento de conceitos) efetuar a leitura dos dois primeiros conteúdos (links disponíveis a seguir). Eles trazem visões conceituais e práticas que fazem parte da base não apenas para o conteúdo deste texto como de outros no futuro também.
- Post #1 – Visão geral sobre o Kubernetes
- Post #2 – O conceito de Deployment
Um pouco de contexto
Ao ser confrontado com conceitos sobre ambientes virtualizados, uma das primeiras coisas que você descobre é que, em termos práticos, uma máquina virtual nada mais é do que uma abstração (outros chamam de emulação) criada sobre o hardware e sistema operacional do servidor. Tal processo é feito para que, dentre tantas outras coisas, se consiga uma melhor utilização dos recursos computacionais (processamento, memória, storage, etc.) do servidor e também, para que seja possível ter ambientes 100% isolados uns dos outros em um mesmo appliance físico. Neste modelo, os recursos computacionais são gerenciados por um elemento fundamental em todo o processo – o hypervisor.
O modelo de evolução mais aceito (e utilizado) até hoje em relação aquele trazido pelas máquinas virtuais é, sem dúvidas, o dos containers. A ideia aqui é que seja possível criar (utilizando uma nova engine de “containerização” especializada e mais leve) pequenos ambientes (os ditos containers) sendo executados no topo de alguma máquina virtual. “Mas, em que isso difere de uma máquina virtual?”, você deve estar pensando. Para que esta “leveza” estrutural seja possível, deverá existir a dependência explícita do sistema operacional (SO) guest da máquina host e assim, todas as aplicações utilizam as chamadas do mesmo SO e portanto, são dependentes dele. Dessa forma, diferentemente das máquinas virtuais onde as instâncias de máquinas são 100% isoladas umas das outras, com containers você possui isolamento apenas de aplicações finais. Aqui o hypervisor visto anteriormente dá lugar para um novo ator – a engine de containerização. A mais famosa? Docker engine. A Figura 1 a seguir apresenta esta diferença entre abordagens de maneira visual.
Figura 1. Diferenças entre máquinas virtuais e containers
Descobriu-se após isso que, ao invés de colocar containers para serem executados apenas em uma máquina host, seria possível (desde que houvesse algum mecanismo de gerenciamento) colocar estes mesmos containers para serem executados em um ambiente tradicional de cluster, isto é, com várias máquinas cooperando entre sí para entregar alta disponibilidade e performance para as aplicações. Grande ideia, não?! É aí que entram os orquestradores (neste caso, Kubernetes) e seus recursos específicos.
Mas o que isso tudo tem a ver com Kubernetes e seus Pods?
Pense por um minuto em como seria o processo de distribuir processamento, memória RAM, tráfego de rede e armazenamento entre os n containers em um host versus em um cluster. Não é muito complicado inferir que, em um único host, o próprio engine de containerização (como Docker, por exemplo), provavelmente fará a distribuição dos recursos locais de maneira simples e direta, dado que todos os elementos estão no mesmo ambiente. Mas, e em relação a um cluster, como ficaria, dado que são várias máquinas físicas ou virtuais fornecendo os recursos para os containers? Como o engine de containerização está rodando localmente em cada nó, o que certamente irá ocorrer é que, no momento em que um dado container for alocado pra rodar em um destes ditos nós, ele utilizará recursos do nó e não do cluster como um todo. Este comportamento poderia gerar um cluster “desbalanceado” em termos de utilização de recursos, com um dado nó sendo bem mais utilizado que seus semelhantes, certo?
É aqui que entram os Pods no contexto do Kubernetes.
O que é um Pod?
Em termos conceituais, um Pod é uma unidade lógica de agrupamento de containers de mesma natureza operacional. Por exemplo, se um container A tem uma relação estrita com um container B (digamos, compartilham uma mesma unidade de storage, por exemplo) provavelmente eles poderiam (ou melhor, deveriam) ser alocados no mesmo Pod. Na visão do cluster Kubernetes, um Pod nada mais é do que um processo em execução. Outra informação importante em relação aos Pods é que, cada Pod possui um endereço de IP único. Essa é outra característica que mostra a ideia de agrupamento de containers semelhantes. A Figura 2 dá uma ideia de como os Pods são distribuídos em um cluster Kubernetes.
Figura 2. Cluster Kubernetes com containers distribuídos entre os nós
No artigo anterior, quando falamos sobre “Deployments”, cheguei a mencionar em algum momento que uma das tarefas que o agente de deploy executa em seu pipeline é a de criar o Pod e fazer o dispatch do(s) container(s) dentro dele. Se você analisar o log de saída ou mesmo a interface de administração do Kubernetes, poderá visualizar que, para nossa aplicação exemplo (criada e publicada no artigo anterior também), ao realizar o deployment, um novo Pod foi criado automaticamente e em seu interior encontra-se nosso container. A Figura 3 apresenta esta visualização.
Figura 3. Visualizando as informações do Pod criado junto com o deployment da aplicação exemplo
Na Figura 3 você pode visualizar todos os detalhes de nosso Pod, incluindo qual container está sendo executado em seu interior, o IP que dinamicamente foi atribuído a ele, a imagem base do container em execução e também o nome do Pod, também automaticamente atribuído pelo processo de deployment. Se você clicar na opção “View logs” na seção que contém as informações do(s) container(s) dentro do Pod, você verá todos os logs registrados pelo container.
Observação: para visualizar o portal de administração do Kubernetes localmente, com o Minikube já iniciado (obviamente), execute o comando “minikube dashboard"
.
Pods com múltiplos containers
No exemplo apresentado pela Figura 3, você pode observar que a Pod “kubernetes-frontend-1427058349-0zvpj” possui apenas um container sendo executado em seu contexto, entretanto, como já mencionamos anteriormente, as Pods foram projetadas para suportar um ou múltiplos containers relacionados em seu interior. Isso porque elas possuem mecanismos nativos de processos cooperativos que juntos, formam uma robusta unidade operacional.
O que você pode estar pensando a esta altura é: “Ok, entendi o conceito de múltiplos containers na mesma Pod, entretanto, não estou conseguindo pensar em situações práticas. Tem como apresentar um exemplo real em que isso ocorreria?”. Justo. Considere o cenário típico de uma aplicação “produtor” e “consumidor”, conforme ilustra a Figura 4.
Figura 4. Cenário de produtor e consumidor
Enquanto temos um serviço (que roda em um container) chamado “File Puller” que recebe determinada mídia e a coloca em uma unidade temporária de armazenamento, temos outro “Web Server” (que também roda em um container) que “olha” para a mesma unidade temporária de armazenamento para obter os arquivos já gravados e submeter os mesmos para um processo de encoding e publicação para os usuários finais. Os containers que rodam estes dois serviços são dependentes da mesma estrutura de armazenamento temporária e portanto, devem ser agrupados na mesma Pod.
Em uma determindada Pod, os containers podem compartilhar basicamente dois recursos: armazenamento e rede. Memória e processamento são automaticamente distribuídos pelo Kubernetes. Além disso, para que n containers possam rodar na mesma Pod, você precisará manualmente os atrelar estes à Pod. O processo mais comumente utilizado para isso são os arquivos YAML, conforme ilustra a Listagem 1.
Listagem 1. YAML com dois containers (Nginx e Debian) compartilhando o mesmo storage no mesmo Pod
No exemplo acima, temos dois containers (um com Nginx e outro com uma imagem Debian padrão) compartilhando o mesmo volume de disco (nomeado aqui como “shared-data”). Os containers estão realizando a montagem em dois pontos distintos no mesmo volume. Neste caso, se estes dois containers precisassem comunicar-se entre si, eles poderiam simplesmente utilizar o DNS name “localhost” para isso, uma vez que estão sob o mesmo IP.
Aspectos importantes sobre Pods
Muito embora as Pods sejam elementos vitais para que o Kubernetes consiga realizar a orquestão de containers de maneira efetiva, elas são elementos efêmeros, projetados para serem criados e removidos com bastante facilidade. Dessa forma, quando uma Pod é criada pelo controller do Kubernetes, ela necessariamente será alocada para um nó saudável do cluster. Ela viverá neste nó até que:
- O ciclo de vida do processo termine (os containers que lá existiam simplesmente não existem mais);
- A Pod por algum motivo é removida;
- O nó não possua mais recursos para executar os containers da Pod;
- O nó por algum motivo não está mais disponível;
Outro importante aspecto sobre as Pods é que elas não tem o poder de serem auto-regeneráveis. Isso quer dizer que, se por algum motivo determinada Pod é corrompida, tem seu processo de deployment com falha ou ainda, se ela teve algum erro gerado em tempo de execução, esta Pod é removida imediatamente pelo controller do Kubernetes. Uma nova instância precisará ser criada em algum nó “saudável” para atender os novos containers.
É isso. Até a próxima!
Facebook
Twitter
Instagram
LinkedIn
RSS