O que é Kubernetes?

Introdução

O Kubernetes é um sistema poderoso de código aberto, desenvolvido inicialmente pelo Google e suportado pela Cloud Native Computing Foundation (CNCF), para gerenciar aplicações em containers em um ambiente de cluster. Seu objetivo é fornecer melhores maneiras de gerenciar componentes e serviços distribuídos relacionados em infraestruturas variadas. Para saber mais sobre o Kubernetes, explore o guia abaixo. Se você está procurando por um serviço de hospedagem Kubernetes gerenciado, confira nosso serviço Kubernetes gerenciado e simples, construído para crescimento.

Neste guia, discutiremos o que é o Kubernetes, alguns dos conceitos básicos do Kubernetes. Falaremos sobre a arquitetura do sistema, os problemas que ele resolve e o modelo que ele usa para lidar com implantações e dimensionamento em containers.

O que é o Kubernetes?

O Kubernetes, em seu nível básico, é um sistema para executar e coordenar aplicações em containers em um cluster de máquinas. É uma plataforma projetada para gerenciar completamente o ciclo de vida de aplicações e serviços em containers usando métodos que proporcionam previsibilidade, escalabilidade e alta disponibilidade.

Como usuário do Kubernetes, você pode definir como suas aplicações devem ser executadas e as formas pelas quais elas devem ser capazes de interagir com outras aplicações ou com o mundo exterior. Você pode escalar seus serviços para cima ou para baixo, realizar atualizações graduais e suaves, e alternar o tráfego entre diferentes versões de suas aplicações para testar funcionalidades ou reverter implantações problemáticas. O Kubernetes fornece interfaces e primitivas de plataforma compostáveis que permitem que você defina e gerencie suas aplicações com alto grau de flexibilidade, poder e confiabilidade.

Arquitetura do Kubernetes

Para entender como o Kubernetes é capaz de fornecer essas capacidades, é útil ter uma ideia de como ele é projetado e organizado em um nível alto. O Kubernetes pode ser visualizado como um sistema construído em camadas, com cada camada superior abstraindo a complexidade encontrada nos níveis inferiores.

Na sua base, o Kubernetes reúne máquinas físicas ou virtuais individuais em um cluster usando uma rede compartilhada para se comunicar entre cada servidor, novamente, seja máquinas físicas ou virtuais. Este cluster Kubernetes é a plataforma física onde todos os componentes, capacidades e cargas de trabalho do Kubernetes são configurados.

As máquinas no cluster Kubernetes recebem cada uma um papel dentro do ecossistema Kubernetes. Um servidor (ou um pequeno grupo em implantações altamente disponíveis) funciona como o servidor mestre. Este servidor atua como um gateway e cérebro para o cluster, expondo uma API Kubernetes para usuários e clientes, verificando a saúde de outros servidores, decidindo a melhor forma de dividir e atribuir trabalho (conhecido como “agendamento”), e orquestrando a comunicação entre outros componentes (às vezes referido como orquestração de contêineres). O servidor mestre atua como o principal ponto de contato com o cluster e é responsável pela maioria da lógica centralizada fornecida pelo Kubernetes.

As outras máquinas no cluster são designadas como nós: servidores responsáveis por aceitar e executar cargas de trabalho usando recursos locais e externos. Para ajudar na isolamento, gerenciamento e flexibilidade, o Kubernetes executa aplicativos e serviços em contêineres, então cada nó precisa estar equipado com um tempo de execução de contêiner (como Docker ou rkt). O nó recebe instruções de trabalho do servidor mestre e cria ou destrói contêineres conforme necessário, ajustando as regras de rede para rotear e encaminhar o tráfego adequadamente.

Conforme mencionado acima, as aplicações e serviços em si são executados no cluster dentro de contêineres. Os componentes subjacentes garantem que o estado desejado das aplicações corresponda ao estado real do cluster. Os usuários interagem com o cluster comunicando-se com o servidor principal da API do Kubernetes, seja diretamente ou com clientes e bibliotecas. Para iniciar uma aplicação ou serviço, um plano declarativo é enviado em JSON ou YAML definindo o que criar e como deve ser gerenciado. O servidor principal então pega o plano e descobre como executá-lo na infraestrutura examinando os requisitos e o estado atual do sistema. Esse grupo de aplicações definidas pelo usuário em execução de acordo com um plano especificado representa a camada final do Kubernetes.

Componentes do Servidor Principal

Conforme descrito acima, o servidor principal atua como o plano de controle primário para os clusters do Kubernetes. Ele serve como o principal ponto de contato para administradores e usuários, e também fornece muitos sistemas de cluster amplo para os nós de trabalho relativamente não sofisticados. No geral, os componentes no servidor principal trabalham juntos para aceitar solicitações de usuário, determinar as melhores maneiras de agendar contêineres de carga de trabalho, autenticar clientes e nós, ajustar a rede em todo o cluster e gerenciar responsabilidades de dimensionamento e verificação de saúde.

Estes componentes podem ser instalados em uma única máquina ou distribuídos por vários servidores. Vamos dar uma olhada em cada um dos componentes individuais associados aos servidores mestre para clusters Kubernetes nesta seção.

etcd

Um dos componentes fundamentais que o Kubernetes precisa para funcionar é um armazenamento de configuração globalmente disponível. O projeto etcd, desenvolvido pela equipe da CoreOS (sistema operacional), é um armazenamento de chave-valor distribuído e leve que pode ser configurado para abranger vários nós.

O Kubernetes usa o etcd para armazenar dados de configuração que podem ser acessados por cada um dos nós no cluster. Isso pode ser usado para descoberta de serviços e pode ajudar os componentes a se configurarem ou reconfigurarem de acordo com informações atualizadas. Ele também ajuda a manter o estado do cluster com recursos como eleição de líder e bloqueio distribuído. Ao fornecer uma API HTTP/JSON simples, a interface para definir ou recuperar valores é bastante direta.

Assim como a maioria dos outros componentes no plano de controle, o etcd pode ser configurado em um único servidor mestre ou, em cenários de produção, distribuído entre vários servidores. O único requisito é que ele seja acessível pela rede para cada uma das máquinas Kubernetes.

kube-apiserver

Um dos serviços principais mais importantes é um servidor de API. Este é o principal ponto de gerenciamento de todo o cluster, pois permite que um usuário configure as cargas de trabalho e unidades organizacionais do Kubernetes. Também é responsável por garantir que o armazenamento etcd e os detalhes do serviço dos contêineres implantados estejam em acordo. Ele age como a ponte entre vários componentes para manter a saúde do cluster e disseminar informações e comandos.

O servidor de API implementa uma interface RESTful, o que significa que muitas ferramentas e bibliotecas diferentes podem se comunicar facilmente com ele. Um cliente chamado kubectl está disponível como método padrão de interação com o cluster Kubernetes a partir de um computador local.

kube-controller-manager

O gerenciador de controladores é um serviço geral que possui muitas responsabilidades. Primariamente, ele gerencia diferentes controladores que regulam o estado do cluster, gerenciam os ciclos de vida da carga de trabalho e realizam tarefas de rotina. Por exemplo, um controlador de replicação garante que o número de réplicas (cópias idênticas) definidas para um pod corresponda ao número atualmente implantado no cluster. Os detalhes dessas operações são escritos no etcd, onde o gerenciador de controladores observa por mudanças por meio do servidor de API.

Quando uma mudança é vista, o controlador lê as novas informações e implementa o procedimento que atende ao estado desejado. Isso pode envolver dimensionar uma aplicação para cima ou para baixo, ajustar pontos finais, etc.

kube-scheduler

O processo que realmente atribui cargas de trabalho a nós específicos no cluster é o agendador. Este serviço lê os requisitos operacionais de uma carga de trabalho, analisa o ambiente de infraestrutura atual e coloca o trabalho em um ou mais nós aceitáveis.

O agendador é responsável por rastrear a capacidade disponível em cada host para garantir que as cargas de trabalho não sejam agendadas em excesso em relação aos recursos disponíveis. O agendador deve conhecer a capacidade total, bem como os recursos já alocados para cargas de trabalho existentes em cada servidor.

cloud-controller-manager

O Kubernetes pode ser implantado em muitos ambientes diferentes e pode interagir com vários provedores de infraestrutura para entender e gerenciar o estado dos recursos no cluster. Embora o Kubernetes trabalhe com representações genéricas de recursos como armazenamento anexável e balanceadores de carga, ele precisa de uma maneira de mapear esses recursos para os recursos reais fornecidos por provedores de nuvem não homogêneos.

Os controladores de nuvem atuam como a cola que permite ao Kubernetes interagir com provedores com diferentes capacidades, recursos e APIs, mantendo construções internas relativamente genéricas. Isso permite que o Kubernetes atualize suas informações de estado de acordo com as informações coletadas do provedor de nuvem, ajuste os recursos de nuvem conforme as mudanças são necessárias no sistema, e crie e use serviços de nuvem adicionais para satisfazer os requisitos de trabalho enviados para o cluster.

Componentes do Servidor de Nó

No Kubernetes, os servidores que executam o trabalho rodando contêineres são conhecidos como nós. Os servidores de nós têm alguns requisitos que são necessários para se comunicar com os componentes mestre, configurar a rede de contêineres e executar as cargas de trabalho atribuídas a eles.

A Container Runtime

O primeiro componente que cada nó deve ter é um tempo de execução de contêiner. Tipicamente, este requisito é satisfeito instalando e executando Docker, mas alternativas como rkt e runc também estão disponíveis.

O tempo de execução do contêiner é responsável por iniciar e gerenciar contêineres, aplicações encapsuladas em um ambiente operacional relativamente isolado, mas leve. Cada unidade de trabalho no cluster é, em seu nível básico, implementada como um ou mais contêineres que devem ser implantados. O tempo de execução do contêiner em cada nó é o componente que finalmente executa os contêineres definidos nas cargas de trabalho enviadas para o cluster.

kubelet

O ponto de contato principal para cada nó com o grupo de clusters é um pequeno serviço chamado kubelet. Este serviço é responsável por transmitir informações de e para os serviços do plano de controle, além de interagir com a loja etcd para ler detalhes de configuração ou escrever novos valores.

O serviço kubelet se comunica com os componentes principais para autenticar no cluster e receber comandos e trabalho. O trabalho é recebido na forma de um manifesto que define a carga de trabalho e os parâmetros operacionais. O processo kubelet assume então a responsabilidade de manter o estado do trabalho no servidor do nó. Ele controla o tempo de execução do contêiner para iniciar ou destruir contêineres conforme necessário.

kube-proxy

Para gerenciar o subnetting de hosts individuais e disponibilizar serviços para outros componentes, é executado em cada servidor de nó um pequeno serviço de proxy chamado kube-proxy. Este processo encaminha solicitações para os contêineres corretos, pode fazer balanceamento de carga primitivo e geralmente é responsável por garantir que o ambiente de rede seja previsível e acessível, mas isolado quando apropriado.

Objetos e Cargas de Trabalho do Kubernetes

Enquanto os contêineres são o mecanismo subjacente usado para implantar aplicativos em contêineres, o Kubernetes utiliza camadas adicionais de abstração sobre a interface do contêiner para fornecer recursos de dimensionamento, resiliência e gerenciamento do ciclo de vida. Em vez de gerenciar contêineres diretamente, os usuários definem e interagem com instâncias compostas por vários primitivos fornecidos pelo modelo de objeto do Kubernetes. Abaixo, vamos examinar os diferentes tipos de objetos que podem ser usados para definir essas cargas de trabalho.

Pods

A pod is the most basic unit that Kubernetes deals with. Containers themselves are not assigned to hosts. Instead, one or more tightly coupled containers are encapsulated in an object called a pod.

A pod generally represents containers that should be controlled as a single application. Pods consist of containers that operate closely together, share a life cycle, and should always be scheduled on the same node. They are managed entirely as a unit and share their environment, volumes, and IP space. In spite of their containerized implementation, you should generally think of pods as a single, monolithic application to best conceptualize how the cluster will manage the pod’s resources and scheduling.

Normalmente, os pods consistem em um contêiner principal que satisfaz o propósito geral da carga de trabalho e, opcionalmente, alguns contêineres auxiliares que facilitam tarefas intimamente relacionadas. Estes são programas que se beneficiam de serem executados e gerenciados em seus próprios contêineres, mas estão intimamente ligados à aplicação principal. Por exemplo, um pod pode ter um contêiner executando o servidor de aplicativos principal e um contêiner auxiliar baixando arquivos para o sistema de arquivos compartilhado quando são detectadas alterações em um repositório externo. A escalabilidade horizontal geralmente não é recomendada no nível do pod porque existem outros objetos de nível superior mais adequados para a tarefa.

Normalmente, os usuários não devem gerenciar os pods por si mesmos, porque eles não fornecem algumas das características normalmente necessárias em aplicações (como gerenciamento de ciclo de vida sofisticado e escalonamento). Em vez disso, os usuários são incentivados a trabalhar com objetos de nível superior que utilizam pods ou modelos de pod como componentes base, mas implementam funcionalidades adicionais.

Controladores de Replicação e Conjuntos de Replicação

Frequentemente, ao trabalhar com Kubernetes, em vez de trabalhar com pods individuais, você estará gerenciando grupos de pods replicados idênticos. Estes são criados a partir de modelos de pod e podem ser escalonados horizontalmente por meio de controladores conhecidos como controladores de replicação e conjuntos de replicação.

A replication controller is an object that defines a pod template and control parameters to scale identical replicas of a pod horizontally by increasing or decreasing the number of running copies. This is an easy way to distribute load and increase availability natively within Kubernetes. The replication controller knows how to create new pods as needed because a template that closely resembles a pod definition is embedded within the replication controller configuration.

O controlador de replicação é responsável por garantir que o número de pods implantados no cluster corresponda ao número de pods em sua configuração. Se um pod ou host subjacente falhar, o controlador iniciará novos pods para compensar. Se o número de réplicas na configuração de um controlador mudar, o controlador inicializa ou encerra containers para corresponder ao número desejado. Os controladores de replicação também podem realizar atualizações progressivas para substituir um conjunto de pods por uma nova versão, um de cada vez, minimizando o impacto na disponibilidade da aplicação.

Os conjuntos de replicação são uma iteração no design do controlador de replicação com maior flexibilidade na forma como o controlador identifica os pods que ele deve gerenciar. Os conjuntos de replicação estão começando a substituir os controladores de replicação por causa de suas maiores capacidades de seleção de réplicas, mas não podem realizar atualizações progressivas para ciclar back-ends para uma nova versão como os controladores de replicação podem. Em vez disso, os conjuntos de replicação são destinados a serem usados dentro de unidades adicionais de nível superior que fornecem essa funcionalidade.

Assim como os pods, tanto os controladores de replicação quanto os conjuntos de replicação raramente são as unidades com as quais você trabalhará diretamente. Embora se baseiem no design do pod para adicionar escalabilidade horizontal e garantias de confiabilidade, eles carecem de algumas das capacidades de gerenciamento de ciclo de vida detalhadas encontradas em objetos mais complexos.

Implantações

Implantações são uma das cargas de trabalho mais comuns para criar e gerenciar diretamente. As implantações usam conjuntos de replicação como um bloco de construção, adicionando funcionalidades flexíveis de gerenciamento de ciclo de vida à mistura.

Embora as implantações construídas com conjuntos de replicação possam parecer duplicar a funcionalidade oferecida pelos controladores de replicação, as implantações resolvem muitos dos pontos problemáticos que existiam na implementação de atualizações graduais. Ao atualizar aplicativos com controladores de replicação, os usuários são obrigados a enviar um plano para um novo controlador de replicação que substituiria o controlador atual. Ao usar controladores de replicação, tarefas como rastrear histórico, recuperar falhas de rede durante a atualização e reverter alterações ruins são ou difíceis ou deixadas como responsabilidade do usuário.

Implantações são um objeto de alto nível projetado para facilitar o gerenciamento do ciclo de vida de pods replicados. As implantações podem ser modificadas facilmente alterando a configuração e o Kubernetes ajustará os conjuntos de réplicas, gerenciará transições entre diferentes versões do aplicativo e, opcionalmente, manterá automaticamente o histórico de eventos e as capacidades de desfazer. Devido a essas características, as implantações provavelmente serão o tipo de objeto Kubernetes com o qual você trabalhará com mais frequência.

Conjuntos de Estados

Conjuntos de Estados são controladores especializados de pods que oferecem garantias de ordenação e unicidade. Primariamente, esses são utilizados para ter um controle mais detalhado quando há requisitos especiais relacionados à ordenação de implantação, dados persistentes ou rede estável. Por exemplo, conjuntos de estados estão frequentemente associados a aplicativos orientados a dados, como bancos de dados, que precisam de acesso aos mesmos volumes mesmo se forem reprogramados para um novo nó.

Conjuntos de estados fornecem um identificador de rede estável ao criar um nome único baseado em números para cada pod que persistirá mesmo se o pod precisar ser movido para outro nó. Da mesma forma, os volumes de armazenamento persistentes podem ser transferidos com um pod quando for necessário reprogramar. Os volumes persistem mesmo após o pod ser excluído para evitar perda acidental de dados.

Ao implantar ou ajustar a escala, conjuntos de estados realizam operações de acordo com o identificador numerado em seu nome. Isso oferece uma maior previsibilidade e controle sobre a ordem de execução, o que pode ser útil em alguns casos.

Conjuntos de Demônios

Conjuntos de Demônios são outra forma especializada de controlador de pods que executam uma cópia de um pod em cada nó do cluster (ou um subconjunto, se especificado). Isso é mais frequentemente útil ao implantar pods que ajudam a realizar manutenção e fornecer serviços para os próprios nós do Kubernetes.

Por exemplo, coletar e encaminhar logs, agregar métricas e executar serviços que aumentam as capacidades do próprio nó são candidatos populares para conjuntos de daemons. Como conjuntos de daemons frequentemente fornecem serviços fundamentais e são necessários em toda a frota, eles podem contornar restrições de agendamento de pod que impedem outros controladores de atribuir pods a determinados hosts. Como exemplo, devido às suas responsabilidades únicas, o servidor mestre frequentemente é configurado para ficar indisponível para o agendamento normal de pods, mas conjuntos de daemons têm a capacidade de anular a restrição caso a caso para garantir que os serviços essenciais estejam em execução.

Trabalhos e Trabalhos Cron

As cargas de trabalho que descrevemos até agora assumiram todas um ciclo de vida semelhante a um serviço em execução contínua. O Kubernetes utiliza uma carga de trabalho chamada trabalhos para fornecer um fluxo de trabalho mais baseado em tarefas, onde os contêineres em execução são esperados para encerrar com êxito após algum tempo, uma vez que tenham concluído seu trabalho. Os trabalhos são úteis se você precisa realizar processamento único ou em lote em vez de executar um serviço contínuo.

A construção em trabalhos é trabalhos cron. Assim como os daemons cron convencionais em sistemas Linux e Unix-like que executam scripts em um cronograma, os trabalhos cron no Kubernetes fornecem uma interface para executar trabalhos com um componente de agendamento. Os trabalhos cron podem ser usados para agendar um trabalho para executar no futuro ou de forma regular e recorrente. Os trabalhos cron do Kubernetes são basicamente uma reimplantação do comportamento clássico do cron, usando o cluster como plataforma em vez de um único sistema operacional.

Outros Componentes do Kubernetes

Além das cargas de trabalho que você pode executar em um cluster, o Kubernetes fornece uma série de outras abstrações que ajudam você a gerenciar seus aplicativos, controlar a rede e permitir a persistência. Vamos discutir alguns dos exemplos mais comuns aqui.

Serviços do Kubernetes

Até agora, temos usado o termo “serviço” no sentido convencional, à moda Unix: para denotar processos de longa duração, frequentemente conectados em rede, capazes de responder a solicitações. No entanto, no Kubernetes, um serviço é um componente que age como um balanceador de carga interno básico e embaixador para pods. Um serviço agrupa coleções lógicas de pods que executam a mesma função para apresentá-los como uma única entidade.

Isso permite implantar um serviço que pode acompanhar e rotear todos os contêineres de backend de um tipo específico. Os consumidores internos só precisam saber sobre o ponto de extremidade estável fornecido pelo serviço. Enquanto isso, a abstração de serviço permite dimensionar ou substituir as unidades de trabalho de backend conforme necessário. O endereço IP de um serviço permanece estável independentemente de alterações nos pods aos quais roteia. Ao implantar um serviço, você ganha facilmente descoberta e pode simplificar seus projetos de contêineres.

Sempre que precisar fornecer acesso a um ou mais pods para outra aplicação ou para consumidores externos, você deve configurar um serviço. Por exemplo, se você tiver um conjunto de pods executando servidores web que devem ser acessíveis pela internet, um serviço fornecerá a abstração necessária. Da mesma forma, se seus servidores web precisarem armazenar e recuperar dados, você desejará configurar um serviço interno para dar a eles acesso aos seus pods de banco de dados.

Embora os serviços, por padrão, só estejam disponíveis usando um endereço IP internamente roteável, eles podem ser disponibilizados fora do cluster escolhendo uma das várias estratégias. A configuração de NodePort funciona abrindo uma porta estática na interface de rede externa de cada nó. O tráfego para a porta externa será roteado automaticamente para os pods apropriados usando um serviço de IP de cluster interno.

Alternativamente, o tipo de serviço LoadBalancer cria um balanceador de carga externo para rotear para o serviço usando a integração do balanceador de carga do Kubernetes do provedor de nuvem. O controlador de nuvem criará o recurso apropriado e o configurará usando os endereços de serviço do serviço interno.

Volumes e Volumes Persistentes

Compartilhar dados de forma confiável e garantir sua disponibilidade entre reinicializações de contêineres é um desafio em muitos ambientes containerizados. As plataformas de execução de contêineres frequentemente oferecem algum mecanismo para anexar armazenamento a um contêiner que persiste além da vida útil do contêiner, mas as implementações geralmente carecem de flexibilidade.

Para abordar isso, o Kubernetes usa sua própria abstração de volumes que permite que os dados sejam compartilhados por todos os contêineres dentro de um pod e permaneçam disponíveis até que o pod seja encerrado. Isso significa que pods fortemente acoplados podem compartilhar arquivos facilmente sem mecanismos externos complexos. As falhas de contêiner dentro do pod não afetarão o acesso aos arquivos compartilhados. Uma vez que o pod seja encerrado, o volume compartilhado é destruído, portanto, não é uma boa solução para dados verdadeiramente persistentes.

Volumes persistentes são um mecanismo para abstrair armazenamento mais robusto que não está vinculado ao ciclo de vida do pod. Em vez disso, eles permitem que administradores configurem recursos de armazenamento para o cluster que os usuários podem solicitar e reivindicar para os pods que estão executando. Uma vez que um pod tenha terminado com um volume persistente, a política de recuperação do volume determina se o volume é mantido até ser excluído manualmente ou removido junto com os dados imediatamente. Os dados persistentes podem ser usados para proteger contra falhas baseadas em nós e alocar quantidades maiores de armazenamento do que está disponível localmente.

Rótulos e Anotações

A Kubernetes organizational abstraction related to, but outside of the other concepts, is labeling. A label in Kubernetes is a semantic tag that can be attached to Kubernetes objects to mark them as a part of a group. These can then be selected for when targeting different instances for management or routing. For instance, each of the controller-based objects use labels to identify the pods that they should operate on. Services use labels to understand the backend pods they should route requests to.

Os rótulos são dados como pares de chave-valor simples. Cada unidade pode ter mais de um rótulo, mas cada unidade só pode ter uma entrada para cada chave. Normalmente, uma chave “nome” é usada como identificador de propósito geral, mas você também pode classificar objetos por outros critérios, como estágio de desenvolvimento, acessibilidade pública, versão da aplicação, etc.

As anotações são um mecanismo semelhante que permite anexar informações arbitrários de chave-valor a um objeto. Enquanto os rótulos devem ser usados para informações semânticas úteis para combinar um pod com critérios de seleção, as anotações são mais livres e podem conter dados menos estruturados. Em geral, as anotações são uma maneira de adicionar metadados ricos a um objeto que não são úteis para fins de seleção.

Conclusão

O Kubernetes é um projeto emocionante que permite aos usuários executar cargas de trabalho em contêineres escaláveis e altamente disponíveis em uma plataforma altamente abstraída. Embora a arquitetura do Kubernetes e seu conjunto de componentes internos possam parecer assustadores à primeira vista, seu poder, flexibilidade e conjunto de recursos robusto são incomparáveis no mundo de código aberto e para o desenvolvimento nativo de nuvem. Ao entender como os blocos de construção básicos se encaixam, você pode começar a projetar sistemas que aproveitam totalmente as capacidades da plataforma para executar e gerenciar suas cargas de trabalho em escala, construindo aplicativos nativos de nuvem incríveis.

Source:
https://www.digitalocean.com/community/tutorials/an-introduction-to-kubernetes