Оригинал: CloudNativePG Recipe 2 — Inspecting Default Resources in a CloudNativePG Cluster — 8 марта 2024.
Разбираем, что именно CloudNativePG создаёт «бесплатно» при поднятии кластера. Предполагается, что у вас уже есть cluster-example из Рецепта 1 и установлен плагин cnpg.
ConfigMaps по умолчанию
kubectl get configmapsNAME DATA AGE
cnpg-default-monitoring 1 14hcnpg-default-monitoring содержит встроенные метрики для встроенного Prometheus exporter. Содержимое:
kubectl get -o yaml configmaps cnpg-default-monitoring | lessCloudNativePG автоматически привязывает этот ConfigMap к кластеру. Проверить:
kubectl get cluster cluster-example \
-o jsonpath="{.spec.monitoring}" | jq -CПолучите что-то вроде:
{
"customQueriesConfigMap": [
{
"key": "queries",
"name": "cnpg-default-monitoring"
}
],
"disableDefaultQueries": false,
"enablePodMonitor": false
}Secrets по умолчанию
kubectl get secretsNAME TYPE DATA AGE
cluster-example-app kubernetes.io/basic-auth 9 14h
cluster-example-ca Opaque 2 14h
cluster-example-replication kubernetes.io/tls 2 14h
cluster-example-server kubernetes.io/tls 2 14hЧто хранят:
cluster-example-app— учётка и пароль пользователяapp, владельца БДapp.cluster-example-ca— Certificate Authority, которой оператор подписывает TLS-сертификаты.cluster-example-replication— клиентский TLS-сертификат для streaming replication.cluster-example-server— серверный TLS-сертификат PostgreSQL.
Секрет пользователя app
Тип kubernetes.io/basic-auth. Внутри — username, password, pgpass-файл, connection string. Всё в base64 — стандарт для Secret-ресурсов.
kubectl describe secret cluster-example-appИзвлечь pgpass:
kubectl get secret cluster-example-app \
-o jsonpath="{.data.pgpass}" | base64 -dВ тестовой среде покажет что-то вроде:
cluster-example-rw:5432:app:app:<password>Этот секрет можно монтировать как projected volume в контейнер приложения — пароль доступен через файл, а не через переменные окружения. Безопаснее.
Секреты для PKI и TLS
Один из принципов CloudNativePG — secure by default (shift-left на безопасность). По умолчанию оператор поднимает CA для кластера, выпускает с ней TLS-сертификаты для каждого Postgres-сервера и реализует mTLS для клиентских приложений.
Посмотреть CA:
kubectl get secret cluster-example-ca \
-o jsonpath="{.data['ca\.crt']}" | \
base64 -d | \
openssl x509 -text -nooutПример вывода:
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
d2:a1:0f:48:4b:c4:33:38:72:f9:64:cf:d9:b0:56:e5
Signature Algorithm: ecdsa-with-SHA256
Issuer: OU=default, CN=cluster-example
Validity
Not Before: Mar 7 17:09:44 2024 GMT
Not After : Jun 5 17:09:44 2024 GMT
Subject: OU=default, CN=cluster-example
...
X509v3 extensions:
X509v3 Key Usage: critical
Certificate Sign
X509v3 Basic Constraints: critical
CA:TRUEЭтой CA подписан серверный сертификат PostgreSQL в cluster-example-server:
kubectl get secret cluster-example-server \
-o jsonpath="{.data['tls\.crt']}" | \
base64 -d | \
openssl x509 -text -nooutОсобое внимание — на Subject и X509v3 Subject Alternative Name. В SAN перечислены все DNS-имена сервисов кластера: cluster-example-rw, cluster-example-r, cluster-example-ro и их FQDN-варианты в namespace.
Кроме сертификатов, секреты содержат приватные ключи — оператор использует их для самоподписи клиентских сертификатов (например, для streaming replication).
TLS-сертификат для streaming replication
cluster-example-replication хранит сертификат пользователя streaming_replica:
kubectl get secret cluster-example-replication \
-o jsonpath="{.data['tls\.crt']}" | \
base64 -d | \
openssl x509 -text -nooutВ Subject: CN=streaming_replica — имя пользователя PostgreSQL. По умолчанию CloudNativePG ротирует эти сертификаты каждые 90 дней.
Проверить, что primary_conninfo на реплике уже настроен на mTLS без пароля:
kubectl exec -ti -c postgres cluster-example-2 \
-- psql -qAt -c 'SHOW primary_conninfo'Вывод:
host=cluster-example-rw
user=streaming_replica
port=5432
sslkey=/controller/certificates/streaming_replica.key
sslcert=/controller/certificates/streaming_replica.crt
sslrootcert=/controller/certificates/server-ca.crt
application_name=cluster-example-2
sslmode=verify-caЕсли самоподписанных сертификатов недостаточно — можно подключить cert-manager.
Глобальные объекты в PostgreSQL по умолчанию
CloudNativePG создаёт:
- пользователя
streaming_replica; - application-пользователя
app; - application-БД
app.
Список ролей:
kubectl exec -ti -c postgres cluster-example-1 -- psql -c '\du' List of roles
Role name | Attributes
-------------------+------------------------------------------------------------
app |
postgres | Superuser, Create role, Create DB, Replication, Bypass RLS
streaming_replica | ReplicationСписок БД:
kubectl exec -ti -c postgres cluster-example-1 -- psql -c '\l'Помимо стандартных postgres, template0, template1, появилась app, владелец — app.
Вывод
Подход «один кластер = одна БД» — это и есть микросервисная БД: вместо того, чтобы держать пять БД в одном кластере, держим пять отдельных кластеров. Имя БД и владельца становятся менее важны — главным «адресом» становится пара namespace:name самого кластера, она уникальна на весь Kubernetes.