Você pode usar o kaniko para criar imagens do Docker em um contêiner enquanto estiver sem o Docker. Vamos descobrir como executar o kaniko localmente e em um cluster Kubernetes.

Em seguida, será um livro múltiplo
Suponha que você decida criar imagens do Docker em um cluster Kubernetes (bem, você precisa). O que é conveniente, vamos dar uma olhada em um exemplo real, com mais clareza.
Também falaremos sobre o Docker-in-Docker e sua alternativa, kaniko, com a qual você pode criar imagens do Docker sem usar o Docker. Por fim, aprenderemos como configurar a montagem de imagens no cluster Kubernetes.
Uma descrição geral de Kubernetes está no livro "Kubernetes em ação" ("Kubernetes em ação") .
Exemplo real
Na web nativa, temos muitas imagens privadas do Docker que precisam ser armazenadas em algum lugar. Por isso, implementamos um Docker Hub particular. O Docker Hub público possui dois recursos nos quais estamos particularmente interessados.
Primeiro, queríamos criar uma fila para coletar imagens do Docker no Kubernetes de forma assíncrona. Em segundo lugar, implemente o envio das imagens coletadas para o registro do Docker privado.
Normalmente, a CLI do Docker é usada diretamente para implementar estas funções:
$ docker build ... $ docker push ...
Porém, no cluster Kubernetes, hospedamos contêineres baseados em pequenas e elementares imagens do Linux, nas quais o Docker não está contido por padrão. Se agora queremos usar o Docker (por exemplo, docker build...
) em um contêiner, precisamos de algo como o Docker-in-Docker.
O que há de errado com o Docker-in-Docker?
Para coletar imagens de contêiner no Docker, precisamos de um daemon Docker em execução no contêiner, ou seja, Docker-in-Docker. O daemon do Docker é um ambiente virtualizado e o contêiner no Kubernetes é virtualizado por conta própria. Ou seja, se você deseja executar o daemon do Docker em um contêiner, precisará usar a virtualização aninhada. Para fazer isso, execute o contêiner no modo privilegiado - para obter acesso ao sistema host. Mas isso levanta problemas de segurança: por exemplo, você precisa trabalhar com diferentes sistemas de arquivos (host e contêiner) ou usar o cache de compilação do sistema host. É por isso que não queremos tocar no Docker-in-Docker.
Familiaridade com Kaniko
Não o Docker-in-Docker sozinho ... Há outra solução - o kaniko . Esta é uma ferramenta escrita em Go , que coleta imagens de contêiner de um Dockerfile sem o Docker. Em seguida, os envia para o registro do Docker especificado. Recomenda-se configurar o kaniko - use uma imagem de executor pronta para ser executada como um contêiner do Docker ou um contêiner no Kubernetes.
Lembre-se de que o kaniko ainda está em desenvolvimento e não suporta todos os comandos do Dockerfile, por exemplo --chownflag
para o COPY
.
Lançamento do Kaniko
Se você deseja executar o kaniko, precisará especificar vários argumentos para o contêiner do kaniko. Primeiro, insira o Dockerfile com todas as suas dependências no contêiner kaniko. Localmente (no Docker), o parâmetro -v <__>:<__>
usado para isso e o Kubernetes possui volumes .
Após inserir a dependência Dockerfile no contêiner kaniko, adicione o argumento --context
, ele indicará o caminho para o diretório anexado (dentro do contêiner). O próximo argumento é --dockerfile
. Indica o caminho para o Dockerfile (incluindo o nome). Outro argumento importante é o --destination
com a URL completa para o registro do Docker (incluindo o nome e a tag da imagem).
Lançamento local
Kaniko começa de várias maneiras. Por exemplo, no computador local usando o Docker (para não mexer no cluster Kubernetes). Execute o kaniko com o seguinte comando:
$ docker run \ -v $(pwd):/workspace \ gcr.io/kaniko-project/executor:latest \ --dockerfile=<path-to-dockerfile> \ --context=/workspace \ --destination=<repo-url-with-image-name>:<tag>
Se a autenticação estiver ativada no registro do Docker, o kaniko deverá primeiro fazer login. Para fazer isso, conecte o Docker config.jsonfile
local com credenciais para o registro do Docker ao contêiner kaniko usando o seguinte comando:
$ docker run \ -v $(pwd):/workspace \ -v ~/.docker/config.json:/kaniko/.docker/config.json \ gcr.io/kaniko-project/executor:latest \ --dockerfile=<path-to-dockerfile> \ --context=/workspace \ --destination=<repo-url-with-image-name>:<tag>
Lançamento no Kubernetes
No exemplo, queríamos executar o kaniko em um cluster do Kubernetes. E também precisávamos de uma fila para montar imagens. Se ocorrer uma falha ao montar ou enviar a imagem para o registro do Docker, seria bom se o processo fosse iniciado automaticamente novamente. Para isso, existe um trabalho no Kubernetes. Configure o backoffLimit
especificando com que frequência o processo deve tentar novamente.
A maneira mais fácil de incorporar um Dockerfile com dependências em um contêiner kaniko é com o objeto PersistentVolumeClaim (no nosso exemplo, é chamado kaniko-workspace
). Ele será vinculado ao contêiner como um diretório e todos os dados já devem estar no kaniko-workspace
. Digamos que em outro contêiner já exista um Dockerfile com dependências no kaniko-workspace
/my-build
no kaniko-workspace
.
Não esqueça que, na AWS, há problemas com o PersistentVolumeClaim. Se você criar um PersistentVolumeClaim na AWS, ele aparecerá em apenas um nó no cluster da AWS e estará disponível apenas lá. (atual: na verdade, ao criar um PVC, um volume RDS será criado em uma zona de disponibilidade aleatória do cluster. Portanto, esse volume estará disponível para todas as máquinas nessa zona. O próprio Kubernetes controla que, sob esse PVC, ele será lançado em um nó na zona de disponibilidade. RDS volyuma. - aprox. Por.) Portanto, se você executar o Job kaniko e esta tarefa estiver em outro nó, ela não será iniciada, porque o PersistentVolumeClaim não está disponível. Esperamos que o Amazon Elastic File System esteja disponível no Kubernetes em breve e o problema desapareça. (atual: o EFS no Kubernetes é suportado pelo provedor de armazenamento . - aprox .)
O recurso de trabalho para criar imagens do Docker geralmente se parece com isso:
apiVersion: batch/v1 kind: Job metadata: name: build-image spec: template: spec: containers: - name: build-image image: gcr.io/kaniko-project/executor:latest args: - "--context=/workspace/my-build" - "--dockerfile=/workspace/my-build/Dockerfile" - "--destination=<repo-url-with-image-name>:<tag>" volumeMounts: - name: workspace mountPath: /workspace volumes: - name: workspace persistentVolumeClaim: claimName: kaniko-workspace restartPolicy: Never backoffLimit: 3
Se o registro do Docker de destino exigir autenticação, passe o arquivo config.json
com as credenciais para o contêiner kaniko. A maneira mais fácil é conectar o PersistentVolumeClaim a um contêiner que já tenha um arquivo config.json
. Aqui PersistentVolumeClaim será montado não como um diretório, mas como um arquivo no caminho /kaniko/.docker/config.json
no contêiner /kaniko/.docker/config.json
:
apiVersion: batch/v1 kind: Job metadata: name: build-image spec: template: spec: containers: - name: build-image image: gcr.io/kaniko-project/executor:latest args: - "--context=/workspace/my-build" - "--dockerfile=/workspace/my-build/Dockerfile" - "--destination=<repo-url-with-image-name>:<tag>" volumeMounts: - name: config-json mountPath: /kaniko/.docker/config.json subPath: config.json - name: workspace mountPath: /workspace volumes: - name: config-json persistentVolumeClaim: claimName: kaniko-credentials - name: workspace persistentVolumeClaim: claimName: kaniko-workspace restartPolicy: Never backoffLimit: 3
Se você deseja verificar o status de um trabalho de construção em kubectl
, use o kubectl
. Para filtrar o status por stdout
, execute o comando:
$ kubectl get job build-image -o go-template='{{(index .status.conditions 0).type}}'
Sumário
Você aprendeu com o artigo quando o Docker-in-Docker não é adequado para criar imagens do Docker no Kubernetes. Teve uma idéia do kaniko - uma alternativa ao Docker-in-Docker, com o qual as imagens do Docker sem o Docker são montadas. Também aprendemos a escrever recursos da tarefa para coletar imagens do Docker no Kubernetes. E, finalmente, eles viram como descobrir o status de uma tarefa em andamento.