BT

O Efeito Kubernetes

| por Bilgin Ibryam Seguir 5 Seguidores , traduzido por Marcelo Costa Seguir 39 Seguidores em 30 ago 2018. Tempo estimado de leitura: 16 minutos |

Pontos Principais

  • A forma como devemos olhar para o Kubernetes é mais como um paradigma fundamental que tem implicações em múltiplas dimensões, que uma API para interação.
  • O Kubernetes adiciona uma dimensão completamente nova às linguagens baseadas em blocos de construção, oferecendo um novo conjunto de primitivas distribuídas e tempo de execução para criar sistemas distribuídos que se espalham por vários processos e nós.
  • Os princípios fundamentais para a criação de aplicativos em container usam a imagem do container como a primitiva básica e a plataforma de orquestração do container como o ambiente de tempo de execução alvo. Os princípios incluem preocupação única, autocontenção, imutabilidade da imagem, alta observabilidade, conformidade com o ciclo de vida, descartabilidade do processo e confinamento em tempo de execução.
  • Padrões de design de container estão focados na sua estruturação e outras primitivas distribuídas da melhor maneira possível para resolver os desafios em questão. Os padrões incluem sidecar, ambassador, adapter, initializer, work queue, custom controller e self awareness.
  • As práticas recomendadas para containers estão relacionadas ao tamanho da imagem, à especificação da porta, ao uso do volume, aos metadados da imagem e muito mais.

O Kubernetes (k8s) percorreu um longo caminho em muito pouco tempo. Apenas dois anos atrás, ele teve que competir e provar ser melhor do que as soluções Fleet, Docker Swarm, Cloud Foundry Diego, Nomad, Kontena, Rancher's Cattle, Apache Mesos, Amazon ECS, etc.

Hoje temos um cenário completamente diferente. Alguns desses projetos anunciaram abertamente sua descontinuação em favor de unir esforços com o Kubernetes, outros não aceitaram a derrota de forma aberta e taticamente anunciaram suporte parcial ou uma integração completa e paralela com o Kubernetes, o que significou uma morte silenciosa e lenta para o seus orquestradores de containers. . Em ambos os casos, o k8s é a última plataforma de pé.

Além disso, cada vez mais, grandes nomes continuaram se juntando ao ecossistema Kubernetes, não apenas como usuários ou patrocinadores platinum, mas apostando totalmente em seus negócios de containers sobre o sucesso do Kubernetes. O Kubernetes Engine da Google, o OpenShift da Red Hat, o Azure Container Service da Microsoft, o Cloud Container Service da IBM, o Container Engine da Oracle e outros são os primeiros a serem lembrados aqui.

Mas o que tudo isso significa? Primeiro, significa que os desenvolvedores precisam dominar uma única plataforma para a orquestração de containers para ser relevante a 90% do mercado de trabalho relacionado à containers. Um bom motivo para investir tempo para aprender bem o k8s. Isso também significa que estamos todos mergulhados até o joelho em k8s.

O Kubernetes é como a Amazon, mas, para os containers, se não quiser ficar preso a apenas um fornecedor, inevitavelmente optará por Kubernetes. Projetando, implementando e executando aplicativos no Kubernetes, você tem a liberdade de mover seus aplicativos entre os diferentes provedores de nuvem, distribuições do kubernetes e provedores de serviços.

O Kubernetes também provê a oportunidade de encontrar desenvolvedores certificados em Kubernetes para iniciar um projeto e apoiar o seu pessoal para continuar a executá-lo depois. Não é a VM, não é a JVM, é o Kubernetes que é a nova camada de portabilidade da aplicação. É o denominador comum entre tudo e todos.

Mergulhando no Kubernetes

A seguir temos um diagrama de um serviço em container demonstrando o quanto ele depende do Kubernetes.

[Clique para ampliar]

Figura 1 - Dependência de uma aplicação no Kubernetes

Observe que não escrevemos que o Kubernetes é uma API de portabilidade entre aplicações, e sim uma camada. O diagrama apresenta apenas os objetos K8 que temos que criar explicitamente - que podemos chama-los de API k8s. Mas, na realidade, estamos muito mais ligados à plataforma. Os K8s oferecem um conjunto completo de primitivas distribuídos (como pods, serviços, controladores) que atendem aos requisitos e orientam o design de nossas aplicações. Essas novas primitivas e os recursos da plataforma ditam os princípios de design e os padrões de design que usamos para implementar todos os serviços futuros. Eles, por sua vez, afetam as técnicas que utilizaremos para enfrentar os desafios cotidianos e inclusive podem afetar o que chamamos de "melhor prática". Portanto, a maneira como devemos olhar para o Kubernetes é mais como um paradigma fundamental que tem implicações em múltiplas dimensões, ao invés de apenas uma API.

O efeito Kubernetes

O container e os recursos do orquestrador fornecem um novo conjunto de abstrações e primitivas. Para obter o melhor valor dessas novas primitivas e equilibrar suas forças, precisamos de um novo conjunto de princípios de design que nos guie. Posteriormente, quanto mais usarmos essas novas primitivas, mais acabaremos resolvendo problemas repetitivos e reinventando a roda.

É aqui que os padrões entram em cena. Padrões de projeto nos fornecem receitas sobre como estruturar as novas primitivas para resolver problemas repetidos mais rapidamente. Embora os princípios sejam mais abstratos, mais fundamentais e mudem com menos frequência, os padrões podem ser afetados por uma mudança no comportamento primitivo. Um novo recurso na plataforma pode tornar o padrão um antipadrão ou menos relevante. Então, também existem práticas e técnicas que usamos diariamente. As técnicas vão desde pequenos truques técnicos para realizar uma tarefa de maneira mais eficiente, até formas mais extensas de trabalho e práticas. Nós mudamos as técnicas e práticas assim que encontramos uma maneira um pouco melhor de fazer as coisas, mais fácil e mais rápido. É assim que nós e a plataforma evoluímos. E por que fazemos tudo isso? É aí que obtemos os benefícios e os valores de usar essa nova plataforma e satisfazer nossas necessidades. Em certo sentido, "O Efeito Kubernetes" é auto-imposto e multifacetado:

Figura 2: O efeito Kubernetes no ciclo de desenvolvimento de software

Para o restante deste artigo, vamos nos aprofundar e ver exemplos de cada categoria.

Abstrações e Primitivas Distribuídos

Para explicar o que quero dizer com novas abstrações e primitivas, vou compará-las com o conhecido mundo orientado a objetos e Java especificamente. No universo da OOP, temos conceitos como classe, objeto, pacote, herança, encapsulamento, polimorfismo, etc. Então, o Java runtime fornece certos recursos e garantias sobre como ele gerencia o ciclo de vida de nossos objetos e a aplicação como um todo. A linguagem Java e o tempo de execução da JVM fornecem blocos de construção locais em processo para criar aplicações. O Kubernetes adiciona uma dimensão completamente nova a essa mentalidade bem conhecida, oferecendo um novo conjunto de primitivas distribuídas e tempo de execução para criar sistemas distribuídos que se espalham por vários processos e nós. Com o Kubernetes em mãos, não confio apenas nas primitivas Java para implementar todo o comportamento do aplicativo. Eu ainda preciso usar os blocos de construção orientados a objeto para criar os componentes do aplicativo distribuído, mas também posso usar primitivas do Kubernetes para alguns dos comportamentos do aplicativo. Alguns exemplos de abstrações e primitivas distribuídas do Kubernetes são:

  • Pod - a unidade de implementação de uma coleção relacionada de contêineres.
  • Service - serviço e primitiva para balanceamento de carga.
  • Job - uma unidade atômica de trabalho programada de forma assíncrona.
  • CronJob - uma unidade atômica de trabalho agendada em um horário específico no futuro ou periodicamente.
  • ConfigMap - um mecanismo para distribuir dados de configuração entre instâncias de serviço.
  • Secret - um mecanismo para gerenciamento configuração de de dados sensíveis.
  • Deployment - um mecanismo de lançamento de aplicações declarativas.
  • Namespace - uma unidade de controle para isolar pools de recursos.

Por exemplo, posso confiar nas verificações de integridade do Kubernetes (por exemplo, testes de prontidão e de vivacidade) para alguma confiabilidade do meu aplicativo. Eu posso usar o Kubernetes Services para a descoberta de serviço em vez de fazer a descoberta de serviço do lado do cliente a partir do aplicativo. Posso usar o Kubernetes Jobs para agendar uma unidade de trabalho atômica assíncrona. Eu posso usar o ConfigMap para o gerenciamento de configuração e o Kubernetes CronJob para agendamento de tarefas periódicas, em vez de usar a biblioteca Quartz baseada em Java ou uma implementação da interface ExecutorService.

Figura 3: Primitivos locais e distribuídos como parte de um sistema distribuído

As primitivas em processo e as primitivas distribuídas têm semelhanças, mas não são diretamente comparáveis e substituíveis. Eles operam em diferentes níveis de abstração e têm condições e garantias diferentes. Algumas primitivas devem ser usadas juntas. Por exemplo, ainda precisamos usar classes para criar objetos e colocá-los em imagens de container. Mas algumas outras primitivas, como o CronJob no Kubernetes, podem substituir completamente o comportamento do ExecutorService em Java. Aqui estão alguns conceitos que eu encontrei em comum entre a JVM e o Kubernetes, mas não leve isso longe demais.

Figura 4: Categorização de primitivas local e distribuída

Eu já escrevi sobre abstrações distribuídas e primitivas no passado aqui. O ponto neste artigo é que, como desenvolvedor, você pode usar um conjunto mais rico de primitivas locais e globais para projetar e implementar uma solução distribuída. Com o tempo, essas novas primitivas dão origem a novas maneiras de resolver problemas, e algumas dessas soluções repetitivas se tornam padrões. É isso que vamos explorar a seguir.

Container Design Principles

Princípios para design de container

Princípios de design são regras fundamentais e diretrizes abstratas para escrever software de qualidade. Os princípios não especificam regras concretas, mas representam uma linguagem e a sabedoria comum que muitos desenvolvedores entendem e usam como referência regularmente. Da mesma forma que os princípios do SOLID introduzidos por Robert C. Martin, que representam diretrizes para escrever um software melhor orientado a objetos, também existem princípios de design para criar aplicativos melhor conteinerizados. Os princípios do SOLID usam primitivas orientadas a objeto e conceitos como classes, interfaces e herança para raciocinar sobre projetos orientados a objetos. De maneira semelhante, os princípios para criar aplicativos em container listados abaixo usam a imagem do container como a primitiva básica e a plataforma de orquestração do container como o ambiente de tempo de execução do container de destino. Os princípios para o design de aplicativo baseado em container são os seguintes:

Tempo de construção

  • Princípio de preocupação única - cada container deve abordar uma única preocupação e executá-la bem.
  • Princípio de autocontenção - um container deve se basear somente na presença do kernel do Linux e ter quaisquer outras bibliotecas adicionadas a ele no momento em que o container é construído.
  • Princípio da imutabilidade da imagem - as aplicações conteinerizadas são imutáveis e, uma vez construídas, não se espera que mudem entre diferentes ambientes.

Tempo de execução

  • Princípio da Alta Observabilidade - cada container deve implementar todas as APIs necessárias para ajudar a plataforma a observar e gerenciar o aplicativo da melhor maneira possível.
  • Princípio de Conformidade do Ciclo de Vida - um container deve ter uma maneira de ler os eventos vindos da plataforma e adaptar-se a esses eventos.
  • Princípio da Descartabilidade do Processo - aplicações em containers precisam ser tão efêmeras quanto possível e prontas para serem substituídas por outra instância de container em qualquer ponto no tempo.
  • Princípio de Confinamento do Tempo de Execução - cada container deve declarar seus requisitos de recursos e também é importante que o aplicativo permaneça confinado aos requisitos de recursos indicados.

Seguindo esses princípios, é mais provável que criemos aplicações em container que sejam mais adequados para plataformas nativas em nuvem, como o Kubernetes.

[Clique para ampliar]

Figura 5: Princípios para design de containers

Estes princípios estão bem documentados e disponíveis gratuitamente para download como um white paper. Uma antevisão dos princípios é descrita na Figura 5 acima.

Padrões para design de containers

As novas primitivas precisam de novos princípios que expliquem as forças entre elas. Quanto mais usamos as primitivas, mais acabamos resolvendo problemas repetitivos que nos levam a reconhecer soluções repetidas chamadas padrões. Padrões de design para container estão focados na estruturação dos containers e outras primitivas distribuídas da melhor maneira possível para resolver os desafios em questão. Uma pequena lista de padrões de design relacionados à containers é a seguinte:

  • O padrão Sidecar - um container de sidecar estende e aprimora a funcionalidade de um container pré-existente sem alterá-lo.
  • O padrão Ambassador - esse padrão oculta a complexidade e fornece uma visão unificada do mundo para o seu container.
  • O padrão Adapter - um adapter é uma espécie de Ambassador reverso e fornece uma interface unificada para um pod do mundo exterior.
  • O padrão Initialize - os containers de inicialização permitem a separação das tarefas relacionadas à inicialização da lógica principal do aplicativo.
  • O padrão de Fila de Trabalho (Queue Pattern) - um padrão de fila de trabalho genérico baseado em containers permite aceitar código de processamento arbitrário empacotado como um container e dados arbitrários e construir um sistema de fila de trabalho completo.
  • O padrão de controlador personalizado - com esse padrão, um controlador procura alterações nos objetos e age nessas alterações para conduzir o cluster a um estado desejado. Esse padrão de reconciliação pode ser usado para implementar a lógica personalizada e estender a funcionalidade da plataforma.
  • Padrão de auto-conhecimento - descreve ocasiões em que um aplicativo precisa analisar e obter metadados sobre si mesmo e o ambiente em que está sendo executado.

O trabalho de base nesta área foi realizado por Brendan Burns e David Oppenheimer em seu artigo sobre padrões de design de container. Desde então, Brendan publicou um livro que também cobre os padrões de design e tópicos relacionados a sistemas distribuídos. Roland Huß e eu também estamos escrevendo um livro intitulado Kubernetes Patterns cobrindo todos esses padrões de design e casos de uso para aplicativos baseados em containers. A seguir estão alguns desses padrões visualizados.

[Clique para ampliar]

Figura 6: Padrões para design de containers

Os primitivos precisam de princípios e padrões de maquiagem. Vejamos também algumas das melhores práticas e benefícios gerais do uso do Kubernetes.

Práticas / Técnicas

Além dos princípios e padrões, a criação de boas aplicações em container exige familiaridade com outras práticas recomendadas e técnicas relacionadas à containers. Princípios e padrões são idéias abstratas e fundamentais que mudam com menos frequência. As melhores práticas e as técnicas relacionadas são mais concretas e podem mudar com mais frequência. Aqui estão algumas das práticas comuns recomendadas relacionadas à containers:

  • Apontar para imagens pequenas - isso reduz o tamanho do container, o tempo de construção e o tempo de rede ao copiar as imagens do container.
  • Suportar IDs de usuários arbitrários - evite usar o comando sudo ou exigir um ID de usuário específico para executar seu container.
  • Marque portas importantes - especificar portas usando o comando EXPOSE facilita o uso da imagem para humanos e software.
  • Use volumes para dados persistentes - os dados que precisam ser preservados depois que um container é destruído devem ser gravados em um volume.
  • Defina metadados de imagem - os metadados de imagem na forma de tags, rótulos e anotações tornam as imagens do seu container mais detectáveis.
  • Sincronize o host e a imagem - algumas aplicações em container exigem que o container seja sincronizado com o host em determinados atributos, como horário e ID de máquina.
  • Registre os logs em STDOUT e STDERR - o registro em log nesses fluxos de sistema, e não em um arquivo, garantirá que os logs de um container sejam coletados e agregados adequadamente.

A seguir, estão alguns links de leituras recomendadas relacionadas às melhores práticas para o uso de containers:

Os benefícios do Kubernetes

Como você pode ver neste artigo, o Kubernetes dita as operações de design, desenvolvimento e operações de 2o. dia para sistemas distribuídos de maneira fundamental. A curva de aprendizado também não é curta e atravessar o abismo do Kubernetes requer tempo e paciência. Por isso, gostaria de terminar com uma lista de benefícios que o Kubernetes traz aos desenvolvedores. Espero que isso ajude a justificar por que vale a pena entrar no Kubernetes e usá-lo para orientar sua estratégia de TI.

  • Ambientes de autoatendimento - permitem que equipes e integrantes da equipe criem instantaneamente ambientes isolados do cluster para propósitos de CI/CD e experimentação.
  • Aplicativos alocados dinamicamente - permitem que as aplicações sejam alocadas no cluster de maneira previsível, com base nas demandas de aplicações, recursos disponíveis e políticas de orientação.
  • Declarative Service Deployments - essa abstração encapsula o processo de upgrade e reversão de um grupo de containers e torna a execução de uma atividade repetível e automatizável.

Figura 7: Exemplos de estratégias para deployment e lançamento com Kubernetes

  • Resiliência de aplicação - os containers e as plataformas de gerenciamento melhoram a resiliência da aplicação de várias formas, como por exemplo:
  • Loops infinitos: compartilhamentos de CPU e cotas
  • Vazamentos de memória: OOM dele mesmo
  • Hogs em disco: cotas
  • Fork bombs: limites de processo
  • Circuit breaker, timeout, retentativas como sidecar
  • Failover e service discovery como sidecar
  • Processo bulkheading com contêineres
  • Hardware bulkheading através de um agendador
  • Auto-scaling / self-healing
  • Service Discovery / Balanceamento de Carga / Circuit Breaker - a plataforma permite que os serviços descubram e consumam outros serviços sem fazer uso dos agentes de aplicações. Além disso, o uso de containers e ferramentas sidecar, como a do framework Istio, permitem mover completamente as responsabilidades relacionadas à rede de fora da aplicação para o nível de plataforma.
  • Topologia declarativa de aplicação - o uso de objetos API do Kubernetes nos permite descrever como nossos serviços devem ser implantados, sua dependência de outros serviços e pré-requisitos de recursos. E ter todas essas informações em um formato executável nos permite testar os aspectos de implantação do aplicativo no estágio inicial do desenvolvimento e tratá-lo como uma infraestrutura de aplicação programável.

[Clique para ampliar]

Figura 8: Topologia de aplicação declarativa utilizando arquivos de descrição Kubernetes

Recursos

Espero ter conseguido descrever como vejo o Kubernetes afetando o dia a dia dos desenvolvedores. Se você quiser ler mais sobre este tópico, ou seja, o Kubernetes do ponto de vista de um desenvolvedor, confira meu livro e siga-me no twitter em @bibryam.

A seguir, estão alguns links para recursos que focam em Kubernetes do ponto de vista de um desenvolvedor:

Sobre o Autor

Bilgin Ibryam(@bibryam) é arquiteto chefe na Red Hat, committer e membro da ASF. Ele é um evangelista de código aberto, blogueiro e autor de livros de Padrões de Design para o Camel e o Kubernetes. Em seu trabalho do dia-a-dia, Bilgin gosta de orientar, codificar e liderar desenvolvedores para obter sucesso com a criação de soluções nativas em cloud. Seu trabalho atual concentra-se em integração de aplicativos, sistemas distribuídos, mensageria, microservices, devops e desafios em cloud nativo em geral. Você pode encontrá-lo no Twitter, no Linkedin ou no Blog dele.

Avalie esse artigo

Relevância
Estilo/Redação

Olá visitante

Você precisa cadastrar-se no InfoQ Brasil ou para enviar comentários. Há muitas vantagens em se cadastrar.

Obtenha o máximo da experiência do InfoQ Brasil.

Dê sua opinião

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão
Comentários da comunidade

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

HTML é permitido: a,b,br,blockquote,i,li,pre,u,ul,p

Receber mensagens dessa discussão

Dê sua opinião

Faça seu login para melhorar sua experiência com o InfoQ e ter acesso a funcionalidades exclusivas


Esqueci minha senha

Follow

Siga seus tópicos e editores favoritos

Acompanhe e seja notificados sobre as mais importantes novidades do mundo do desenvolvimento de software.

Like

Mais interação, mais personalização

Crie seu próprio feed de novidades escolhendo os tópicos e pessoas que você gostaria de acompanhar.

Notifications

Fique por dentro das novidades!

Configure as notificações e acompanhe as novidades relacionada a tópicos, conteúdos e pessoas de seu interesse

BT