Разворачивание Rails-приложения через Gitlab CI/CD и Capistrano

Peter Bazov
8 min readMar 22, 2021

--

Rails auto deploy via Gitlab CI/CD and Capistrano

Описание

В инструкции показано, как настроить автоматическое разворачивание приложения Ruby On Rails через Gitlab CI/CD используя Capistrano с сохранением возможности запускать Capistrano локально. Разворачивание будет автоматически запускаться при публикации изменений в рабочую ветку конкретного окружения, после окончания будет отправлено уведомление в Slack.

Перед выполнением

Инструкция предполагает, что у вас:

  • Настроен облачный сервер под управлением Ubuntu с не-root пользователем с sudo правами и доступом по SSH.
  • Есть GitLab-репозиторий с Rails-приложением, в котором настроено разворачивание через Capistrano.
  • Скрипты Capistrano добавлены в репозиторий. Если ранее они у вас игнорировались git’ом, то перед их добавлением убедитесь, что все приватные данные вынесены в переменные окружения.

Алгоритм

Инструкция включает следующие шаги:

  1. Установка и регистрация GitLab Runner’а. Это программное обеспечение будет запускать CI/CD на сервере GitLab.
  2. Настройка подключения по SSH со стороны GitLab, чтобы процесс автоматического разворачивания мог производить удаленное подключение к серверу.
  3. Настройка переменных GitLab CI/CD, с помощью которых CI/CD получит доступ к приватной информации, которая отсутствует в репозитории.
  4. Создание файла .gitlab-ci.yml, в котором будет будет описан алгоритм выполнения автоматического разворачивания.
  5. Настройка уведомлений в Slack об окончании разворачивания.

Если у вас кроме Production сервера имеется Staging окружение, то рекомендуется настроить CI/CD сначала для него, а затем повторить необходимые пункты инструкции для Production.

Установка и регистрация GitLab Runner’а

Runner, это приложение, которое работает на сервере GitLab и исполняет операции CI/CD. Если у вас уже настроен Runner, то данный пункт инструкции можно пропустить.

Для начала установите саму программу Runner на сервер по этой инструкции:

Далее необходимо зарегистрировать новый экземпляр Runner’а, в котором будет исполняться CI/CD. Таких Runner’ов можно создавать несколько под разные нужды. Зарегистрируйте Runner на Linux с тегом ruby, работающий под executor’ом docker по этой инструкции:

Настройка подключения по SSH со стороны GitLab

GitLab CI/CD во время выполнения инструкций будет подключаться по SSH к облачному серверу. Необходимо настроить доступ.

Подключитесь к серверу по SSH и создайте новую пару ключей. Для этого выполните команду:

ssh-keygen -t rsa -b 2048

Пароль необходимо оставить пустым. Когда система задаст вопросы “Enter passphrase (empty for no passphrase)” и “Enter same passphrase again”, то нажимайте Enter.

Скопируйте публичную часть ключа в файл ~/.ssh/authorized_keys, выполнив команду:

cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys

Выведите на экран и скопируйте приватную часть ключа:

cat ~/.ssh/id_rsa

Далее необходимо добавить приватную часть ключа в переменную GitLab CI/CD — он имеет доступ к этим переменным и может использовать их значения в процессе выполнения. Откройте проект на GitLab и зайдите в пункт меню Settings -> CI/CD:

Разверните раздел Variables:

В поле Key введите значение SSH_PRIVATE_KEY, в поле Value вставьте приватную часть ключа.

В поле Scope можно настраивать область видимости переменной в зависимости от окружения, в котором разворачивается приложение. Для этого напечатайте его название в текстовом поле и нажмите “Create wildcard <ENVIRONMENT>”.

В результате должно получиться так:

Сохраните изменения, нажав кнопку Save variables:

Подробнее про переменные Gitlab CI/CD можно узнать здесь.

Далее необходимо добавить публичную часть ключа в настройки репозитория Project -> Settings -> Repository в качестве Deploy Key, что даст доступ к репозиторию от имени сервера через SSH:

Выведите на экран и скопируйте публичную часть ключа:

cat ~/.ssh/id_rsa.pub

Необходим только доступ на чтение, поэтому галочку Write access allowed отмечать не нужно.

После добавления ключа удостоверьтесь, что сервер имеет доступ к репозиторию. Для этого склонируйте его:

git clone git@gitlab.example.com:<GROUP>/project-sample.git

На вопрос “Are you sure you want to continue connecting (yes/no)?” отвечайте yes, чтобы добавить GitLab в список известных хостов. После проверки созданную папку можно удалить:

rm -rf project-sample/

Настройка переменных GitLab CI/CD

В проекте могут быть файлы, которые не добавлены в репозиторий посредством .gitignore и имеют свои собственные версии для разных окружений.

Предположим, что это файлы .env, Procfile и config/database.yml, версии которых для разных окружений хранятся в папке shared/<ENVIRONMENT>/ и копируются на сервер через Capistrano в момент выполнения разворачивания.

Нужно предоставить доступ к этим файлам для CI/CD. Для этого откройте окно управления переменными, в поле Type выберите File, а в поле Value вставьте контент файла:

Укажите следующие имена для файлов:

  • .envDOT_ENV
  • ProcfilePROCFILE
  • config/database.ymlDATABASE_YML

Далее для CI/CD нужно указать данные для подключения к серверу. Предположим, что скрипт Capistrano получает их из переменных окружения DEPLOY_USER, DEPLOY_PASSWORD, SERVER_ADDRESS, SSH_PORT, которые описаны в специальном файле .deploy.<ENVIRONMENT>.env. Добавьте соответствующие переменные в CI/CD с типом Variable.

Создание файла .gitlab-ci.yml

Чтобы настроить CI/CD для проекта, необходимо создать в корневом каталоге файл .gitlab-ci.yml. Файл должен присутствовать в ветке master. Переключитесь в неё:

git checkout master

Скопируйте себе следующий файл .gitlab-ci.yml:

Данный файл настраивает GitLab CI/CD на выполнение следующих действий:

  • Выполнение bundle install, чтобы запустить Capistrano.
  • Настройка подключения по SSH.
  • Копирование файлов из переменных GitLab CI/CD в нужную для Capistrano папку.
  • Создание файла с переменными окружения для Capistrano на основе переменных GitLab CI/CD.
  • Запуск Capistrano.

В файле встречаются два типа блоков: без точки в начале имени и с точкой. Блоки без точек — это прямые инструкции для CI/CD. Блоки с точкой — это вспомогательные блоки кода, на которые можно ссылаться из основных блоков:

  • В виде якорей через связку &*. Аналог определения и вызова функций в языках программирования.
  • В виде ключа extends — Аналог наследования в языках программирования.

Более детально ознакомиться с форматом файла можно здесь. Ниже приведено описание ключей из файла:

  • image — Снимок Docker, на основе которого будет создан Docker-контейнер для выполнения CI/CD. Замените версию ruby на ту, которая используется в вашем проекте.
  • stages — описывает последовательность шагов, которые нужно выполнить. В данном случае производится только автоматическое разворачивание, поэтому шаг всего один — deploy. Названия для шагов можно выдавать любые, они не фиксированы. Далее в файле будет описана реализация шагов.
  • cache — настраивает кэш Runner’а. По умолчанию при каждом новом запуске CI/CD вы получаете чистый Docker-контейнер, а значит, bundle install будет заново устанавливать все Gem’ы. Кэш позволяет сохранить их между запусками CI/CD. С помощью ключа key настроено, чтобы каждая ветка репозитория имела свой собственный кэш.
  • before_script — скрипт, который нужно выполнить перед каждым шагом. Может быть объявлен глобально, а может для каждого шага в отдельности. В данном случае настроено, чтобы перед каждым шагом выполнялся bundle install.
  • .init-ssh-script — вспомогательный блок кода для настройки SSH-подключения по открытому ключу.
  • .init-shared-script — вспомогательный блок кода для копирования файлов из переменных CI/CD в папку с проектом, где они будут видны скрипту Capistrano.
  • .init-capistrano-env-script — вспомогательный блок кода для создания файла с переменными окружения для подключения к серверу.
  • .run-capistrano-script — вспомогательный блок кода для запуска Capistrano.
  • .capistrano — вспомогательный блок кода для общего описания шага deploy. В нём с помощью ключа stage указан шаг CI/CD. Ключ tags указывает, на каком Runner’е запустить CI/CD. Ключ only.variables указывает, какие переменные должны быть настроены в CI/CD, иначе шаг не запустится. Ключ script, это основной код шага, где и запускается Capistrano.
  • capistrano:<ENVIRONMENT> — конкретная реализация шага deploy для конкретного окружения. В данном примере реализация написана для Production и Staging окружений. Ключ extends указывает, на основе какого блока создан этот шаг. Ключ only.refs ограничивает запуск CI/CD для конкретных веток. Ветка, для которой выполняется скрипт, доступна в нём под переменной $CI_COMMIT_REF_SLUG. Ключ environment указывает имя окружения, которое доступно в скрипте через специальную переменную $CI_ENVIRONMENT_NAME.

Дальнейший ход событий зависит от того, для каких окружений настроены переменные CI/CD. Если они настроены для Production, то при первой публикации изменений в ветку master запустится автоматическое разворачивание. Если они настроены только для другого окружения, например Staging, то CI/CD запустится только при публикации изменений в соответствующую ветку.

Зафиксируйте изменения в ветке и опубликуйте её на GitLab:

git add -A
git commit -m "Added file .gitlab-ci.yml"
git push origin master

Посмотреть выполнение CI/CD можно в пункте меню GitLab’a CI/CD->Pipelines:

Надпись running указывает на то, что в данный момент выполняется процесс CI/CD. Если нажмете на неё, то откроется более детальный интерфейс, в котором видно все этапы, описанные в файле .gitlab-ci.yml:

При нажатии на конкретный этап можно посмотреть логи его выполнения. Если всё сделано правильно, то в самом конце вы увидите сообщение об успехе:

Настройка уведомлений в Slack

В GitLab’е можно включить различные уведомления в Slack, но без возможности настройки текста сообщений. Обойти это ограничение можно, если вручную вызвать API-запрос на отправку сообщения в Slack.

Для начала добавьте интеграцию входящего вебхука: https://my.slack.com/services/new/incoming-webhook.

Выберите канал по-умолчанию для отправки сообщений и нажмите кнопку Add Incoming WebHooks integration:

После этого откроется экран, на котором нужно скопировать значение Webhook URL. На этой же странице вы можете настроить имя пользователя, который будет писать сообщение в Slack, его аватарку и описание:

Заполните 2 новых переменных в GitLab CI/CD без указания Scope:

  • SLACK_CHANNEL_NAME — имя канала, в который необходимо присылать уведомления по проекту. Если будете отправлять личные сообщения, то имя нужно начинать с символа @.
  • SLACK_WEBHOOK — полученный URL вебхука.

Создайте в корне проекта скрипт для отправки сообщения в Slack с названием gitlab_ci_slack_notification.sh и следующим содержанием:

Сделайте файл исполняемым:

chmod +x gitlab_ci_slack_notification.sh

Доработайте файл .gitlab-ci.yml. Добавьте в stages два новых пункта — notify_success и notify_failure, их реализации и запуск для конкретных окружений:

Теперь, после выполнения разворачивания, в Slack будет отправлено сообщение со статусом выполнения операции.

Используемые источники

--

--