Criando imagens Docker no Kubernetes
Vitalis Ogbonna
3 de maio de 2022
0 minutos de leituraHospedar uma plataforma de CI/CD no Kubernetes está se tornando cada vez mais comum entre engenheiros. Essa abordagem economiza tempo com automação, garante implantações consistentes e facilita o monitoramento e o gerenciamento de microsserviços. No entanto, criar imagens de contêiner em clusters Kubernetes envolve alguns desafios técnicos que exigem soluções alternativas.
Neste artigo, vamos conhecer algumas maneiras de criar imagens Docker em um cluster Kubernetes para processos de CI/CD. Também vamos abordar as vantagens e desvantagens desses métodos.
Ferramentas para criar imagens Docker no Kubernetes
Se você já criou uma imagem de contêiner, provavelmente executou um comando como docker build. Depois, quando chegou a hora de automatizar esse processo, talvez você tenha configurado seus recursos de CI/CD para também usar docker build. Isso funciona em servidores de CI simples, mas talvez você queira, mais adiante, implantar uma plataforma de CI baseada em Kubernetes.
O desafio é que o daemon do Docker não fica livremente acessível no cluster Kubernetes. Por isso, precisamos usar alternativas sem comprometer a integridade da aplicação nem a infraestrutura.
Há várias ferramentas para isso:
O Buildah é especializado na criação de imagens da Open Container Initiative (OCI). Seus comandos reproduzem todos os comandos de um Dockerfile. A ferramenta permite criar imagens com ou sem Dockerfiles, sem exigir privilégios de root.
O img é uma ferramenta independente para criar imagens de contêiner compatíveis com Dockerfile e OCI, sem daemon e sem privilégios. É eficiente no uso de cache e pode executar várias etapas de build simultaneamente, pois usa internamente o solucionador de DAG do BuildKit como ferramenta de criação de imagens.
O kaniko cria imagens de contêiner a partir de um Dockerfile dentro de um contêiner ou cluster Kubernetes. O kaniko não depende de um daemon do Docker e executa cada comando do Dockerfile inteiramente no espaço do usuário.
O Docker in Docker é uma receita para executar o Docker dentro do Docker. Ele cria contêineres Docker em clusters Kubernetes montando o arquivo
/var/run/docker.sockcomo um volume em um contêiner Docker.A Enterprise Edition (Sysbox-EE) do Sysbox, da Nestybox, permite que contêineres sem root executem cargas de trabalho como Docker, systemd e Kubernetes como máquinas virtuais.
A BuildKit CLI cria imagens OCI e Docker de arquitetura única e múltipla em clusters Kubernetes. Ela substitui o comando docker build por kubectl build para criar imagens em clusters Kubernetes.
O Jib para contêineres Java cria imagens de contêiner sem usar um Dockerfile nem exigir uma instalação do Docker. Há plugins do Jib para Maven e Gradle. O Jib também está disponível como uma biblioteca Java.
O KO é uma ferramenta rápida e simples de criação de imagens de contêiner para aplicações Go. Ela cria imagens executando, na prática, o go build na sua máquina local, sem exigir a instalação do Docker.
Vamos nos concentrar em duas abordagens populares para criar imagens Docker em um cluster Kubernetes: Docker in Docker e kaniko.
Docker in Docker
O método Docker in Docker (DIND) é usado com frequência em pipelines de CI/CD nos quais as imagens são criadas e enviadas após um build de código bem-sucedido. Esse método também é usado para integrar o Jenkins a pipelines de implantação (por exemplo, durante testes em ambientes isolados).
A abordagem DIND pode parecer conveniente e simples. No entanto, o ex-funcionário da Docker e colaborador do DIND Jérôme Petazzoni afirma que a Docker criou essa abordagem para acelerar processos internos e aponta preocupações de segurança como motivos para não usá-la em ambientes de produção.
Originalmente, a Docker criou contêineres para serem executados em modo privilegiado com a abordagem DIND. O daemon do Docker é executado como root, então o contêiner também é executado como root no host. Qualquer pessoa com acesso ao socket do Docker tem acesso root, o que permite executar qualquer software, criar novos usuários e acessar tudo o que está conectado ao contêiner. Isso deixa os contêineres vulneráveis a ataques que podem se espalhar por toda a arquitetura.
Além disso, como o Kubernetes removeu oficialmente o suporte ao Dockershim, montar o docker.sock no host provavelmente deixará de funcionar no futuro, a menos que adicionemos o Docker a todos os nós do Kubernetes. A AWS oferece uma ferramenta útil para detectar o uso do socket do Docker em clusters.
O método DIND também apresenta problemas de compatibilidade com drivers de armazenamento. Além disso, gerenciar caches de imagens pode ser um desafio, pois precisamos baixar as imagens Docker sempre que iniciamos um build.
Uma maneira de resolver esses problemas é usar ferramentas que não exijam um runtime de contêiner para criar imagens. Uma delas é o kaniko, solução de código aberto do Google para criar imagens Docker em um cluster Kubernetes.
kaniko
O kaniko cria imagens de contêiner a partir de um Dockerfile dentro de um contêiner ou cluster Kubernetes. Ele não depende de um daemon do Docker e executa cada comando do Dockerfile inteiramente no espaço do usuário. Isso permite criar imagens de contêiner em ambientes nos quais não é fácil nem seguro executar um daemon do Docker, como clusters Kubernetes padrão.
Vamos usar ferramentas gratuitas e disponíveis publicamente para demonstrar o fluxo de trabalho do kaniko. Para acompanhar este tutorial, você vai precisar de:
Docker Desktop instalado no seu computador, com o Kubernetes habilitado
Uma conta válida do Docker Hub para que o pod do kaniko faça a autenticação e envie a imagem Docker
Uma conta do GitHub para que o kaniko acesse o Dockerfile
Vamos usar este projeto de exemplo no GitHub para demonstrar como o kaniko funciona. Clone o repositório com git clone https://github.com/agavitalis/kaniko-kubernetes.git para acompanhar.
Este projeto de exemplo tem dois arquivos e um arquivo README.md:
#sample project directory
kaniko-build-demo
dockerfilepod.ymlREADME.md
O dockerfile contém este código com os comandos para criar a imagem:
No código de configuração do kaniko, o executor de imagens do kaniko usa a versão mais recente. Também especificamos o local do Dockerfile e do repositório de imagens, além do nome das credenciais do registro de imagens no Kubernetes.
Como o kaniko funciona
O kaniko funciona de maneira simples. A imagem do executor do kaniko, gcr.io/kaniko-project/executor:latest, executa os comandos do Dockerfile para criar imagens. Ela lê o Dockerfile especificado, baixa a imagem base definida no comando FROM (neste caso, ubuntu) para o sistema de arquivos do contêiner definido e, em seguida, envia as imagens a um registro.
Depois de baixar a imagem base indicada pela diretiva FROM, o kaniko executa cada comando do Dockerfile individualmente e cria um snapshot do espaço do usuário após a execução de cada comando. Em seguida, a cada execução, adiciona a camada do snapshot à camada base.
Definimos estas configurações no arquivo pod.yml:
context: o local do Dockerfile. Neste caso, ele está no diretório raiz do repositório. Use as variáveisGIT_USERNAMEeGIT_PASSWORD(token de API) para se autenticar em repositórios Git privados.destination: substitua <dockerhub-username> pelo seu nome de usuário para que o kaniko envie a imagem ao registro do Docker Hub.docker-file: o caminho do Dockerfile relativo ao contexto.
Agora que entendemos como o kaniko funciona, vamos criar um Secret do Kubernetes. Depois, vamos usá-lo para criar e implantar uma imagem.
Como criar um Secret do Kubernetes para o Docker Hub
Precisamos criar um Secret do Kubernetes para que o kaniko acesse o Docker Hub. Para isso, precisamos das seguintes informações:
docker-server: o servidor do registro do Docker que vai hospedar suas imagens. Se você usa o Docker Hub, o valor deve serhttps://index.docker.io/v1/.docker-username: seu nome de usuário do registro do Docker.docker-password: sua senha do registro do Docker.docker-email: o e-mail configurado no seu registro do Docker.
Execute os comandos a seguir, substituindo cada variável pelo valor correspondente:
O comando acima monta esse Secret no pod do kaniko para facilitar a autenticação ao enviar a imagem criada para um registro do Docker. Você deverá receber uma mensagem de confirmação semelhante a esta:

Como implantar o pod do kaniko para criar uma imagem Docker
Agora, vamos iniciar o build criando o pod no nosso cluster Kubernetes. Implante o pod com o comando:

Isso inicia o processo de criação da imagem e, em seguida, envia a imagem ao registro do Docker especificado.
Você pode listar os pods disponíveis no seu cluster Kubernetes com o comando:

Isso exibe os pods disponíveis, o status e o tempo de existência de cada um. (Observe que pode ocorrer um erro se o kaniko estiver usando credenciais incorretas ou enviando a imagem para o repositório errado.)
Se quiser, use o comando kubectl delete pod <pod-name> para excluir os pods existentes.
Para ver informações detalhadas sobre o pod que você acabou de implantar, use o comando:

Você também pode ver o log do build com o comando:

Confira a folha de consulta rápida do kubectl para ver outros comandos que você pode usar para explorar o cluster, solucionar problemas e obter mais informações.
Em seguida, acesse o Docker Hub para confirmar que tudo funcionou e que você implantou suas imagens no Docker com sucesso.

Criamos e implantamos com sucesso nossa imagem Docker a partir de um cluster Kubernetes usando o kaniko!
Snyk para segurança de contêineres
O kaniko oferece uma maneira segura de criar imagens Docker em clusters Kubernetes. Ele obtém o Dockerfile do contexto de build definido, cria a imagem e envia o resultado para um registro de imagens. Seu poderoso sistema de cache acelera a criação da imagem.
Mesmo que você não use um método inseguro para criar imagens Docker no Kubernetes, ainda pode estar exposto a vulnerabilidades de segurança do Kubernetes. O Snyk Container oferece uma solução confiável de segurança de contêineres para encontrar e corrigir vulnerabilidades em aplicações nativas da nuvem. A Snyk se integra perfeitamente ao Docker, GitHub, Kubernetes, Jenkins e outras ferramentas para manter sua aplicação e infraestrutura seguras.
Segurança de contêineres que prioriza os desenvolvedores
O Snyk encontra e corrige automaticamente vulnerabilidades em imagens de contêiner e workloads do Kubernetes.
