Pull to refresh
Comments 20
Я возможно не верно понял Makefile, но у вас в остановке контейнеров и их чистке нет фильтрации по CI_JOB_ID. т.е убиваются контейнеры из параллельных пайпов, которые возможно еще работают?
Все верно.
Задача по расписанию на очистку раннера настроена на 5 утра. В 5 утра крайне низкая вероятность, что кто-то будет что-то пушить.
Но, если возникла необходимость почистить стенд прямо сейчас, то да. Все запущенные контейнеры будут остановлены и выполняемые задачи с интеграционными тестами упадут. Но предполагается, что запускающий понимает последствия.
Еще момент. Для очистки стенда, фильтрация по CI_JOB_ID и не предполагается. Мы же раннер чистим в принципе, а не от «ошметков» какой-либо конкретной задачи.
Ясно. Пропустил момент что вы чистите по расписанию, а не после сборки. А у вас места хватает тогда? У нас за рабочий день может быть до 100 сборок (тестируем каждый новый пуш коммитов во всех ветках). Если волумы не удалять сразу — за день гигов 100 мусора. И это с ограничением в 4 раннера.
Коммитов могло быть много, а пушей в репу вот не сильно много было. Чтоб 100 гигов за день, такого не помню.
В моей практике мы делали максимально удобно для локального запуска окружения/тестов. Разработчики прежде чем пушить гоняли тесты у себя локально. Но тут повторюсь все должно быть максимально удобно. И собрать и тесты прогнать (быстро), и в случае ошибок максимально информативные логи посмотреть. Как оказалось, разработчику проще локально все прогнать и чуть-что логи грепнуть, чем по ссылкам GitLab маневрировать.
А почему бы не фильтровать по дате запуска? Ну к примеру чистить только то, что живо более часа?

А с отменой мы вроде с помощью trap справляемся вместо after_script, но надо посмотреть точнее, возможно ошибаюсь.
trap к сожалению не работает для отмененных задач. На сколько я понял, при отмене задачи терминальная сессия убивается с SIGKILL вместе с исполняемыми в данной сессии процессами. Т.е. trap как процесс тоже убивается. Но штука определенно классная.
Почему не docker-runner и dind? Это решает проблему чистки раннера, а логи в виде артефактов так же можно сохранять и видеть в панели гитлаба.
Почему docker-compose v3? Вы же наверняка swarm не используете — так и используйте тогда v2.4
Почему не docker-runner и dind? Это решает проблему чистки раннера, а логи в виде артефактов так же можно сохранять и видеть в панели гитлаба.


Ну наверное потому, что это не так-то просто. Вы же имеете в виду запустить в dind-е демон docker, а потом в этом же dind-е запускать инстансы docker-compose?

Идея завлекательная, но вызывает кучу вопросов, которые нужно как-то решить. К примеру — как в dind будут попадать образы сервисов, например mysql? Загружаться через docker pull? Тогда загрузку этих образов придется делать каждый раз при запуске нового теста, ведь контейнер dind-а будет удален после теста, а вместе с ним и загруженные образы.

Или Вы имеете в виду что-то другое?
Нет. Вы все правильно говорите. С другой стороны, кто мешает пустить весь трафик через docker registry proxy, чтобы не скачивать образы из интернета?
Зато в плюсах у вас всегда «чистая» среда. Просто реально бывают кейсы, что образ скачан, в источнике он обновился, а пока ручками пулл не сделаешь, то и сборка пойдет на базе старого.
К тому же, между тестами можно сервисы пошарить. В общем, проблема со временем загрузки — надуманная.
Поэтому, кмк, dind — хорошая вещь.
Вы же имеете в виду запустить в dind-е демон docker, а потом в этом же dind-е запускать инстансы docker-compose?

гитлаб так не работает. Я сам долго допетрить не мог, но суть в том, что поднимается два контейнера.
Один — в котором бегут ваши тесты (и докер-клиентом, если нужно). А второй — с докер-демоном. Из контейнера с тестами с помощью docker cli можно сходить во второй контейнер и запустить еще контейнеров. А еще есть volume в котором лежат данные запусков… Рекомендую ознакомиться с документацией и поэкспериментировать.

dind — не нужен, ибо тру мозахизм. А вот образ dind с примонтированным docker.sock — вот это вещь! И кэширование работает!

Действительно, почему не docker-runner и services?
gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/ci/docker/using_docker_images.md#what-is-a-service
Делаем свои образы с центральным логированием на основном, логи в артефактах забираем.
И concurrent на одной машине без изоляции — плохо. Лично сталкивался с этим багом gitlab.com/gitlab-org/gitlab-ee/issues/2588
Лучше сделать несколько раннеров, способных работать с одним инстансом системы.

Спасибо! Весьма полезно. А какую задачу вырешали выводя CI_JOB_ID в имя контейнера?
И знали ли при -p ключ у docker-compose? Что бы можно было делать например так


  script:
    - docker-compose -f .docker/docker-compose.yml -p ${CI_COMMIT_REF_SLUG}-tests build tests
    - docker-compose -f .docker/docker-compose.yml -p ${CI_COMMIT_REF_SLUG}-tests up --exit-code-from tests tests
  after_script:
    - docker-compose -f .docker/docker-compose.yml -p ${CI_COMMIT_REF_SLUG}-tests down -v

А почему не использовать COMPOSE_PROJECT_NAME=CI_JOB_ID, в этом случае у всех контейнеров и сетей будет уникальное имя?

Там выше уже пару комментариев про изоляцию написали, но всё-таки вставлю свои более подробные пять копеек.

В первую очередь мы делаем уникальные названия сервисов для CI. Одной из уникальных переменных в GitLab CI является переменная CI_JOB_ID. Если указать container_name со значением «service-${CI_JOB_ID:-local}»...


Менять название контейнера, добавляя в него номер задания, не нужно. Изоляция одного инстанса от другого делается с помощью опции -p:

docker-compose -p $CI_JOB_ID


С этой опцией все сервисы, указанные в docker-compose.yml, будут запущены в изолированном окружении — инстансе. Каждому контейнеру инстанса будет автоматически добавлен префикс $CI_JOB_ID_ и все контейнеры инстанса будут запущены в автоматически созданной для них сети с таким же префиксом.

Во вторую очередь мы делаем общую сеть для запускаемых сервисов. Это дает нам изоляцию на уровне сети при запуске нескольких тестовых окружений.


Создавать сеть вручную тоже не нужно. Как написал выше — опция -p создаст для инстанса нужную сеть автоматически.

# Останавливаем контейнеры и удаляем сеть
docker-kill:
docker-compose -f $${CI_JOB_ID:-.indirect}/docker-compose.yml kill


Так останавливать инстанс не нужно. Вместо kill используйте down — эта команда удалит после себя мусор (контейнеры, сети и прочее) и дальнейшая очистка раннера будет не в пример проще.

Мне сейчас не хочется поштучно пересматривать Ваши команды очистки, но с большой вероятностью все они (или большая часть) окажутся не нужны.
Кстати.

Сборка логов в after_script — плохое решение и вот почему: эта процедура будет выполняться всегда, в том числе и тогда, когда тесты прошли успешно. А если тесты прошли успешно — то логи не нужны. В итоге, в случае успешного прохождения тестов тратится куча времени на ненужную сборку логов.

Сейчас у Вас, вероятно, мало логов, плюс Вы их сохраняете в артефакты всегда, без разбора, поэтому проблема Вам может быть не очевидна. Но я вот столкнулся с этим в полный рост — у меня собираются не просто логи, а видео тестирования GUI, и копирование сотен мегабайт ненужных файлов весьма напрягает.

Что с этим делать — не знаю, не нашел пока изящного решения, поэтому советов не даю, это скорее пророчество Вам на будущее:)

Решение выше предложил 411.
trap “<муваем логи в отдельную папочку>” ERR
make test


В этом случе, если make test завершится с ошибкой, то сработает перемещение логов в специальную папку, а дальше их уже собрать как артефакты. Если же все хорошо, то в логах пайплайна будет предупреждение, что артефакты не найдены.

О, спасибо за наводку на trap. Выглядит многообещающе.
Only those users with full accounts are able to leave comments. Log in, please.