Тестирование серверов и контейнеров с goss

тестирование серверовНедавно почитывал последний выпуск Technology Radar и нашёл вот какую интересную штуку в разделе новых техник программирования: «разработка контейнеров по TDD». Мдя. Ментально я пока ещё не могу провести соединительную линию между Докером и TDD, но инструменты, которые там упомянуты, оказались достаточно интересными.

Первый — serverspec. С его помощью можно прогонять локальные и удалённые сервера-контейнеры по набору BDD-подобных юнит-тестов. Тулза выглядит вполне зрелой и продуманной, поддерживает не только Linux, и всё было бы хорошо, если бы один огромный косяк (возможно, только для меня): serverspec написан на Ruby, и значит, что он абсолютно не совместим со стеком, в котором я обычно работаю.

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

Что такое goss

goss — это инструмент, который проверяет, соответствует ли локальный сервер или контейнер спецификации. В спецификацию может входить много чего: от проверки запущенного процесса и установленного пакета, до поиска пользовательских аккаунтов и строк в файлах и HTTP ответах. К глубокому огорчению некоторых категорий граждан, goss работает только на никсах. Муа-ха-ха.

Быстрый пример

Я собрал простенький Vagrantfile, чтобы по-быстрому развернуть виртуальную Убунту с goss внутри. В такой и поиграться не страшно, и удалить не жалко:

Задаём спецификацию сервера

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

Например, на моей Убунте есть пользователь по имени ubuntu, запущен sshd сервис, а порты 80 и 443 никем не заняты. Это выглядит как замечательный набор качеств для любой созданной в будущем виртуальной машины, так что я попрошу goss создать спецификацию на их основе, чтобы потом погонять её на остальных серверах командой goss validate.

Результирующий goss.yaml файл пришлось немного почистить, потому что мне совсем не интересно проверять, в каких группах состоит пользователь ubuntu, или на каких именно сетевых интерфейсах не должны быть задействованы порты 80 и 443. В итоге файл получился каким-то таким:

Проверяем, соответствует ли машина спецификации

Тут вообще всё просто:

Проверяем, соответствует ли контейнер спецификации

goss поставляется вместе с братом-акробатом dgoss, который, оказывается, знает, как тестировать Docker контейнеры. Инструкцию к нему очень просто запомнить:

  • docker run ubuntu sleep 1 запускает контейнер, используя свежайший образ Убунты, ждёт одну секунду и завершается, а
  • dgoss run ubuntu sleep 1 проверяет этот же контейнер по ближайшему goss.yaml.

В моём случае dgoss честно признался, что контейнерная Убунта спецификации никак не соответствует:

Так как, в зависимости от того, прошли тесты или нет, и dgoss, и goss возвращают код ошибки 0 или 1, их можно запросто подключить к своей CI системе и тестировать, например, Dockerfile’ы после каждого коммита.

Любопытные побочные эффекты

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

Во-первых, команда goss validate умеет ждать:

Тут мы запускаем тесты раз в пять секунд до тех пор, пока они не выполнятся успешно, либо пока не пройдёт минута. И это очень круто, потому что если мой контейнер с веб сервисом должен запуститься только после контейнера с Postgres, я могу сделать goss.yaml, который убедится, что на постгресовском порту 5432 творится что-нибудь вразумительное:

Во-вторых, мы можем использовать goss  в  проверках состояния Docker контейнеров или Kubernetes зондах на живучесть и готовность. В одном из старых постов я проверял здоровье контейнера, делая запрос на его localhost через curl: ответил — здоров. Не ответил — перегружаем:

Вместо curl и exit можно было бы использовать goss и положить все мыслимые проверки в него:

Кстати, постоянно запускать goss validate не обязательно. Можно запустить его как сервис — goss serve — и спрашивать по http://127.0.0.1:8080/healthz, всё ли там хорошо. URL вернёт результаты тестов и 200 OK статус код, если всё прекрасно, и 503 Service Unavailable и грустные результаты, если всё плохо. И Docker и Kubernetes знают, как интерпретировать HTTP коды, так что их сразу можно натравливать на этот URL.

Мораль

Хотя goss и выглядит, как адекватный инструмент для проверки спецификаций сервера, я больше впечатлён перспективой использовать его для проверки живучести Kubernetes и Docker контейнеров. Серьёзно, я уже сейчас готов положить какой-нибудь goss.yaml во вспомогательный контейнер какого-нибудь Kubernetes pod’а, натравить на него readiness probe, и радоваться, видя, как Kubernetes направляет траффик в обход pod’а, потому что тот ещё недостаточно запущен. Конечно, всего этого можно было бы достигнуть и обычным bash скриптом, но зачем, если есть уже готовые инструменты.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *