GitOps для контура Directum RX: изменения только через репозиторий и что это даёт при проверке ИБ
Чем GitOps отличается от запуска Ansible с ноутбука администратора, как устроить изменения инфраструктуры Directum RX через репозиторий с ревью и откатом на виртуальных машинах и в Kubernetes, как ловить ручные правки и что отвечать службе ИБ на вопрос «кто и когда это поменял».
Коротко. Желаемое состояние в репозитории, изменения только через запрос на слияние, применяет агент или конвейер. На виртуальных машинах дрейф ловится ночным
--check --diff, в кластере это делает агент. Секреты шифруются поштучно, у аварийных правок есть процедура, и о приостановленной синхронизации напоминает мониторинг.
Служба ИБ спрашивает простую вещь: кто в прошлый четверг поменял настройки PostgreSQL на продуктивном контуре RX, кто это согласовал и как вернуть как было. Если инфраструктура меняется запуском Ansible с ноутбука администратора или правкой файлов на сервере, честный ответ звучит как «сейчас поищем». GitOps делает ответ на этот вопрос ссылкой на запрос на слияние в репозитории.
Симптом
- Конфигурация на двух серверах, которые должны быть одинаковыми, отличается, и никто не помнит почему.
- Повторный запуск плейбука «откатывает» исправление, которое кто-то сделал руками на сервере.
- У разных администраторов разные версии Ansible и ролей, и один и тот же плейбук ведёт себя по-разному.
- Пароли и ключи лежат в репозитории открытым текстом или на ноутбуках в файлах переменных.
- На вопрос «что сейчас раскатано на продуктивном» отвечают по памяти.
Почему так
Привычная схема выглядит так: репозиторий с ролями есть, но запускает их человек со своей машины, когда сочтёт нужным. Репозиторий при этом описывает, как должно быть, но не то, что стоит на серверах. Между ними три разрыва:
- Что запущено. Администратор мог запустить плейбук из ветки, с незакоммиченными правками или с другой версией роли.
- Кто разрешил. Запуск с ноутбука не проходит ревью. В лучшем случае остаётся строка в чате.
- Что изменилось после. Ручная правка на сервере нигде не записана и живёт до следующего запуска плейбука.
GitOps закрывает все три разрыва одним правилом: желаемое состояние описано в репозитории, менять его можно только через запрос на слияние с ревью, применяет изменения автоматика.
Как это устроено
| «Ansible с ноутбука» | GitOps | |
|---|---|---|
| Кто применяет | администратор со своей машины | агент в кластере или сборочный конвейер |
| Что применяется | что лежит у администратора локально | ровно то, что в защищённой ветке |
| Ревью | по желанию | обязательно, ветка защищена |
| Доступ к серверам | у каждого администратора | у агента или конвейера |
| Ручная правка | живёт до следующего запуска | агент возвращает состояние из репозитория или сообщает о расхождении |
| Откат | вспомнить, что было, и запустить | отменить коммит |
В Kubernetes
Агент внутри кластера (Flux или Argo CD) регулярно читает репозиторий и приводит кластер к описанному в нём состоянию: чарты, значения, манифесты. Агенту нужен только доступ на чтение репозитория, учётные данные администратора кластера в конвейере не хранятся.
Основные команды Flux для эксплуатации:
flux get kustomizations -A # что применено, на каком коммите, есть ли ошибки
flux get helmreleases -A # то же для Helm-релизов
flux diff kustomization rx --path ./clusters/prod/rx # что изменится, до слияния
flux reconcile kustomization rx --with-source # применить сейчас, не дожидаясь интервала
flux events -n flux-system # что агент делал и на чём споткнулся
В выводе первой команды видно, какой коммит сейчас раскатан. Это и есть ответ на вопрос «что на продуктивном».
На виртуальных машинах
Большинство инсталляций RX работают на виртуальных машинах без Kubernetes, и там агента нет. Принцип тот же, исполнитель другой: Ansible запускает сборочный конвейер.
- Роли и коллекции закреплены по версиям в файле зависимостей с конкретными коммитами или тегами.
- Изменение приходит запросом на слияние. Конвейер прогоняет проверки (
ansible-lint, синтаксис) и пробный запуск с--check --diffпротив целевого контура. Вывод пробного запуска прикладывается к запросу, и ревьюер видит, какие файлы на каких серверах поменяются. - После слияния конвейер запускает плейбук. Учётные данные для серверов есть только у конвейера.
- Плейбук записывает на сервер, какой коммит применён, например в файл в
/etc. Тогда ответ на вопрос «что здесь раскатано» лежит на самом сервере. - По расписанию, например каждую ночь, конвейер запускает тот же плейбук с
--check --diff. Любое изменение в выводе означает ручную правку или дрейф, и об этом приходит уведомление.
ansible-playbook -i inventories/prod site.yml --check --diff
Последний пункт заменяет агента: изменения применяются не автоматически, но расхождение видно на следующее утро, а не через полгода.
Секреты
Пароли в репозитории открытым текстом недопустимы, а GitOps без секретов в репозитории не работает. Обычно выбирают одно из двух.
- Шифрование в репозитории. SOPS с ключами age или Ansible Vault. Файл лежит в репозитории зашифрованным, расшифровывает его агент или конвейер своим ключом. Удобно для небольшой команды.
- Внешнее хранилище секретов. HashiCorp Vault, OpenBao или аналог. В репозитории только ссылка на секрет, значение подставляется при применении. Удобно, когда секретов много и их нужно менять по расписанию.
Шифровать стоит только секретные значения, а не файлы целиком. Иначе ревьюер не видит, что поменялось в остальной конфигурации, и ревью теряет смысл.
Аварийные правки
Во время ночной аварии ревью никто ждать не будет, и для этого заранее описывают процедуру.
- Правка делается руками или ускоренным слиянием без ревью. Если в кластере работает агент, сначала
приостанавливается его синхронизация для нужного объекта (
flux suspend), иначе он вернёт состояние из репозитория через несколько минут. - В течение рабочего дня правка оформляется запросом на слияние, задним числом проходит ревью.
- Синхронизация возобновляется (
flux resume). Приостановленный и забытый объект хуже, чем отсутствие GitOps: репозиторий и кластер расходятся, а все думают, что совпадают. Мониторинг должен сообщать о приостановленных объектах дольше суток.
Что это даёт при проверке ИБ
| Вопрос проверяющего | Где ответ |
|---|---|
| Кто внёс изменение | автор коммита и запроса на слияние |
| Кто согласовал | одобрение в запросе на слияние, ветка защищена от прямых коммитов |
| Когда применено | журнал конвейера или статус агента |
| Что было до изменения | история репозитория |
| Как откатить | отмена коммита и повторное применение |
| У кого есть доступ к серверам | у конвейера или агента; у людей только аварийный доступ, и его использование видно |
Это закрывает большую часть пунктов про управление изменениями и доступами в методике ФСТЭК об уровне зрелости. Коммиты можно подписывать, и Flux умеет применять только подписанные коммиты: тогда подменить содержимое репозитория в обход ревью тоже не выйдет.
Ревью роли идёт быстрее, когда в редакторе видно, где модуль, где его параметры, а где ключи задачи. Как включить такую подсветку в VS Code, разобрано в статье про подсветку Ansible по смыслу.
Чего не делать
- Не оставлять администраторам постоянный доступ к серверам «на всякий случай». Тогда ручные правки продолжатся, и GitOps останется на бумаге.
- Не держать окружения в разных ветках с ручным переносом коммитов. Ветки расходятся незаметно. Удобнее одна ветка и отдельный каталог на каждое окружение.
- Не шифровать файлы конфигурации целиком. Ревью зашифрованного файла ничего не показывает.
- Не забывать возобновить синхронизацию после аварии.
- Не считать GitOps заменой резервного копирования. Репозиторий восстанавливает конфигурацию, но не базу и не документы.
Похожая картина у вас?
Разберём ваш контур за 30 минут бесплатного созвона: версия RX, состав сервисов, что болит сильнее всего.
Написать