Доброе время суток!
В данном посте я расскажу о том, как просто и быстро писать различные скрипты проверки состояния инфраструктуры с помощью инструментов Bash, Outthentic и Sparrow ...
Задача — у нас есть сервер, на который мы устанавливаем приложения и делаем настройку конфигурации. Хочется написать скрипт, который быстро даст нам ответ, что с сервером все хорошо, и приложение настроено и работает корректно. Этакий smoke тест, который будет нам полезен, когда мы будем заниматься поиском проблем или же просто проверять, что очередной деплоймент ничего не сломал. Предвидя возможные вопросы, я знаю, что уже существуют инструменты, которые делают что-то подобное ( inspec ), тем не менее, хочу рассказать об альтернативном походе. ( Будет интересно сравнить ).
Выбор инструментария
Итак, почему Bash? Потому что он достаточно прост в использовании и позволяет быстро и эффективно писать разного рода скрипты, imho я бы не стал использовать Bash для более сложных задач, но для данного рода проблем он вполне подходит.
Затем, что такое Outthentic и как он нам здесь пригодится? Outthentic — это фреймворк для написания скриптов, позволяющий быстро написать, настроить и запустить ваш скрипт ( в данном случае, написанный на Bash, но можно и на других языках ), так же, что немаловажно, Outthentic имеет встроенный DSL, подходящий под написание скриптов в стиле автоматизированных тестов, что может быть удобным при написании скриптов мониторинга.
И последнее — почему ( или что-то такое ) Sparrow и как он нам поможет? Sparrow — это платформа и среда выполнения пользовательских скриптов, позволяющая распространять и настраивать готовые скрипты в виде т.н. Sparrow плагинов. Основной выхлоп в том, что когда наш скрип написан и оттестирован, вы можете упаковать его в виде плагина, загрузить в Sparrow репозитарий и передать далее в отдел эксплуатации и/или любым другим коллегам, которые захотят воспользоваться вашим скриптом.
Практический пример
Пример отчасти основан на реальной практике, и отчасти сознательно упрощен, что бы не перегружать статью излишними деталями. Более-менее подобного рода проверки мне приходится делать постоянно, поэтому я и решил написать для них скрипт автоматизации, итак, будем проверять, что на целевом сервере target-server
:
запущен tomcat, то есть виден в списке процессов
http запросы на некоторые ресурсы приложения ( развернутого на сервере )
возвращают успешный http код (200
) —GET 127.0.0.1:8080/healthcheck
- с целевого сервера доступен сервер баз данных (
192.168.0.2
), на уровне доступа по tcp порту ( очень часто из-за некорректно настроенной политики безопасности это может быть не так, что приводит к неработоспособности приложения )
Да, и важно отметить, что все проверки выполняются прямо на целевом сервере:
$ ssh target-server
$ bash /path/to/check/script.bash
Bash скрипт
В данном случае скрипт будет тривиальным:
$ cat script.bash
#!/bin/bash
ps uax | grep tomcat | grep -v grep
echo; echo
timeout 5 curl -sL 127.0.0.1:8080/healthcheck -w "GET /healhcheck --- %{http_code}\n" -o /dev/null
echo; echo
timeout 5 bash -c "echo OK | telnet 192.168.0.2 3306"
Запустив скрипт на целевом сервере получим в выводе что-то похоже на это: ( на данном этапе пока никаких проверок не происходит, просто убедимся, что скрипт отрабатывает ):
$ bash script.bash
GET /healhcheck --- 200
tomcat 8264 0.0 32.1 2222884 326452 ? Sl Sep14 4:04 /usr/lib/jvm/java-1.8.0/bin/java -Djava.util.logging.config.file=/usr/share/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xmx128M -Djava.awt.headless=true -Djava.endorsed.dirs=/usr/share/tomcat8/endorsed -classpath /usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar -Dcatalina.base=/usr/share/tomcat8 -Dcatalina.home=/usr/share/tomcat8 -Djava.io.tmpdir=/usr/share/tomcat8/temp org.apache.catalina.startup.Bootstrap start
Trying 192.168.0.2 ...
Connected to 192.168.0.2.
Escape character is '^]'.
Connection closed by foreign host.
Проверка вывода скрипта
Вся суть нашего мониторинга — возможность последовательного запуска нескольких команд и далее анализ их вывода с помощью набора простых правил, здесь и вступает в игру Outthentic.
Для начала установим пакет как CPAN модуль:
$ cpanm Outthentic
Далее слегка модифицируем наш скрипт, что бы его можно было запускать через Outthentic:
- переименуем скрипт в
strory.bash
— это соглашение на имеование скриптов во фреймворке Outthentic:
$ mv script.bash story.bash
- запустим скрипт через консольный клиента
strun
, который поставляется вместе с фреймворком Outthentic и собственно запускает скрипты:
$ strun
Получим вывод, аналогично тому, когда мы запускали скрипт напрямую. Пока, что польза Outthentic не очевидна. Доходим до использования DSL. Создадим несколько простых проверочных правил для валидации вывода скрипта и положим правила в файл story.check
:
$ cat story.check
GET /healhcheck --- 200
tomcat8
Connected to 192.168.0.2
Запустим снова strun
:
$ strun
2017-09-18 17:39:55 : [path] /
GET /healhcheck --- 200
tomcat 8264 0.0 32.1 2222884 326452 ? Sl Sep14 4:04 /usr/lib/jvm/java-1.8.0/bin/java -Djava.util.logging.config.file=/usr/share/tomcat8/conf/logging.properties -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager -Xmx128M -Djava.awt.headless=true -Djava.endorsed.dirs=/usr/share/tomcat8/endorsed -classpath /usr/share/tomcat8/bin/bootstrap.jar:/usr/share/tomcat8/bin/tomcat-juli.jar -Dcatalina.base=/usr/share/tomcat8 -Dcatalina.home=/usr/share/tomcat8 -Djava.io.tmpdir=/usr/share/tomcat8/temp org.apache.catalina.startup.Bootstrap start
Trying 192.168.0.2 ...
Connected to 192.168.0.2.
Escape character is '^]'.
Connection closed by foreign host.
ok scenario succeeded
ok text has 'GET /healhcheck --- 200'
ok text has 'tomcat8'
ok text has 'Connected to 192.168.0.2'
STATUS SUCCEED
Мы видим, что проверочные правила сработали и, что вывод от скрипта успешно прошел все проверки, а это все что нам нужно от нашего мониторинга. Формат отчетов strun
настраивается и имеет несколько вариантов, например, мы можем выбрать более лаконичный вывод, который выдаст всю детализацию, только в случае ошибки:
$ strun --format production
Вот как будет выглядеть отчет в случае если, по каким-то причинам, у нас не запущен tomcat сервер:
$ strun --format production
2017-09-18 17:44:43 : [path] /
not ok text has 'tomcat8'
GET /healhcheck --- 200
Trying 192.168.0.2 ...
Connected to 192.168.0.2.
Escape character is '^]'.
Connection closed by foreign host.
STATUS FAILED (2)
Параметризация скрипта мониторинга
Outthentic еще удобен и тем, что он позволяет просто добавлять и настраивать входные параметры для ваших скриптов. Допустим, чисто теоретически, мы захотим задавать хост и порт для сервера баз данных.
Добавим дефолтные значения входных параметров через suite.yaml — файл для хранения дефолтных настроек в терминологии Outthentic:
$ cat suite.yaml
---
db_server:
ip_address: "192.168.0.2"
port: 3306
В данном случае иерархия конфигурационного файла может быть произвольной, просто я хочу показать, как легко и просто с помощью Outthentic передавать входные параметры, описанные в виде иерархический структуры данных и использовать их даже внутри Bash скриптов ( не применяя дополнительного парсинга ):
Чуть-чуть изменим скрип мониторинга, что бы он брал свои входные параметры из-вне :
$ cat script.bash
#!/bin/bash
db_server_address=$(config db_server.ip_address)
db_server_port=$(config db_server.port)
# ... следующие строчки кода остаются неизменными
# ...
timeout 5 bash -c "echo OK | telnet $db_server_address $db_server_port $db_server_port"
Теперь мы можем запустить наш скрипт с дефолтными параметрами:
# для сервера баз данных будут использоваться ip address 192.168.0.2 и порт 3306
$ strun
Или же переопределить параметры через командную строку:
$ strun --param db_server.ip_address=192.168.0.3 --param db_server.port=3307
Идем дальше, все что нам осталось сделать — это передать скрипт в эксплуатацию всем заинтересованным лицам, для этого нам понадобится Sparrow.
Дистрибуция скрипта в виде Sparrow плагина
Sparrow предоставляет две основные возможности дистрибуции скриптов — посредством публичного репозитария SparrowHub и посредством приватных репозитаиев, построенных на использовании удаленных репозиториях Git.
Скорее всего, когда мы пишем чисто внутренние скрипты, нам больше подходит второй способ. Он к тому же еще и более простой, так как требует только того, что бы исходники скрипта лежали в некотором удаленном Git репозитарии, что же сделаем это:
$ git init .
$ git add .
$ git commit -a -m "outthentic monitoring script"
Добавив основные файлы проекта (story.bash и story.check ), нам остается настроить файл с мета данными ( который собственно и дает понять, что это не просто скрипт, а Sparrow плагин ) :
$ cat sparrow.json
{
"name" : "server-check"
"description" : "check server health"
}
На самом деле файл с мета данными может содержать гораздо большее число параметров, но мы ограничимся здесь для простоты минимальным набором.
Окей, мы фактически сделали наш первый Sparrow плагин, осталось отправить файлы в git remote:
git add sparrow.json
git commit -a -m "add sparrow meta file"
git remote add origin $remote-git-repository
git push -u origin master
Использование готового скрипта мониторинга как Sparrow плагина
Это самая интересная часть в том смысле, что он показывает как Sparrow облегчает процесс установки и интеграции ваших скриптов сторонними командами.
Для начала, что бы использовать созданный нами плагин на каком-то целевом сервере, нам необходимо установить на этом сервере Sparrow клиент:
$ cpanm Sparrow
Далее все просто, т.к. плагин — приватный и не будет загружен с общего репозитариия, уведомляем об этом Sparrow:
$ echo "server-check $remote-git-repository" >> ~/sparrow.list
Пара значений которую мы должны положить в локальный индексный файл ~/sparrow.list
это название плагина ( не обязательно должно совпадать с тем, что мы использовали в предыдущей части и URL удаленного репозитария, где лежит исходный код плагина )
Теперь обновляем индекс sparrow, что бы стал доступен добавленный нами плагин:
$ sparrow index update
И устанавливаем сам плагин:
$ sparrow plg install server-check
Теперь мы можем запустить плагин как есть:
$ sparrow plg install server-check
Или же, передав ему параметры:
$ sparrow plg install server-check --param db_server.ip_address=192.168.0.3 --param db_server.port=3307
И наконец-то, все тоже самое можно запустить в виде Sparrow задачи:
$ sparrow project create monitoring
$ sparrow task add monitoring app1 server-check
$ sparrow task ini monitoring/app1
---
db_server:
ip_address: "192.168.0.2"
port: 3306
---
$ sparrow task run monitoring/app1
Последний вариант запуска удобен тем, что вы можете создать несколько задач ( с разными конфигурациями ) для запуска одного и того же плагина. По сути задача — это именованная конфигурация запуска Sparrow плагина, а проект — группа задач.
PS
На этом все. Если кому-то будет интересно, вот о чем я еще не сказал:
приватные Sparrow репозитарии можно настраивать не только через локальные индекс файлы
~/sparrow.list
( что неудобно при большом количестве плагинов ), но и через Sparrow::Nest — API управления приватными Sparrow репозитариями.
Sparrow плагины можно запускать удаленно на серверах ( через ssh ) с автоматической предустановкой Sparrow клиента — добро пожаловать в проект Sparrowdo. Там есть еще Perl6 API для Sparrow и много другого (-: !
- Outthentic DSL позволяет создавать гораздо более сложные и интересные проверочные правила, чем просто соответствие подстроке. Среди них — проверка по Perl5 regexp, проверка по диапазону и последовательности строк, а так же динамическая генерация правила с помощью языков программирования общего назначения.
Как всегда — вопросы, замечания, предложения, конструктивная критика — приветствуется.
С уважением.
Алексей