Оборудование пришло на площадку за несколько месяцев до пика продаж. Служба эксплуатации, разумеется, знает, как и что настраивать на серверах, чтобы ввести их в production-окружение. Но нам нужно было автоматизировать это и исключить человеческий фактор. К тому же серверы заменяли перед миграцией набора систем SAP, критически важных для компании.
Ввод в действие новых серверов был жестко привязан к дедлайну. И сдвинуть его означало поставить под угрозу и отгрузки миллиарда подарков, и миграцию систем. Изменить дату не могла бы даже команда в составе Деда Мороза, Санта Клауса переносить систему SAP для управления складом можно только раз в году. С 31 декабря на 1 января огромные склады ритейлера, суммарно как 20 футбольных полей, останавливают свою работу на 15 часов. И это единственный промежуток времени для переезда системы. Права на ошибку с вводом серверов у нас не было.
Поясню сразу: мой рассказ отражает такой инструментарий и процесс управления конфигурациями, которые применяет наша команда.
Комплекс управления конфигурациями состоит из нескольких уровней. Ключевой компонент CMS-система. При промышленной эксплуатации отсутствие одного из уровней неизбежно привело бы к неприятным чудесам.
Управление установкой ОС
Первый уровень это система управления установкой операционных систем на физические и виртуальные серверы. Она создает базовые конфигурации ОС, избавляя от человеческого фактора.
С помощью этой системы мы получали типовые и пригодные для дальнейшей автоматизации экземпляры серверов с ОС. При разливке они получали минимальный набор локальных пользователей и публичных ключей SSH, а также согласованную конфигурацию ОС. Мы могли гарантированно управлять серверами через CMS и были уверены, что внизу, на уровне ОС, нет сюрпризов.
Задача максимум для системы управления установкой автоматически настраивать серверы от уровня BIOS/Firmware до ОС. Многое здесь зависит от оборудования и задач настройки. Для разнородного оборудования можно рассмотреть REDFISH API. Если всё железо от одного вендора, то, зачастую, удобнее использовать готовые средства управления (например, HP ILO Amplifier, DELL OpenManage и т. п.).
Для установки ОС на физических серверах мы применяли всем хорошо знакомый Cobbler, в котором определён набор согласованных со службой эксплуатации профилей инсталляции. При добавлении нового сервера в инфраструктуру инженер привязывал MAC-адрес сервера к требуемому профилю в Cobbler. При первой загрузке по сети сервер получал временный адрес и свежую ОС. Затем его переводили в целевую VLAN/IP-адресацию и продолжали работу уже там. Да, смена VLAN отнимает время и требует согласования, но зато это дает дополнительную защиту от случайной инсталляции сервера в production-окружении.
Виртуальные серверы мы создавали на основе шаблонов, подготовленных с помощью HashiСorp Packer. Причина была та же: чтобы предотвратить возможные человеческие ошибки при установке ОС. Но, в отличие от физических серверов, Packer позволяет не использовать PXE, сетевую загрузку и смену VLAN. Это облегчило и упростило создание виртуальных серверов.
Рис. 1. Управление установкой операционных систем.
Управление секретами
Любая система управления конфигурациями содержит в себе данные, которые должны быть скрыты от рядовых пользователей, но нужны для подготовки систем. Это пароли локальных пользователей и сервисных учетных записей, ключи сертификатов, всевозможные API Tokens и пр. Обычно их называют секретами.
Если с самого начала не определить, где и как хранить эти секреты, то, в зависимости от строгости требований ИБ, вероятны такие способы хранения:
- прямо в коде управления конфигурации или в файлах в репозитории;
- в специализированных инструментах управления конфигурациями (например, Ansible Vault);
- в системах СI/CD (Jenkins/TeamCity/GitLab/и т. п.) или в системах управления конфигурациями (Ansible Tower/Ansible AWX);
- также секреты могут передавать на ручном управлении. Например, выкладывают в оговоренное место, а затем их используют системы управления конфигурациями;
- различные комбинации вышеописанного.
У каждого метода свои недостатки. Главный из них отсутствие политик доступа к секретам: нельзя или трудно определить, кто может использовать те или иные секреты. Ещё один минус отсутствие аудита доступа и полноценного жизненного цикла. Как быстро заменить, например, публичный ключ, который прописан в коде и в ряде смежных систем?
Мы использовали централизованное хранилище секретов HashiCorp Vault. Это позволило нам:
- хранить секреты безопасно. Они зашифрованы, и даже если кто-то получит доступ к базе данных хранилища Vault (например, восстановив её из резервной копии), то не сможет прочитать хранящиеся там секреты;
- организовать политики доступа к секретам. Пользователям и приложениям доступны только выделенные им секреты;
- проводить аудит доступа к секретам. Любые действия с секретами записываются в журнал аудита Vault;
- организовать полноценный жизненный цикл работы с секретами. Их можно создавать, отзывать, задавать срок действия и т. д.
- легко интегрироваться с другими системами, которым нужен доступ к секретам;
- а еще применять сквозное шифрование, одноразовые пароли для ОС и БД, сертификаты уполномоченных центров и т.д.
Теперь перейдем к центральной системе аутентификации и авторизации. Можно было обойтись и без неё, но администрировать пользователей во множестве сопутствующих систем слишком нетривиально. Мы настроили аутентификацию и авторизацию через службу LDAP. Иначе в том же Vault пришлось бы непрерывно выпускать и вести учет аутентификационным токенам для пользователей. А удаление и добавление пользователей превратилось бы в квест а везде ли я создал/удалил эту УЗ?
Добавляем еще один уровень нашу в систему: управление секретами и центральную аутентификацию/авторизацию:
Рис. 2. Управление секретами.
Управление конфигурациями
Добрались до сердцевины до системы CMS. В нашем случае это связка Ansible и Red Hat Ansible AWX.
Вместо Ansible может выступать Chef, Puppet, SaltStack. Мы выбрали Ansible по нескольким критериям.
- Во-первых, это универсальность. Набор готовых модулей для управления производит впечатление. А если его не хватает, можно поискать на GitHub и Galaxy.
- Во-вторых, не нужно ставить и поддерживать агенты на управляемом оборудовании, доказывать, что они не мешают нагрузке, и подтверждать отсутствие закладок.
- В-третьих, у Ansible низкий порог вхождения. Грамотный инженер напишет рабочий playbook буквально в первый день работы с продуктом.
Но одного Ansible в промышленном окружении нам было недостаточно. Иначе возникло бы много проблем с ограничением доступа и аудитом действий администраторов. Как разграничить доступ? Ведь нужно было, чтобы каждое подразделение управляло (читай запускало Ansible playbook) своим набором серверов. Как разрешить запуск конкретных Ansible playbook только определенным сотрудникам? Или как проследить, кто запускал playbook, не заводя множество локальных УЗ на серверах и оборудовании под управлением Ansible?
Львиную долю подобных вопросов решает Red Hat Ansible Tower, или его open-source upstream проект Ansible AWX. Поэтому мы и предпочли его для заказчика.
И еще один штрих к портрету нашей CMS-системы. Ansible playbook должен храниться в системах управления репозиторием кода. У нас это GitLab CE.
Итак, самими конфигурациями управляет связка из Ansible/Ansible AWX/GitLab (см. Рис. 3). Разумеется, AWX/GitLab интегрированы с единой системой аутентификации, а Ansible playbook с HashiCorp Vault. Конфигурации попадают в production-окружение только через Ansible AWX, в котором заданы все правила игры: кто и что может конфигурировать, откуда брать код управления конфигурациями для CMS и т. д.
Рис. 3. Управление конфигурациями.
Управление тестированием
Наша конфигурация представлена в виде кода. Поэтому мы вынуждены играть по тем же правилам, что и разработчики ПО. Нам необходимо было организовать процессы разработки, непрерывного тестирования, доставки и применения конфигурационного кода на production-серверы.
Если это не сделать сразу, то написанные роли для конфигурации либо перестали бы поддерживать и изменять, либо прекратили бы запускать в production. Лекарство от этой боли известно, и оно оправдало себя в этом проекте:
- каждая роль покрыта модульными тестами;
- тесты прогоняются автоматически при любом изменении в коде, управляющем конфигурациями;
- изменения в коде управления конфигурациями попадают в production-окружение только после успешного прохождения всех тестов и code review.
Разработка кода и управление конфигурациями стали спокойнее и предсказуемее. Для организации непрерывного тестирования мы использовали инструментарий GitLab CI/CD, а в качестве фреймворка для организации тестов взяли Ansible Molecule.
При любом изменении в коде управления конфигурациями GitLab CI/CD вызывает Molecule:
- та проверяет синтаксис кода,
- поднимает Docker-контейнер,
- применяет измененный код в созданный контейнер,
- проверяет роль на идемпотентность и прогоняет тесты для этого кода (гранулярность здесь на уровне ansible role, см. Рис. 4).
Конфигурации в production-окружение мы доставляли с помощью Ansible AWX. Ответственные за эксплуатацию инженеры применяли изменения в конфигурации через заранее определенные шаблоны. AWX самостоятельно при каждом применении запрашивал последнюю версию кода с мастер-ветки GitLab. Так мы исключали употребление непроверенного или устаревшего кода в production-окружении. Естественно, код в мастер-ветку попадал только после тестирования, просмотра и согласования.
Рис. 4. Автоматическое тестирование ролей в GitLab CI/CD.
Есть еще проблема, связанная с эксплуатацией production-систем. В реальной жизни очень трудно вносить изменения в конфигурацию только через код CMS. Возникают внештатные ситуации, когда инженер должен менять конфигурацию здесь и сейчас, не дожидаясь правки кода, тестирования, согласования и т. п.
В результате из-за ручных изменений появляются расхождения в конфигурации на однотипном оборудовании (например, на узлах HA-кластера разная конфигурация настроек sysctl). Или реальная конфигурация на оборудовании отличается от той, которая задана в коде CMS.
Поэтому в дополнение к непрерывному тестированию мы проверяем production-окружения на расхождение конфигураций. Выбрали самый простой вариант: запуск кода конфигурации СMS в режиме dry run, то есть без применения изменений, но с уведомлением обо всех расхождениях между запланированной и реальной конфигурацией. Мы реализовали это с помощью периодических запусков всех Ansible playbook с опцией --check на production-серверах. За запуск и актуальность playbook, как всегда, отвечает Ansible AWX (см. Рис. 5):
Рис. 5. Проверки на расхождение конфигураций в Ansible AWX.
После проверок AWX отправляет отчет о расхождениях администраторам. Они изучают проблемную конфигурацию, а затем исправляют её через скорректированные playbook. Так мы поддерживаем конфигурацию в production-окружении и CMS всегда находится в актуальном и синхронизированном состоянии. Это избавляет от неприятных чудес, когда код CMS применяется на боевых серверах.
Теперь у нас появился важный уровень тестирования, состоящий из Ansible AWX/GitLab/Molecule (Рис. 6).
Рис. 6. Управление тестированием.
Сложно? Не спорю. Но такой комплекс управления конфигурациями стал исчерпывающим ответом на множество вопросов, связанных с автоматизацией настройки серверов. Теперь у ритейлера у типовых серверов всегда строго определенная конфигурация. СMS, в отличие от инженера, не забудет добавить необходимые настройки, создать пользователей и выполнить десятки или сотни требуемых настроек.
В настройках серверов и окружений сегодня отсутствуют тайные знания. Все необходимые особенности отражены в playbook. Больше никакого творчества и туманных инструкций: ставь как обычный Oracle, но там нужно пару настроек sysctl прописать, и пользователей с нужным UID добавить. Спроси у ребят из эксплуатации, они знают.
Возможность обнаруживать расхождение конфигураций и заранее их исправлять придаёт спокойствия. Без системы управления конфигурациям это обычно выглядит по-другому. Проблемы накапливаются до тех пор, пока однажды не выстреливают в production. Потом проводится разбор полетов, проверяют и исправляют конфигурации. И цикл повторяется снова
И конечно, мы ускорили запуск серверов в эксплуатацию с нескольких дней до часов.
Ну а в саму новогоднюю ночь, когда дети радостно разворачивали подарки и взрослые загадывали желания под бой курантов, наши инженеры мигрировали SAP-систему на новые серверы. Даже Дед Мороз скажет, что самые лучшие чудеса хорошо подготовленные.
P.S. Наша команда часто сталкивается с тем, что заказчики хотят как можно проще решить задачу управления конфигурациями. В идеале, чтобы как по волшебству одним инструментом. Но в жизни всё сложнее (да, опять не завезли серебряные пули): приходится создавать целый процесс с помощью удобных для команды заказчика инструментов.
Автор: Сергей Артемов, архитектор отдела DevOps-решений Инфосистемы Джет