Pag-setup ng CD sa pamamagitan ng gitlab

Minsan naisip ko ang pag-automate ng deployment ng aking proyekto. Ang gitlab.com ay magiliw na nagbibigay ng lahat ng mga tool para dito, at siyempre nagpasya akong gamitin ito sa pamamagitan ng pag-uunawa nito at pagsulat ng isang maliit na script ng pag-deploy. Sa artikulong ito, ibinabahagi ko ang aking karanasan sa komunidad.

Tl; DR

  1. I-set up ang VPS: huwag paganahin ang root, password login, i-install ang dockerd, i-configure ang ufw
  2. Bumuo ng mga sertipiko para sa server at kliyente docs.docker.com/engine/security/https/#create-a-ca-server-and-client-keys-with-openssl Paganahin ang dockerd control sa pamamagitan ng tcp socket: alisin ang -H fd:// na opsyon mula sa docker config.
  3. Magtakda ng mga path sa mga certificate sa docker.json
  4. Magrehistro sa mga variable ng gitlab sa mga setting ng CI / CD kasama ang mga nilalaman ng mga sertipiko. Sumulat ng .gitlab-ci.yml script para sa deployment.

Ipapakita ko ang lahat ng mga halimbawa sa pamamahagi ng Debian.

Paunang pag-setup ng VPS

Dito ka bumili ng isang instance halimbawa sa DO, ang unang bagay na dapat gawin ay protektahan ang iyong server mula sa agresibong labas ng mundo. Hindi ko patunayan o igigiit ang anuman, ipapakita ko lang ang /var/log/messages log ng aking virtual server:

ScreenshotPag-setup ng CD sa pamamagitan ng gitlab

Una, i-install ang ufw firewall:

apt-get update && apt-get install ufw

Paganahin ang default na patakaran: i-block ang lahat ng papasok na koneksyon, payagan ang lahat ng papalabas na koneksyon:

ufw default deny incoming
ufw default allow outgoing

Mahalaga: huwag kalimutang payagan ang koneksyon sa pamamagitan ng ssh:

ufw allow OpenSSH

Ang pangkalahatang syntax ay: Payagan ang koneksyon sa port: ufw allow 12345, kung saan ang 12345 ay ang port number o pangalan ng serbisyo. Deny: ufw deny 12345

I-on ang firewall:

ufw enable

Lumabas kami sa session at mag-log in muli sa pamamagitan ng ssh.

Magdagdag ng user, magtalaga sa kanya ng password, at idagdag siya sa sudo group.

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

Susunod, ayon sa plano, dapat mong huwag paganahin ang pag-login sa password. para magawa ito, kopyahin ang iyong ssh key sa server:

ssh-copy-id [email protected]

Ang ip ng server ay dapat na sa iyo. Ngayon subukang mag-log in sa ilalim ng user na nilikha ng mas maaga, hindi mo na kailangang magpasok ng isang password. Susunod, sa mga setting ng pagsasaayos, baguhin ang sumusunod:

sudo nano /etc/ssh/sshd_config

huwag paganahin ang pag-login ng password:

PasswordAuthentication no

I-restart ang sshd daemon:

sudo systemctl reload sshd

Ngayon kung ikaw o ibang tao ay sumusubok na mag-log in bilang root, ito ay mabibigo.

Susunod, nag-install kami ng dockerd, hindi ko ilalarawan ang proseso dito, dahil ang lahat ay maaari nang mabago, sundin ang link sa opisyal na website at dumaan sa mga hakbang ng pag-install ng docker sa iyong virtual machine: https://docs.docker.com/install/linux/docker-ce/debian/

Pagbuo ng sertipiko

Upang makontrol ang docker daemon nang malayuan, kinakailangan ang isang naka-encrypt na koneksyon sa TLS. Para magawa ito, kailangan mong magkaroon ng certificate at key na kailangan mong gawin at ilipat sa iyong remote na makina. Sundin ang mga hakbang na ibinigay sa mga tagubilin sa opisyal na website ng docker: https://docs.docker.com/engine/security/https/#create-a-ca-server-and-client-keys-with-openssl Lahat ng nabuong *.pem file para sa server, katulad ng ca.pem, server.pem, key.pem, ay dapat ilagay sa /etc/docker directory sa server.

setup ng docker

Sa docker daemon startup script, alisin ang -H df:// na opsyon, ang opsyong ito ay nagsasabi kung aling host ang docker daemon ay maaaring kontrolin.

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

Susunod, lumikha ng isang file ng mga setting kung wala pa ito at itakda ang mga pagpipilian:

/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
}

Payagan ang mga koneksyon sa port 2376:

sudo ufw allow 2376

I-restart ang dockerd gamit ang mga bagong setting:

sudo systemctl daemon-reload && sudo systemctl restart docker

Suriin natin:

sudo systemctl status docker

Kung berde ang lahat, pagkatapos ay isinasaalang-alang namin na matagumpay naming na-configure ang docker sa server.

Pagse-set up ng tuluy-tuloy na paghahatid sa gitlab

Upang ang manggagawang gitalab ay makapagsagawa ng mga utos sa isang malayuang docker host, kailangan mong magpasya kung paano at saan mag-iimbak ng mga sertipiko at isang susi para sa isang naka-encrypt na koneksyon sa dockerd. Nalutas ko ang problemang ito sa pamamagitan lamang ng pagsulat sa mga variable sa mga setting ng gitlbab:

pamagat ng spoilerPag-setup ng CD sa pamamagitan ng gitlab

I-output lamang ang mga nilalaman ng mga sertipiko at susi sa pamamagitan ng pusa: cat ca.pem. Kopyahin at i-paste sa mga variable na halaga.

Sumulat tayo ng script para sa pag-deploy sa pamamagitan ng gitlab. Ang docker-in-docker (dind) na imahe ay gagamitin.

.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 # скрипт дСплоя Ρ‚ΡƒΡ‚

Ang mga nilalaman ng script ng deployment na may mga komento:

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

Ang pangunahing problema ay ang "bunutin" ang mga nilalaman ng mga sertipiko sa normal na anyo mula sa mga variable ng gitlab CI / CD. Hindi ko maisip kung bakit hindi gumana ang koneksyon sa remote host. Tiningnan ko ang sudo journalctl -u docker log sa host, may error sa handshake. Nagpasya akong tingnan kung ano ang karaniwang nakaimbak sa mga variable, para dito makikita mo ang cat -A $DOCKER_CERT_PATH/key.pem. Napagtagumpayan ang error sa pamamagitan ng pagdaragdag ng pag-alis ng character na caret na tr -d 'r'.

Dagdag pa, maaari kang magdagdag ng mga post-release na gawain sa script ayon sa iyong paghuhusga. Maaari mong tingnan ang gumaganang bersyon sa aking imbakan https://gitlab.com/isqad/gitlab-ci-cd

Pinagmulan: www.habr.com

Magdagdag ng komento