0 Votes
Last modified by Сергей Коршунов on 2022/04/21 12:59

Show last authors
1 = Настройка CI/CD в GitLab для синхронизации проекта с веб-серверами =
2
3
4 Используемые термины: GitLab, CI/CD, веб-сервер, Linux.
5
6 Runner в GitLab позволяют автоматизировать рутинные задачи при обновлении проектов в репозитории. В нашем примере мы рассмотрим ситуацию, когда у нас используется сервер GitLab для хранения проекта и 5 веб-серверов, куда должны попадать изменения после выполнения git push. Мы настроим наш CI/CD на синхронизацию файлов с помощью rsyncd. Предполагается, что у нас уже установлен GitLab на Linux, в противном случае, воспользуйтесь инструкцией для Ubuntu или CentOS.
7
8 Нам потребуется выполнить:
9
10 Установку и регистрацию обработчика GitLab
11 Установка
12 Регистрация
13 Создать .gitlab-ci.yml для CI/CD с тестовым этапом
14 Настроить Rsyncd
15 На веб-серверах
16 На сервере с GitLab
17 Изменить настройку CI/CD для синхронизации проекта с веб-серверами
18 Дополнительные настройки и возможности
19 Возможные ошибки
20
21 == Установка и регистрация Runner ==
22
23 Runner — это отдельное приложение, которое запускается для выполнения заданий CI/CD. Его можно установить на любой компьютер под управлением любой популярной операционной системы (Linux, Windows, BSD, Mac OS и так далее). Также доступны различные варианты установки — из репозитория, скачивание бинарника или запуск как приложения в Docker или кластере Kubernetes. Мы выполним установку из репозитория Linux на тот же сервер, где работает наш GitLab.
24
25 === Установка ===
26
27 По умолчанию, Runner не устанавливается вместе с GitLab. Для его установки необходимо сначала настроить репозиторий — наши действия зависят от используемой системы.
28
29 ==== Настройка репозитория ====
30
31 **а) система на базе deb-пакетов (Debian / Ubuntu):**
32
33 curl -L "https:~/~/packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash
34
35 **б) система на базе RPM-пакетов (Red Hat / CentOS):**
36
37 curl -L "https:~/~/packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh" | sudo bash
38
39 **в) для систем, которые не поддерживаются GitLab, но которые основаны на базе поддерживаемых систем.**
40
41 Сначала загружаем скрипт:
42
43 wget https:~/~/packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh
44
45 //* в данном примере, загружен скрипт для систем на базе пакетов RPM.//
46
47 Открываем его на редактирование:
48
49 vi script.rpm.sh
50
51 Находим строки:
52
53 # remove whitespace from OS and dist name
54 os="${os~/~/ /}"
55 dist="${dist~/~/ /}"
56
57 И меняем их на что-то подобное:
58
59 # remove whitespace from OS and dist name
60 os="centos"
61 dist="8"
62
63 //* в данном примере мы указали, что установка будет выполняться как для CentOS 8.//
64
65 Запускаем скрипт:
66
67 bash script.rpm.sh
68
69 ==== Установка ====
70
71 После настройки репозитория, выполняем установку. Команда также зависит от типа операционной системы.
72
73 **а) для Debian / Ubuntu (системы на основе deb-пакетов):**
74
75 apt-get install gitlab-runner
76
77 **б) для Red Hat / CentOS (системы на основе RPM):**
78
79 yum install gitlab-runner
80
81 После установки gitlab-runner разрешаем автозапуск сервиса и стартуем его:
82
83 systemctl enable gitlab-runner ~-~-now
84
85 === Регистрация ===
86
87 Для корректной работы Runner его нужно связать с нашим проектом в GitLab. Для этого сначала заходим на портал последнего - переходим на страницу проекта - в меню слева выбираем **Settings** - **CI / CD**:
88
89 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/01.jpg||alt="Переходим к настройкам CI/CD нашего проекта"]]
90
91 Находим раздел **Runners**:
92
93 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/02.jpg||alt="Находим Runners в настройках CI/CD проекта"]]
94
95 Справа от названия кликаем по **Expand**:
96
97 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/03.jpg||alt="Раскрываем настройки для раннеров"]]
98
99 Находим параметры для регистрации нового раннера:
100
101 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/04.jpg||alt="Находим параметры для регистрации Runner"]]
102
103 ... и оставляем страницу открытой — она понадобиться на следующем шаге.
104
105 В командной строке нашего сервера GitLab вводим:
106
107 gitlab-runner register
108
109 //* установить и запустить Runner можно не только на локальном сервере GitLab, но мы рассмотрим только данный способ.//
110
111 Система в интерактивном режиме запросит данные для регистрации — вводим их:
112
113 Enter the GitLab instance URL (for example, https:~/~/gitlab.com/):
114 https:~/~/gitlab.dmosk.ru/
115 Enter the registration token:
116 zX_Kvkxk7ywrgwYHsod5
117 Enter a description for the runner:
118 [git-server.dmoks.ru]: DMOSK Metrics API
119 Enter tags for the runner (comma-separated):
120 dmosk, metrics, api
121 Registering runner... succeeded runner=zX_Kvkxk
122 Enter an executor: parallels, virtualbox, docker+machine, docker-ssh+machine, kubernetes, custom, docker, docker-ssh, shell, ssh:
123 shell
124
125 //* где~://
126
127 * //**https:~/~/gitlab.dmosk.ru/ —** адрес нашего сервера GitLab. Его можно увидеть на странице с параметрами, которую мы оставили открытой на предыдущем шаге. В моем случае, на данной странице ссылка была типа http, однако, при регистрации Runner мы ее должны поменять на https (если наш сервер использует его).//
128 * //**zX_Kvkxk7ywrgwYHsod5 —** токен для регистрации раннера. Его смотрим на странице с параметрами, которые мы открывали выше.//
129 * //**DMOSK Metrics API —** произвольное описание для нашего раннера.//
130 * //**dmosk, metrics, api —** теги. Рекомендуется максимально точно описывать раннер тегами.//
131 * //**shell —** выбираем исполнителя из предложенных вариантов. В нашем случае это просто командный интерпретатор.//
132
133 В конце мы должны увидеть:
134
135 Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
136
137 //* если мы получим ошибку «status couldn execute post against certificate signed by unknown authority», [[переходим к решению>>url:https://www.dmosk.ru/miniinstruktions.php?mini=gitlab-runner-web#errors-cert]] ниже.//
138
139 Обновим страницу с параметрами для регистрации раннера — ниже мы должны увидеть, что у нас появился один новый элемент. Кликаем по изображению редактирования справа от токена:
140
141 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/05.jpg||alt="Переходим к редактированию только что созданного раннера"]]
142
143 Выставляем следующие галочки для настройки Runner:
144
145 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/06.jpg||alt="Настраиваем Runner"]]
146
147 //* где~://
148
149 * //**Paused Runners don't accept new jobs —** если наш обработчик заданий приостановлен, он не принимает новые задания.//
150 * //**This runner will only run on pipelines triggered on protected branches —** Runner должен запускаться только на защищенных ветках.//
151 * //**Indicates whether this runner can pick jobs without tags —** раннер может запускать задания без тегов.//
152 * //**When a runner is locked, it cannot be assigned to other projects —** если обработчик заблокирован, его нельзя назначать для других проектов.//
153
154 И так, обработчик зарегистрирован и настроен. Переходим к созданию CI/CD.
155
156 == Создание CI/CD для проекта ==
157
158 На первоначальном этапе, мы создадим простой сценарий, который просто будет выводить путь до каталога на сервере, в котором находится проект.
159
160 Переходим в GitLab на страницу проекта и кликаем по **Set up CI/CD**:
161
162 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/07.jpg||alt="На странице проекта нужно кликнуть по Set up CI/CD"]]
163
164 //* данной кнопки может и не быть.//
165
166 ... или можно просто в корне проекта создать файл:
167
168 vi .gitlab-ci.yml
169
170 Задаем содержимое нашего сценария:
171
172 stages:
173 - test
174 \\test:
175 stage: test
176 script: echo $CI_PROJECT_DIR/
177
178 //* Из расширения файла понятно, что формат текста должен быть yml, а значит, отступы имеют значения. В данном примере мы создаем pipeline с одним единственным этапом, которое называется **test**. По данному заданию будет запускаться скрипт вывода значения переменной **$CI_PROJECT_DIR** — путь, по которому клонируется проект и где выполняется задание (если установлен **$builds_dir**, эта переменная устанавливается относительно данного значения. Список возможных переменных можно посмотреть на официальном сайте в разделе документации [[GitLab CI/CD environment variables>>url:http://docs.gitlab.com/ee/ci/variables/README.html]].//
179
180 После сохранения файла ждем несколько секунд и перезапускаем страницу — мы должны увидеть успешный результат выполнения сценария CI/CD:
181
182 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/08.jpg||alt="Задание CI/CD выполнено успешно"]]
183
184 Кликнем по значку зеленой галочки и в открывшейся странице кликаем по нашей единственной стадии:
185
186 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/09.jpg||alt="Кликаем по названию нашей стадии pipeline"]]
187
188 Мы должны увидеть ход процесса выполнения задания и результат его работы:
189
190 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/10.jpg||alt="Наш CI/CD показал нампуть до каталога на сервере, где хранится проект"]]
191
192 На этой же странице справа можно вручную запустить задание еще раз:
193
194 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/13.jpg||alt="Повторяем запуск задания"]]
195
196 CI/CD создан. Теперь необходимо подготовить систему к синхронизации данных.
197
198 == Настройка Rsyncd ==
199
200 Наша синхронизация будет выполняться с помощью Rsyncd. Это удобный инструмент, с помощью которого можно поддерживать актуальное состояние двух и более каталогов. Также у нас не возникнет проблем с правами — rsync после копирования будет задавать файлам нужного владельца и нам не нужно будет выдавать права root для runner с помощью файла sudoerst. Подробнее об [[установке и настройке Rsyncd>>url:https://www.dmosk.ru/instruktions.php?object=rsync-server]].
201
202 Настройки нужно выполнить как на веб-серверах, так и сервере с GitLab.
203
204 === Настройка на веб-серверах ===
205
206 Данные действия нужно выполнить на каждом веб-сервере. Мы должны установить и настроить в качестве сервиса rsyncd. Сначала установим его. В зависимости от типа Linux, наши действия будут различаться.
207
208 **а) Ubuntu / Debian:**
209
210 apt-get install rsync
211
212 Открываем следующий файл:
213
214 vi /etc/default/rsync
215
216 Находим запись:
217
218 RSYNC_ENABLE=false
219
220 И меняем на:
221
222 RSYNC_ENABLE=true
223
224 Запускаем:
225
226 systemctl enable rsync
227
228 systemctl start rsync
229
230 **б) CentOS 7**
231
232 yum install rsync
233
234 systemctl enable rsyncd ~-~-now
235
236 **в) CentOS 8**
237
238 yum install rsync rsync-daemon
239
240 systemctl enable rsyncd ~-~-now
241
242 После установки и запуска rsyncd, открываем его конфигурационный файл:
243
244 vi /etc/rsyncd.conf
245
246 И добавим в него следующие настройки:
247
248 max connections = 10
249 exclude = lost+found/ .gitlab-ci.yml
250 dont compress = *.gz *.tgz *.zip *.z *.Z *.rpm *.deb *.bz2 *.rar *.7z *.mp3 *.jpg
251 \\[dmosk]
252 path = /var/www/dmosk/www/
253 comment = Site dmosk.ru
254 uid = apache
255 gid = apache
256 read only = no
257 list = yes
258 auth users = rsync_dmosk
259 secrets file = /etc/rsyncd.scrt
260 #pre-xfer exec =
261 #post-xfer exec =
262 hosts allow = localhost 192.168.0.10
263 hosts deny = *
264
265 ~* наибольший интерес для нас имеют следующие опции:
266
267 * **[dmosk] —** название для экземпляра синхронизации. К нему мы будем обращаться при выполнении команды rsync.
268 * **path —** путь до каталога, в котором находятся файлы для синхронизации. Это путь до папки проекта на самом веб-сервере.
269 * **uid/gid —** пользователь и группа, от которых будет выполнена синхронизация для конкретного ресурса. Именно они будут назначены в качестве владельца файлов.
270 * **auth users —** проверка подлинности, вводом логина с паролем.
271 * **secrets file —** файл, в котором размещены логин и пароль, который будет использоваться для проверки подлинности при выполнении синхронизации.
272 * **pre-xfer exec/post-xfer exec —** команды, которые необходимо выполнить, соответственно, перед синхронизацией и после. Полезно, если наш веб-сервер необходимо перезапускать после обновления контента. Например: post-xfer exec = /usr/bin/systemctl reload uwsgi.
273 * **hosts allow —** узлы, с которых разрешено подключение для синхронизации. Тут должен быть IP-адрес нашего сервера GitLab.
274
275 Создадим файл, в котором должны быть логин и пароль для проверки подлинности rsync:
276
277 vi /etc/rsyncd.scrt
278
279 rsync_dmosk:password
280
281 //* в данном примере мы задали логин **rsync_dmosk** и пароль **password**.//
282
283 Необходимо задать минимально необходимые права на файл с аутентификационными данными:
284
285 chmod 600 /etc/rsyncd.scrt
286
287 Убедимся, что у целевого каталога выставлен правильный владелец:
288
289 chown -R apache:apache /var/www/dmosk/www
290
291 Можно перезапускать сервис:
292
293 systemctl restart rsyncd || systemctl restart rsync
294
295 Также необходимо создать правила в брандмауэре для разрешения TCP-порта 873, на котором работает rsyncd.
296
297 **а) для систем на базе deb-пакетов (Ubuntu, Debian):**
298
299 iptables -I INPUT 1 -p tcp ~-~-dport 873 -j ACCEPT
300
301 apt-get install iptables-persistent
302
303 netfilter-persistent save
304
305 **б) для систем на базе RPM-пакетов (Red Hat, CentOS):**
306
307 firewall-cmd ~-~-permanent ~-~-add-port=873/tcp
308
309 firewall-cmd ~-~-reload
310
311 Данные настройки выполняем на всех веб-серверах. После переходим к настройке сервера GitLab.
312
313 === Настройка GitLab ===
314
315 На стороне сервера GitLab мы должны настроить подключение к сервисам rsyncd. Для начала устанавливаем rsync.
316
317 **а) для систем на базе deb:**
318
319 apt-get install rsync
320
321 **б) для RPM-систем:**
322
323 yum install rsync
324
325 После создаем файл, в котором будем хранить пароль для подключения к rsyncd:
326
327 vi /etc/rsyncd.scrt
328
329 password
330
331 //* это тот пароль, который мы задали в аналогичном файле на стороне веб-серверов.//
332
333 Задаем права минимально необходимые для чтения файла с паролем:
334
335 chmod 640 /etc/rsyncd.scrt
336
337 Задаем в качестве группы владельца файла с паролем нашего пользователя **gitlab-runner**:
338
339 chown :gitlab-runner /etc/rsyncd.scrt
340
341 Создаем файл, который отправим на серверы веб в качестве теста:
342
343 touch testfile
344
345 Выполняем команду для синхронизации данного файла с веб-серверами:
346
347 for i in 1 2 3 4 5; do rsync -rult ~-~-password-file=/etc/rsyncd.scrt testfile rsync_dmosk@web-0$i::dmosk; done
348
349 //* обратите внимание, что в моем примере веб-серверы имеют имена web-01, web-02 и так далее, поэтому, чтобы не выполнять все 5 команд по отдельности, мы используем цикл, в котором подставляем разные цифры в названия серверов.//
350
351 В итоге, на стороне веб-серверов должен появиться файл testfile. Теперь остается последний шаг — настроить созданный ранее CI/CD для синхронизации.
352
353 == Настройка синхронизации в CI/CD ==
354
355 Переходим на страницу нашего проекта и кликаем по **CI/CD configuration**:
356
357 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/11.jpg||alt="Переходим к настройке CI/CD нашего проекта"]]
358
359 Чтобы открылся редактор, кликаем по **Edit**:
360
361 [[image:https://www.dmosk.ru/img/miniinstruktions/gitlab-runner-web/12.jpg||alt="Открываем редактор для изменения CI/CD"]]
362
363 Или из командной строки, можно открыть на редактирование наш файл .gitlab-ci.yml:
364
365 vi .gitlab-ci.yml
366
367 Меняем содержимое нашего файла:
368
369 stages:
370 - copy
371 \\copy:
372 stage: copy
373 script: for i in 1 2 3 4 5; do rsync -rult ~-~-delete-after ~-~-exclude=.git/ ~-~-exclude=.gitlab-ci.yml ~-~-password-file=/etc/rsyncd.scrt $CI_PROJECT_DIR/ rsync_dmosk@web-0$i::dmosk; done
374
375 //* мы заменили наш этап test на **copy**. В данном примере мы выполняем команду для запуска синхронизации с веб-серверами с помощью rsync. В качестве источника данных мы используем переменную **$CI_PROJECT_DIR**, в которой находится наш проект. В качестве экземпляра, куда синхронизируем данные используем **dmosk**.//
376
377 Готово. Пробуем выполнить git push в наш проект. Данные должны разойтись по всем веб-серверам.
378
379 == Дополнительно ==
380
381 Дополнительная информация, которая может быть полезна.
382
383 === Запуск runner внутри контейнера Docker ===
384
385 Выше мы рассмотрели регистрацию раннера, который будет запускать выполнение команд в системной оболочке (shell). Но если мы хотим, чтобы задания pipeline выполнялись внутри контейнера Docker, то пошагово мы должны сделать следующее:
386
387 ~1. При регистрации раннера на последнем этапе, где предлагается выбрать средство запуска (Enter an executor), выбираем docker:
388
389 ...
390 Enter an executor: parallels, virtualbox, docker+machine, docker-ssh+machine, kubernetes, custom, docker, docker-ssh, shell, ssh:
391 docker
392
393 2. При написании pipeline мы должны добавить опцию image с указанием образа, который хотим использовать:
394
395 ...
396 copy:
397 stage: copy
398 image~: dmosk/ubuntu:latest
399 ...
400
401 3. По умолчанию, runner всегда будет пытаться скачать образ Docker с внешнего источника. Если на целевом компьютере, где запускается runner у нас уже есть нужный образ и мы хотим, чтобы использовался именно он, открываем файл:
402
403 vi /etc/gitlab-runner/config.toml
404
405 Среди:
406
407 ~[~[runners]]
408
409 ... находим созданный раннер (определяем по описанию, которое мы задавали при регистрации) и в нем также находим **[runners.docker]**. Добавим опцию **pull_policy**:
410
411 ~[~[runners]]
412 ...
413 [runners.docker]
414 ...
415 pull_policy = "if-not-present"
416
417 Перезапустим сервис:
418
419 systemctl restart gitlab-runner
420
421 == Возможные ошибки ==
422
423 === status couldn execute post against certificate signed by unknown authority ===
424
425 Ошибка возникает при попытке зарегистрировать Runner, а при отправке curl-запроса на сервер:
426
427 curl https:~/~/gitlab.dmosk.ru
428
429 ... мы получаем сообщение о неправильном сертификате:
430
431 curl performs SSL certificate verification by default, using a "bundle"
432 of Certificate Authority (CA) public keys (CA certs). If the default
433 bundle file isn't adequate, you can specify an alternate file
434 using the ~-~-cacert option.
435 If this HTTPS server uses a certificate signed by a CA represented in
436 the bundle, the certificate verification probably failed due to a
437 problem with the certificate (it might be expired, or the name might
438 not match the domain name in the URL).
439 If you'd like to turn off curl's verification of the certificate, use
440 the -k (or ~-~-insecure) option.
441
442 **Причина:** нужна полная цепочка сертификатов.
443
444 **Решение:** подробнее, процесс настройки https описан в инструкции [[Правильная настройка SSL в NGINX>>url:https://www.dmosk.ru/miniinstruktions.php?mini=nginx-ssl]].
445
446 === @ERROR: chroot failed ===
447
448 Ошибка появляется при попытке синхронизировать файлы с применением команды rsync.
449
450 **Причины:**
451
452 ~1. На целевом сервере нет целевого каталога (указан в опции path), в который необходимо синхронизировать данные.
453
454 2. Доступ к целевой папке запрещен политикой selinux.
455
456 **Решение:** для обоих причин опишим соответствующие решения.
457
458 ~1. Проверяем наличие каталога, который мы указали в конфигурационном файле /etc/rsyncd.conf (опция path). Если его нет, создаем, например:
459
460 mkdir -p /var/www/dmosk/www
461
462 2. Для начала пробуем отключить разово selinux:
463
464 setenforce 0
465
466 Если это решило проблему, либо [[отключаем его совсем>>url:https://www.dmosk.ru/miniinstruktions.php?mini=selinux-centos]], либо настраиваем командами:
467
468 semanage fcontext -a -t rsync_data_t '/var/www(/.*)?'
469
470 restorecon -Rv '/var/www'
471
472 setsebool -P rsync_client on
473
474 //* в данном примере мы разрешам контекст безопасности **rsync_data_t** для всего содержимого каталога, где находятся наши сайты.//