Серебряная пуля системного администрирования

в 11:09, , рубрики: continuous integration, cron, Jenkins, автоматизация, системное администрирование, метки: , , ,

image

В чем заключается основная задача системного администратора? Если выразить ее очень кратко, одним предложением? Еще лучше, одним словом?

Автоматизация.

Автоматизация бывает разных видов — управление пользователями и политиками (Active Directory), управление конфигурацией (Puppet) итд. Для автоматизации каких-то регулярных действий как в Windows, так и в Linux/Unix есть встроенные планировщики задач. Наверняка каждый администратор использует их ежедневно. Это же так удобно — написал скрипт, закинул в cron и забыл о нем.

Проблема в том, что забыть не получается.

Предыстория

Сколько я ни писал скриптов за свою жизнь (немало, скажем так), они были недостаточно совершенны. Время от времени какой-нибудь скрипт ломался по причине, которой я никак не ожидал. И я об этом даже не знал. Конечно, я боролся с этим — узнал про опцию "-e" для bash, пытался обрабатывать ошибки, сохранял логи выполнения, стал использовать строки вида "12 5 * * * /opt/scripts/backup.sh || mail -s 'backup error' my@email" в кроне. В принципе, это даже работало. Для одного сервера. Двух. Трех. Пяти. А потом я задолбался. Даже если бы мои скрипты были идеальны, это просто жутко неудобно и долго — поддерживать кучу кронтабов на серверах, поддерживать скрипты в актуальной версии (для тех, которые использовались более чем на одном сервере), искать ошибки в логах в консоли. А если нужно запустить несколько скриптов на разных серверах в определенной последовательности? Из этого может получиться только какой-то жуткий костыль.
И что самое плохое, я все же не был до конца уверен, что все действительно работает как положено. Вдруг почтовый сервер был в дауне когда скрипт пытался отправить алерт? Вдруг скрипт подвис на какой-то команде? Вдруг еще что-то?

Похожая ситуация была с бэкапами. Как и, наверное, всякий Linux администратор, я начинал с простеньких shell-скриптов, потом потихоньку эволюционировал — rsync, rsnapshot, Amanda, Bacula. Одно время мне казалось, что Bacula — венец. Но нет, и на старуху случалась проруха. То какой-то client lock на 2 дня, то еще чем-то очередь забьет (а при одновременном запуске несколько backup job-ов путали тома итп.). Плюс неинтуитивная система управления/восстановления, так сразу не поймешь сколько бэкапов сохранено, за какие даты. Очень далеко ушло от KISS. В общем, опять же я не был полностью уверен в системе.
(Отступление: посколько я специализируюсь в Linux, то с коммерческими системами бэкапа не знаком. Возможно, там ситуация лучше. Но, в любом случае, не всем они достаются)

Решение

И вот однажды мне пришлось настроить билд-систему для разработчиков. Выбрали Jenkins CI. (Вообще-то тогда он еще был Hudson, но в силу некоторых обстоятельств в настоящий момент я рекомендую его форк — Jenkins). Самое обычное его применение, для чего он и был создан — скомпилировать код, выложить на тестовый сервер. Затем они захотели ежедневную синхронизацию базы продакшена с тестовой. Я подумал и добавил такой билд в Jenkins. Затем я заметил, что они часто просят создать им новую БД. Почему бы не создать билд, чтобы они сами могли это делать? Потом перенес туда же скрипты бэкапов. Дальше… пошло-поехало. Я нарадоваться не мог:

  1. Все билды и их история видны как на ладони — когда, во сколько, сколько времени длился билд. Какие были успешными, какие нет. Время хранения истории настраивается. Каждый билд можно запустить руками в любое время, и все это из единого интерфейса.
  2. Весь вывод консоли также сохранен в истории. Каждый билд отдельно. После получения алерта по почте хватает 2 кликов мышкой, чтобы увидеть лог выполнения провалившегося билда.
  3. Установка и настройка проста. Подключение нод — еще проще. Может выполнять скрипты как на Linux, так и на Windows.
  4. Важно для корпоративного сегмента: возможность авторизации через LDAP (и другие провайдеры), гибкая система прав.
  5. Репозиторий с кучей плагинов на любой вкус и цвет.
  6. При большом количестве билдов, когда в них становится трудно ориентироваться, можно группировать их в виды (view). Более того, каждый пользователь может создавать свои виды.
  7. Билды можно соединять в цепочки. Цепочки могут ветвится и соединяться обратно. Можно настроить чтобы некоторые билды блокировали выполнение друг друга. Невероятно удобно.
  8. Last but not the least. Наконец-то я действительно уверен, что ни одна ошибка не останется незамеченной.

Одни плюсы, никаких минусов. Или есть минусы? Ну, вообще-то, есть:

  1. Требует Java. Как на мастере, так и на нодах.
  2. Вносит SPOF. В самом деле, собрали вы все задачи в него, а сервер раз и умер. К счастью, все данные хранятся в текстовых файлах. Никаких повреждений БД итп быть не может. Восстановление сводится к следующему: a) установить Jenkins на другой сервер (3 минуты, буквально), и b) скопировать файлы из бэкапа на новый сервер. Никто не умрет если придется подождать полчаса следующего билда.
  3. Jenkins нужен аккаунт на каждой ноде для доступа к ней.

Ни один из них не критичен, и, на мой взгляд, плюсы в абсолютном перевесе. Единственная проблема, которая у меня возникала с подключением slave — какой-то очень старый сервер с Redhat 7.3 имел соответственно очень старую версию JDK, на которой slave процесс просто не запускался. Честно говоря, не помню точно чем закончилось, но, кажется, я нашел-таки версию JDK, удовлетворявшую обе стороны.

Примеры

Чтобы не быть голословным, приведу несколько real-life примеров использования:

  • Очевидно, разворачивание новых версий приложений. Недавно одному клиенту сделал билд для разворачивания сайта на ферму Scalr. Важный момент: после пары тестов выяснилось, что scalr-tools всегда возвращает 0, неважно успешно прошла операция или нет. Написал в поддержку, ребята за несколько дней исправили (ребята, если вы это читаете — спасибо). Будьте уверены, что используемые команды возвращают правильные коды выхода.
  • Бэкапы. Много чего у разных клиентов я бэкаплю с помощью shell-скриптов, запускаемых Jenkins. Иногда он просто проверяет бэкапы, сделанные стандартными средствами. Например, ISPmanager не умеет отправлять алерт при ошибке. Соответственно, билд в Jenkins проверяет его лог на наличие слова error.
  • Делегация людям некомпетентым или тем, кому полный доступ не положен. Как я упоминал, была задача по созданию тестовых БД в Oracle — для разработчиков. Согласно регламенту, полный доступ к серверу им не полагался, да и не все из них сходу знали как это сделать. В результате создали билд в Jenkins, который они могли выполнять. То же самое насчет выдачи доступа на какую-то операцию с помощью sudo. Чаще всего проще дать sudo на эту команду Jenkins, создать отдельный билд и выдать права на его выполнение группе разработчиков, чем создавать для каждого аккаунт на сервере. Здесь Jenkins реально выступает в роли кнопки «сделать хорошо».
  • На одном из проектов плотно используется AWS. Суть проблемы в том, что на большом количестве серверов хранится достаточно большое количество пользовательских данных. И оно постоянно растет. Поскольку место на диске не бесконечное, надо время от времени к той или иной ноде добавлять новые EBS диски. Вручную — часто, утомительно. Добавлять сразу большие диски, чтобы хватило на долгое время — накладно. В итоге имеем следующую схему: Zabbix мониторит свободное место, при пересечении какого-то порога генерирует алерт и исполняет действие. Действием является запуск билда, который создает новый диск, подключает его к нужной ноде, добавляет в LVM, расширяет том и затем файловую систему. Поначалу казалось костыльно, но работает безотказно. Почему не запускать скрипт прямо из Zabbix? А вы пробовали потом разобраться в его логах? А нотификацию он пришлет если какая-то ошибка случится? Где-то мы это уже проходили.

Несколько советов

В принципе, все что я говорил до этого, можно отнести к любому CI инструменту. Это не принципиально. Но если я кого-то убедил попробовать Jenkins и для уже использующих, обратите внимание:

  • Slave может отвалиться. Нотификации по этому поводу не будет, и привязанные к нему билды перестанут выполняться. Чтобы не попасть впросак, используйте wiki.jenkins-ci.org/display/JENKINS/Monitor+and+Restart+Offline+Slaves
  • По умолчанию, Jenkins исполняет shell скрипты с опциями "-xe". Если возможно (версия bash на ноде позволяет), добавляйте "-o pipefail". Если пишете на других языках — используйте аналогичные опции (use strict + use warnings для perl итп). Любой ненулевой код выхода любой команды должен прерывать билд. Иногда бывает необходимо сделать исключение, в таком случае не делайте просто "set +e; ...; set -e", а проверяйте код выхода — действительно ли он означает некритичную ошибку? (ну, это применяется к написанию скриптов вообще).
  • Храните скрипты билдов в системе контроля версий. Абсолютное большинство билдов, настроенных мной, выглядят так: script_name='test-script.sh' && svn export "$svn_url/$script_name" --username "$JENKINS_SVN_NAME" --password "$JENKINS_SVN_PASSWORD" --force && bash -xe -o pipefail "$script_name",
    где меняется лишь переменная $script_name. Думаю, плюсы очевидны.
  • Используйте плагин Timestamper, чтобы видеть сколько времени заняло выполнение каждой команды.
  • Плагины Console Column + Compact columns позволят сделать сделать интерфейс компактней и добираться до логов выполнения в 1 клик (тут также может быть интересна информация о дефолтном виде: wiki.jenkins-ci.org/display/JENKINS/Editing+or+Replacing+the+All+View).
  • Плагин Build Timeout следит за «застрявшими» билдами и отменяет их (+нотификация по желанию). Тоже нужен.

Заключение

Вот уже 2 года как пользователи дергают меня меньше, я сплю спокойней, а мои волосы стали мягкими и шелковистыми. Если серьезней, в настоящий момент я как администратор Linux с опытом более 5 лет считаю best practice использование инструмента CI для автоматизации любых повторяющихся задач, которые хоть сколько-нибудь критичны. Это необязательно должен быть Jenkins, есть и другие. Главное — забудьте про cron. Видеть статус всех задач на одной панели — это действительно удобно. CI tool vs cron — это примерно как Puppet vs ручная настройка. Разница качественная.

Автор: joneleth

Источник


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js