- PVSM.RU - https://www.pvsm.ru -
Часто бывает, когда что-то не работает. И никто не хочет, чтобы что-то не работало по его вине. В контексте больших инфраструктур и распределенных приложений ошибка конфигурации может быть фатальной.
В статье я покажу как правильно тестировать окружение для приложения, какие инструменты использовать, приведу примеры удачного и целесообразного тестирования.
Статья будет интересна командам, которые практикуют DevOps или SRE, ответственным Dev, и прочим хорошим людям.
Следует сказать, что реализовывать концепцию Infrastructure as Code можно и без тестирования. И даже будет работать. Но разве есть предел совершенству?
Тестирование к нам пришло из мира разработки, тестирование – это целая огромная эпопея, которая включает в себя такие варианты реализаций:
И тут может прийти лживое осознание, что в нашем мире Ansible/Chef/Puppet/Salt все очень примитивно, все очень просто, и в экосистеме наших тулзовин нету реализации чего-то подобного.
А вот как-бы не так.
Все это есть, все это используют уже давно и успешно.
Уточню сразу, что мы не будем рассматривать высокоуровневое программирование для Configuration management. Например, если вы написали свой Ansible модуль, или Chef LWRP – ваших знаний достаточно, чтобы понять как правильно тестировать ваше творение.
По сути все рассматриваемые фреймворки для тестирования очень похожи, отличаются набором готовых тестовых кейсов и синтаксисом.
Везде будем решать одну задачу для примера: мы должны убедиться в том, что пакет 'apache2' у нас установлен, и сервис 'apache2' запущен и работает. В конце проверяем, что порт 80 кто-то слушает.
Первый фреймворк для тестирования, который мы рассмотрим — Serverspec [1].
Пример использования:
require 'spec_helper'
describe package('apache2') do
it { should be_installed }
end
describe service('apache2') do
it { should be_enabled }
it { should be_running }
end
describe port(80) do
it { should be_listening }
end
Второй фреймворк — InSpec [2].
Синтаксис идентичный Serverspec.
Третий фреймворк – Testinfra [3].
def test_apache_is_installed(Package):
apache = Package("apache2")
assert apache.is_installed
def test_apache_running_and_enabled(Service):
apache = Service("apache2")
assert apache.is_running
assert apache.is_enabled
def test_apache_port(Socket):
sock = Socket("tcp://80")
assert sock.is_listening
Четвертый фреймворк – Goss [4].
package:
apache2:
installed: true
service:
apache2:
enabled: true
running: true
port:
tcp:80:
listening: true
Как видно по синтаксису – есть из чего выбрать. Кому что больше нравится, то лучше всего и использовать. Например, если у вас Chef – отлично ляжет InSpec или Serverspec. Если Ansible или Salt – круто подойдет Testinfra или Goss.
Все отличия – это наличие или отсутствие готовых модулей, первым делом необходимо подготовить список необходимых требований для фреймворка и искать тот, в котором есть все что нужно (или почти все).
Окей, выбрали. Что же именно тестировать?
Несколько недель назад мы общались в нашем DevOps Community по поводу того, что именно нужно тестировать, нужно ли вообще что-то тестировать, сколько лет лететь до Trappist-1 и так далее.
Например, ctrlok [5] считает что тестировать декларативные штуки не правильно. И я с ним согласен.
Оговорюсь, что точно не нужно тестировать:
Что нужно тестировать:
У нас есть очень много приложений в контексте одного продукта, и все они требуют тонкой настройки окружения для нормальной работы. Одним из самых тревожных и узких мест было приложение, которое занимается конвертацией различных форматов документов. Не трудно догадаться, что в нем используются десятки пакетов и сотни библиотек, и это все может внезапно перестать работать, если обновляется какой-нибудь пакет, от которого оно зависит.
Для того, чтобы правильно оценить приложение и подготовить его для тестирования – нужно думать как тестировщик. Или, например, проконсультироваться у команды QA.
Во время общения необходимо продумать основные тест-кейсы и попытаться покрыть все из них. Практический пример (на нашем приложении):
В нашем случае отдельные пункты – это отдельные модули приложения, именно так мы их и будем тестировать.
Покажу небольшой пример интеграционно-системных тестов первого модуля приложения. Уточню, что у нас есть роль, которая должна правильно установить консольную утилиту pdf2htmlex, где четко описаны все зависимости и необходимые штуки, т.е. мы имеем ввиду что процесс развертывания окружения прошел успешно, и наступил этап тестирования инфраструктуры.
Для начала, предлагаю убедиться что бинарник доступен, его можно запустить, и что-то получить в результат:
# Validate binary exists and working
describe bash('pdf2htmlEX --version') do
its('stderr') { should match /pdf2htmlEX version 0.14.6/ }
its('exit_status') { should eq 0 }
end
Теперь давайте протестируем, что этот бинарник реально умеет конвертировать тестовый документ, и результат нас устраивает:
# Try to convert and validate result html
describe bash('pdf2htmlEX /opt/test/pdf-sample.pdf /tmp/pdf-sample.html') do
its('stderr') { should match /Working/ }
its('exit_status') { should eq 0 }
end
describe file('/tmp/pdf-sample.html') do
it { should exist }
its('content') { should match /<!DOCTYPE html>/}
its('size') { should eq 267189 }
end
В данном случае, если тест пройдет успешно – мы можем четко декларировать, что модуль приложения, который отвечает за конвертацию из PDF в HTML работает. Мало того, он работает корректно, нас устраивает результат его работы.
Сложно и долго делать такой тест? Не думаю.
Сколько это сэкономит денег бизнесу? У каждого своя цена ошибки.
Стоит сказать, что тестировать окружения мы начали не сразу. Зачем тратить время на такие вещи – это же очевидно, что все мы супермены, и пишем код для Configuration Management сразу без ошибок?
И такой подход работает, когда DevOps команда состоит из 1-2 человек. В таком случае каждый инженер знает как должно работать приложение, знает как готовить для него окружение, и как его «потыкать» — посмотреть, что оно будет работать на площадке, которую он только что подготовил.
Все заканчивается тогда, когда в production среде все должно работать, но не работает. Начинается debug процесс руками на проде или откаты-роллбеки, а каждая минута очень дорого стоит для бизнеса.
Именно поэтому тестирование инфраструктуры – это инвестиция в будущее.
Теперь, когда что-то ломается – мы абсолютно уверены, что наша часть работы была сделана на 100%, и с нашей стороны все вопросы закрыты.
Поэтому мы и уверены в том, что только что развернули.
Все мы работаем с приложениями, которые очень часто меняются в очень динамичном мире благодаря нашим же правильно настроенным процессам – CI и CD. Мы все очень серьезно относимся к работе самих приложений, тестируя со всех сторон одно и тоже. И в это же время халатно относиться к инфраструктуре, на которой это приложение работает – не очень разумно. Тем более, это чревато большими последствиями.
Для себя мы решили, что будем тестировать в таких случаях:
Основным посылом было донести всю важность тестирования инфраструктуры и побудить использовать приведенные инструменты если не прямо сейчас, то в ближайшем будущем.
А сколько процентов вашей инфраструктуры покрыто тестами?
Автор: mukolaich
Источник [6]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/qa/248669
Ссылки в тексте:
[1] Serverspec: http://serverspec.org
[2] InSpec: http://inspec.io
[3] Testinfra: https://testinfra.readthedocs.io
[4] Goss: https://goss.rocks
[5] ctrlok: https://habrahabr.ru/users/ctrlok/
[6] Источник: https://habrahabr.ru/post/323472/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.