kitchen-ci schema


Это текстовая версия выступления 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


kitchen-ci schema


Идея до безобразия простая. Создаем новую виртуальную машину, применяем роль, прогоняем smoke-test.


Green Build Policy


Green build policy schema


Но решили идти дальше. Использовать аля github flow, т.е. роли в отдельных бранчах и после ревью мерджим в мастер. Если тесты ок, то накатываем роли на инфраструктуру.


Вложенная виртуализация


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


we need to go deeper


Изначально попробовали 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

Есть идеи что происходит?


Это был забавный сценарий:


  1. У нас включался биндинг IPv4 только в настройках oracle listener.
  2. oracle использует FQDN.
  3. linux содержит специальную базу "myhostname" для разрешения доменных имен, она использовалась после /etc/hosts & dns серверов.
  4. Vagrant создает VM & обновляет /etc/hosts.

Чуть поясню:
Что происходит в случае vm-oracle


  1. vagrant создает виртуальную машину.
  2. vagrant обновляет /etc/hosts(vm-oracle x2)
  3. oracle listener слушает IPv4.
  4. oracle listeners разрешает доменное имя vm-oracle. & получает IPv6.
  5. FAILED

Что происходит в случае vm-oracle.


  1. vagrant создает виртуальную машину.
  2. vagrant обновляет /etc/hosts ( vm-oracle &  vm-oracle.).
  3. oracle listener слушает IPv4.
  4. oracle listeners разрешает доменное имя vm-oracle. & получает IPv4
  5. OK

OOM в гости к нам приходит


OOM случайным образом убивал виртуальные машину. Testkitchen при этому в логах своих давал всякие странные собщение.


Решение: Увеличить колличество памяти.


Медленные билды


Вся эта схма работала медленно, десятки минут, иногда и больше часа.


Решения:


  • Packer. Предсобирать образы виртуальных машин.
  • Пускать несолько тестовых сценариев в параллель

Заключение


Если мы говорим, что инфраструктура это код, то к её созданию должна применяться та же философия, что и для разработки ПО. С одной стороны получилось рабочее решение, но есть некоторые неприятные момент:


  • Не дружелюбно оно все выглядит.
  • Смесь ruby & python.
  • Отсутсвует проверки иимутабельности ролей.
  • Медленно работает.
  • Сложно....

На выходе molecule с docker смотрится интересно и более нативно. Мы подумываем об этом.


Ссылки


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


  1. nad_oby
    22.01.2019 09:03

    Молекула вполне хороша для юнит-тестинга ролей.
    Я даже пробовал TTD с ней. Ну так, нормально получается.
    Но как с ней без боли делать интеграционные тесты — тайна великая есть.
    Так что похоже придется брать у коллег вариант с vagrant или придумывать свой вариант.
    А теперь добавьте к этому то что инфраструктура может быть не только в ansible но и в оркестрации — terraform или ещё чего. И тут вообще лес тёмный.


    1. ultral Автор
      22.01.2019 10:59

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

      Поэтому и пишу что кухня «сложная». Щас вектор мысли примерно такой:
      1. по максимуму выносить «юнит тестирование», это как раз молекула.
      2. на создание виртуалок забить из-за того что долго, делать ревью при мерджах.
      3. модули ansible тестировать средствами языка


    1. Xop
      23.01.2019 06:16

      Странно, как раз молекулой интеграционное тестирование нескольких ролей очень даже неплохо получается, за счет возможности нормально поднять одновременно несколько разных виртуалок, в отличие от test kitchen, которая в автоматическом режиме поднимает виртуалки по одной. Или я чего-то не знаю?


      1. ultral Автор
        23.01.2019 07:13

        Нескольких ролей на одном хосте — да. А если мне надо тестировать поэйбук который конфигурирует 3 сервера? Как молекула с таким справится?


        Имхо никак. Это не ее цель


        1. nad_oby
          23.01.2019 12:26

          Похожая проблема.
          Я хочу тестировать плейбуки, а это несколько комбинаций хостов ролей и переменных.
          И вот как это делать и не сойти с ума, не представляю.


          1. ultral Автор
            23.01.2019 12:59

            в testkitchen такой подход как раз удобно реализовать, но дружить с ansible не очень удобно


            1. Xop
              23.01.2019 17:16

              Вот только вроде при запуске kitchen test кухня поднимает и тушит виртуалки по очереди, в отличие от молекулы. Или есть какой то обходной путь помимо руками вызвать kitchen converge && kitchen verify && kitchen destroy?


              1. ultral Автор
                24.01.2019 08:29

                кухне можно подсунуть свой vagrantfile, в котором несколько виртуалок. строго говоря там же тестируется не роль, а плэйбук. Что вы там напишите это же ваше дело.


                1. Xop
                  24.01.2019 18:39

                  Эмм, но в этом же случае имхо теряется половина привлекательности кухни, разве нет?


                  1. ultral Автор
                    24.01.2019 18:50

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


                    Может для конкретики обсудим более прикладную задачу?


        1. Xop
          23.01.2019 17:14

          Очень даже справляется. Пример можно посмотреть например тут: https://github.com/ansible/molecule/tree/master/test/scenarios/driver/docker/molecule/multi-node Для AWS или вагранта — аналогичные тесты в соседних директориях


          1. ultral Автор
            24.01.2019 08:31

            спасибо, интересная ссылка. на кухне подобное делал подсовывая свой vagrantfile


  1. nad_oby
    22.01.2019 09:05

    дубль, удалён


  1. Xop
    23.01.2019 06:17

    Небольшой вопрос — а вы не сталкивались с необходмостью перезагружать виртуалки в ролях? Просто в этом случае test kitchen теряет соединение, и говорит что test failed, в отличие от молекулы, которые отрабатывает такие ситуации нормально. Возможно вы как-то смогли это обойти?


    1. ultral Автор
      23.01.2019 07:17

      Именно в такой формулировке не сталкивался. В packer это решали отдельным шагом. При тестирование своего линукс дистрибутива в эта логика была в обертке на баше которая выжидала поднятие сети по таймауту