Доброе время суток!


В данном посте я расскажу о том, как просто и быстро писать различные скрипты проверки состояния инфраструктуры с помощью инструментов 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, проверка по диапазону и последовательности строк, а так же динамическая генерация правила с помощью языков программирования общего назначения.

Как всегда — вопросы, замечания, предложения, конструктивная критика — приветствуется.


С уважением.


Алексей

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