Это текстовая версия выступления 2018-04-25 на Saint-Petersburg Linux User Group. Пример кода тут: https://github.com/ultral/ansible-role-testing
Полагаю что вы используете configuration mangement, а не bash. Т.е. ваша конфигурация это код. Если мы говорим, что инфраструктура это код, то к её созданию должна применяться та же философия, что и для разработки ПО. Вы задумывались об этом? Как у вас это сделано? А у других?
Пререквизиты
В описываемом случае было множество вводных:
- Множество ansible ролей.
- Hyper-V как основной гипервизор.
- Приватное облако с ограниченными возможностями по созданию виртуальных машин на лету.
- Proxy для доступа к интернету.
- Невозможность запускать тестирование ansible ролей в docker, потому что роль это конфиг целой вм, в том числе сетевые настройки например.
- Желание использовать политику зеленого мастера для репозитория с ansible ролями.
Преждем чем делать своё, сравним существующие решения.
Проект | Test Kitchen | Molecule | Свой |
---|---|---|---|
Language | ruby | python | bash/ruby |
Watchers | 132 | 126 | 0 |
Stars | 1413 | 1154 | 1 |
Forks | 502 | 174 | 2 |
License | Apache 2.0 | MIT | Any |
Commits | 1929 | 1264 | 0 |
Releases | 101 | 121 | 0 |
Contributors | 109 | 82 | 5 |
Name | testinfra | serverspec | inspec | Goss |
---|---|---|---|---|
Github | philpep/testinfra | mizzy/serverspec | chef/inspec | aelsabbahy/goss |
Language | python | ruby | ruby | go |
Watchers | 93 | 145 | 165 | 67 |
Stars | 997 | 2105 | 1167 | 2170 |
Forks | 138 | 361 | 330 | 156 |
License | Apache 2.0 | MIT | Apache 2.0 | Apache 2.0 |
Commits | 380 | 1854 | 4609 | 309 |
Releases | 35 | 282 | 346 | 47 |
Contributors | 43 | 110 | 159 | 31 |
Мы решили не изобретать велосипед и взять готовое решение. Наша инфраструктурная команда умеет в ruby поэтому был выбран Test Kitchen & inspec
Kitchen-CI
Идея до безобразия простая. Создаем новую виртуальную машину, применяем роль, прогоняем smoke-test.
Green Build Policy
Но решили идти дальше. Использовать аля github flow, т.е. роли в отдельных бранчах и после ревью мерджим в мастер. Если тесты ок, то накатываем роли на инфраструктуру.
Вложенная виртуализация
Как вы помните, у нас были ограничения на создание виртуальных машин, по этому пришлось делать непритное решение в виде вложенной виртуализации.
Изначально попробовали Virtualbox x32 что бы не включать поддержку nested. Это оказалось не очень идей из-за стабильныз kernel panic. Второй важный фактор, что мы сидим на x86_64, так что изыскания продолжились(привет libvirt), но остановились на virtualbox как более распространным по поддерживаемым ОС.
Сложности
Во время запуска это всего добра был ряд сложностей
Прокинуть настройки proxy с хоста в гостя гостя
В некоторых тестовых сценарияъ использовалась настройки proxy, при этому на хосте с testkitchen использовался прозрачный прокси и бонусом ansible не принимал extra variables с пустыми значениями.
Решение: банально — создаем ERB шаблон.
<%= ENV['http_proxy'].to_s.empty? ? 'http://proxy.example.com:3128' : ENV['http_proxy'] %>
Управление сетевыми настройками через ansible
В некоторых ролях настраивалась сеть, в тестах это выглядело так:
- Настраиваем сеть копированием файлика.
- Применяем настройки сети.
- Все плохо.
Решение: Добавить интерфейс к виртуальной машине
Если тестовый набор содержи "_" все падает
Virtualbox не может пользовать "_" в имени виртуальной машины. А виртуальная машина использовала название сценария.
Решение: переименовать тестовые наборы "vm_" => "vm-"
Тестовые сценарии с установкой Oracle без "." в конце имени виртуальной машины падают
Роль пользовалась в условном продашине, когда решили покрыть ее тестами. Когда раскатываешь на подготовленную вм — роль отрабатывает, через testkitchen падает.
Небольшая подсказка
[root@vm-oracle vagrant]# getent ahosts vm-oracle
127.0.0.1 STREAM vm-oracle
127.0.0.1 DGRAM
127.0.0.1 RAW
[root@vm-oracle vagrant]# getent ahosts vm-oracle.
fe80::a00:27ff:febd:bd6a STREAM vm-oracle
fe80::a00:27ff:febd:bd6a DGRAM
fe80::a00:27ff:febd:bd6a RAW
10.0.2.15 STREAM
10.0.2.15 DGRAM
10.0.2.15 RAW
[root@oracle vagrant]# getent ahosts oracle.example.com.
192.168.128.182 STREAM oracle.example.local
192.168.128.182 DGRAM
192.168.128.182 RAW
Есть идеи что происходит?
Это был забавный сценарий:
- У нас включался биндинг IPv4 только в настройках oracle listener.
- oracle использует FQDN.
- linux содержит специальную базу "myhostname" для разрешения доменных имен, она использовалась после /etc/hosts & dns серверов.
- Vagrant создает VM & обновляет
/etc/hosts
.
Чуть поясню:
Что происходит в случае vm-oracle?
- vagrant создает виртуальную машину.
- vagrant обновляет
/etc/hosts
(vm-oracle x2) - oracle listener слушает IPv4.
- oracle listeners разрешает доменное имя vm-oracle. & получает IPv6.
- FAILED
Что происходит в случае vm-oracle.?
- vagrant создает виртуальную машину.
- vagrant обновляет /etc/hosts ( vm-oracle & vm-oracle.).
- oracle listener слушает IPv4.
- oracle listeners разрешает доменное имя vm-oracle. & получает IPv4
- OK
OOM в гости к нам приходит
OOM случайным образом убивал виртуальные машину. Testkitchen при этому в логах своих давал всякие странные собщение.
Решение: Увеличить колличество памяти.
Медленные билды
Вся эта схма работала медленно, десятки минут, иногда и больше часа.
Решения:
- Packer. Предсобирать образы виртуальных машин.
- Пускать несолько тестовых сценариев в параллель
Заключение
Если мы говорим, что инфраструктура это код, то к её созданию должна применяться та же философия, что и для разработки ПО. С одной стороны получилось рабочее решение, но есть некоторые неприятные момент:
- Не дружелюбно оно все выглядит.
- Смесь ruby & python.
- Отсутсвует проверки иимутабельности ролей.
- Медленно работает.
- Сложно....
На выходе molecule с docker смотрится интересно и более нативно. Мы подумываем об этом.
Ссылки
Комментарии (15)
Xop
23.01.2019 06:17Небольшой вопрос — а вы не сталкивались с необходмостью перезагружать виртуалки в ролях? Просто в этом случае test kitchen теряет соединение, и говорит что test failed, в отличие от молекулы, которые отрабатывает такие ситуации нормально. Возможно вы как-то смогли это обойти?
ultral Автор
23.01.2019 07:17Именно в такой формулировке не сталкивался. В packer это решали отдельным шагом. При тестирование своего линукс дистрибутива в эта логика была в обертке на баше которая выжидала поднятие сети по таймауту
nad_oby
Молекула вполне хороша для юнит-тестинга ролей.
Я даже пробовал TTD с ней. Ну так, нормально получается.
Но как с ней без боли делать интеграционные тесты — тайна великая есть.
Так что похоже придется брать у коллег вариант с vagrant или придумывать свой вариант.
А теперь добавьте к этому то что инфраструктура может быть не только в ansible но и в оркестрации — terraform или ещё чего. И тут вообще лес тёмный.
ultral Автор
да все так примерно, кода тебе надо тестировать не отдельную роль, а множество связных ролей/северов/сервисов. В принципе же классическая пирамида тестирования получается.
Поэтому и пишу что кухня «сложная». Щас вектор мысли примерно такой:
1. по максимуму выносить «юнит тестирование», это как раз молекула.
2. на создание виртуалок забить из-за того что долго, делать ревью при мерджах.
3. модули ansible тестировать средствами языка
Xop
Странно, как раз молекулой интеграционное тестирование нескольких ролей очень даже неплохо получается, за счет возможности нормально поднять одновременно несколько разных виртуалок, в отличие от test kitchen, которая в автоматическом режиме поднимает виртуалки по одной. Или я чего-то не знаю?
ultral Автор
Нескольких ролей на одном хосте — да. А если мне надо тестировать поэйбук который конфигурирует 3 сервера? Как молекула с таким справится?
Имхо никак. Это не ее цель
nad_oby
Похожая проблема.
Я хочу тестировать плейбуки, а это несколько комбинаций хостов ролей и переменных.
И вот как это делать и не сойти с ума, не представляю.
ultral Автор
в testkitchen такой подход как раз удобно реализовать, но дружить с ansible не очень удобно
Xop
Вот только вроде при запуске kitchen test кухня поднимает и тушит виртуалки по очереди, в отличие от молекулы. Или есть какой то обходной путь помимо руками вызвать kitchen converge && kitchen verify && kitchen destroy?
ultral Автор
кухне можно подсунуть свой vagrantfile, в котором несколько виртуалок. строго говоря там же тестируется не роль, а плэйбук. Что вы там напишите это же ваше дело.
Xop
Эмм, но в этом же случае имхо теряется половина привлекательности кухни, разве нет?
ultral Автор
Не обязательно же весь переписывать. Вагрант хитро инклюдит из множнства мест. Кухня это фрэймворк с кучей ручек ддя настройки. И то что так можно настроить, не означает что так надо.
Может для конкретики обсудим более прикладную задачу?
Xop
Очень даже справляется. Пример можно посмотреть например тут: https://github.com/ansible/molecule/tree/master/test/scenarios/driver/docker/molecule/multi-node Для AWS или вагранта — аналогичные тесты в соседних директориях
ultral Автор
спасибо, интересная ссылка. на кухне подобное делал подсовывая свой vagrantfile