Всем привет! Меня зовут Валентина, я разработчик в тестировании облака Selectel. В своей прошлой статье я рассказала, как мы автоматизировали запуск Tempest-тестов в GitLab. Статья вам понравилась, поэтому я написала продолжение.

В нашей автоматизации была проблема: после тестов ресурсы «подвисали» и не удалялись. Отработавшие тесты занимали проектные квоты и это влияло на стабильность пайплайна.

Для решения этой проблемы нам нужен был инструмент, который умеет автоматически утилизировать ресурсы после каждого теста — и мы кое-что нашли. Интересно? Тогда добро пожаловать под кат!

Используйте навигацию, если не хотите читать текст целиком:

Исследование существующих решений
Знакомство с Tempest Cleanup
Что было исправлено
Как интегрировали Cleanup в пайплайн
Заключение

Исследование существующих решений


Первое, о чем я задумалась, можно ли использовать bash-скрипты для утилизации ресурсов. Однако нашлись причины против этой идеи — и их было несколько:

  • Очистка ресурсов будет проходить в production-окружении, а значит должна быть безопасной.
  • Чтобы удаление ресурсов было безопасным, важно производить его с учетом уникальных идентификаторов (UUID) ресурсов.
  • Поскольку процесс будет выполняться от имени администратора, есть вероятность удалить лишнее, но это можно также отнести к безопасности.

Поэтому нужно было найти уже существующее решение, которое соответствует всем требованиям, или же написать собственное.

Первым делом я решила исследовать сам Tempest: предположила, что с проблемой очистки ресурсов сталкивались не только мы — и оказалась права. Tempest предлагает встроенный Cleanup, но в сети о нем крайне мало информации, если не учитывать официальную документацию с инструкцией по запуску.



Знакомство с Tempest Cleanup


По умолчанию Tempest Cleanup содержит в себе три основные команды, каждая из которых отвечает за определенный этап очистки:

--init-saved-state

Позволяет сохранить исходное состояние облака до запуска тестов. Обычно рекомендуется сначала запустить tempest cleanup --init-saved-state. Он создает файл saved_state.json со списком объектов, которые уже существуют в OpenStack и не будут удалены в процессе работы Cleanup.

Однако если по каким-то причинам она не была запущена, необходимо отредактировать файл saved_state.json, добавив туда объекты, которые не подлежат удалению.

--dry-run

Перед запуском самого процесса очистки рекомендуется запустить tempest cleanup --dry-run. Это позволит создать файл dry_run.json со списком объектов, которые будут удалены при запуске Cleanup. Следует убедиться, что данный файл не содержит объектов, которые не подлежат удалению.

tempest cleanup

Если запустить команду tempest cleanup без каких-либо аргументов, запустится процесс очистки. При этом если сделать это сразу, есть вероятность удалить нужные данные. Поэтому необходимо запускать Tempest Cleanup в следующей последовательности:
1
tempest cleanup --init-saved-state

2
tempest cleanup --dry-run

3
tempest cleanup

При запуске Cleanup обращается к конфигурационному файлу tempest.conf, чтобы найти, где собирать информацию об объектах. В конфигурации с помощью параметра region указывается, где будут запускаться тесты, а в случае с Cleanup — собираться информация об объектах OpenStack.

Если рассматривать работу Tempest Cleanup из коробки, то он собирает информацию о следующих OpenStack объектах:


Отчеты Tempest Cleanup


Повторюсь: при запуске Cleanup с флагом --init-saved-state генерируется saved_state.json, в котором хранится информация об уже существующих объектах. Они не будут удалены при запуске очистки ресурсов, поэтому наличие этого файла особенно важно.

Структура saved_state.json — словарь со всеми типами объектов:

{
  "floatingips": {...},
  "keypairs": {...},
  "loadbalancers": {...},
  …

Если объектов конкретного типа не найдено, в отчете мы увидим пустой словарь, например:

"floatingips": {}

Если же объекты найдены, в отчете мы получаем основную информацию: uuid, name, status, project_id и другие данные.

"servers": {
    "5a809ed6-0807-45ea-8eff-abab9755919d": "tempest-lb_member_webserver1-1486231687",
    "8108601b-e2a3-4b5b-ac3c-30bd50b55702": "tempest-lb_member_webserver2-916916348"
  }

При запуске Cleanup с флагом --dry-run генерируется файл dry_run.json, в котором хранится информация об объектах, которые остались после тестирования и буду удалены. Файл отчета имеет схожую структуру с файлом saved_state.json:

{
 "floatingips": [],
  "keypairs": [],
  "loadbalancers": [],
  "networks": [],
  "ports": [],
  "routers": [],
  "server_groups": [],
  "servers": [],
  "snapshots": [],
  "subnetpools": [],
  "subnets": [],
  "volumes": []
}

В целом, такое решение нам подходит, однако есть парочка нюансов, которые следует исправить.

Что было исправлено


Одна из главных проблем Cleanup заключалась в том, что у него большая область действия — целый регион, в котором могут быть не только тестовые ресурсы, но и объекты других команд, а также ресурсы клиента. Поэтому мы приняли решение сократить области действия.

Все объекты, которые попадают под область действия Cleanup, можно условно разделить на две группы:

  • project related — объекты, которые находятся под определенным проектом. На изображении такие объекты помечены полем project_id:


  • global — объекты, которые не принадлежат определенным проектам — например, пользователи. На изображении они окрашены в фиолетовый цвет:


Нам было важно, чтобы Tempest Cleanup был универсальным и конфигурируемым, поскольку его будет использовать не только наша команда. Вся необходимая настройка должна проводиться через tempest.conf, как и при запуске тестов. Для этого внутри конфигурационного файла мы создали раздел [cleanup], внутри которого были добавлены параметры для настройки Tempest Cleanup:

cleanup_group = cfg.OptGroup(name="cleanup",
                            title="Tempest Cleanup")
CleanupGroup = [
   cfg.ListOpt('cleanup_project_ids',
               default=[],
               help='The list of project ids that using for '
                    'the testing of OpenStack services.'),
   cfg.BoolOpt('skip_global_cleanup_services',
               default=False,
               help='This parameter shows include global '
                    'services in cleanup or not.'),
   cfg.BoolOpt('include_octavia',
               default=False,
               help='This parameter shows include Octavia '
                    'service in cleanup or not'),
   cfg.BoolOpt('skip_quotas_deletion',
               default=True,
               help='This parameter shows include quotas '
                    'deletion in cleanup or not'),
]

Далее я более подробно расскажу о каждом из добавленных параметров.

cleanup_project_ids


Первым делом мы сделали, чтобы project related объекты собирались только внутри тестовых проектов. Однако у каждой команды свои проекты, следовательно, и свой набор UUID. Поэтому внутри раздела [cleanup] мы добавили параметр cleanup_project_ids, который включает в себя список UUID тестовых проектов.

skip_global_cleanup_services


Проведя небольшой анализ используемых во время тестирования объектов, мы обнаружили, что зачастую пользователи, проекты и роли не создаются и не удаляются во время тестов, потому что используется accounts.yaml. Это файл с заранее созданными проектами, внутри которых уже есть пользователи с определенными ролями.

Поскольку для тестирования выделен конкретный домен и регион, в создании и удалении новых объектов также нет необходимости. Так как все эти объекты относятся к группе global, можно в раздел [cleanup] добавить параметр, который будет принимать значение True или False, и включать или исключать глобальные объекты в Tempest Cleanup.

Так в tempest.conf появился новый параметр — skip_global_cleanup_services. Если skip_global_cleanup_services=True, то Cleanup не будет собирать информацию об объектах flavor, image, user, project, domain, role и region. Если же skip_global_cleanup_services=False, то данные объекты будут включены в работу Cleanup.

include_octavia


Поскольку мы настраивали Tempest Cleanup для сервиса Octavia, который по умолчанию не включен в набор тестов Tempest и отсутствует в Cleanup, появилась необходимость включить объекты loadbalancer в логику работы.

Однако Octavia не является дефолтным сервисом, поэтому нужно было сделать его включение в Tempest Cleanup опциональным. Для этого в раздел [cleanup] был добавлен новый параметр — include_octavia, который принимает значения True или False, в зависимости от того, тестируется на данный момент Octavia или нет.

Важно отметить: если в тестовый набор Tempest не подключен octavia tempest plugin, то объекты типа loadbalancers не будут принимать участие в тестировании. Поэтому при запуске Tempest Cleanup их счетчик будет равен 0 и удалять будет нечего.

Однако если внутри облака не подключен сам сервис Octavia, то при запуске Tempest Cleanup будет ошибка, которая будет указывать на то, что мы пытаемся отправить запрос на несуществующий/неизвестный эндпоинт. В этом случае стоит перевести параметр include_octavia в значение False.


skip_quotas_deletion


В ходе запуска тестов выяснилось, что после каждого прогона происходит удаление не только объектов OpenStack, но и проектных квот. Под проектными квотами я подразумеваю количественное ограничение на создание объектов внутри тестовых проектов. Из-за этого перед каждым прогоном необходимо было идти и выставлять квоты для всех проектов. После небольшого исследования выяснилось, что Tempest Cleanup содержит в себе также три набора квот, разбитых по сервисам:

  • квоты для Nova сервиса,
  • квоты для Volume сервиса,
  • квоты для Network сервиса.

На изображении они выделены желтым цветом.

Чтобы решить эту проблему, достаточно было исключить квоты из области действия Cleanup. Для этого мы создали параметр skip_quotas_deletion, который находится в разделе [cleanup] конфигурационного файла tempest.conf. Этот параметр принимает значение True, если необходимо исключить проектные квоты из очистки. И принимает значение False, если проектные квоты нужно подчистить. По умолчанию мы исключаем квоты из области действия Cleanup.


...
[cleanup]
cleanup_project_ids = 6042b0a6ce2a4dceafaef8a498a8b1f0, 19702fd891424abe8c4a3eaa11a45265, 7ac6ecefb18342a987196ddee14c0793, c9a7a655778c47d5821184b7d9178ba6, 73efca72787f4214b02ba66267a412b4, ef68e4ff6ff446b8993c6e6863e231ca, de7726c73ad1492a8339e2d51221a009, ee85660db32e443684c60678b42c1647, 7c48c62b939c4c1e8d5e04c3cc318188, 27e90ed7c49e4528ae40a0633f79f51b, 76e60bff1a8249b0820bee9c1ebcf553, c2e232675dc6424385d5de4b8cbf34f2, f194e990a099449683b6460ba45ef469
include_octavia = True
skip_global_cleanup_services = True
skip_quotas_deletion = True

Таким образом, нам удалось избавиться от очистки ненужных ресурсов и минимизировать ручное вмешательство в процесс подготовки к тестированию. И выглядит так, что наш Cleanup готов к использованию.

Как интегрировали Cleanup в пайплайн


В прошлой своей статье я поделилась, как мы автоматизировали процесс запуска тестов. Теперь передо мной стояла задача включить модифицированный Tempest Cleanup в уже созданный пайплайн.

Важно отметить, что перед тем, как запускать Tempest Cleanup, необходимо выполнить необходимые настройки. Для запуска — в директорию /etc/tempest/ положить конфигурационный файл tempest.conf. Однако по умолчанию этой директории нет, поэтому ее нужно создать самостоятельно, используя права администратора.

В основе пайплайна заложен скрипт, внутри которого реализована следующая последовательность действий:

1. Создание тестового окружения:

# Creation of environment
rally env create --name octavia --spec /home/rally/env_octavia.yaml > /dev/null
# Checking of created environment
rally env check

2. Создание конфигурационного файла tempest.conf:

# Creation of verify
rally --debug verify create-verifier --system-wide --type tempest --name tempest-octavia --source /home/rally/tempest/
# Reconfigure existing verifier
rally --debug verify configure-verifier --show --extend /home/rally/tempest_extra_option.conf
find ~/.rally/verification/ -name tempest.conf -type f -print0 | xargs -0 sed -i 's/ca_certificates_file//g'

3. Копирование файла в директорию /etc/tempest/ для работы Tempest Cleanup:

# Create folder for config file for Tempest Cleanup
sudo mkdir /etc/tempest
# Copy config file to created folder
find ~/.rally/verification/ -name tempest.conf -type f -exec sudo cp {} /etc/tempest/ \;

4. Запуск Tempest Cleanup с флагом --init-saved-state:

# Run Tempest cleanup with flag --init-saved-state
tempest cleanup --init-saved-state

5. Запуск тестов Tempest:

# Run of Tempest tests for Octavia
rally --debug verify start --concurrency 4 --detailed --pattern octavia_tempest_plugin --skip-list /home/rally/skip_list.yaml

6. Запуск Tempest Cleanup с флагом --dry-run:

# Run Tempest cleanup with flag --dry-run
tempest cleanup --dry-run

7. Запуск Tempest Cleanup для очистки ресурсов после тестирования:

# Run Tempest cleanup
tempest cleanup

8. Создание отчетов:

# Make report
rally verify report --type html --to ./octavia_tempest_reports/"$ENVIRONMENT"-"$REGION"-$(date "+%F-%H_%M_%S").html
# Upload reports to the storage
swift upload rally_reports octavia_tempest_reports

Заключение


Нам удалось решить вопрос с очисткой «подвисших» ресурсов. Теперь после каждого запуска тестов активируется Cleanup, который экономит время на ручной уборке. Также благодаря своевременной очистке ресурсов дальнейшие запуски пайплайнов производятся без проблем с квотами.

В дальнейшем планирую рассказать о полезных улучшениях для нашего пайплайна. Если интересно, следите за обновлениями в нашем блоге на Хабре!

Комментарии (1)


  1. MaxPro33
    16.11.2023 14:36

    Какие конкретные виды ресурсов (например, виртуальные машины, хранилища данных, сетевые ресурсы) были включены в область очистки, и какие трудности вы испытали при автоматизации процесса их выявления?