Выстраиваем эффективную эксплуатацию серверного ПО при помощи DevOps-практик

Серверное программное обеспечение (ПО) составляет ИТ-инфраструктуру организации. От работы серверного ПО зависят все службы и сервисы компании, поэтому оно требует особых правил эксплуатации.
Что такое CI/CD
Уже почти 10 лет мы занимаемся DevOps-аутсорсингом и эксплуатацией всех видов серверных ИТ-инфраструктур в России. Наш опыт показывает, что у разных клиентов выстроены свои процессы эксплуатации ПО, к которым они пришли по собственным соображениям. Эти подходы обеспечивают те параметры работы инфраструктуры, которые по тем или иным причинам критичны либо бизнесу, либо только системному архитектору или администратору. Между тем, есть устоявшиеся, эффективные эксплуатационные методологии. Но они либо не используются, либо применяются крайне выборочно. К каким последствиям это приводит и как их избежать — читайте в статье.

Чем отличается классическое программное обеспечение от серверного

Серверы отличаются от ПК тем, что являются общими вычислительными ресурсами, а ПК — персональными. Серверное программное обеспечение создано в основном для непрерывной обработки запросов клиентов. Эта непрерывность работы, а также необходимость функционировать при большой нагрузке накладывает на серверные программы большую «ответственность» и требования к эффективности.

От того, насколько эффективно и безопасно работает сервер и установленное на нем ПО, зависит то, как работают все приложения и сервисы ИТ-инфраструктуры организации. Следствием некорректной работы программных сервисов могут стать финансовые и репутационные потери всего бизнеса, а не просто задержка в работе одного сотрудника, как в случае со сбоем программы на персональном компьютере.

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

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

Поэтому важно понимать, насколько критичны могут быть некоторые эксплуатационные характеристики программного обеспечения серверов для компании.

Критичность эксплуатационных характеристик серверного ПО для бизнеса

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

Отказоустойчивость и доступность. Параметр, показывающий возможности работоспособности системы при различных воздействиях (например, отказ некоторых элементов системы) или время, в течение которого доступна система (uptime, измеряется в процентах).

Безопасность. Показатель степени защищенности системы от несанкционированного использования, злонамеренных атак, утечки данных, уязвимостей, защищенности и конфиденциальности данных (152-ФЗ). В целом — это свойство программы функционировать без негативных последствий при негативном внутреннем или внешнем воздействии.

Масштабируемость. Характеристика, определяющая способность системы, приложения, инфраструктуры или ресурсов адаптироваться и расширяться для удовлетворения возрастающих потребностей, объемов работы или нагрузки. Масштабируемость измеряется способностью системы эффективно и безопасно увеличивать или уменьшать свои ресурсы, обрабатывать большее количество данных или запросов, поддерживать растущее число пользователей или улучшать производительность при увеличении объемов работы.

Чтобы избежать потерь, бизнесу желательно придерживаться проверенных подходов к эксплуатации серверного программного обеспечения с учетом значимости его характеристик для компании. А именно:

  • Использовать централизованный мониторинг с уведомлениями (алертами) по метрикам производительности, системным и бизнес-метрикам;

  • Описывать инфраструктуру кодом;

  • Хранить код инфраструктуры в системе контроля версий;

  • Организовать журналирование с единой базой данных по журналам и поиском по ним;

  • Соблюдать стандартные требования по безопасности: минимум открытых портов в интернет, сложные пароли, двухфакторная авторизация, журналирование попыток входа, автоматические блокировки при вводе неправильного пароля несколько раз;

  • Иметь готовый к исполнению Disaster Recovery Plan.

За годы практики и мы разработали методологию эксплуатации, которой хотим поделиться.

Методология эксплуатации серверного ПО от опытных инженеров Git in Sky, основанная на лучших DevOps-практиках

С нашей точки зрения есть отличные DevOps-практики, которые можно применить к систематизированию процесса эксплуатации серверного ПО, независимо от архитектуры инфраструктуры и используемого стека технологий. Этот подход состоит из пяти шагов по настройке ИТ-инфраструктуры.

1. Обеспечить централизованный мониторинг за всеми событиями

Это первое, с чего желательно начинать настраивать инфраструктуру. Организовать централизованный мониторинг позволяют системы мониторинга, построенные на Open Source технологиях Grafana и Prometheus. С ними знакомы большинство системных и DevOps-инженеров, приложения позволяют создавать свои наработки в виде дашбордов, отсутствует вендерлок. На рынке существуют и другие решения — их выбор зависит от многих критериев, в том числе, от интересующих преимуществ программы, архитектуры инфраструктуры и пр.

Система мониторинга должна размещаться в другом сегменте сети относительно основной инфраструктуры, потому что при аварии может быть недоступен весь сегмент сети, включая мониторинг. В идеале надо настроить и внутренний, и внешний контуры мониторинга. Это позволит понимать, как функционирует система «внутри себя» и как со стороны пользователей, если они «внешние».

В мониторинге важно настроить превентивный алертинг, чтобы можно было видеть и во время контролировать состояние инфраструктуры (например, увидеть заранее, что кончается место на дисках с данными).

Для чувствительных проектов, где любое простаивание выходит очень дорого, важно организовать круглосуточную службу поддержки, сотрудники которой будут получать алерты и понимать, насколько они критичны. Сотрудники службы могут принимать соответствующие решения — эскалировать инженеров, архитекторов или нет, потому что алерт был ложным (а такое часто случается).

Пример. Мы часто встречаемся с такой ошибкой владельцев инфраструктуры, как неоплаченные домены. Когда ежегодная оплата серверного домена заканчивается, перестает работать вся инфраструктура. Мы настраиваем превентивные алерты за 2-4 недели до окончания подписки на домен. Чтобы предотвратить простои и даже аварии, таких «напоминаний» можно сделать десятки или сотни.

Желательно настроить и систему предиктивных алертов, которые срабатывают не по заданным критическим порогам, а рассчитаны на основании расчетов-формул, алгоритмов машинного обучения. Эти несложные действия позволяют «предсказывать» возможные проблемы, аварии.

Пример. Если мы видим, что на диск сейчас активно записываются данные, то при сохранении текущей интенсивности записи место на диске закончится через X-часов/дней/месяцев. Предиктивный алертинг обеспечивает и возможность узнать о предстоящей проблеме до того, как она реально появится, и принять соответствующие меры.

Правильное логирование (журналирование)

Сбор и обработка логов — крайне полезная практика. Как правило, современная инфраструктура состоит из десятков приложений. Особенно если инфраструктура мультисервисная со множеством контейнеров, каждый из которых пишет свои логи. Для эффективного журналирования (т.е. такого, которое поможет при аварии) важно не просто собирать логи от всех приложений, а привести их к одному формату. Можно использовать несколько программ для агрегирования всех логов, однако важно иметь единое хранилище логов с поиском событий и ошибок по всем приложениям (например, по ключевому слову, номеру порта).

При выборе системы обработки логов важно обратить внимание на то, чтобы она имела возможность осуществления статистических запросов. Это нужно для того, чтобы понимать, сколько тех или иных событий произошло за определенный период времени. Важно наглядно видеть кривую отказов: что в один месяц их произошло больше, в другой меньше (насколько больше или меньше). И делать из этого какие-то выводы. Это позволит видеть, когда, где и какие сбои происходят; позволит легче принимать решения о том, как их предотвращать.

2. Обеспечить производительность серверной инфраструктуры

Можно существенно повысить производительность серверного ПО через DevOps-подход к его эксплуатации. Для этого нужно описать инфраструктуру кодом и выстроить CI/CD-процессы. А для лучшего распределения системных ресурсов и унификации схем развертывания ПО — внедрить контейнеризацию.

Инфраструктура как код

Если на проекте применять подход описания инфраструктуры кодом (Infrastructure-as-Code; Iac), то при ее обслуживании не будет нужна никакая другая документация. Все, что задействовано и актуально в инфраструктуре, все, что можно развернуть с нуля — есть в коде: переменные, ip-адреса, порты, конфигурации. Код — это лучшая документация, так как она самая актуальная.

Iac — самая современная и популярная практика из DevOps-методологии. Чтобы эффективно описать инфраструктуру кодом, можно использовать буквально несколько инструментов. Мы в своей практике даже разработали стандарт написания кода (code convention), который создает удобство и для других инженеров — они могут быстро разобраться, что к чему.

Не все можно описать кодом, но тогда это можно описать в файле README в корне проекта (например, в случае, если оператору надо совершить телефонный звонок). Несколько строк или даже страниц файла README написать проще, чем тома документации, которые через пару недель все равно будут уже неактуальны (например, если разработчики внесли изменения и выкатили новую версию).

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

Еще один плюс Iac — это минимизация ручных операций. Наш десятилетний опыт показывает, что 90% аварий происходят из-за человеческого фактора. Современная система представляет собой множество связанных между собой элементов, и эти связи человеку просто невозможно упомнить. Все изменения лучше делать из кода, сопровождая их коммитами, а уже потом «накатывать» соответствующим инструментом на реальную инфраструктуру. Такой способ работы обеспечивает минимальное количество аварий и максимальную безопасность.

CI/CD

Подход непрерывной интеграции и непрерывного развертывания ПО в процессе разработки (CI/CD) позволяет команде эксплуатации подготовиться к релизу разработчиков и выкатить изменения в инфраструктуре, которые будут максимально поддерживать изменения в коде релиза. Таким образом, релиз будет сразу же содержать необходимые изменения в инфраструктуре, которые при помощи CI/CD будут автоматически развернуты на всех средах — тестовой (test), проверочной (stage), продуктовой (production). Такой подход позволяет командам разработчиков быстрее выводить на рынок ИТ-продукты без потери качества.

Контейнеризация ПО

Контейнеризация позволяет унифицировать и упаковать все приложения в контейнеры, а затем упростить их развертывание. Процесс развертывания сводится к запуску контейнера, содержащего все необходимые компоненты для работы приложения (библиотеки, файлы, конфигурации).

Вместо долгой сборки образа на каждой среде и использования разных сборок,
при контейнеризации один и тот же собранный образ развертывается на всех средах. Контейнеризация также исключает ошибки, возникающие в процессе сборки.

3. Обеспечить отказоустойчивость ПО в процессе эксплуатации

Для обеспечения отказоустойчивости программной части серверной инфраструктуры важно позаботиться о регулярном правильном создании резервных копий данных и о доступности баз данных.

Резервное копирование (бэкапирование)

Пожалуй, лучшая практика которую мы хотим порекомендовать — это бэкапирование. Однако надо не просто «делать бэкапы», а сохранять проверенные, консистентные бэкапы, на которые ориентируется мониторинг.

Пример. К нам часто приходят аварийные проекты, в которых бэкапы собираются, но они испорчены. Их никто никогда не проверял, а оказалось, что бэкапы не консистентны. Это значит, что при аварии их нельзя будет развернуть или разворачивание будет происходить крайне долго — до нескольких суток. У бизнеса часто нет этого времени, потому что сутки простоя могут стоить ему миллиардов.

Нужно постоянно проверять данные на консистентность. Такую процедуру можно запускать во время каждого бэкапа. Также важно периодически проверять время восстановления и в целом возможность восстановления: как именно оно будет происходить, по какой процедуре. Если этого не делать, то может сложиться ситуация с накоплением бэкапа большого размера (например, 1 ТБ), который не сможет быстро развернуться по обычным интернет-системам.

Отказоустойчивость и высокая доступность СУБД

Чтобы обеспечить работоспособность системы управления базами данных в почти любых условиях, нужно внедрить кластеры баз данных, в том числе географически распределенные. Отказоустойчивые кластеры — это группа независимых серверов, гарантирующих минимальное время простоя.

Кластеры высокой доступности бывают следующими:

  • Кластер с репликацией данных (Data Replication Cluster). В таком кластере данные реплицируются на несколько узлов (нод), обычно распределенных на разных физических серверах или виртуальных машинах. Каждый узел содержит полную копию данных, что обеспечивает отказоустойчивость. В случае сбоя одного узла, остальные узлы продолжают обслуживать запросы. Репликация данных может быть синхронной или асинхронной, в зависимости от требований к согласованности данных и задержки.

  • Кластер с мастер-слейв архитектурой (Master-Slave Cluster). В таком кластере существует один узел-мастер, который обрабатывает записи и обновления, и несколько узлов-слейвов, которые реплицируют данные от мастера. Узлы-слейвы используются для чтения данных или для обработки запросов в случае отказа мастера. При сбое мастера один из узлов-слейвов может быть повышен до роли мастера.

  • Кластер с распределенными транзакциями (Distributed Transaction Cluster). В этом кластере данные распределяются по различным узлам, а транзакции выполняются и согласовываются между узлами. Это позволяет обрабатывать транзакции, включающие данные из разных узлов. Если один из узлов недоступен, остальные узлы могут продолжать выполнять транзакции.

  • Кластер с кворумом (Quorum Cluster). В таком кластере узлы формируют группу, и принятие решений основывается на большинстве голосов. Кластер требует кворум (определенное количество узлов), чтобы продолжать работу. Если число доступных узлов падает ниже кворума, кластер может остановиться или перейти в режим «только для чтения».

Между серверами происходит синхронизация данных методом потоковой репликации, который позволяет передавать изменения с активного на пассивные серверы так, чтобы в каждый момент времени на Slave-сервере хранилась полная и консистентная копия БД.

4. Обеспечить безопасность серверов

В идеале для обеспечения безопасности серверной инфраструктуры надо настроить передачу данных по безопасным каналам, выстроить защиту серверов и периодически проводить аудит серверной безопасности и аудит серверного ПО, проводить тесты на проникновение с помощью сторонних независимых команд-пентестеров. Но ваш системный администратор, вероятно, и так это знает.

При заказном выстраивании эффективной эксплуатации серверного ПО с помощью DevOps-практик системные инженеры Git in Sky выполняют лишь базовые настройки безопасности. А именно:

  1. Проверяют, надежно ли закрыты порты серверов от внешних проникновений.

  2. Проверяют, чтобы авторизация на серверах выполнялась посредством ключей, а не паролей. При этом на чувствительных сервисах должна быть включена двухфакторная аутентификация.

В отличие от общепринятого полноценного аудита безопасности наш аудит представляет собой санитарные меры, без которых риски могут сильно возрасти. Дополнительно к ним мы даем рекомендации о том, как выполнить базовые серверные настройки так, чтобы компания могла еще больше снизить очевидные риски.

5. Обеспечить масштабируемость инфраструктуры

Безопасно вносить изменения в серверное программное обеспечение, а также масштабировать серверные ресурсы по требованию позволят контейнеризация и/или виртуализация, максимальное использование облачных решений и грамотное распределение мощностей. А Iac позволит добавлять новые мощности буквально по нажатию кнопки или даже автоматически (автоскейлинг).

Выводы:

Перечислим основные тезисы статьи, которые позволят систематизировать информацию.

Что часто происходит в рабочей инфраструктуре?

  • Отсутствие бэкапов;

  • Неконсистентные или поврежденные данные;

  • Отсутствие или неполное покрытие сервисов мониторингом;

  • Описание инфраструктуры кодом не более, чем на 50% проектов;

  • Отсутствие единой базы логов со сквозным поиском по ним.

Что надо сделать для перевода эксплуатационных задач компаний на современные рельсы

  • Описать инфраструктуру кодом;

  • Хранить код всех приложений в репозиториях системы контроля версий;

  • Реализовать единую систему мониторинга и алертинга на зарекомендовавших себя инструментах;

  • Реализовать единую систему сбора и анализа логов;

  • Реализовать единую систему резервного копирования с едиными политиками, контролем консистентности копий, проверкой времени восстановления и мониторингом самого процесса.

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

Еще один плюс такого подхода заключается в том, что разработчикам не надо будет думать о том, как именно эксплуатировать ПО: какой ставить мониторинг, как собирать логи и т.д. Опытные системные инженеры Git in Sky уже разработали для них методологию эксплуатации серверного ПО. Благодаря такой рекомендации отпадает проблема выбора.

Что дает стандартизация эксплуатирования серверного ПО бизнесу

  • Выполнение рекомендаций по эксплуатации могут сохранить многие часы на восстановление систем после аварий.

  • Меньше простоев.

  • Облегченный поиск проблем.

  • Сокращение времени, а значит и стоимости эксплуатации.

  • Сокращение проблем выбора эксплуатационных технологий для разработчиков.

Заметим, что это общие рекомендации, которые по закону Парето подходят в 80% случаев, а 20% — это более уникальные, редкие ситуации, требующие индивидуального подхода.