Kubernetes: création d'images Docker dans un cluster

Vous pouvez utiliser kaniko pour créer des images Docker dans un conteneur sans faire Docker. Voyons comment exécuter kaniko localement et dans un cluster Kubernetes.


image
Le prochain sera un multi-livre


Supposons que vous décidiez de créer des images Docker dans un cluster Kubernetes (enfin, vous en avez besoin). Ce qui est pratique, regardons un exemple réel, donc plus clairement.


Nous parlerons également de Docker-in-Docker et de son alternative, kaniko, avec laquelle vous pouvez créer des images Docker sans utiliser Docker. Enfin, nous apprendrons à configurer l'assemblage d'images dans le cluster Kubernetes.


Une description générale de Kubernetes se trouve dans le livre "Kubernetes in Action" ("Kubernetes in Action") .


Exemple réel


Sur le Web natif, nous avons de nombreuses images Docker privées qui doivent être stockées quelque part. Nous avons donc implémenté un Docker Hub privé. Le Docker Hub public a deux fonctionnalités qui nous intéressent particulièrement.


Tout d'abord, nous voulions créer une file d'attente qui collecterait les images Docker dans Kubernetes de manière asynchrone. Deuxièmement, implémentez l'envoi des images collectées au registre Docker privé.


En général, la Docker CLI est utilisée directement pour implémenter ces fonctions:


$ docker build ... $ docker push ... 

Mais dans le cluster Kubernetes, nous hébergeons des conteneurs basés sur des images Linux petites et élémentaires, dans lesquelles Docker n'est pas contenu par défaut. Si maintenant nous voulons utiliser Docker (par exemple Docker docker build... ) dans un conteneur, nous avons besoin de quelque chose comme Docker-in-Docker.


Quel est le problème avec Docker-in-Docker?


Pour collecter des images de conteneur dans Docker, nous avons besoin d'un démon Docker en cours d'exécution dans le conteneur, c'est-à-dire Docker-in-Docker. Le démon Docker est un environnement virtualisé, et le conteneur de Kubernetes est virtualisé seul. Autrement dit, si vous souhaitez exécuter le démon Docker dans un conteneur, vous devez utiliser la virtualisation imbriquée. Pour ce faire, exécutez le conteneur en mode privilégié - pour accéder au système hôte. Mais cela pose des problèmes de sécurité: par exemple, vous devez travailler avec différents systèmes de fichiers (hôte et conteneur) ou utiliser le cache de génération du système hôte. C'est pourquoi nous ne voulions pas toucher Docker-in-Docker.


Connaissance de kaniko


Pas Docker-in-Docker seul ... Il y a une autre solution - kaniko . Il s'agit d'un outil écrit en Go , il collecte des images de conteneurs à partir d'un Dockerfile sans Docker. Il les envoie ensuite au registre Docker spécifié. Il est recommandé de configurer kaniko - utilisez une image exécuteur prête à l' emploi qui peut être exécutée en tant que conteneur Docker ou conteneur dans Kubernetes.


Gardez à l'esprit que kaniko est toujours en cours de développement et ne prend pas en charge toutes les commandes Dockerfile, par exemple --chownflag pour la COPY .


Lancement de Kaniko


Si vous souhaitez exécuter kaniko, vous devez spécifier plusieurs arguments pour le conteneur kaniko. Insérez d'abord le Dockerfile avec toutes ses dépendances dans le conteneur kaniko. Localement (dans Docker), l'option -v <__>:<__> est utilisée pour cela -v <__>:<__> , et Kubernetes a des volumes .


Après avoir inséré la dépendance Dockerfile dans le conteneur kaniko, ajoutez l'argument --context , il indiquera le chemin vers le répertoire attaché (à l'intérieur du conteneur). L'argument suivant est --dockerfile . Il indique le chemin d'accès au Dockerfile (y compris le nom). Un autre argument important est la --destination avec l'URL complète du registre Docker (y compris le nom et la balise d'image).


Lancement local


Kaniko démarre de plusieurs façons. Par exemple, sur l'ordinateur local à l'aide de Docker (afin de ne pas jouer avec le cluster Kubernetes). Exécutez kaniko avec la commande suivante:


 $ docker run \ -v $(pwd):/workspace \ gcr.io/kaniko-project/executor:latest \ --dockerfile=<path-to-dockerfile> \ --context=/workspace \ --destination=<repo-url-with-image-name>:<tag> 

Si l'authentification est activée dans le registre Docker, kaniko doit d'abord être connecté. Pour ce faire, connectez le config.jsonfile Docker config.jsonfile local avec les informations d'identification du registre Docker au conteneur kaniko à l'aide de la commande suivante:


 $ 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> 

Lancement dans Kubernetes


Dans l'exemple, nous voulions exécuter kaniko dans un cluster Kubernetes. Et nous avions également besoin de quelque chose comme une file d'attente pour assembler des images. Si un échec se produit lors de l'assemblage ou de l'envoi de l'image dans le registre Docker, ce serait bien si le processus redémarre automatiquement. Pour cela, il y a un Job à Kubernetes. Configurez backoffLimit en spécifiant la fréquence à laquelle le processus doit réessayer.


La façon la plus simple d'incorporer un Dockerfile avec des dépendances dans un conteneur kaniko est avec l'objet PersistentVolumeClaim (dans notre exemple, il s'appelle kaniko-workspace ). Il sera lié au conteneur en tant que répertoire, et toutes les données devraient déjà être dans kaniko-workspace . Disons que dans un autre conteneur, il y a déjà un Dockerfile avec des dépendances dans le kaniko-workspace /my-build dans kaniko-workspace .


N'oubliez pas qu'en cas de problème AWS avec PersistentVolumeClaim. Si vous créez un PersistentVolumeClaim dans AWS, il n'apparaîtra que sur un seul nœud du cluster AWS et n'y sera disponible. (upd: en fait, lors de la création d'un PVC, un volume RDS sera créé dans une zone de disponibilité aléatoire de votre cluster. En conséquence, ce volume sera disponible pour toutes les machines de cette zone. Kubernetes contrôle lui-même qu'en utilisant ce PVC il sera lancé sur un nœud dans la zone de disponibilité Volyuma RDS - environ Per.) Donc, si vous exécutez Job kaniko et que cette tâche se trouve sur un autre nœud, elle ne démarrera pas, car PersistentVolumeClaim n'est pas disponible. Espérons que Amazon Elastic File System sera bientôt disponible sur Kubernetes et que le problème disparaîtra. (upd: EFS dans Kubernetes est pris en charge par le provisionneur de stockage . - environ .)


La ressource de travail pour la création d'images Docker ressemble généralement à ceci:


 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 

Si le registre Docker de destination nécessite une authentification, transmettez le fichier config.json avec les informations d'identification au conteneur kaniko. Le moyen le plus simple consiste à connecter PersistentVolumeClaim à un conteneur qui possède déjà un fichier config.json . Ici, PersistentVolumeClaim sera monté non pas comme un répertoire, mais plutôt comme un fichier dans le chemin /kaniko/.docker/config.json dans le conteneur kaniko:


 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 

Si vous souhaitez vérifier l'état d'un travail de génération en kubectl , utilisez kubectl . Pour filtrer le statut par stdout , exécutez la commande:


 $ kubectl get job build-image -o go-template='{{(index .status.conditions 0).type}}' 

Résumé


Vous avez appris de l'article lorsque Docker-in-Docker n'est pas adapté à la création d'images Docker dans Kubernetes. Vous avez une idée de kaniko - une alternative à Docker-in-Docker, avec laquelle les images Docker sans Docker sont assemblées. Nous avons également appris à écrire des ressources Job pour collecter des images Docker dans Kubernetes. Et enfin, ils ont vu comment connaître l'état d'une tâche en cours.

Source: https://habr.com/ru/post/fr436126/


All Articles