
В предыдущих статьях о dapp было рассказано про сборку приложений и про запуск в Minikube. При этом dapp запускался локально на машине разработчика. Однако инструмент задумывался для поддержки процессов непрерывной интеграции (CI) и сами мы используем его в основном в связке с GitLab. Чем dapp помогает в процессах CI/CD?
Во-первых, конечно же, это сборка. Dapp позволяет ускорить инкрементальную сборку приложений, привязывая команды сборки к изменениям между коммитами в Git-репозитории (подробнее об этом и других оптимизациях на этапе сборки см. в докладе «Собираем Docker-образы для CI/CD быстро и удобно вместе с dapp»: статья, видео).
Во-вторых, dapp помогает выкатывать приложение в кластер Kubernetes с помощью Helm. Помимо некоторого упрощения работы с секретами и проверки Helm-шаблонов, dapp помогает ожиданию выката
Deployments, указанных в шаблонах.В-третьих, в dapp реализована логика очистки кэша как в локальном, так и в удалённом Registry с Docker-образами. Очистка была улучшена в последних версиях: теперь dapp удаляет образы, созданные по веткам Git, если эти ветки удалены из Git-репозитория. С образами по тегам немного сложнее: остаётся не более 10 образов не старше 30 дней. В следующих версиях планируется сделать настраиваемые политики очистки.
Всё перечисленное критично в большей степени для сервера сборки, поэтому далее с помощью несложного стенда GitLab + Minikube покажу пример внедрения dapp в процессы непрерывной интеграции и доставки (CI/CD).
Обновлено 13 августа 2019 г.: в настоящее время проект dapp переименован в werf, его код переписан на Go, а документация значительно улучшена.
Стенд GitLab + Minikube + dapp
Стенд состоит из установленного GitLab, GitLab Runner, Registry и кластера Kubernetes:

Схема приближена к варианту, который используется нами в реальных проектах. Вкратце всё работает так:
- Разработчик push'ит свои изменения в Git-репозиторий.
- GitLab запускает задачу сборки, GitLab Runner запускает dapp, который собирает образ и push'ит образ в Registry.
- Чтобы выкатить приложение в кластер, запускается задача деплоя: GitLab Runner (с доступом к kubectl и Helm) выполняет
dapp kube deploy. - Кластер Kubernetes при получении обновлённых ресурсов проверяет, есть ли новый образ в Registry, скачивает его и запускает поды с новым образом.
Стенд — демонстрационный, поэтому, чтобы не плодить виртуальные машины, вместе с GitLab нужно установить Registry, GitLab Runner, dapp, Docker, kubectl и Helm. В качестве Kubernetes-кластера используется Minikube как самый простой способ запустить K8s на локальной машине.
В качестве приложения опять используется symfony-demo. Сборка этого проекта в локальном варианте была описана в статье «Практика с dapp. Часть 1: Сборка простых приложений», а пример выката приложения в Minikube был описан в статье «Практика с dapp. Часть 2. Деплой Docker-образов в Kubernetes с помощью Helm». Отличие от второй статьи будет в том, что Registry для Minikube становится внешним (расположен в виртуальной машине с GitLab) и команда
dapp kube minikube setup не требуется.Подготовка хост-системы
Перед созданием виртуальных машин лучше заранее добавить имена хостов, например, в
/etc/hosts:192.168.33.20 gitlab.example.com # доступ к интерфейсу gitlab
192.168.33.20 registry.gitlab.example.com # доступ к registry
192.168.33.100 cluster.example.com # доступ к приложению и к api k8sGitLab в виртуальной машине
Установка GitLab с помощью готового
Vagrantfile (https://github.com/rgl/gitlab-vagrant) была упомянута во второй части «Практики с dapp», но теперь опишу подробнее. Чтобы запустить виртуальную машину, понадобится отредактировать Vagrantfile, сменить базовый образ на xenial64 и увеличить память с 2048 до 4096.После
vagrant up нужно установить GitLab Runner по инструкции проекта. Также потребуется инсталляция Docker и dapp. И для деплоя — скачать бинарники kubectl и Helm.Чтобы запустить Registry, нужно отредактировать
/etc/gitlab/gitlab.rb, раскомментировав там строчки:gitlab_rails['registry_enabled'] = true gitlab_rails['registry_host'] = "registry.gitlab.example.com" gitlab_rails['registry_port'] = "5000" gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry" gitlab_rails['registry_api_url'] = "http://localhost:5000" gitlab_rails['registry_key_path'] = "/var/opt/gitlab/gitlab-rails/certificate.key" gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer" registry['registry_http_addr'] = "0.0.0.0:5000"
После сохранения — запустить
gitlab-ctl reconfigure. Omnibus изменит конфигурацию и перезапустит GitLab.Всё вышеперечисленное уже есть в форке gitlab-vagrant — достаточно его склонировать и выполнить
vagrant up.Minikube
Время запустить и настроить Minikube. Инструкция довольно проста: скачать бинарник проекта и вызвать команду:
minikube start --insecure-registry registry.gitlab.example.com:5000 --host-only-cidr 192.168.33.1/24
К сожалению, для работы в составе стенда придётся остановить кластер (
minikube stop) и вручную отредактировать ~/.minikube/machines/minikube/config.json, включив HostDNSResolver, чтобы виртуальная машина воспринимала /etc/hosts хоста. Также, если Minikube был установлен после прочтения второй части, проверьте ключ InsecureRegistry.{ "Driver": { … "HostDNSResolver": true, … “HostOptions”: { "EngineOptions": { "InsecureRegistry": [ "registry.gitlab.example.com:5000" ], …
Чтобы проверить доступность кластера после запуска
minikube start, можно выполнить команду kubectl get all.Настройка GitLab Runner
Кластер запущен — нужно настроить связь с кластером для gitlab-runner. Для этого в виртуальную машину копируется локальный конфиг из
.kube и сертификаты для доступа к Kubernetes API:$ cd ~ $ tar zcf kube-config.tar.gz .kube/config .minikube/ca.crt .minikube/apiserver.* $ cp kube-config.tar.gz $GITLAB_VM_DIR $ cd $GITLAB_VM_DIR $ vagrant ssh ubuntu@gitlab:~$ sudo su - gitlab-runner gitlab-runner@gitlab:~$ tar zxf /vagrant/kube-config.tar.gz
Следующий шаг — отредактировать
.kube/config, чтобы был правильный путь к файлам:- certificate-authority:
/home/gitlab-runner/.minikube/ca.crt - client-certificate:
/home/gitlab-runner/.minikube/apiserver.crt - client-key:
/home/gitlab-runner/.minikube/apiserver.key
Далее можно проверить связь и настроить Helm:
gitlab-runner@gitlab:~$ kubectl get all
Если Minikube уже был установлен ранее по второй части, то tiller уже есть и достаточно команды:
gitlab-runner@gitlab:~$ helm init --client-only
Если minikube не был ранее установлен, то нужно, чтобы установился tiller:
gitlab-runner@gitlab:~$ helm init
Для dapp необходимо добавить plugin
template:gitlab-runner@gitlab:~$ helm plugin install https://github.com/technosophos/helm-template
Импорт проекта и pipeline
Теперь можно импортировать репозиторий symfony-demo в GitLab. В списке проектов нажать New Project, выбрать Import, затем Repo by URL, ввести URL, группу и имя нового проекта.

В проекте уже есть ветка с
Dappfile и шаблонами в .helm, созданными при работе над предыдущими статьями, — dapp_deploy_minikube.Для демонстрации работы CI/CD нужно добавить конфигурацию CI —
.gitlab-ci.yml. Это будет простой pipeline из двух заданий:
Задание Build
Build: stage: build script: - dapp --version - dapp dimg build --build-dir ~/dapp_build/${CI_PROJECT_NAME} - dapp dimg push --build-dir ~/dapp_build/${CI_PROJECT_NAME} ${CI_REGISTRY_IMAGE} --tag-ci tags: - build
Задание 3 раза запускает dapp. Первый раз — информативный, чтобы видеть версию dapp. Второй запуск — сборка образов, описанных в
Dappfile. Третий — push собранных образов в Registry, при этом теги образам будут проставлены на основании переменных CI_* (Обновлено 13 августа 2019 г.: документация по опциям тегирования werf).Задание Deploy
Deploy: stage: deploy script: - dapp --version - dapp kube deploy --tag-ci --namespace ${CI_PROJECT_NAME}-stage --set "global.env=stage" --set "global.git_rev=${CI_COMMIT_SHA}" $CI_REGISTRY_IMAGE tags: - build
Здесь тоже первым запуском выводится версия dapp. Второй запуск — выкат приложения в кластер.
Можно заметить, что в пространстве имён используется суффикс
stage — это сделано, чтобы показать, что имя namespace можно задать любое. В полноценном варианте pipeline потребуется создать несколько заданий для нужных окружений.Helm-шаблоны
Registry, установленный в GitLab, в отличие от Registry, устанавливаемого командой
dapp kube minukube setup, имеет разграничение прав и поэтому в Helm-шаблоны нужно добавить registrysecret с логином и паролем для Registry. Можно сформировать секрет вручную с помощью команды base64, а можно воспользоваться подсказкой.В итоге, в
.helm/values.yaml добавятся такие значения:imageCredentials: registry: registry.gitlab.example.com:5000 username: root password: password
А в
backend.yaml — такой ресурс:apiVersion: v1 kind: Secret type: kubernetes.io/dockercfg metadata: name: registrysecret data: .dockercfg: {{ printf "{\"%s\": {\"auth\": \"%s\"}}" .Values.imageCredentials.registry (printf "%s:%s" .Values.imageCredentials.username .Values.imageCredentials.password | b64enc) | b64enc }}
… и
imagePullSecrets в spec шаблонов контейнеров:spec: template: ... spec: imagePullSecrets: - name: registrysecret containers: - command: [ '/demo/start.sh' ] image: {{ tuple "symfony-demo-app" . | include "dimg" }}
Выкат по таким Helm-шаблонам уже должен быть успешен — результат можно наблюдать в браузере по адресу
http://cluster.example.com/symfony-demo:

Резюмируя
В целом можно считать, что развёрнут стенд с процессом CI/CD, очень приближенным к тому, что работает у наших клиентов. Следующими шагами будет усложнение pipeline (см. «GitLab CI для непрерывной интеграции и доставки в production. Часть 1: наш пайплайн» и «Часть 2: преодолевая трудности»), введение динамических окружений (обзорная статья коллеги), добавление очистки Registry по расписанию, добавление запуска интеграционных тестов. Вопросы про описанный стенд и про dapp можно задать в комментариях и в нашем Telegram-чате.
P.S.
Читайте также в нашем блоге:
- «werf — наш инструмент для CI/CD в Kubernetes (обзор и видео доклада)» (Дмитрий Столяров; 27 мая 2019 на DevOpsConf);
- «Практика с dapp. Часть 1: Сборка простых приложений»;
- «Практика с dapp. Часть 2. Деплой Docker-образов в Kubernetes с помощью Helm»;
- «Лучшие практики CI/CD с Kubernetes и GitLab (обзор и видео доклада)»;
- «Инфраструктура с Kubernetes как доступная услуга».
