Продолжаю разбираться с GitLab. Установил docker runner для сборки и тестирования тестового проекта «hello». И внезапно возник вопрос — а как это работает? В общих чертах понятно, но как более детально?
В pipeline я добавил команду sleep на 30 минут, которая задержит выполнение и даст провести кое-какие эксперименты:
build:
stage: build
image: alpine:latest
tags:
- build
script:
- cat /etc/os-release
- sleep 1800
Ищем PID процесса
Теперь на сервере, где запущен этот runner, находим процесс:
ps aux | grep sleep
Получился такой вывод:
root 909153 0.0 0.0 1612 8 ? S 00:07 0:00 sleep 1800
909153 — PID процесса. Посмотреть командную строку можно так:
cat /proc/909153/cmdline
# вывод:
sleep1800
Однако аргументы в ней перечислены через нулевой символ, и поэтому плохо читаются. Это можно исправить 2 способами:
# 1 способ
cat /proc/PID/cmdline | tr '\000' ' '
# 2 способ
cat /proc/PID/cmdline | xargs -0 echo
# вывод:
sleep 1800
Хорошо, теперь нужно найти всю цепочку родителей. Делается так:
pstree -sg 909153
# Вывод
systemd(1)───containerd-shim(909074)───sh(909099)───sh(909099)───sleep(909099)
Ищем билд-контейнер
Теперь попробуем найти контейнер, в котором запущена эта команда. Для этого я определил функцию, которую сохранил в ~/.zshrc. Также будет работать способ: просто вставить в терминал.
# Определение контейнера по PID процесса в системе (ps aux | grep php-fpm, например)
pidcont(){SCAN_PID=`pstree -sg $1 | head -n 1 | grep -Po 'shim\([0-9]+\)---.*?\(\K[^)]*'`; docker ps -q | xargs docker inspect --format '{{.State.Pid}}, {{.Name}}' | grep "${SCAN_PID}"}
Затем вызываем:
pidcont 909153
Этот скрипт взят из enSO и доработал регулярку. Вывод:
909099, /runner-1osnsbqh-project-6-concurrent-0-73b16fd95f3e5d07-build-2
Рассматриваем билд-контейнер
Отлично, теперь у нас есть название контейнера.
Посмотрим, что выдаст эта команда:
docker inspect runner-1osnsbqh-project-6-concurrent-0-73b16fd95f3e5d07-build-2
Из интересного — делаются docker volume, которые монтируются в /cache и /build. Можно посмотреть переменные окружения (CI_* и другие).
Входим в контейнер:
docker exec -it runner-1osnsbqh-project-6-concurrent-0-73b16fd95f3e5d07-build-2 sh
Смотрим процессы:
# ps
PID USER TIME COMMAND
1 root 0:00 /bin/sh
10 root 0:00 /bin/sh
13 root 0:00 sleep 1800
20 root 0:00 sh
26 root 0:00 ps
Теперь мы находимся внутри контейнера, в котором происходит сборка, и можем делать что угодно! Например, посмотреть все переменные окружения:
# cat /proc/1/environ | tr '\000' ' '
# вывод (сокращен)
FF_USE_WINDOWS_LEGACY_PROCESS_STRATEGY=true FF_SCRIPT_SECTIONS=false FF_POSIXLY_CORRECT_ESCAPES=false CI_BUILD_ID=20 ...
Затем я перешел в каталог «build», где происходит сборка проекта. Там оказался ожидаемый каталог «hello» и в добавок к нему — «hello.tmp»:
.
├── hello
│ ├── README.md
│ └── docker-compose.yml
└── hello.tmp
├── CI_SERVER_TLS_CA_FILE
└── git-template
└── config
В этом tmp-каталоге находится сертификат и конфигурация git. Ничего интересного.
Под конец я убил основной sleep: kill 13. Это привело с завершению работы контейнера, а в GitLab высветилось сообщение:
ERROR: Job failed: exit code 143
gitlab-ctl
Напоследок — немного об этой команде. GitLab у меня запущен в докер-контейнере. Что именно там работает было секретом для меня. Конечно, можно посмотреть сорцы. Я сделал проще:
# Входим в контейнер
docker-compose exec gitlab bash
# Запускаем получение статусов
gitlab-ctl status
run: gitaly: (pid 291) 829684s; run: log: (pid 340) 829681s
run: gitlab-kas: (pid 524) 829672s; run: log: (pid 545) 829669s
run: gitlab-workhorse: (pid 752) 829620s; run: log: (pid 635) 829651s
run: logrotate: (pid 162536) 1689s; run: log: (pid 270) 829695s
run: nginx: (pid 638) 829648s; run: log: (pid 653) 829645s
run: postgresql: (pid 422) 829678s; run: log: (pid 434) 829675s
run: puma: (pid 548) 829666s; run: log: (pid 557) 829663s
run: redis: (pid 274) 829690s; run: log: (pid 288) 829687s
run: registry: (pid 770) 829620s; run: log: (pid 696) 829639s
run: sidekiq: (pid 561) 829660s; run: log: (pid 576) 829659s
run: sshd: (pid 31) 829706s; run: log: (pid 30) 829706s
Таким способом получаем список всех компонентов.