Anatomia de contêineres 101: O que é um cluster?
Do ponto de vista da rede, os contêineres estendem a “borda” da rede — o limite entre as decisões de encaminhamento de rede e um pacote chegando ao destino final — até o host. A borda não é mais a interface de rede de um host, mas sim várias camadas profundas em construções lógicas dentro de um host. E a topologia da rede é abstraída e se aprofunda nessas construções lógicas dentro de um host, na forma de tunelamento de rede sobreposto, interfaces virtuais, limites de NAT, balanceadores de carga e plug-ins de rede. Os arquitetos de rede e segurança não podem mais ignorar os componentes internos do sistema operacional ao projetar suas arquiteturas. Os contêineres forçam essas arquiteturas a entender para onde um pacote vai depois de passar pela NIC do host.
Sistemas de orquestração
Dito isso, é necessário um sistema de orquestração para colocar alguma forma de ordem nos ambientes de contêineres. Um sistema de orquestração gerencia os detalhes da organização, escalabilidade e automação de contêineres e cria construções lógicas em torno de vários componentes que são relevantes para o comportamento do contêiner. Eles também são responsáveis por organizar os limites lógicos associados aos tempos de execução do contêiner e criar construções lógicas que podem ser atribuídas a um endereço IP. Dito isso, esses sistemas são externos e não podem realmente implantar e gerenciar o ciclo de vida de instâncias de tempo de execução de contêineres específicos, que ainda são gerenciados pelo Docker, por exemplo.
Existem muitos sistemas de orquestração de contêineres, mas os dois mais usados atualmente são Kubernetes e OpenShift. Ambos atingem os mesmos objetivos básicos, com a principal diferença de que um é um projeto e o outro é um produto: o Kubernetes é um projeto nascido em grande parte do Google e o OpenShift é um produto de propriedade da Red Hat. De um modo geral, o Kubernetes é visto com mais frequência em ambientes de nuvem pública e o OpenShift é mais frequentemente visto em data centers locais, mas há uma sobreposição significativa entre os dois. Resumindo, o Kubernetes é a base de ambas as abordagens, com uma pequena diferença na terminologia entre cada uma.
Uma breve história dos contêineres
Acredite ou não, os contêineres são anteriores ao Kubernetes. A Docker, por exemplo, lançou sua plataforma de contêineres pela primeira vez em 2013, enquanto a Kubernetes não lançou seu projeto focado na nuvem pública até 2014. O OpenShift foi lançado antes de ambos, com foco em hosts implantados em data centers locais.
A simples implantação de tempos de execução de contêineres em um host local geralmente atende às necessidades dos desenvolvedores, já que os tempos de execução podem se comunicar entre si por meio de “localhost” e portas exclusivas. Os tempos de execução do contêiner não recebem endereços IP específicos. Se você está focado em escrever código rápido e eficiente e implantar seu aplicativo em uma coleção de tempos de execução de contêineres associados, essa abordagem funciona bem. Mas se você quiser que esse aplicativo acesse recursos externos fora do host local, ou se quiser que clientes externos acessem esse aplicativo, você não pode ignorar os detalhes da rede. Essa é uma das razões pelas quais um sistema de orquestração é necessário.
O Kubernetes foi criado com base em um conjunto de blocos de construção e um fluxo de trabalho orientado por API para organizar o comportamento dos tempos de execução dos contêineres. Nessa abordagem, o Kubernetes cria uma série de construções lógicas dentro e entre hosts associadas a um ambiente contêiner específico e cria um conjunto totalmente novo de vocabulário para se referir a essas construções. Embora o Kubernetes aplique esses blocos de construção e fluxos de trabalho orientados por API em torno de um conjunto de métricas de computação associadas à alocação de CPU, requisitos de memória e outras métricas, como armazenamento, autenticação e medição, a maioria dos profissionais de segurança e rede está focada em uma coisa:
Por quais limites um pacote IP passa quando está a caminho de alguma construção lógica à qual é atribuído um endereço IP?
Do ponto de vista da rede, tanto o Kubernetes quanto o OpenShift criam construções lógicas e relevantes em uma abordagem hierárquica, com apenas uma pequena diferença de vocabulário entre cada sistema. Isso é ilustrado abaixo.

O ABC de um cluster de contêineres
Esse diagrama mostra a construção lógica básica de um ambiente Kubernetes. Não explica o que cada construção faz, mas apenas como elas se relacionam logicamente umas com as outras.
Começando da construção mais ampla até a menor, aqui estão algumas explicações rápidas:
- Cluster: um cluster é a coleção de hosts associados a uma implantação específica em contêineres.
- Nodos: Dentro de um cluster, existem nós. Um nó é o host no qual os contêineres residem. Um host pode ser um computador físico ou uma VM e pode residir em um data center local ou em uma nuvem pública. Geralmente, há duas categorias de nós em um cluster: os “nós principais” e os “nós de trabalho”. Para simplificar demais as coisas, um nó principal é o plano de controle que fornece o banco de dados central do cluster e do servidor de API. Os nós de trabalho são as máquinas que executam os pods de aplicativos reais.
- Vagens: Dentro de cada nó, tanto o Kubernetes quanto o OpenShift criam pods. Cada pod engloba um ou mais tempos de execução do contêiner e é gerenciado pelo sistema de orquestração. Os pods recebem endereços IP pelo Kubernetes e pelo OpenShift.
- Contêiner: Dentro dos pods, é onde residem os tempos de execução do contêiner. Todos os contêineres dentro de um determinado pod compartilham o mesmo endereço IP desse pod e se comunicam entre si pelo Localhost, usando portas exclusivas.
- Namespace: um determinado aplicativo é implantado “horizontalmente” em vários nós em um cluster e define um limite lógico para alocar recursos e permissões. Pods (e, portanto, contêineres) e serviços, mas também funções, segredos e muitas outras construções lógicas pertencem a um namespace. O OpenShift chama isso de projeto, mas é o mesmo conceito. De um modo geral, um namespace é mapeado para um aplicativo específico, que é implantado em todos os contêineres associados dentro dele. Um namespace não tem nada a ver com uma construção de rede e segurança (diferente de um namespace IP Linux)
- Serviço: Como os pods podem ser efêmeros — eles podem desaparecer repentinamente e depois ser reimplantados dinamicamente — um serviço é um “front-end”, implantado na frente de um conjunto de pods associados e funciona como um balanceador de carga com um VIP que não desaparece se um pod desaparecer. Um serviço é uma construção lógica não efêmera, com seu próprio endereço IP. Com apenas algumas exceções no Kubernetes e no OpenShift, as conexões externas apontam para o endereço IP de um serviço e são encaminhadas para pods de “backend”.
- Servidor de API Kubernetes: É aqui que o fluxo de trabalho da API é centralizado, com o Kubernetes gerenciando a criação e o ciclo de vida de todas essas construções lógicas.
Desafios de segurança com contêineres
Para criar segmentos de segurança ao longo dos limites da carga de trabalho, é necessário entender essas construções lógicas básicas criadas pelo Kubernetes. O tráfego de rede externa que entra e sai do aplicativo hospedado geralmente não aponta para o endereço IP do host subjacente, o nó. Em vez disso, o tráfego da rede apontará para um serviço ou um pod dentro desse host. Portanto, os serviços e pods associados a uma carga de trabalho precisam ser suficientemente compreendidos para criar um arquitetura de segurança de segmentação eficaz.
Interessado em mais? Confira nosso artigo sobre os desafios das abordagens baseadas em rede para segmentação de contêineres e como superá-los usando a segmentação baseada em host.