1. Введение
В этом уроке мы рассмотрим создание образов контейнеров с помощью Kaniko .
2. Канико
Kaniko — это инструмент для создания образов контейнеров из Dockerfile
. В отличие от Docker, Kaniko не требует демона Docker.
Поскольку процесс демона не зависит, его можно запустить в любой среде, где у пользователя нет root-доступа, например в кластере Kubernetes.
Kaniko выполняет каждую команду в Dockerfile
полностью в пользовательском пространстве, используя образ исполнителя
: gcr.io/kaniko-project/executor
, который запускается внутри контейнера; например, модуль Kubernetes. Он выполняет каждую команду внутри Dockerfile
по порядку и делает снимок файловой системы после каждой команды.
Если в файловой системе есть изменения, исполнитель делает моментальный снимок изменения файловой системы в качестве слоя «diff» и обновляет метаданные изображения.
Существуют разные способы развертывания и запуска Kaniko:
- Кластер Kubernetes
- gVisor
- Облачная сборка Google
В этом руководстве мы будем развертывать Kaniko с помощью кластера Kubernetes.
3. Установка миникуба
Мы будем использовать Minikube для локального развертывания Kubernetes. Его можно скачать как отдельный бинарный файл:
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 &&
chmod +x minikube
Затем мы можем добавить исполняемый файл Minikube в путь:
$ sudo mkdir -p /usr/local/bin/
$ sudo install minikube /usr/local/bin/
Затем давайте удостоверимся, что демон Docker запущен:
$ docker version
Кроме того, эта команда сообщит нам установленную версию клиента и сервера.
И теперь мы можем создать наш кластер Kubernetes:
$ minikube start --driver=docker
После успешного выполнения команды запуска мы увидим сообщение:
Done! kubectl is now configured to use "minikube"
For best results, install kubectl: https://kubernetes.io/docs/tasks/tools/install-kubectl/
После запуска команды состояния minikube
мы должны увидеть статус kubelet
как « Выполняется
»:
m01
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
Далее нам нужно настроить двоичный файл kubectl
, чтобы иметь возможность запускать команды Kubernetes. Скачиваем бинарник и делаем его исполняемым:
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/`curl -s \
https://storage.googleapis.com/kubernetes-release/release/stable.txt`/bin/linux/amd64/kubectl &&
chmod +x ./kubectl
Давайте теперь переместим это на путь:
$ sudo mv ./kubectl /usr/local/bin/kubectl
Мы можем проверить версию, используя:
$ kubectl version
4. Создание изображений с помощью Kaniko
Теперь, когда у нас есть готовый кластер Kubernetes, давайте начнем создавать образ с помощью Kaniko.
Во-первых, нам нужно создать локальный каталог, который будет смонтирован в контейнере Kaniko в качестве контекста сборки.
Для этого нам нужно подключиться к кластеру Kubernetes по SSH и создать каталог:
$ minikube ssh
$ mkdir kaniko && cd kaniko
Далее давайте создадим Dockerfile, который извлекает образ Ubuntu и выводит строку « hello»
:
$ echo 'FROM ubuntu' >> dockerfile
$ echo 'ENTRYPOINT ["/bin/bash", "-c", "echo hello"]' >> dockerfile
Если мы сейчас запустим cat dockerfile
, мы должны увидеть:
FROM ubuntu
ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
И, наконец, мы запустим команду pwd
, чтобы получить путь к локальному каталогу, который позже нужно будет указать в постоянном томе.
Вывод для этого должен быть похож на:
/home/docker/kaniko
И, наконец, мы можем прервать сеанс SSH:
$ exit
4.1. Kaniko Executor Image Аргументы
Прежде чем приступить к созданию файлов конфигурации Kubernetes, давайте рассмотрим некоторые аргументы, которые требуются для образа исполнителя Kaniko:
- Dockerfile (
--dockerfile
) — файл, содержащий все команды, необходимые для сборки образа. - Контекст сборки (
--context
) — похож на контекст сборки Docker, который относится к каталогу, который Канико использует для создания образа. На данный момент Kaniko поддерживает Google Cloud Storage (GCS), Amazon S3, хранилище BLOB-объектов Azure, репозиторий Git и локальный каталог. В этом руководстве мы будем использовать локальный каталог, который мы настроили ранее. - Место назначения (
–destination
) — относится к реестру Docker или любому подобному репозиторию, в которое мы отправляем образ. Этот аргумент является обязательным. Если мы не хотим отправлять изображение, мы можем переопределить поведение, используя вместо этого флаг–no-push .
Мы также можем видеть дополнительные флаги, которые можно передать .
4.2. Настройка файлов конфигурации
Теперь давайте приступим к созданию файлов конфигурации, необходимых для запуска Kaniko в кластере Kubernetes.
Во-первых, давайте создадим постоянный том, который предоставляет путь монтирования тома, созданный ранее в кластере. Назовем файл volume.yaml
:
apiVersion: v1
kind: PersistentVolume
metadata:
name: dockerfile
labels:
type: local
spec:
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
storageClassName: local-storage
hostPath:
path: /home/docker/kaniko # replace this with the output of pwd command from before, if it is different
Далее давайте создадим заявку на постоянный том для этого постоянного тома. Мы создадим файл volume-claim.yaml
с:
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: dockerfile-claim
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 8Gi
storageClassName: local-storage
Наконец, давайте создадим дескриптор модуля, который содержит образ исполнителя. Этот дескриптор имеет ссылку на указанные выше монтирования томов, которые, в свою очередь, указывают на Dockerfile
, который мы создали ранее.
Мы назовем файл pom.yaml
:
apiVersion: v1
kind: Pod
metadata:
name: kaniko
spec:
containers:
- name: kaniko
image: gcr.io/kaniko-project/executor:latest
args: ["--dockerfile=/workspace/dockerfile",
"--context=dir://workspace",
"--no-push"]
volumeMounts:
- name: dockerfile-storage
mountPath: /workspace
restartPolicy: Never
volumes:
- name: dockerfile-storage
persistentVolumeClaim:
claimName: dockerfile-claim
Как упоминалось ранее, в этом уроке мы фокусируемся только на создании изображения с помощью Kaniko и не публикуем его. Следовательно, мы указываем флаг отсутствия отправки
в аргументах исполнителя.
Имея все необходимые файлы конфигурации, давайте применим каждый из них:
$ kubectl create -f volume.yaml
$ kubectl create -f volume-claim.yaml
$ kubectl create -f pod.yaml
После применения дескрипторов мы можем проверить, что pod Kaniko переходит в состояние завершено. Мы можем проверить это с помощью kubectl get po
:
NAME READY STATUS RESTARTS AGE
kaniko 0/1 Completed 0 3m
Теперь мы можем проверить журналы этого модуля с помощью kubectl logs kaniko,
чтобы проверить статус создания образа, и он должен показать следующий вывод:
INFO[0000] Resolved base name ubuntu to ubuntu
INFO[0000] Resolved base name ubuntu to ubuntu
INFO[0000] Retrieving image manifest ubuntu
INFO[0003] Retrieving image manifest ubuntu
INFO[0006] Built cross stage deps: map[]
INFO[0006] Retrieving image manifest ubuntu
INFO[0008] Retrieving image manifest ubuntu
INFO[0010] Skipping unpacking as no commands require it.
INFO[0010] Taking snapshot of full filesystem...
INFO[0013] Resolving paths
INFO[0013] ENTRYPOINT ["/bin/bash", "-c", "echo hello"]
INFO[0013] Skipping push to container registry due to --no-push flag
В выводе мы видим, что контейнер выполнил шаги, которые мы указали в Dockerfile
.
Все началось с извлечения базового образа Ubuntu, а закончилось добавлением команды echo
в точку входа. Поскольку был указан флаг отсутствия
отправки, изображение не отправлялось ни в какой репозиторий.
Как упоминалось ранее, мы также видим, что перед добавлением точки входа делается снимок файловой системы.
5. Вывод
В этом уроке мы рассмотрели базовое введение в Канико. Мы видели, как его можно использовать для создания образа, а также для настройки кластера Kubernetes с использованием Minikube с необходимой конфигурацией для запуска Kaniko.
Как обычно, фрагменты кода, использованные в этой статье, доступны на GitHub .