Pewnego dnia pomyślałem o automatyzacji wdrażania mojego projektu. gitlab.com uprzejmie dostarcza do tego wszystkie narzędzia, więc postanowiłem skorzystać, zrozumieć i napisać mały skrypt do wdrożenia. W artykule dzielę się swoim doświadczeniem z społecznością.
TL;DR
- Skonfiguruj VPS: wyłącz root, logowanie hasłem, zainstaluj dockerd, skonfiguruj ufw
- Wygeneruj certyfikaty dla serwera i klienta Włącz zarządzanie dockerd przez gniazdo tcp: usuń opcję -H fd:// z konfiguracji dockera.
- Прописать пути до сертификатов в docker.json
- Zdefiniuj w zmiennych gitlab w ustawieniach CI/CD zawartość certyfikatów. Napisz skrypt .gitlab-ci.yml do wdrożenia.
Wszystkie przykłady będę pokazywał na dystrybucji Debian.
Początkowa konfiguracja VPS
Oto kupiłeś instancję na przykład na , pierwszą rzeczą, jaką musisz zrobić, to zabezpieczyć swój serwer przed agresywnym światem zewnętrznym. Nie będę niczego udowadniał ani twierdził, po prostu pokażę log /var/log/messages swojego wirtualnego serwera:
Zrzut ekranu
Po pierwsze zainstalujemy zaporę ufw:
apt-get update && apt-get install ufwWłączamy politykę domyślną: blokujemy wszystkie połączenia przychodzące, zezwalamy na wszystkie połączenia wychodzące:
ufw default deny incoming
ufw default allow outgoingWażne: nie zapomnij zezwolić na połączenie przez ssh:
ufw allow OpenSSHOgólny składnik jest taki: Zezwolić na połączenie przez port: ufw allow 12345, gdzie 12345 to numer portu lub nazwa usługi. Zablokować: ufw deny 12345
Włączamy zaporę:
ufw enableWychodzimy z sesji i logujemy się ponownie przez ssh.
Dodaj użytkownika, nadaj mu hasło i dodaj go do grupy sudo.
apt-get install sudo
adduser scoty
usermod -aG sudo scotyNastępnie według planu należy wyłączyć logowanie hasłem. W tym celu skopiuj swój klucz ssh na serwer:
ssh-copy-id root@10.101.10.28IP serwera powinno być Twoje. Spróbuj teraz zalogować się jako wcześniej utworzony użytkownik, hasło nie jest już potrzebne. Następnie w konfiguracji zmieniamy następujące:
sudo nano /etc/ssh/sshd_configwyłączamy logowanie hasłem:
PasswordAuthentication noRestartujemy demon sshd:
sudo systemctl reload sshdTeraz, jeśli Ty lub ktoś inny spróbuje zalogować się jako użytkownik root, nie będzie możliwe.
Następnie instalujemy dockerd, tego procesu już nie opiszę, ponieważ wszystko mogło się już zmienić, idź do linku na oficjalnej stronie i przejdź przez kroki instalacji docker na swoją wirtualkę:
Generowanie certyfikatów
Aby zarządzać demonem Dockera zdalnie, potrzebne jest zaszyfrowane połączenie TLS. W tym celu niezbędne jest posiadanie certyfikatu i klucza, które należy wygenerować i przenieść na zdalną maszynę. Postępuj zgodnie z krokami opisanymi w instrukcji na oficjalnej stronie Dockera: Wszystkie wygenerowane pliki *.pem dla serwera, a dokładniej ca.pem, server.pem, key.pem, należy umieścić w katalogu /etc/docker na serwerze.
Konfiguracja dockerd
W skrypcie uruchomieniowym demona Dockera usuwamy opcję -H df://, ta opcja odpowiada za to, z jakiego hosta można zarządzać demonem Dockera.
# At /lib/systemd/system/docker.service
[Service]
Type=notify
ExecStart=/usr/bin/dockerdNastępnie należy utworzyć plik konfiguracyjny, jeśli jeszcze nie istnieje i wpisać opcje:
/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
}Zezwól na połączenia na porcie 2376:
sudo ufw allow 2376Uruchomimy ponownie dockerd z nowymi ustawieniami:
sudo systemctl daemon-reload && sudo systemctl restart dockerSprawdźmy:
sudo systemctl status dockerJeśli wszystko jest „zielone”, uznajemy, że na serwerze pomyślnie skonfigurowaliśmy Dockera.
Konfiguracja continuous delivery w GitLab
Aby worker GitLaba mógł wykonywać polecenia na zdalnym hoście Dockera, należy określić, jak i gdzie przechowywać certyfikaty oraz klucz do szyfrowanego połączenia z dockerd. Rozwiązałem ten problem, wpisując to w zmienne w ustawieniach GitLaba:
Nagłówek spoilera
Po prostu wyświetl zawartość certyfikatów i klucza za pomocą cat: cat ca.pem. Kopiuj i wklej do wartości zmiennych.
Utwórzmy skrypt do wdrożenia przez GitLab. Użyjemy obrazu docker-in-docker (dind).
.gitlab-ci.yml
image:
name: docker/compose:1.23.2
# przeredagujemy entrypoint, aby działał w 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 # skrypt wdrożeniowy tutaj
Zawartość skryptu wdrożeniowego z komentarzami:
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
Głównym problemem było „wyciągnięcie” z zmiennych GitLab CI/CD zawartości certyfikatów w normalnej postaci. Nie mogłem zrozumieć, dlaczego połączenie z zdalnym hostem nie działało. Na hoście sprawdziłem dziennik sudo journalctl -u docker, tam błąd przy uścisku dłoni. Postanowiłem zobaczyć, co w ogóle jest przechowywane w zmiennych, w tym celu można zobaczyć tak cat -A $DOCKER_CERT_PATH/key.pem. Błąd został naprawiony przez dodanie usunięcia znaku powrotu tr -d ‘r’.
Można dodać zadania po wydaniu do scenariusza według własnego uznania. Możesz zapoznać się z wersją roboczą w moim repozytorium.
Źródło: habr.com
