Atualizado: Perguntas frequentes (FAQ) sobre a remoção do Dockershim

Esta é uma atualização do artigo original FAQ sobre a depreciação do Dockershim, publicado no final de 2020.

Este documento aborda algumas perguntas frequentes sobre a descontinuação e remoção do dockershim, que foi anunciado como parte do lançamento do Kubernetes v1.20. Para obter mais detalhes sobre o que isso significa, confira a postagem do blog Não entre em pânico: Kubernetes e Docker.

Além disso, você pode ler verifique se a remoção do dockershim afeta você para determinar qual impacto a remoção do dockershim teria para você ou para sua organização.

Como o lançamento do Kubernetes 1.24 se tornou iminente, estamos trabalhando bastante para tentar fazer uma transição suave.

Por que o dockershim está sendo removido do Kubernetes?

As primeiras versões do Kubernetes funcionavam apenas com um ambiente de execução de contêiner específico: Docker Engine. Mais tarde, o Kubernetes adicionou suporte para trabalhar com outros agentes de execução de contêiner. O padrão CRI (Container Runtime Interface ou Interface de Agente de Execução de Containers) foi criado para habilitar a interoperabilidade entre orquestradores (como Kubernetes) e diferentes agentes de execução de contêiner. O Docker Engine não implementa essa interface (CRI), então o projeto Kubernetes criou um código especial para ajudar na transição, e tornou esse código dockershim parte do projeto Kubernetes.

O código dockershim sempre foi destinado a ser uma solução temporária (daí o nome: shim). Você pode ler mais sobre a discussão e o planejamento da comunidade na Proposta de remoção do Dockershim para aprimoramento do Kubernetes. Na verdade, manter o dockershim se tornou um fardo pesado para os mantenedores do Kubernetes.

Além disso, recursos que são amplamente incompatíveis com o dockershim, como cgroups v2 e namespaces de usuário estão sendo implementados nos agentes de execução de CRI mais recentes. A remoção do suporte para o dockershim permitirá um maior desenvolvimento nessas áreas.

Ainda posso usar o Docker Engine no Kubernetes 1.23?

Sim, a única coisa que mudou na versão 1.20 é a presença de um aviso no log de inicialização do kubelet se estiver usando o Docker Engine como agente de execução de contêiner. Você verá este aviso em todas as versões até 1.23. A remoção do dockershim ocorre no Kubernetes 1.24.

Quando o dockershim será removido?

Dado o impacto dessa mudança, estamos definindo um cronograma de depreciação mais longo. A remoção do dockershim está agendada para o Kubernetes v1.24, consulte a Proposta de remoção do Dockershim para aprimoramento do Kubernetes. O projeto Kubernetes trabalhará em estreita colaboração com fornecedores e outros ecossistemas para garantir uma transição suave e avaliará os acontecimentos à medida que a situação for evoluindo.

Ainda posso usar o Docker Engine como meu agente de execução do contêiner?

Primeiro, se você usa o Docker em seu próprio PC para desenvolver ou testar contêineres: nada muda. Você ainda pode usar o Docker localmente, independentemente dos agentes de execução de contêiner que você usa em seus Clusters Kubernetes. Os contêineres tornam esse tipo de interoperabilidade possível.

Mirantis e Docker comprometeram-se a manter um adaptador substituto para o Docker Engine, e a manter este adaptador mesmo após o dockershim ser removido do Kubernetes. O adaptador substituto é chamado cri-dockerd.

Minhas imagens de contêiner existentes ainda funcionarão?

Sim, as imagens produzidas a partir do docker build funcionarão com todas as implementações do CRI. Todas as suas imagens existentes ainda funcionarão exatamente da mesma forma.

E as imagens privadas?

Sim. Todos os agentes de execução de CRI são compatíveis com as mesmas configurações de segredos usadas no Kubernetes, seja por meio do PodSpec ou ServiceAccount.

Docker e contêineres são a mesma coisa?

Docker popularizou o padrão de contêineres Linux e tem sido fundamental no desenvolvimento desta tecnologia. No entanto, os contêineres já existiam no Linux há muito tempo. O ecossistema de contêineres cresceu para ser muito mais abrangente do que apenas Docker. Padrões como o OCI e o CRI ajudaram muitas ferramentas a crescer e prosperar no nosso ecossistema, alguns substituindo aspectos do Docker, enquanto outros aprimoram funcionalidades já existentes.

Existem exemplos de pessoas que usam outros agentes de execução de contêineres em produção hoje?

Todos os artefatos produzidos pelo projeto Kubernetes (binários Kubernetes) são validados a cada lançamento de versão.

Além disso, o projeto kind vem usando containerd há algum tempo e tem visto uma melhoria na estabilidade para seu caso de uso. Kind e containerd são executados várias vezes todos os dias para validar quaisquer alterações na base de código do Kubernetes. Outros projetos relacionados seguem um padrão semelhante, demonstrando a estabilidade e usabilidade de outros agentes de execução de contêiner. Como exemplo, o OpenShift 4.x utiliza o agente de execução CRI-O em produção desde junho de 2019.

Para outros exemplos e referências, dê uma olhada em projetos adeptos do containerd e CRI-O, dois agentes de execução de contêineres sob o controle da Cloud Native Computing Foundation (CNCF).

As pessoas continuam referenciando OCI, o que é isso?

OCI significa Open Container Initiative (ou Iniciativa Open Source de Contêineres), que padronizou muitas das interfaces entre ferramentas e tecnologias de contêiner. Eles mantêm uma especificação padrão para imagens de contêiner (OCI image-spec) e para contêineres em execução (OCI runtime-spec). Eles também mantêm uma implementação real da especificação do agente de execução na forma de runc, que é o agente de execução padrão para ambos containerd e CRI-O. O CRI baseia-se nessas especificações de baixo nível para fornecer um padrão de ponta a ponta para gerenciar contêineres.

Qual implementação de CRI devo usar?

Essa é uma pergunta complexa e depende de muitos fatores. Se você estiver trabalhando com Docker, mudar para containerd deve ser uma troca relativamente fácil e terá um desempenho estritamente melhor e menos sobrecarga. No entanto, nós encorajamos você a explorar todas as opções do cenário CNCF, pois outro agente de execução de contêiner pode funcionar ainda melhor para o seu ambiente.

O que devo ficar atento ao mudar a minha implementação de CRI utilizada?

Embora o código de conteinerização base seja o mesmo entre o Docker e a maioria dos CRIs (incluindo containerd), existem algumas poucas diferenças. Alguns pontos a se considerar ao migrar são:

  • Configuração de log
  • Limitações de recursos de agentes de execução
  • Scripts de provisionamento que chamam o docker ou usam o docker por meio de seu soquete de controle
  • Plugins kubectl que exigem CLI do docker ou o soquete de controle
  • Ferramentas do projeto Kubernetes que requerem acesso direto ao Docker Engine (por exemplo: a ferramenta depreciada kube-imagepuller)
  • Configuração de funcionalidades como registry-mirrors e registries inseguros
  • Outros scripts de suporte ou daemons que esperam que o Docker Engine esteja disponível e seja executado fora do Kubernetes (por exemplo, agentes de monitoramento ou segurança)
  • GPUs ou hardware especial e como eles se integram ao seu agente de execução e ao Kubernetes

Se você usa solicitações ou limites de recursos do Kubernetes ou usa DaemonSets para coleta de logs em arquivos, eles continuarão a funcionar da mesma forma. Mas se você personalizou sua configuração dockerd, você precisará adaptá-la para seu novo agente de execução de contêiner assim que possível.

Outro aspecto a ser observado é que ferramentas para manutenção do sistema ou execuções dentro de um contêiner no momento da criação de imagens podem não funcionar mais. Para o primeiro, a ferramenta crictl pode ser utilizada como um substituto natural (veja migrando do docker cli para o crictl) e para o último, você pode usar novas opções de construções de contêiner, como img, buildah, kaniko, ou buildkit-cli-for-kubectl que não requerem Docker.

Para containerd, você pode começar com sua documentação para ver quais opções de configuração estão disponíveis à medida que você vá realizando a migração.

Para obter instruções sobre como usar containerd e CRI-O com Kubernetes, consulte o documentação do Kubernetes em Agentes de execução de contêineres

E se eu tiver mais perguntas?

Se você usa uma distribuição do Kubernetes com suporte do fornecedor, pode perguntar a eles sobre planos de atualização para seus produtos. Para perguntas de usuário final, poste-as no nosso fórum da comunidade de usuários: https://discuss.kubernetes.io/.

Você também pode conferir a excelente postagem do blog Espere, o Docker está depreciado no Kubernetes agora?, uma discussão técnica mais aprofundada sobre as mudanças.

Posso ganhar um abraço?

Sim, ainda estamos dando abraços se solicitado. 🤗🤗🤗

Não entre em pânico: Kubernetes e Docker

Autores / Autoras: Jorge Castro, Duffie Cooley, Kat Cosgrove, Justin Garrison, Noah Kantrowitz, Bob Killen, Rey Lejano, Dan “POP” Papandrea, Jeffrey Sica, Davanum “Dims” Srinivas

Tradução: João Brito

Kubernetes está deixando de usar Docker como seu agente de execução após a versão v1.20.

Não entre em pânico. Não é tão dramático quanto parece.

TL;DR Docker como um agente de execução primário está sendo deixado de lado em favor de agentes de execução que utilizam a Interface de Agente de Execução de Containers (Container Runtime Interface "CRI") criada para o Kubernetes. As imagens criadas com o Docker continuarão a funcionar em seu cluster com os agentes atuais, como sempre estiveram.

Se você é um usuário final de Kubernetes, quase nada mudará para você. Isso não significa a morte do Docker, e isso não significa que você não pode, ou não deva, usar ferramentas Docker em desenvolvimento mais. Docker ainda é uma ferramenta útil para a construção de containers, e as imagens resultantes de executar docker build ainda rodarão em seu cluster Kubernetes.

Se você está usando um Kubernetes gerenciado como GKE, EKS, ou AKS (que usa como padrão containerd) você precisará ter certeza que seus nós estão usando um agente de execução de container suportado antes que o suporte ao Docker seja removido nas versões futuras do Kubernetes. Se você tem mudanças em seus nós, talvez você precise atualizá-los baseado em seu ambiente e necessidades do agente de execução.

Se você está rodando seus próprios clusters, você também precisa fazer mudanças para evitar quebras em seu cluster. Na versão v1.20, você terá o aviso de alerta da perda de suporte ao Docker. Quando o suporte ao agente de execução do Docker for removido em uma versão futura (atualmente planejado para a versão 1.22 no final de 2021) do Kubernetes ele não será mais suportado e você precisará trocar para um dos outros agentes de execução de container compatível, como o containerd ou CRI-O. Mas tenha certeza que esse agente de execução escolhido tenha suporte às configurações do daemon do Docker usadas atualmente (Ex.: logs)

Então porque a confusão e toda essa turma surtando?

Estamos falando aqui de dois ambientes diferentes, e isso está criando essa confusão. Dentro do seu cluster Kubernetes, existe uma coisa chamada de agente de execução de container que é responsável por baixar e executar as imagens de seu container. Docker é a escolha popular para esse agente de execução (outras escolhas comuns incluem containerd e CRI-O), mas Docker não foi projetado para ser embutido no Kubernetes, e isso causa problemas.

Se liga, o que chamamos de "Docker" não é exatamente uma coisa - é uma stack tecnológica inteira, e uma parte disso é chamado de "containerd", que é o agente de execução de container de alto-nível por si só. Docker é legal e útil porque ele possui muitas melhorias de experiência do usuário e isso o torna realmente fácil para humanos interagirem com ele enquanto estão desenvolvendo, mas essas melhorias para o usuário não são necessárias para o Kubernetes, pois ele não é humano.

Como resultado dessa camada de abstração amigável aos humanos, seu cluster Kubernetes precisa usar outra ferramenta chamada Dockershim para ter o que ele realmente precisa, que é o containerd. Isso não é muito bom, porque adiciona outra coisa a ser mantida e que pode quebrar. O que está atualmente acontecendo aqui é que o Dockershim está sendo removido do Kubelet assim que que a versão v1.23 for lançada, que remove o suporte ao Docker como agente de execução de container como resultado. Você deve estar pensando, mas se o containerd está incluso na stack do Docker, porque o Kubernetes precisa do Dockershim?

Docker não é compatível com CRI, a Container Runtime Interface (interface do agente de execução de container). Se fosse, nós não precisaríamos do shim, e isso não seria nenhum problema. Mas isso não é o fim do mundo, e você não precisa entrar em pânico - você só precisa mudar seu agente de execução de container do Docker para um outro suportado.

Uma coisa a ser notada: Se você está contando com o socket do Docker (/var/run/docker.sock) como parte do seu fluxo de trabalho em seu cluster hoje, mover para um agente de execução diferente acaba com sua habilidade de usá-lo. Esse modelo é conhecido como Docker em Docker. Existem diversas opções por aí para esse caso específico como o kaniko, img, e buildah.

O que essa mudança representa para os desenvolvedores? Ainda escrevemos Dockerfiles? Ainda vamos fazer build com Docker?

Essa mudança aborda um ambiente diferente do que a maioria das pessoas usa para interagir com Docker. A instalação do Docker que você está usando em desenvolvimento não tem relação com o agente de execução de Docker dentro de seu cluster Kubernetes. É confuso, dá pra entender. Como desenvolvedor, Docker ainda é útil para você em todas as formas que era antes dessa mudança ser anunciada. A imagem que o Docker cria não é uma imagem específica para Docker e sim uma imagem que segue o padrão OCI (Open Container Initiative).

Qualquer imagem compatível com OCI, independente da ferramenta usada para construí-la será vista da mesma forma pelo Kubernetes. Ambos containerd e CRI-O sabem como baixar e executá-las. Esse é o porque temos um padrão para containers.

Então, essa mudança está chegando. Isso irá causar problemas para alguns, mas nada catastrófico, no geral é uma boa coisa. Dependendo de como você interage com o Kubernetes, isso tornará as coisas mais fáceis. Se isso ainda é confuso para você, tudo bem, tem muita coisa rolando aqui; Kubernetes tem um monte de partes móveis, e ninguém é 100% especialista nisso. Nós encorajamos toda e qualquer tipo de questão independente do nível de experiência ou de complexidade! Nosso objetivo é ter certeza que todos estão entendendo o máximo possível as mudanças que estão chegando. Esperamos que isso tenha respondido a maioria de suas questões e acalmado algumas ansiedades! ❤️

Procurando mais respostas? Dê uma olhada em nosso apanhado de questões quanto ao desuso do Dockershim.

Escalando a rede do Kubernetes com EndpointSlices

Autor: Rob Scott (Google)

EndpointSlices é um novo tipo de API que provê uma alternativa escalável e extensível à API de Endpoints. EndpointSlices mantém o rastreio dos endereços IP, portas, informações de topologia e prontidão de Pods que compõem um serviço.

No Kubernetes 1.19 essa funcionalidade está habilitada por padrão, com o kube-proxy lendo os EndpointSlices ao invés de Endpoints. Apesar de isso ser uma mudança praticamente transparente, resulta numa melhoria notável de escalabilidade em grandes clusters. Também permite a adição de novas funcionalidades em releases futuras do Kubernetes, como o Roteamento baseado em topologia..

Limitações de escalabilidade da API de Endpoints

Na API de Endpoints, existia apenas um recurso de Endpoint por serviço (Service). Isso significa que era necessário ser possível armazenar endereços IPs e portas para cada Pod que compunha o serviço correspondente. Isso resultava em recursos imensos de API. Para piorar, o kube-proxy rodava em cada um dos nós e observava qualquer alteração nos recursos de Endpoint. Mesmo que fosse uma simples mudança em um Endpoint, todo o objeto precisava ser enviado para cada uma das instâncias do kube-proxy.

Outra limitação da API de Endpoints era que ela limitava o número de objetos que podiam ser associados a um Service. O tamanho padrão de um objeto armazenado no etcd é 1.5MB. Em alguns casos, isso poderia limitar um Endpoint a 5,000 IPs de Pod. Isso não chega a ser um problema para a maioria dos usuários, mas torna-se um problema significativo para serviços que se aproximem desse tamanho.

Para demonstrar o quão significante se torna esse problema em grande escala, vamos usar de um simples exemplo: Imagine um Service que possua 5,000 Pods, e que possa causar o Endpoint a ter 1.5Mb . Se apenas um Endpoint nessa lista sofra uma alteração, todo o objeto de Endpoint precisará ser redistribuído para cada um dos nós do cluster. Em um cluster com 3.000 nós, essa atualização causará o envio de 4.5Gb de dados (1.5Mb de Endpoints * 3,000 nós) para todo o cluster. Isso é quase que o suficiente para encher um DVD, e acontecerá para cada mudança de Endpoint. Agora imagine uma atualização gradual em um Deployment que resulte nos 5,000 Pods serem substituídos - isso é mais que 22Tb (ou 5,000 DVDs) de dados transferidos.

Dividindo os endpoints com a API de EndpointSlice

A API de EndpointSlice foi desenhada para resolver esse problema com um modelo similar de sharding. Ao invés de rastrar todos os IPs dos Pods para um Service, com um único recurso de Endpoint, nós dividimos eles em múltiplos EndpointSlices menores.

Usemos por exemplo um serviço com 15 pods. Nós teríamos um único recurso de Endpoints referente a todos eles. Se o EndpointSlices for configurado para armazenar 5 endpoints cada, nós teríamos 3 EndpointSlices diferentes: EndpointSlices

Por padrão, o EndpointSlices armazena um máximo de 100 endpoints cada, podendo isso ser configurado com a flag --max-endpoints-per-slice no kube-controller-manager.

EndpointSlices provê uma melhoria de escalabilidade em 10x

Essa API melhora dramaticamente a escalabilidade da rede. Agora quando um Pod é adicionado ou removido, apenas 1 pequeno EndpointSlice necessita ser atualizado. Essa diferença começa a ser notada quando centenas ou milhares de Pods compõem um único Service.

Mais significativo, agora que todos os IPs de Pods para um Service não precisam ser armazenados em um único recurso, nós não precisamos nos preocupar com o limite de tamanho para objetos armazendos no etcd. EndpointSlices já foram utilizados para escalar um serviço além de 100,000 endpoints de rede.

Tudo isso é possível com uma melhoria significativa de performance feita no kube-proxy. Quando o EndpointSlices é usado em grande escala, muito menos dados serão transferidos para as atualizações de endpoints e o kube-proxy torna-se mais rápido para atualizar regras do iptables ou do ipvs. Além disso, os Services podem escalar agora para pelo menos 10x mais além dos limites anteriores.

EndpointSlices permitem novas funcionalidades

Introduzido como uma funcionalidade alpha no Kubernetes v1.16, os EndpointSlices foram construídos para permitir algumas novas funcionalidades arrebatadoras em futuras versões do Kubernetes. Isso inclui serviços dual-stack, roteamento baseado em topologia e subconjuntos de endpoints.

Serviços Dual-stack são uma nova funcionalidade que foi desenvolvida juntamente com o EndpointSlices. Eles irão utilizar simultâneamente endereços IPv4 e IPv6 para serviços, e dependem do campo addressType do Endpointslices para conter esses novos tipos de endereço por família de IP.

O roteamento baseado por topologia irá atualizar o kube-proxy para dar preferência no roteamento de requisições para a mesma região ou zona, utilizando-se de campos de topologia armazenados em cada endpoint dentro de um EndpointSlice. Como uma melhoria futura disso, estamos explorando o potencial de subconjuntos de endpoint. Isso irá permitir o kube-proxy apenas observar um subconjunto de EndpointSlices. Por exemplo, isso pode ser combinado com o roteamento baseado em topologia e assim, o kube-proxy precisará observar apenas EndpointSlices contendo endpoints na mesma zona. Isso irá permitir uma outra melhoria significativa de escalabilidade.

O que isso significa para a API de Endpoints?

Apesar da API de EndpointSlice prover uma alternativa nova e escalável à API de Endpoints, a API de Endpoints continuará a ser considerada uma funcionalidade estável. A mudança mais significativa para a API de Endpoints envolve começar a truncar Endpoints que podem causar problemas de escalabilidade.

A API de Endpoints não será removida, mas muitas novas funcionalidades irão depender da nova API EndpointSlice. Para obter vantágem da funcionalidade e escalabilidade que os EndpointSlices provém, aplicações que hoje consomem a API de Endpoints devem considerar suportar EndpointSlices no futuro.