Построение пайплайна CI/CD в GitLab
Вы можете построить пайплайн непрерывной интеграции и непрерывной поставки (CI/CD) с использованием serverless-продуктов.
В качестве примера проекта будет использовано веб-приложение, реализованное на Django
Для проекта используются два окружения:
prod
— продакшн, доступный пользователям.testing
— тестовое, используется для проверки приложения перед релизом вprod
.
Для каждого из окружений создается отдельный каталог в Yandex Cloud, а так же отдельный набор статических ресурсов — БД, сервисные аккаунты и т. д. Таким образом все окружения изолированы друг от друга на уровне настроек Yandex Identity and Access Management.
Дополнительно используется общий каталог infra
с реестром Yandex Container Registry — в него публикуются все собранные Docker-образы приложения. Публикация образов осуществляется от отдельного сервисного аккаунта builder
. Сервисные аккаунты окружений prod
и testing
имеют ограниченные права в каталоге infra
и могут только скачивать Docker-образы.
Чтобы построить пайплайн CI/CD с использованием serverless-продуктов:
- Создайте инстанс GitLab.
- Настройте GitLab.
- Создайте GitLab Runner.
- Загрузите файлы в репозиторий GitLab.
- Создайте переменные окружения GitLab.
- Создайте файл конфигурации сценария CI.
- Проверьте результат.
Если созданные ресурсы вам больше не нужны, удалите их.
Перед началом работы
Скачайте проект
Клонируйте репозиторий yc-serverless-gitlab-ci-cd
git clone https://github.com/yandex-cloud-examples/yc-serverless-gitlab-ci-cd.git
Установите дополнительные зависимости
Установите в локальном окружении:
-
Библиотеки Python, перечисленные в файле проекта
application/requirements.txt
:python -m pip install -r ./application/requirements.txt
Подготовьте инфраструктуру
-
Перейдите в директорию с проектом и запустите скрипт
bootstrap.sh
, указав идентификатор вашего облака:YC_CLOUD_ID=<идентификатор_облака> ./bootstrap.sh
Этот скрипт развернет базовую инфраструктуру и создаст YAML-файлы в директории
config
с описанием созданных ресурсов. Вы можете отредактировать скрипт, чтобы создать дополнительные каталоги с нужными ресурсами. Например, добавить еще одно тестовое окружение.Важно
В конце выполнения скрипт выведет переменные окружения для GitLab и их значения. Сохраните их, они потребуются в дальнейшем.
-
- Сервисный аккаунт для ресурсов с ролью editor на каталог, в котором создается кластер Yandex Managed Service for Kubernetes. От его имени будут создаваться ресурсы, необходимые кластеру Managed Service for Kubernetes.
- Сервисный аккаунт для узлов с ролью container-registry.images.puller на каталог с реестром Docker-образов. От его имени узлы будут скачивать из реестра необходимые Docker-образы.
Вы можете использовать один и тот же сервисный аккаунт для обеих операций.
-
Создайте кластер Managed Service for Kubernetes и группу узлов. При создании кластера укажите ранее созданные сервисные аккаунты для ресурсов и узлов.
-
Настройте группы безопасности для работы кластера Managed Service for Kubernetes.
-
Настройте группу безопасности для работы инстанса Yandex Managed Service for GitLab.
Создайте инстанс GitLab
Создайте инстанс Managed Service for GitLab или виртуальную машину с образом GitLab в той же облачной сети, где расположен кластер Managed Service for Kubernetes.
Создайте инстанс Managed Service for GitLab согласно инструкции.
Запустите GitLab на ВМ с публичным IP-адресом.
-
На странице каталога в консоли управления
нажмите кнопку Создать ресурс и выберитеВиртуальная машина
. -
В блоке Образ загрузочного диска в поле Поиск продукта введите
Gitlab
и выберите публичный образ GitLab. -
В блоке Расположение выберите зону доступности, в которой будет находиться ВМ. Если вы не знаете, какая зона доступности вам нужна, оставьте выбранную по умолчанию.
-
В блоке Вычислительные ресурсы перейдите на вкладку
Своя конфигурация
и укажите необходимую платформу, количество vCPU и объем RAM:- Платформа —
Intel Ice Lake
. - vCPU —
4
. - Гарантированная доля vCPU —
100%
. - RAM —
8 ГБ
.
- Платформа —
-
В блоке Сетевые настройки:
- В поле Подсеть выберите сеть и подсеть, к которым нужно подключить ВМ. Если нужной сети или подсети еще нет, создайте их.
- В поле Публичный адрес оставьте значение
Автоматически
, чтобы назначить ВМ случайный внешний IP-адрес из пула Yandex Cloud, или выберите статический адрес из списка, если вы зарезервировали его заранее.
-
В блоке Доступ выберите вариант SSH-ключ и укажите данные для доступа на ВМ:
- В поле Логин введите имя пользователя. Не используйте имя
root
или другие имена, зарезервированные ОС. Для выполнения операций, требующих прав суперпользователя, используйте командуsudo
. -
В поле SSH-ключ выберите SSH-ключ, сохраненный в вашем профиле пользователя организации.
Если в вашем профиле нет сохраненных SSH-ключей или вы хотите добавить новый ключ:
- Нажмите кнопку Добавить ключ.
- Задайте имя SSH-ключа.
- Загрузите или вставьте содержимое открытого SSH-ключа. Пару SSH-ключей для подключения к ВМ по SSH необходимо создать самостоятельно.
- Нажмите кнопку Добавить.
SSH-ключ будет добавлен в ваш профиль пользователя организации.
Если в организации отключена возможность добавления пользователями SSH-ключей в свои профили, добавленный открытый SSH-ключ будет сохранен только в профиле пользователя создаваемой виртуальной машины.
- В поле Логин введите имя пользователя. Не используйте имя
-
В блоке Общая информация задайте имя ВМ:
ci-tutorial-gitlab
. -
Нажмите кнопку Создать ВМ.
Создание ВМ может занять несколько минут. Когда ВМ перейдет в статус RUNNING
и запустится GitLab, настройте его.
Настройте GitLab
Чтобы настроить GitLab и подготовить процесс непрерывной интеграции (Continuous Integration, CI), создайте новый проект и введите параметры для авторизации в CI:
-
Авторизуйтесь в веб-интерфейсе инстанса Managed Service for GitLab.
-
Нажмите кнопку Create a project.
-
Нажмите кнопку Create blank project.
-
Заполните поля:
- Project name —
gitlab-test
. - Project URL — выберите пользователя-администратора в поле рядом с FQDN инстанса Managed Service for GitLab.
Остальные поля оставьте без изменений.
- Project name —
-
Нажмите кнопку Create project.
-
На странице сервиса Yandex Compute Cloud выберите созданную ВМ и скопируйте ее публичный IP-адрес.
-
Подключитесь к ВМ по протоколу SSH.
-
Получите пароль администратора GitLab с помощью команды ВМ:
sudo cat /etc/gitlab/initial_root_password
-
Скопируйте пароль из строки
Password
(исключая пробелы) в буфер обмена или отдельный файл. -
Откройте в браузере ссылку
http://<публичный_IP-адрес_ВМ>
. Откроется веб-интерфейс GitLab. -
Войдите в систему с учетной записью администратора:
- Username or email —
root
. - Password — пароль, скопированный ранее.
Если вы не можете войти, сбросьте пароль учетной записи администратора
. - Username or email —
-
Повторно войдите в систему с учетной записью администратора, используя новый пароль.
-
Выберите Create a project.
-
Задайте имя проекта:
gitlab-test
. -
Нажмите кнопку Create project.
Создайте GitLab Runner
Чтобы запускать задачи сборки в кластере Yandex Managed Service for Kubernetes, создайте GitLab Runner
После установки вы можете запускать автоматизированные сборки внутри своего кластера Managed Service for Kubernetes.
Подробнее про установку и настройку GitLab Runner читайте в документации GitLab
Загрузите файлы в репозиторий GitLab
-
Склонируйте репозиторий
gitlab-test
с помощью SSH. -
Скопируйте все файлы из репозитория
yc-serverless-gitlab-ci-cd
вgitlab-test
. -
Перейдите в директорию
gitlab-test
. -
Проиндексируйте новые файлы:
git add .
-
Сделайте коммит:
git commit -m "Add project files"
-
Отправьте изменения в репозиторий
gitlab-test
:git push
Создайте переменные окружения GitLab
-
На панели слева в GitLab перейдите в раздел Settings и во всплывающем списке выберите пункт CI/CD.
-
Нажмите кнопку Expand напротив пункта Variables.
-
Добавьте переменные окружения с выключенной опцией защиты. Все необходимые переменные и их значения были выведены в конце выполнения скрипта
bootstrap.sh
:cloud_id
— идентификатор вашего облака.CI_REGISTRY
— идентификатор реестра Container Registry в каталогеinfra
с префиксомcr.yandex/
.CI_REGISTRY_KEY
— ключ сервисного аккаунтаbuilder
.cart_prod
— имя продакшн каталога в Yandex Cloud.DOCAPI_ENDPOINT_prod
— Document API эндпоинт БД Yandex Managed Service for YDB в каталогеprod
.PROD_SA_ID
— идентификатор сервисного аккаунтаdeployer
в каталогеprod
.SA_PROD_DEPLOYER_PRIVATE_KEY
— ключ сервисного аккаунтаdeployer
в каталогеprod
.prod_container_id
— идентификатор контейнера Serverless Containers в каталогеprod
.cart_testing
— имя тестового каталога в Yandex Cloud.DOCAPI_ENDPOINT_testing
— Document API эндпоинт БД Managed Service for YDB в каталогеtesting
.TESTING_SA_ID
— идентификатор сервисного аккаунтаdeployer
в каталогеtesting
.SA_TESTING_DEPLOYER_PRIVATE_KEY
— ключ сервисного аккаунтаdeployer
в каталогеtesting
.
Для добавления переменной:
- Нажмите кнопку Add variable.
- В появившемся окне в поле Key укажите имя переменной, в поле Value — значение переменной.
- Выключите опцию Protect variable.
- Нажмите кнопку Add variable.
Создайте файл конфигурации сценария CI
-
Откройте проект
gitlab-test
. -
В строке навигации по репозиторию нажмите кнопку
и в выпадающем меню выберите пункт New file. -
Назовите файл
.gitlab-ci.yml
и добавьте в него этапы сборки:.gitlab-ci.yml
stages: - build - deploy-test-env - test - delete-test-env - release # Сборка образа контейнера. build-job: stage: build # Использование kaniko для создания контейнера внутри контейнера для большей безопасности. image: name: gcr.io/kaniko-project/executor:debug entrypoint: [""] script: - mkdir -p /kaniko/.docker # Отправка образа контейнера в реестр. Образ отмечен хэшем коммита. - echo "{\"auths\":{\"$CI_REGISTRY\":{\"auth\":\"$(echo -n "json_key:${CI_REGISTRY_KEY}" | base64 | tr -d '\n' )\"}}}" > /kaniko/.docker/config.json - >- /kaniko/executor --context "${CI_PROJECT_DIR}/application" --dockerfile "${CI_PROJECT_DIR}/application/Dockerfile" --destination "${CI_REGISTRY}/${CI_PROJECT_PATH}:${CI_COMMIT_SHORT_SHA}" # Развертывание тестовой среды с использованием встроенного образа контейнера. deploy-test-env-job: stage: deploy-test-env image: alpine:3.15 script: # Установка инструментов. - apk add -q --no-cache bash curl jq gettext - apk add yq --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community - curl --fail -silent --location --remote-name https://storage.yandexcloud.net/yandexcloud-yc/install.sh - bash install.sh -i /usr/local/yandex-cloud -n - ln -s /usr/local/yandex-cloud/bin/yc /usr/local/bin/yc # Аутентификация с помощью ключа сервисного аккаунта. - echo "$SA_TESTING_DEPLOYER_PRIVATE_KEY" > key.json - yc config profile create sa-profile - yc config set service-account-key key.json # Установка переменных для развертывания API Gateway и создание контейнера. - export sa_id=$TESTING_SA_ID - export container_id=$(yc serverless container create --name testing --cloud-id ${cloud_id} --folder-name ${cart_testing} | yq .id) # Развертывание ревизии. - yc serverless container revision deploy --container-name testing --image "${CI_REGISTRY}/${CI_PROJECT_PATH}:${CI_COMMIT_SHORT_SHA}" --cores 1 --memory 512mb --concurrency 1 --execution-timeout 10s --cloud-id ${cloud_id} --folder-name ${cart_testing} --service-account-id ${TESTING_SA_ID} --environment DOCAPI_ENDPOINT=${DOCAPI_ENDPOINT_testing},DB_TABLE_PREFIX='' --secret environment-variable=AWS_ACCESS_KEY_ID,name=cart-app,key=AWS_ACCESS_KEY_ID --secret environment-variable=AWS_SECRET_ACCESS_KEY,name=cart-app,key=AWS_SECRET_ACCESS_KEY --secret environment-variable=SECRET_KEY,name=cart-app,key=SECRET_KEY # Настройка шаблона и развертывание API Gateway. - (cat ${CI_PROJECT_DIR}/apigw.yaml.j2 | envsubst) > apigw.yaml - cat apigw.yaml - yc serverless api-gateway create --name testing --spec=apigw.yaml --description "created from gitlab CI" --cloud-id ${cloud_id} --folder-name ${cart_testing} - mkdir output - export gwdomain=$(yc serverless api-gateway get testing --cloud-id ${cloud_id} --folder-name ${cart_testing} | yq .domain) - echo "https://"$gwdomain>output/gwurl artifacts: paths: [output/] e2e-test-job: stage: test image: alpine:3.15 script: - apk add -q --no-cache bash curl - apk add yq --repository=http://dl-cdn.alpinelinux.org/alpine/edge/community - cat output/gwurl - export gwurlvar=$(cat output/gwurl) - curl $gwurlvar load-test-job: stage: test image: alpine:3.15 script: - echo "Here goes load testing commands" - echo "Might even invoke bash with prepared bash script" - echo "Hello!" delete-test-env-job: stage: delete-test-env image: alpine:3.15 script: - apk add -q --no-cache bash curl jq gettext yq - curl --fail --silent --location --remote-name https://storage.yandexcloud.net/yandexcloud-yc/install.sh - bash install.sh -i /usr/local/yandex-cloud -n - ln -s /usr/local/yandex-cloud/bin/yc /usr/local/bin/yc - echo "$SA_TESTING_DEPLOYER_PRIVATE_KEY" > key.json - yc config profile create sa-profile - yc config set service-account-key key.json - yc serverless api-gateway delete testing --cloud-id ${cloud_id} --folder-name ${cart_testing} - yc serverless container delete testing --cloud-id ${cloud_id} --folder-name ${cart_testing} release-job: stage: release image: alpine:3.15 script: - apk add -q --no-cache bash curl jq gettext - curl --fail --silent --location -remote-name https://storage.yandexcloud.net/yandexcloud-yc/install.sh - bash install.sh -i /usr/local/yandex-cloud -n - ln -s /usr/local/yandex-cloud/bin/yc /usr/local/bin/yc - echo "$SA_PROD_DEPLOYER_PRIVATE_KEY" > key.json - yc config profile create sa-profile - yc config set service-account-key key.json - yc serverless container revision deploy --container-name prod --image "${CI_REGISTRY}/${CI_PROJECT_PATH}:${CI_COMMIT_SHORT_SHA}" --cores 1 --memory 512mb --concurrency 1 --execution-timeout 10s --cloud-id ${cloud_id} --folder-name ${cart_prod} --service-account-id ${PROD_SA_ID} --environment DOCAPI_ENDPOINT=${DOCAPI_ENDPOINT_prod},DB_TABLE_PREFIX='' --secret environment-variable=AWS_ACCESS_KEY_ID,name=cart-app,key=AWS_ACCESS_KEY_ID --secret environment-variable=AWS_SECRET_ACCESS_KEY,name=cart-app,key=AWS_SECRET_ACCESS_KEY --secret environment-variable=SECRET_KEY,name=cart-app,key=SECRET_KEY - container_id=${prod_container_id} # Создание продакшн среды. environment: name: production/$CI_COMMIT_SHORT_SHA
-
Напишите комментарий к коммиту в поле Commit message:
CI scripts
. -
Нажмите кнопку Commit changes.
В файле .gitlab-ci.yml
описаны следующие этапы сценария CI:
- build — сборка Docker-образа с использованием
Dockerfile
и загрузка образа в Container Registry. - deploy-test-env — тестовое развертывание приложения. Дополнительно описан, но не использован механизм artifacts
для передачи данных из одного этапа в другой. При необходимости настройте его. - test — тестирование приложения. В качестве тестов приведены имитации e2e и нагрузочного тестирования. Опишите и настройте собственные тесты.
- delete-test-env — удаление тестового приложения.
- release — продакшн развертывание приложения. Дополнительно на этом этапе используются среды развертывания
. Они создаются и сохраняются при каждом успешном выполнении пайплайна. Воспользуйтесь ими, чтобы восстановить и развернуть прошлую версию приложения.
После сохранения файла конфигурации .gitlab-ci.yml
запустится сценарий сборки.
Проверьте результат
Чтобы проверить результаты выполнения сценария сборки, на панели слева в проекте gitlab-test
выберите пункт Build, в выпадающем меню выберите пункт Pipelines. Все пять этапов должны успешно завершиться.
Приложение будет доступно по адресу служебного домена API-шлюза API Gateway в каталоге prod
. Адрес можно посмотреть в консоли управленияdomain
в логе выполнения скрипта bootstrap.sh
.
Удалите созданные ресурсы
Некоторые ресурсы платные. Чтобы за них не списывалась плата, удалите ресурсы, которые вы больше не будете использовать:
- Удалите каталоги
prod
,testing
иinfra
вместе с ресурсами в них. - Удалите инстанс Managed Service for GitLab или созданную ВМ с образом GitLab.
- Удалите кластер Managed Service for Kubernetes.
- Если вы зарезервировали для кластера публичный статический IP-адрес, удалите его.
- Удалите сервисные аккаунты.