Drone – это популярная система непрерывной интеграции, основанная на Go. Она может взаимодействовать с GitHub, GitLab и Bitbucket, отслеживать изменения в коде и тестировать новые функции.
Данное руководство поможет установить и настроить среду непрерывной интеграции Drone в инфраструктуре. В качестве фронтенда Drone будет использоваться Nginx, защищенный сертификатом Let’s Encrypt. Сертификат зашифрует запросы к веб-интерфейсу Drone и позволит серверу непрерывной интеграции (дальше – НИ) безопасно взаимодействовать с сервером исходного кода.
Требования
- Сервер Ubuntu 16.04.
- Пользователь с доступом к sudo.
- Брандмауэр (все инструкции вы найдете здесь).
- Docker Compose (для управления контейнерами сервера НИ; Drone в основном распространяется как образ Docker). Читайте Установка Docker Compose в Ubuntu 16.04.
- Веб-сервер Nginx (инструкции по установке – в статье Установка Nginx в Ubuntu 16.04).
- Сертификат Let’s Encrypt (для этого серверу НИ нужен домен). Следуйте руководству Создание сертификата Let’s Encrypt для Nginx в Ubuntu 16.04.
Также вам может пригодиться руководство Установка и использование Docker в Ubuntu 16.04.
В результате на сервере Drone будет:
- Пользователь sudo.
- Брандмауэр UFW. Он будет блокировать все соединения, кроме SSH, HTTP и HTTPS по портам 22, 80 и 443 соответственно.
- Docker и Docker Compose.
- Сервер Nginx, защищенный SSL-сертификатом от Let’s Encrypt.
Добавление Drone в репозиторий исходного кода
Чтобы отслеживать изменения и выполнять тесты, Drone нужен доступ к репозиторию исходного кода проекта. Drone можно интегрировать с GitHub, GitLab, Gogs, Bitbucket Cloud и Bitbucket Server.
В данном руководстве показано, как интегрировать Drone с GitHub, но процесс будет аналогичным и для других систем.
Примечание: Если вы используете другой репозиторий исходного кода, следуйте приведенным выше ссылкам, чтобы получить инструкции по настройке вашего программного обеспечения.
Откройте аккаунт GitHub. Нажмите на иконку пользователя в верхнем правом углу и выберите Settings.
Найдите элемент OAuth applications в разделе Developer settings в левой части экрана.
На следующей странице нажмите Register a new application.
Затем вы увидите регистрационную форму приложения OAuth.
Примечание: Эти поля есть в GitHub. Формы других провайдеров могут отличаться.
Нужно будет заполнить следующие поля:
- Application name: Введите имя интегрируемого приложения. Если у вас нет особых потребностей, можно просто ввести Drone.
- Homepage URL: Доменное имя сервера Drone. Поскольку трафик шифруется, используйте https:// в начале имени.
- Application description: Простое описание приложения и целей Drone.
- Authorization callback URL: Нужно указать https://, затем домен сервера Drone и секцию /authorize. К примеру, для домена example.com это поле выглядит так: https://example.com/authorize.
Чтобы зарегистрировать приложение, нажмите Register application.
На следующей странице вы увидите подробные данные о приложении. Скопируйте здесь Client ID и Client Secret: эти значения нужны для подключения Drone к аккаунту GitHub.
Загрузка образа Drone и подготовка к настройке
Теперь нужно установить Drone на сервер.
Drone распространяется в виде контейнера Docker. Контейнер будет автоматически загружен, если использовать его в файле Docker Compose. Чтобы загрузить образ, введите:
docker pull drone/drone:0.7
Образ Drone – это унифицированный контейнер, который можно запустить несколькими способами. В руководстве показано, как запустить один контейнер как сервер Drone, который координирует доступ к репозиторию, размещает веб-интерфейс и обслуживает API. Второй контейнер будет запущен в качестве агента Drone, который отвечает за создание и тестирование программного обеспечения из репозиториев.
Оба контейнера будут работать на хосте Drone с помощью Docker Compose. Создайте каталог конфигураций:
sudo mkdir /etc/drone
Создание файла Docker Compose для Drone
Создайте файл Docker Compose:
sudo nano /etc/drone/docker-compose.yml
Укажите версию файла (в данном случае – 3). После этого можно определить сервисы контейнеров.
Сервис drone-server запустит главный контейнер сервера Drone, прослушивающий порт 8000. Смонтируйте каталог /var/lib/drone в контейнере, чтобы система Drone могла хранить в нем свои данные. Также нужно настроить сервис для автоматического перезапуска и чтения переменных среды, определенных в файле /etc/drone/server.env (он будет создан позже).
Сервис drone-agent использует тот же образ, но запускается с помощью команды agent. Он получает инструкции от главного сервера Drone. Пока ему не нужен доступ к сети, его необходимо запустить после сервиса Drone. Также drone-agent необходим доступ к файлу сокета Docker, чтобы развернуть контейнеры и выполнить сборку и тестирование. Как и drone-server, этот сервис также автоматически перезагрузится и прочитает переменные среды в /etc/drone/agent.env.
Для настройки этих сервисов можно использовать следующий файл Docker Compose.
Примечание: В файлах YAML нужно внимательно проставлять отступы.
version: '3'
services:
drone-server:
image: drone/drone:0.7
ports:
- 127.0.0.1:8000:8000
volumes:
- /var/lib/drone:/var/lib/drone
restart: always
env_file:
- /etc/drone/server.env
drone-agent:
image: drone/drone:0.7
command: agent
depends_on:
- drone-server
volumes:
- /var/run/docker.sock:/var/run/docker.sock
restart: always
env_file:
- /etc/drone/agent.env
Файл переменных среды сервера Drone
Теперь нужно создать файл для хранения переменных среды, на который вы ссылались в файле Docker Compose.
Сначала нужно создать надежный ключ для аутентификации агента и сервера. В данной установке оба этих компонента установлены на одном сервере, но ключ все равно необходим, так как инфраструктура тестирования быстро масштабируется. В командной строке сгенерируйте ключ:
LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 | head -c 65 && echo
Эта команда временно ограничивает диапазон символов в оболочке. Затем она берет поток случайных байтов из /dev/urandom и дополнительно отфильтровывает все неалфавитные символы. Первые 65 символов используются в качестве ключа.
Внимание: не копируйте приведенное ниже значение! Создайте свой собственный ключ!
ERmA7xubDvTa8i0wYBlljc9yjT1NJPG7xOlZBwAdMAmBYL4RZE4QngxWcCLowk9KN
Скопируйте ключ и используйте его в файле среды сервера.
Создайте новый файл /etc/drone/server.env и откройте его в текстовом редакторе:
sudo nano /etc/drone/server.env
Внутри нужно определить переменные среды, которые Drone использует для запуска сервиса, подключиться к провайдеру и указать политику авторизации. Здесь понадобятся скопированные ранее значения Client ID и Client Secret.
Для начала задайте значения DRONE_HOST и DRONE_SECRET. В DRONE_SECRET укажите ключ, который вы создали в командной строке. Параметр DRONE_HOST сообщает системе Drone общедоступный адрес. Это должен быть защищенный сертификатом Let’s Encrypt домен.
# Service settings
DRONE_SECRET=secret_generated_on_command_line
DRONE_HOST=https://example.com
Затем настройте интеграцию с провайдером, в данном случае это GitHub. Настройки могут отличаться в зависимости от потребностей проекта и настройки GitHub.
Заблокируйте установку Drone и отключите открытую регистрацию, установив в DRONE_OPEN значение false. Это означает, что войти смогут только учетные записи GitHub, которые указаны в DRONE_ADMIN.
Примечание: Если ваша команда разработчиков работает в качестве организации GitHub, лучше установить в DRONE_OPEN значение true и заменить DRONE_ADMIN на DRONE_ORGS. Параметр DRONE_ORGS позволяет указать одну или несколько организаций GitHub, чьи члены должны иметь доступ. Drone разблокирует регистрацию для пользователей, которые принадлежат к этим группам.
В DRONE_ADMIN нужно указать имя пользователя GitHub.
Затем активируйте плагин интеграции GitHub, установив в DRONE_GITHUB значение true. В строках DRONE_GITHUB_CLIENT и DRONE_GITHUB_SECRET укажите ключи, которые вы скопировали со страницы приложения GitHub OAuth во время регистрации приложения Drone.
# Service settings
DRONE_SECRET=secret_generated_on_command_line
DRONE_HOST=https://example.com
# Registration settings
DRONE_OPEN=false
DRONE_ADMIN=8hostblog
# GitHub Settings
DRONE_GITHUB=true
DRONE_GITHUB_CLIENT=Client_ID_from_GitHub
DRONE_GITHUB_SECRET=Client_Secret_from_GitHub
Настройка сервера завершена. Скопируйте значение DRONE_SECRET, а затем сохраните и закройте файл. Этот же ключ пригодится в настройке агента.
Файл переменных среды агента Drone
Создайте файл среды для агента Drone.
sudo nano /etc/drone/agent.env
В нем нужно определить только два значения. DRONE_SECRET должен соответствовать значению в файле server.env.
Параметр DRONE_SERVER будет определять способ подключения агента к серверному компоненту Drone. Значение начинается с префикса протокола wss:// (что значит, что соединение будет использовать зашифрованный веб-сокет), за которым следует доменное имя сервера Drone с секциями /ws/broker:
DRONE_SECRET=secret_generated_on_command_line
DRONE_SERVER=wss://example.com/ws/broker
Сохраните и закройте файл.
Unit-файл для Drone
После этого нужно определить файл unitd для управления службой Drone.
Откройте конфигурационный файл .service в каталоге /etc/systemd/system, чтобы настроить сервис:
sudo nano /etc/systemd/system/drone.service
Вставьте в файл:
[Unit]
Description=Drone server
After=docker.service nginx.service
[Service]
Restart=always
ExecStart=/usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml up
ExecStop=/usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml stop
[Install]
WantedBy=multi-user.target
Первый раздел указывает, что сервис нужно запускать после Docker и Nginx. Второй раздел настраивает перезапуск сервиса в случае сбоев и определяет команды для запуска и остановки сервиса Drone с помощью Docker Compose и файла переменных среды. Последний раздел добавляет сервис в автозагрузку.
Сохраните и закройте файл.
Прежде чем запустить сервис Drone, нужно настроить Nginx. Агент Drone должен иметь возможность подключаться к серверу Drone, для такого соединения необходим прокси-сервер Nginx.
Nginx как прокси-сервер Drone
Затем нужно изменить конфигурацию Nginx и настроить проксирование запросов на сервер Drone.
Откройте файл блока server, который обрабатывает защищенный сертификатом домен. Запросите атрибут server_name во всех включенных блоках server:
grep -R server_name /etc/nginx/sites-enabled
/etc/nginx/sites-enabled/default: server_name example.com;
/etc/nginx/sites-enabled/default: return 301 https://$server_name$request_uri;
/etc/nginx/sites-enabled/default: server_name example.com;
/etc/nginx/sites-enabled/default:# server_name example.com;
Согласно выводу домен (example.com) определяется в файле /etc/nginx/sites-enabled/default. Нужно отредактировать файл, связанный с этим доменным именем.
Возможно, в выводе будет что-то вроде:
/etc/nginx/sites-enabled/default: server_name _;
/etc/nginx/sites-enabled/default: return 301 https://$server_name$request_uri;
/etc/nginx/sites-enabled/default: server_name _;
/etc/nginx/sites-enabled/default:# server_name example.com;
В приведенном выше примере строки server_name _; представляют резервные блоки server. Спецификатор хоста «_» определяет недействительный хост.
В конфигурации они связаны с директивами listen, которые устанавливают параметр default_server, благодаря чему блок действует по умолчанию, когда запрашиваемый хост не соответствует ни одному блоку server. Если вы не можете найти определение server_name, которое соответствует вашему доменному имени, используйте файл, который определяет эти резервные блоки.
Откройте файл в редакторе:
sudo nano /etc/nginx/sites-enabled/default
Добавьте два раздела вне блока server.
upstream drone {
server 127.0.0.1:8000;
}
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
. . .
Первый блок upstream настраивает drone, куда можно проксировать запросы. Директива server определяет способ подключения к сервису Drone по порту 8000.
Второй блок задает пользовательскую переменную $connection_upgrade на основе значения переменной $http_upgrade, которую Nginx устанавливает при получении HTTP-заголовка Upgrade. Если получен заголовок Upgrade, Nginx установит в переменной $connection_upgrade значение upgrade. Если заголовка нет, переменная получит значение close. Эти переменные позволяют устанавливать правильные заголовки при проксировании запросов WebSocket.
Затем найдите блок server с директивой listen 443. Замените содержимое блока location / следующим блоком. Обязательно закомментируйте или удалите любые другие опции в этом блоке, чтобы избежать конфликтов.
. . .
server {
listen 443 ssl;
. . .
location / {
# try_files $uri $uri/ =404;
proxy_pass http://drone;
include proxy_params;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_redirect off;
proxy_http_version 1.1;
proxy_buffering off;
chunked_transfer_encoding off;
proxy_read_timeout 86400;
}
. . .
}
Строка proxy_pass передает весь трафик, обслуживаемый этим блоком, в предыдущий, который вы определили ранее. Затем блок содержит определения заголовков прокси из файла proxy_params и дополнительные заголовки на основе параметров map.
Затем идут другие параметры прокси-сервера, что обеспечивает правильную работу прокси-сервера WebSocket и взаимодействие компонентов.
Тестирование настройки и перезапуск Nginx и Drone
Настройка завершена. Теперь нужно запустить или перезапустить сервисы.
Сначала проверьте настройки Nginx на наличие ошибок:
sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
Если вывод сообщит об ошибках, вернитесь в файл и проверьте конфигурацию Nginx.
Когда ошибок не будет, перезапустите Nginx:
sudo systemctl restart nginx
Теперь, когда Nginx работает как прокси-сервер между агентом и сервером, можно запустить Drone:
sudo systemctl start drone
Убедитесь, что сервер успешно запущен:
sudo systemctl status drone
drone.service - Drone server
Loaded: loaded (/etc/systemd/system/drone.service; disabled; vendor preset: enabled)
Active: active (running) since Fri 2017-06-09 21:56:33 UTC; 2min 58s ago
Main PID: 15225 (docker-compose)
Tasks: 5
Memory: 37.7M
CPU: 1.544s
CGroup: /system.slice/drone.service
├─15225 /usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml up
└─15228 /usr/local/bin/docker-compose -f /etc/drone/docker-compose.yml up
. . .
Jun 09 21:56:35 drone docker-compose[15225]: drone-agent_1 | pipeline: request next execution
Если в выводе есть строка active (running) и нет ошибок, значит, сервис Drone работает правильно.
В случае ошибки проверьте логи Nginx:
sudo less /var/log/nginx/error.log
Чтобы проверить логи Drone, введите:
sudo journalctl -u drone
Если ошибок нет, можно добавить Drone в автозагрузку:
sudo systemctl enable drone
Вход в Drone
Теперь нужно войти в интерфейс приложения Drone и авторизовать взаимодействие с аккаунтом GitHub.
Посетите доменное имя своего сервера в веб-браузере, чтобы открыть веб-интерфейс Drone:
https://example.com
При первом входе нужно ввести учетные данные.
Нажмите login, чтобы аутентифицироваться в Drone с помощью учетной записи GitHub и OAuth. Если вы еще не вошли в GitHub, вам будет необходимо сначала войти в аккаунт GitHub.
После этого вам будет предложено разрешить Drone получать доступ к учетной записи GitHub.
Просмотрите запрашиваемые разрешения и внесите любые поправки. А затем нажмите Authorize username.
Вы будете перенаправлены на сервер Drone.
Здесь можно настраивать и автоматически тестировать новый код в репозитории.
Чтобы настроить Drone для автоматического запуска тестов и определить файл .drone.yml, ознакомьтесь с документацией Drone.