Добавить в корзинуПозвонить
Найти в Дзене

Почему секреты больше не хранят в Git

Долгие годы секреты в Kubernetes хранились ровно так же, как и всё остальное: в виде YAML файла, лежащего в том же репозитории, что и манифесты приложения. Это было удобно, знакомо и, как выяснилось со временем, глубоко ошибочно. Стандартный ресурс Secret в Kubernetes кодирует значения в base64, и это часто ошибочно принимают за шифрование. На самом деле это просто обфускация: base64 обратимо декодируется одной командой, а сам ресурс хранится в etcd в виде, который любой, получивший доступ к хранилищу кластера, способен прочитать без единого ключа. Документация Kubernetes честно предупреждает об этом ещё с 2016 года, но в реальных production кластерах до сих пор регулярно встречаются команды, уверенные, что вывод команды получения секрета как-то защищён самим фактом кодирования. Проблема хранения секретов в Git усугубляется ещё одним неприятным свойством самой системы контроля версий: история коммитов практически необратима. Если однажды реальный пароль или ключ API оказался закоммичен

Долгие годы секреты в Kubernetes хранились ровно так же, как и всё остальное: в виде YAML файла, лежащего в том же репозитории, что и манифесты приложения. Это было удобно, знакомо и, как выяснилось со временем, глубоко ошибочно. Стандартный ресурс Secret в Kubernetes кодирует значения в base64, и это часто ошибочно принимают за шифрование. На самом деле это просто обфускация: base64 обратимо декодируется одной командой, а сам ресурс хранится в etcd в виде, который любой, получивший доступ к хранилищу кластера, способен прочитать без единого ключа. Документация Kubernetes честно предупреждает об этом ещё с 2016 года, но в реальных production кластерах до сих пор регулярно встречаются команды, уверенные, что вывод команды получения секрета как-то защищён самим фактом кодирования.

Проблема хранения секретов в Git усугубляется ещё одним неприятным свойством самой системы контроля версий: история коммитов практически необратима. Если однажды реальный пароль или ключ API оказался закоммичен, простое удаление файла в следующем коммите ничего не решает: значение остаётся доступным в истории репозитория, а если репозиторий когда-либо был публичным или доступным широкому кругу сотрудников, утечка уже произошла и её невозможно откатить назад одним действием.

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

External Secrets Operator как слой доставки, а не хранилище

External Secrets Operator стал фактическим стандартом для команд, уже использующих внешний менеджер секретов у облачного провайдера. Оператор синхронизирует значения из внешнего источника, будь то AWS Secrets Manager, Google Secret Manager, Azure Key Vault или сам Vault, и создаёт на их основе обычные ресурсы Secret внутри Kubernetes. Сегодня у него более сорока поддерживаемых провайдеров, а установлен он примерно в трети production кластеров, чьи команды публично делятся статистикой своего стека.

Важно понимать точную границу того, что решает этот инструмент. External Secrets Operator не решает проблему хранения секретов в etcd в незашифрованном виде: секреты по-прежнему оказываются там же, где и всегда, в виде обычного объекта Kubernetes. Зато он полностью устраняет проблему секретов в Git, потому что реальное значение никогда не попадает в репозиторий вообще, а подтягивается динамически из внешнего, уже защищённого источника в момент синхронизации. Это делает его прежде всего слоем доставки поверх уже существующего надёжного хранилища, а не самостоятельным хранилищем секретов.

HashiCorp Vault для тех, кому нужен полный жизненный цикл

Vault решает задачу принципиально иначе и глубже. Секреты в этой модели вообще не оказываются внутри Kubernetes: они постоянно живут в собственном зашифрованном хранилище Vault, а приложения получают их через аутентифицированные запросы к API в момент реальной потребности. Ключевая возможность, которой не даёт ни один из остальных подходов, это динамические секреты: вместо статичного пароля базы данных Vault способен сгенерировать временную учётную запись по требованию с коротким сроком жизни, автоматически отзываемую по истечении этого срока. Даже если такая учётная запись будет перехвачена, она перестанет работать через считаные минуты.

Честная цена этой возможности реальна и существенна. Эксплуатация Vault требует выделенного кластера высокой доступности, специализированной экспертизы для процедур запечатывания и распечатывания хранилища, регулярного обновления и подготовки к аварийному восстановлению. Для команды, ещё не эксплуатирующей Vault, операционные накладные расходы редко оправдывают выигрыш в безопасности по сравнению с более простыми вариантами, если реальной потребности в динамических секретах и централизованном управлении политиками нет. Для новых развёртываний в 2026 году рекомендуемый способ интеграции с Kubernetes это CSI драйвер, монтирующий секреты как том, а не sidecar контейнер агента, добавляющий собственные накладные расходы на каждый под.

Sealed Secrets для команд, которым нужен GitOps без внешней зависимости

Sealed Secrets предлагает третий, отдельный путь. Секрет шифруется асимметричной криптографией специально под конкретный кластер, и зашифрованный результат абсолютно безопасно хранить даже в публичном репозитории: без приватного ключа, живущего исключительно внутри контроллера этого конкретного кластера, расшифровать значение невозможно. Это делает подход по настоящему привлекательным для команд, работающих строго в парадигме GitOps со статичными секретами и минимальным числом внешних зависимостей.

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

Облачные Secret Manager как управляемый, но привязанный к одному провайдеру вариант

AWS Secrets Manager, Google Secret Manager и Azure Key Vault решают ту же задачу с упором на минимальные операционные усилия. Команда получает управляемый сервис с ротацией, журналом аудита и глубокой интеграцией с остальной экосистемой конкретного облака, полностью снимая с себя заботу об эксплуатации собственной инфраструктуры хранения. Обратная сторона этого удобства — это привязка к одному облачному провайдеру: организация, работающая одновременно в нескольких облаках или на собственном оборудовании, вынуждена либо смириться с фрагментацией подхода между средами, либо выбрать более универсальное, но и более сложное в эксплуатации решение вроде Vault.

Как реально меняется подход к управлению конфигурацией?

Настоящий сдвиг происходит не на уровне выбора конкретного продукта, а на уровне самой философии. Раньше конфигурация приложения, включая секреты, воспринималась как единый, неделимый артефакт, целиком живущий в одном месте, обычно в Git рядом с остальным кодом развёртывания. Современный подход разделяет эту модель на явные, разные по своей природе слои: службу защиты ключей, отвечающую за криптографическую защиту на самом нижнем уровне, центральное хранилище секретов, будь то Vault или облачный менеджер, отвечающее за само хранение и жизненный цикл значения, и слой доставки в Kubernetes, будь то External Secrets Operator или прямая интеграция, отвечающий исключительно за то, чтобы нужное значение оказалось в нужном поде в нужный момент.

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

Практический вывод для команды, только начинающей наводить порядок в этой области, звучит просто. Если секреты уже хранятся у одного облачного провайдера, естественным первым шагом становится External Secrets Operator поверх уже существующего хранилища. Если требуется динамическая генерация учётных данных, централизованный аудит доступа или работа сразу в нескольких облаках, оправданным усложнением становится Vault. Если единственная задача — это сохранить рабочий процесс GitOps без добавления внешней зависимости, Sealed Secrets закрывает именно эту, более узкую потребность. И в любом из этих сценариев базовым, не подлежащим обсуждению минимумом остаётся шифрование самого etcd в состоянии покоя, потому что ни один из перечисленных инструментов не заменяет эту защиту, а лишь дополняет её сверху.

Автор: Коробов Алексей

© Коробов А.Е., 2026