Всем привет.
У нас не так много задач, которым необходим полноценный CI. Некоторое время мы использовали в качестве CI-сервиса Jenkins. Там всё довольно очевидно, он прост и гибок в настройке, имеет кучу плагинов, но пару раз мы столкнулись с OOM-убийцами агентов на слабых машинах и решили рассмотреть в качестве CI-сервиса Gitlab CI, потому что мы любим эксперименты и тем более в комментариях к нашей прошлой статье задавали такой вопрос.
Установка GitLab-CE
Тут всё довольно тривиально, т. к. есть Omnibus package.
Устанавливаем и запускаем необходимые пакеты:
sudo yum install curl openssh-server openssh-clients postfix cronie
sudo service postfix start
sudo chkconfig postfix on
Устанавливаем Gitlab-CE:
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | sudo bash
sudo yum install gitlab-ce
Настраиваем и запускаем Gitlab-CE:
sudo gitlab-ctl reconfigure
Установка раннера
GitLab Runner — это агент, который собственно и занимается выполнением инструкций из специального файла .gitlab-ci.yml.
В отличие от Jenkins раннеры гитлаба написаны на Go, поэтому они очень маленькие и быстрые. И умеют запускать задачи совершенно различными способами: локально, в докер-контейнерах, в различных облаках или через ssh-коннект к какому либо серверу. Подробности, как всегда, в документации
Кто-то в комментариях к прошлой статье просил рассмотреть Gitlab для тестирования ansible-плейбуков, его и возьмём.
Для обеспечения идентичности среды тестирования и продакшен будем использовать Docker.
Для работы раннера в Docker — сначала необходимо установить docker:
curl -sSL https://get.docker.com/ | sh
Установка раннера
# Для Debian/Ubuntu
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.deb.sh | sudo bash
# для RHEL/CentOS
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-ci-multi-runner/script.rpm.sh | sudo bash
# Для Debian/Ubuntu
sudo apt-get install gitlab-ci-multi-runner
# Для RHEL/CentOS
sudo yum install gitlab-ci-multi-runner
Настройка и подключение раннера к CI-сервису:
sudo gitlab-ci-multi-runner register
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com/ci )
http://domain.example.com/ci
Please enter the gitlab-ci token for this runner
bQ0nvkVJACDUrvQ9ttqx
Please enter the gitlab-ci description for this runner
my-runner
INFO[0034] fcf5c619 Registering runner... succeeded
Please enter the executor: shell, docker, docker-ssh, ssh?
docker
Please enter the Docker image (eg. ruby:2.1):
centos:7
INFO[0037] Runner registered successfully. Feel free to start it, but if it's
running already the config should be automatically reloaded!
Указываем URL нашего Gitlab, и прописываем токен для авторизации.
Также необходимо задать название раннера, способ запуска джоба, в случае с docker — указываем образ который будет запускать раннер.
Конфигурация для раннера указана по урлу example.com/groupname/projectname/runners
Здесь можно редактировать название раннера и метки, с которыми будет собираться проект на этом раннере. Например, нам нужно на разных стадиях протестировать проект сначала в shell, затем запаковать его в docker-контейнер и выкатить куда-нибудь по ssh. Об этом немного позже.
Оттуда необходимо взять URL мастера и токен для авторизации раннера на «мастере».
Запуск
sudo gitlab-ci-multi-runner start
После этого он должен появиться в списке раннеров проекта:
Установка Container Registry
Не так давно в Gitlab интегрировали Container Registry.
GitLab Container Registry — это защищённый приватный репозиторий для хранения Docker-образов (Docker images).
Ищем в /etc/gitlab/gitlab.rb секцию Container registry settings
registry_external_url 'https://domain.example.com'
# Settings used by GitLab application
gitlab_rails['registry_enabled'] = true
gitlab_rails['registry_host'] = "domain.example.com"
gitlab_rails['registry_port'] = "5000"
gitlab_rails['registry_api_url'] = "http://localhost:5000"
gitlab_rails['registry_key_path'] = "/var/opt/gitlab/gitlab-rails/certificate.key"
gitlab_rails['registry_path'] = "/var/opt/gitlab/gitlab-rails/shared/registry"
# gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer"
# Settings used by Registry application
registry['enable'] = true
registry['username'] = "registry"
registry['group'] = "registry"
# registry['uid'] = nil
# registry['gid'] = nil
registry['dir'] = "/var/opt/gitlab/registry"
registry['log_directory'] = "/var/log/gitlab/registry"
registry['log_level'] = "info"
registry['rootcertbundle'] = "/var/opt/gitlab/registry/gitlab-registry.crt"
registry['storage_delete_enabled'] = true
Из необходимого:
нужно выставить gitlab_rails['registry_enabled'] = true и registry['enable'] = true
В registry_external_url указываем доменное имя сервера, на котором будет находится репозиторий.
Также нужно найти следующие настройки:
registry_nginx['ssl_certificate'] = "/path/to/certificate.pem"
registry_nginx['ssl_certificate_key'] = "/path/to/certificate.key"
И указать правильные пути к сертификатам.
Если будут использоваться самоподписные сертификаты, то на стороне docker-daemon, с которого будет проходить вся работа с образами нужно выставить опцию --insecure-registry, в противном случае при попытке залогинится — мы получим ошибку (раннеров тоже касается).
В Debian: /etc/systemd/system/multi-user.target.wants/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network.target docker.socket
Requires=docker.socket
[Service]
Type=notify
ExecStart=/usr/bin/docker daemon -H fd:// --insecure-registry domain.example.com
MountFlags=slave
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
TimeoutStartSec=0
[Install]
WantedBy=multi-user.target
(Да, порт указывать не нужно. Существует API для registry — он висит на localhost:5000 и фронт, через который происходит авторизация и дальнейшая работа с образами. Я же долго искал способ перевесить API с локалхоста :) )
применяем изменения
systemctl daemon-reload
systemctl restart docker
И пробуем зайти под нашей учётной записью gitlab
docker login domain.example.com
Username: root
Password:
Email: admin@example.com
WARNING: login credentials saved in /root/.docker/config.json
Login Succeeded
Ну что, теперь самое время что-нибудь с этим сделать, построить первый пайплайн и посмотреть, как проект будет собираться.
Настройка CI
Приступаем к тестированию ansible-плейбуков:
Я не буду вдаваться в глубины и рассказывать о serverspec и test-kitchen, о них уже было написано в моём прошлом посте.
Первым делом — собираем простой образ с окружением для тестов. Обойдёмся Dry run и ansible-lint.
vim Dockerfile
FROM centos:7
RUN yum -y update && yum -y install epel-release \
&& yum -y install ansible python-pip
RUN pip install ansible-lint
# Default command
CMD ["/bin/bash"]
Окей, собраем образ
docker build -t centos:7 .
и пушим в Registry
docker tag centos:7 domain.example.com/<groupname>/<projectname>
docker push domain.example.com/<groupname>/<projectname>
Теперь самое время описать пайплайн
В корне нашего проекта создаём файл .gitlab-ci.yml (опять YAML, ага) и описываем шаги сборки проекта.
image: domain.example.com/root/my-repo
stages:
- test
- deploy
test_job:
stage: test
script:
- ansible-lint playbook.yml
- ansible-playbook --check playbook.yml
tags:
- ansible
deploy_job:
stage: deploy
script:
- ansible-playbook playbook.yml
tags:
- ansible
Здесь мы указываем стадии сборки проекта. На стадии тестирования — мы проходимся lint'ом на предмет синтаксических ошибок и запускаем Ansible в Dry mode, то есть не применяя изменения на хосте, а просто их показывая. Если вдруг что-то ломается во время проигрывания плейбука — мы об этом узнаем до того, как конфигурация на хосте изменится.
Соответсвенно, если мы сейчас попробуем в плейбук добавить где-нибудь пробелов — то конфигурация не применится, lint сообщит об ошибке и упадёт на этапе тестирования, о чём можно узнать после коммита прямо в веб-интерфейсе gitlab.
У .gitlab-ci.yml очень много различных опций на все случаи стадии жизни проекта. К сожалению, за один вечер со всем ознакомиться не удалось.
Как видите, Gitlab ничем не хуже других CI-сервисов, имеет позитивный и удобный интерфейс, но есть особенности в плане написания сценария тестирования и деплоя.
Спасибо за внимание. Удачной автоматизации!