Оригинал: CNPG Recipe 27 — Running OpenBao on Kubernetes with a CloudNativePG PostgreSQL backend — 17 августа 2026. Адаптивный перевод; манифесты и SQL — как в оригинале.
OpenBao — форк HashiCorp Vault под эгидой Linux Foundation. У него есть storage-бэкенд postgresql, который превращает обычный PostgreSQL-кластер в зашифрованное key-value хранилище для секретов. Смысл связки прост: хранилище секретов работает поверх той же БД, которую вы уже умеете эксплуатировать, а Raft-кластер разворачивать не нужно.
Кластер PostgreSQL
Ключевые моменты манифеста — три реплики, синхронная репликация и аутентификация по сертификатам вместо паролей:
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: openbao-db
namespace: openbao
spec:
instances: 3
imageCatalogRef:
apiGroup: postgresql.cnpg.io
kind: ClusterImageCatalog
name: postgresql-minimal-trixie
major: 18
postgresql:
synchronous:
method: any
number: 1
pg_hba:
- hostssl openbao openbao all cert
- hostssl openbao openbao-rw all certЗдесь всё сходится с тем, что разбирали раньше: image catalog из Рецепта 22, минимальный образ PostgreSQL 18 из статьи про релиз, а сертификаты для ролей выпускаются через DatabaseRole из Рецепта 25. Паролей в схеме нет вообще — правила pg_hba требуют cert.
Схема таблиц
В HA-режиме (ha_enabled = "true") OpenBao ожидает две таблицы: хранилище ключей и таблицу блокировок для выбора активного узла.
CREATE TABLE IF NOT EXISTS openbao_kv_store (
parent_path TEXT NOT NULL,
path TEXT NOT NULL,
key TEXT NOT NULL,
value BYTEA,
CONSTRAINT openbao_kv_store_pkey PRIMARY KEY (path, key)
);
CREATE TABLE IF NOT EXISTS openbao_ha_locks (
ha_key TEXT NOT NULL,
ha_identity TEXT NOT NULL,
ha_value TEXT,
valid_until TIMESTAMP WITH TIME ZONE NOT NULL,
CONSTRAINT openbao_ha_locks_pkey PRIMARY KEY (ha_key)
);Таблицы создаются заранее, а роли openbao-rw выдаются только права DML — без CREATE. Это принцип наименьших привилегий из Рецепта 3 в чистом виде: приложение не должно уметь менять схему.
Конфигурация OpenBao
storage "postgresql" {
connection_url = "postgres://openbao-rw@openbao-db-rw:5432/openbao?sslmode=verify-full&sslcert=/etc/openbao/certs/tls.crt&sslkey=/etc/openbao/certs/tls.key&sslrootcert=/etc/openbao/ca/ca.crt"
table = "openbao_kv_store"
ha_table = "openbao_ha_locks"
ha_enabled = "true"
skip_create_table = "true"
}Два обязательных момента:
skip_create_table = "true"— раз у роли нетCREATE, попытка OpenBao создать таблицы самостоятельно провалится на старте.sslmode=verify-fullи путь к CA — полноценная проверка подлинности сервера, а не просто шифрование канала.
Секреты монтируются с defaultMode: 0640: libpq отказывается работать с приватным ключом, у которого права шире, но при этом нужно оставаться в рамках дефолтов Kubernetes.
Высокая доступность и распечатывание
Три реплики OpenBao с обязательной podAntiAffinity по хостам. Важная особенность, которую легко упустить:
Состояние Shamir у каждого пода своё и живёт в памяти. Поэтому распечатывать (unseal) нужно каждый под отдельно, подавая все три ключа по очереди:
# Инициализация — только на первом поде
kubectl exec -it -n openbao openbao-0 -- bao operator init
# Распечатывание: три ключа на каждый под
kubectl exec -it -n openbao openbao-0 -- bao operator unseal <UNSEAL_KEY_1>
kubectl exec -it -n openbao openbao-0 -- bao operator unseal <UNSEAL_KEY_2>
kubectl exec -it -n openbao openbao-0 -- bao operator unseal <UNSEAL_KEY_3>
# Повторить для openbao-1 и openbao-2Из этого следует практическое: любой перезапуск пода требует повторного unseal вручную, если не настроено авто-распечатывание. Планируйте это до продакшена.
Подводный камень: ротация сертификатов
Самая ценная часть рецепта. Клиентские сертификаты живут 90 дней и автоматически обновляются примерно за 7 дней до истечения. Но:
storage-бэкенд
postgresqlв OpenBao открывает пул соединений один раз при старте процесса и больше никогда не перечитывает файлы сертификатов.
То есть сертификат на диске обновится, а работающий процесс продолжит использовать старый — и в какой-то момент потеряет доступ к базе. Лечится rolling restart подов OpenBao в течение окна обновления (те самые 7 дней). Ставьте себе напоминание или автоматизацию — иначе получите отказ хранилища секретов в момент, который сложно связать с причиной.
Итог
Схема получается аккуратной: секреты лежат в PostgreSQL под управлением CloudNativePG, доступ идёт по TLS-сертификатам без единого пароля, права роли урезаны до DML, а HA обеспечивается таблицей блокировок. Две вещи, которые нужно держать в голове при эксплуатации, — ручной unseal каждого пода и обязательный перезапуск при ротации сертификатов.