Как настроить автоматическое удаление временной тестовой среды после завершения тестов

После выполнения автоматизированных тестов временная среда (контейнер, виртуальная машина, слот в кластере) должна удаляться, иначе ресурсы тратятся впустую, а накопленные артефакты могут повлиять на последующие запуски. Надёжная очистка работает независимо от результата тестов и выполняется даже при прерывании пайплайна.

Основные подходы к автоматической очистке

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

Очистка на уровне контейнеров

Если тесты запускаются в изолированных контейнерах (Docker, podman), удаление выполняется после завершения контейнера. Самый простой способ — запускать контейнер с флагом —rm, который заставляет движок автоматически удалить его после остановки. В системах CI можно указать этот флаг в шаге запуска тестов.

Очистка в Kubernetes

В кластере Kubernetes типичный паттерн — запуск тестов как Job или CronJob. После завершения пода можно задать параметр ttlSecondsAfterFinished, который указывает контроллеру удалить объект через заданное число секунд. Это работает независимо от того, завершился Job успешно или с ошибкой.

Очистка виртуальных машин в облаке

Когда тестовая среда представляет собой VM (например, в AWS EC2, GCP Compute Engine, Azure VM), удаление обычно выполняется скриптом, который после завершения тестов вызывает API провайдера дляterminate/instances. Чтобы гарантировать выполнение даже при падении скрипта, такой шаг помещают в блок finally или используют hook‑механизмы CI (например, after_script в GitLab CI).

Очистка через инфраструктуру как код (IaC)

Если среда создаётся с помощью Terraform, Pulumi или Ansible, удаление можно реализовать как отдельный шаг destroy или undeploy. Важно, чтобы этот шаг был идемпотентным: повторный запуск не должен вызывать ошибок, если ресурсы уже удалены.

Ключевые критерии выбора метода очистки

При оценке подхода учитывайте следующие факторы:

  • Связь с созданием среды. Чем ближе точка удаления к точке создания, тем проще гарантировать, что никакие ресурсы не останутся «забытыми».
  • Надёжность при аварийном завершении. Метод должен срабатывать даже если тесты падают, таймаут превышается или процесс получает сигнал SIGTERM.
  • Простота настройки и поддержки. Предпочтительно использовать встроенные возможности платформы (флаги, параметры) вместо написания собственных скриптов.
  • Стоимость простоя. Чем быстрее происходит удаление, тем меньше платё за выделенные ресурсы (особенно важно в облаке с оплатой за секунду).
  • Совместимость с существующим пайплайном. Метод должен легко интегрироваться в текущие этапы CI/CD без существенной переработки конфигурации.

Пошаговая настройка в популярных системах CI/CD

GitLab CI

  1. Определите job, который поднимает тестовую среду (например, запускает docker‑compose или применяет Terraform).
  2. В том же job добавьте секцию after_script, где разместите команду очистки: docker compose down -v для Docker Compose, terraform destroy -auto-approve для Terraform или вызов API облака для удаления VM.
  3. Если используете Kubernetes Job, задайте ttlSecondsAfterFinished: 300 в спецификации job, чтобы объект удалялся через 5 минут после завершения.
  4. Проверьте, что очистка выполняется и при падении job: добавьте when: on_failure к отдельному job с той же командой очистки, либо rely on after_script, который исполняется независимо от результата.

GitHub Actions

  1. В шаге, который поднимает окружение, используйте действие с параметром continue-on-error: false (по умолчанию).
  2. После этого шага добавьте новый шаг с условием if: always(), который выполнит очистку. Пример для Docker: docker compose down -v.
  3. Для Kubernetes можно использовать действие azure/k8s-set-context seguida kubectl delete job или полагаться на ttlSecondsAfterFinished в манифесте job.
  4. Для облачных VM вызов CLI провайдера (aws ec2 terminate-instances, gcloud compute instances delete) поместите в шаг с if: always().

Jenkins

  1. В Declarative Pipeline разместите блок post с условиями always и/или failure.
  2. Внутри always { sh ‘docker compose down -v’ } разместите команду очистки.
  3. Если используете Kubernetes Plugin, указывайте ttlSecondsAfterFinished в шаблоне pod.
  4. Для VM добавьте шаг sh ‘aws ec2 terminate-instances —instance-ids $INSTANCE_ID’ внутри блока post.

Сравнение вариантов очистки

Метод Где применяется Преимущества Ограничения
—rm у контейнера Docker/podman в локальном запуске или CI Простейшая настройка, гарантирует удаление после остановки контейнера Не подходит, если нужно сохранять логи или артефакты после теста (требуется предварительная выгрузка)
Kubernetes Job с ttlSecondsAfterFinished Кластеры K8s Автоматичное удаление без дополнительных шагов, работает при любом завершении job Требует доступа к API кластера, минимальная задержка равна указанному ttl
Скрипт очистки в блоке after_script / post { always } Любая CI‑система, поддерживающая хуки после выполнения Гибкость: можно выполнять дополнительные действия (сохранение артефактов, уведомления) Нужно правильно обработать коды возврата и обеспечить идемпотентность
IaC destroy (Terraform, Pulumi, Ansible) Инфраструктура, описываемая кодом Удаляет всё, что было создано тем же кодом, обеспечивает согласованность Может быть дольше из‑за этапа планирования; требует корректного хранения состояния

Типичные ошибки и как их избежать

  • Забыть про ошибки. Если очистка помещена только в блок success, она не выполнится при падении тестов. Решение — использовать условия always или finally.
  • Не проверять идемпотентность. Повторный запуск команды удаления может завершиться ошибкой, если ресурс уже отсутствует. Используйте флаги вроде -f, —force или проверяйте существование перед удалением.
  • Удалять слишком рано. Очистка, расположенная перед завершением сохранения логов или артефактов, приведёт к потере полезной информации. Размещайте очистку после всех шагов, которые могут потребовать артефактов.
  • Зависимость от переменных окружения, которые не установлены в случае аварии. Если идентичник VM хранится только в переменной, которая теряется при крахе скрипта, очистка не сработает. Сохраняйте идентификаторы в надёжном месте (файл, артефакт, вывод предыдущего шага) перед выполнением тестов.
  • Избыточная задержка. Большие значения ttlSecondsAfterFinished prowadzą к ненужному потреблению ресурсов. Подбирайте минимальное достаточного времени (обычно 5‑10 минут достаточно, чтобы собрать логи).

Практический checklist перед запуском пайплайна

  1. Убедитесь, что точка создания среды и точка её удаления находятся в одном job/стадии или связаны через надёжный механизм передачи идентификатора.
  2. Проверьте, что команда очистки идемпотентна (можно запустить дважды подряд без ошибок).
  3. Запустите пайплайн с намеренным падением теста (например, добавьте exit 1 в скрипт) и подтвердите, что очистка всё равно сработала.
  4. Если сохраняете логи или артефакты, выгрузите их до шага очистки и проверьте их наличие после завершения job.
  5. Измерьте время между окончанием тестов и фактическим удалением ресурсов; убедитесь, что оно соответствует вашим требованиям по стоимости.
  6. Документируйте порядок действий в файле README или в комментариях к пайплайну, чтобы новые члены команды могли быстро воспроизвести процесс.

Что делать дальше

Начните с самого простого варианта, доступного в вашей текущей инфраструктуре:

  • Если вы уже используете Docker Compose в локальном запуске или CI, добавьте флаг —rm к команде docker compose up.
  • Если тесты запускаются в Kubernetes, проверьте, есть ли у вашего Job параметр ; если нет — добавьте его со значением 300 секунд.
  • Для облачных VM создайте отдельный шаг в пайплайне с условием always() (GitHub Actions) или post { always } (Jenkins), который вызывает соответствующий CLI‑командой terminate.

После внедрения базовой очистки проведите проверку по checklist выше, затем, если нужно, улучшайте процесс: добавляйте сохранение артефактов, настройте уведомления об unsuccessful cleanup или переходите к более продвинутым подходам (например, использование GitLab environment с автоматическим stop_action).

PEFile.ru