Налаштування CD через gitlab

Якось замислився я про автоматизацію розгортання свого проекту. gitlab.com люб'язно надає для цього всі інструменти, і я, звичайно, вирішив скористатися, розібравшись і написавши невеликий сценарій деплою. У статті я ділюся своїм досвідом із спільнотою.

TL, д-р

  1. Налаштувати VPS: відключити root, вхід паролем, поставити dockerd, налаштувати ufw
  2. Згенерувати сертифікати для сервера та клієнта docs.docker.com/engine/security/https/#create-a-ca-server-and-client-keys-with-openssl Увімкнути керування dockerd через tcp сокет: прибрати опцію -H fd:// з конфігу докеру.
  3. Прописати шляхи до сертифікатів у docker.json
  4. Прописати в змінні gitlab у налаштуваннях CI/CD із вмістом сертифікатів. Написати скрипт .gitlab-ci.yml для деплою.

Всі приклади я показуватиму на дистрибутиві Debian.

Початкове налаштування VPS

Ось ви купили інстанс наприклад на DOперше, що необхідно зробити, це захистити ваш сервер від агресивного зовнішнього світу. Я не буду нічого доводити і стверджувати, просто покажу лог /var/log/messages свого віртуального сервера:

СкріншотНалаштування CD через gitlab

По-перше встановимо фаєрвол ufw:

apt-get update && apt-get install ufw

Включимо політику за замовчуванням: блокуємо всі вхідні з'єднання, дозволяємо всі вихідні з'єднання:

ufw default deny incoming
ufw default allow outgoing

Важливо: не забудемо дозволити з'єднання по ssh:

ufw allow OpenSSH

Загальний синтаксис такий: Дозволити з'єднання по порту: ufw allow 12345, де 12345 - номер порту або назва сервісу. Заборонити: ufw deny 12345

Включаємо фаєрвол:

ufw enable

Виходимо із сесії і знову логінимось по ssh.

Додайте користувача, призначте йому пароль та додайте його до групи sudo.

apt-get install sudo
adduser scoty
usermod -aG sudo scoty

Далі за планом слід відключити вхід паролем. для цього скопіюйте ваш ssh-ключ на сервер:

ssh-copy-id [email protected]

ip сервер повинен бути вказаний ваш. Спробуйте тепер залогінити під створеним раніше користувачем, пароль вводити більше не треба. Далі в налаштуваннях конфігурації змінюємо наступне:

sudo nano /etc/ssh/sshd_config

відключаємо вхід за паролем:

PasswordAuthentication no

Перезапускаємо демон sshd:

sudo systemctl reload sshd

Тепер, якщо ви чи хтось інший спробує увійти через користувача root, у нього нічого не вийде.

Далі ставимо dockerd, тут процес вже не описуватиму, так як все може бути вже змінено, сходіть за посиланням на офіційний сайт і пройдіть етапи встановлення docker на вашу віртуалку: https://docs.docker.com/install/linux/docker-ce/debian/

Генерація сертифікатів

Щоб керувати демоном докера, віддалено потрібне шифроване TLS з'єднання. Для цього необхідно мати сертифікат та ключ, які треба згенерувати та перенести на віддалену вашу машину. Дотримуйтесь кроків, вказаних в інструкції на офіційному сайті docker: https://docs.docker.com/engine/security/https/#create-a-ca-server-and-client-keys-with-openssl Усі згенеровані файли *.pem для сервера, а саме ca.pem, server.pem, key.pem треба помістити в директорію /etc/docker на сервері.

Налаштування dockerd

У сценарії запуску демона docker прибираємо опцію -H df://, ця опція відповідає, на якому хості можна управляти демоном докера.

# At /lib/systemd/system/docker.service
[Service]
Type=notify
ExecStart=/usr/bin/dockerd

Далі слід створити файл налаштувань, якщо його ще немає та прописати опції:

/etc/docker/docker.json

{
  "hosts": [
    "unix:///var/run/docker.sock",
    "tcp://0.0.0.0:2376"
  ],
  "labels": [
    "is-our-remote-engine=true"
  ],
  "tls": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server.pem",
  "tlskey": "/etc/docker/key.pem",
  "tlsverify": true
}

Дозволимо підключення по порту 2376:

sudo ufw allow 2376

Перезапустимо dockerd з новими налаштуваннями:

sudo systemctl daemon-reload && sudo systemctl restart docker

перевіримо:

sudo systemctl status docker

Якщо все зелене, то вважаємо, що на сервері ми успішно налаштували docker.

Налаштування continuous deleivery на gitlab

Для того, щоб воркер гіталабу зміг виконувати команди на віддаленому хості докера необхідно визначитися, як і де зберігати сертифікати та ключ для шифрованого з'єднання з dockerd. Я вирішив цю проблему просто прописавши в змінні в налаштуваннях gitlbab:

Заголовок спойлераНалаштування CD через gitlab

Просто виводьте вміст сертифікатів та ключа через cat: cat ca.pem. Копіюєте і вставляєте значення змінних.

Пропишемо сценарій для деплою через гітлаб. Використовуватиме docker-in-docker (dind) образ.

.gitlab-ci.yml

image:
  name: docker/compose:1.23.2
  # перепишем entrypoint , чтобы работало в dind
  entrypoint: ["/bin/sh", "-c"]

variables:
  DOCKER_HOST: tcp://docker:2375/
  DOCKER_DRIVER: overlay2

services:
  - docker:dind

stages:
  - deploy

deploy:
  stage: deploy
  script:
    - bin/deploy.sh # скрипт деплоя тут

Вміст скрипту деплою з коментарями:

bin/deploy.sh

#!/usr/bin/env sh
# Падаем сразу, если возникли какие-то ошибки
set -e
# Выводим, то , что делаем
set -v

# 
DOCKER_COMPOSE_FILE=docker-compose.yml
# Куда деплоим
DEPLOY_HOST=185.241.52.28
# Путь для сертификатов клиента, то есть в нашем случае - gitlab-воркера
DOCKER_CERT_PATH=/root/.docker

# проверим, что в контейнере все имеется
docker info
docker-compose version

# создаем путь (сейчас работаем в клиенте - воркере gitlab'а)
mkdir $DOCKER_CERT_PATH
# изымаем содержимое переменных, при этом удаляем лишние символы добавленные при сохранении переменных.
echo "$CA_PEM" | tr -d 'r' > $DOCKER_CERT_PATH/ca.pem
echo "$CERT_PEM" | tr -d 'r' > $DOCKER_CERT_PATH/cert.pem
echo "$KEY_PEM" | tr -d 'r' > $DOCKER_CERT_PATH/key.pem
# на всякий случай даем только читать
chmod 400 $DOCKER_CERT_PATH/ca.pem
chmod 400 $DOCKER_CERT_PATH/cert.pem
chmod 400 $DOCKER_CERT_PATH/key.pem

# далее начинаем уже работать с удаленным docker-демоном. Собственно, сам деплой
export DOCKER_TLS_VERIFY=1
export DOCKER_HOST=tcp://$DEPLOY_HOST:2376

# проверим, что коннектится все успешно
docker-compose 
  -f $DOCKER_COMPOSE_FILE 
  ps

# логинимся в docker-регистри, тут можете указать свой "местный" регистри
docker login -u $DOCKER_USER -p $DOCKER_PASSWORD

docker-compose 
  -f $DOCKER_COMPOSE_FILE 
  pull app
# поднимаем приложение
docker-compose 
  -f $DOCKER_COMPOSE_FILE 
  up -d app

Основна проблема в тому, щоб «витягнути» зі змінних gitlab CI/CD вміст сертифікатів у нормальному вигляді. Я не міг зрозуміти, чому не працювало з'єднання з віддаленим хостом. На хості подивився журнал sudo journalctl -u docker, там помилка при рукостисканні. Вирішив глянути, що взагалі зберігається в змінних, для цього можна подивитись так cat -A $DOCKER_CERT_PATH/key.pem. Помилка подолала, додавши видалення символу каретки tr -d 'r'.

Далі до сценарію можна додати пост-релізні таски на свій розсуд. Ознайомитись з робочою версією можете у моєму репозиторії https://gitlab.com/isqad/gitlab-ci-cd

Джерело: habr.com

Додати коментар або відгук