PostgreSQL Role management
注釈
CloudNativePGは、当初から、PostgreSQLインスタンスで必要な特定のロールの作成を管理してきました。
postgresスーパーユーザー、streaming_replica、cnpg_pooler_pgbouncerなどの一部の予約済みユーザーPgBouncerPoolerを使用する場合アプリケーションデータベースの低特権の所有者として設定されたアプリケーションユーザー
このプロセスは、 Bootstrap セクションで説明しています。
CloudNativePGは、PostgreSQLデータベースロールの完全なライフサイクル管理を提供します。ロールは次のいずれかで定義できます。
as standalone `DatabaseRole resources <#the-databaserole-resource>` 推奨 、または
the `managed stanza within the Cluster spec <#inline-managed-roles>` 経由 。
共存と優先
2つの方法は相互排他的ではありません。それぞれで異なるロールを同時に管理できます。これが、インラインスタンザからDatabaseRole
リソースへの段階的な移行が可能です。同じロール名が両方の場所で定義されている場合のルールのみが必要です。
その場合、 クラスター仕様``managed.roles`` が常に優先されます 。
DatabaseRole
はリコンサイル化されず、そのステータスの競合を報告します
:ref:``DatabaseRole` リソースのステータス <DatabaseRole リソースのステータス>` を参照してください。
重要
宣言的ロール管理は、データベースには存在するが、クラスター仕様にも`DatabaseRole` にも含まれていないロールを無視します。これらのロールのライフサイクルはPostgreSQL内で引き続き管理されるため、都合の良いときにこの機能を採用できます。
一般的なロール構成の注意事項
使用される管理方法に関係なく、ロール仕様は PostgreSQL structure and naming conventions に従います。
Tip
API Reference を参照してください。
属性の完全なリストについては、
いくつかの点に注意してください。
ensure属性はPostgreSQLの ではありません 。宣言的ロール管理がロールを作成するpresentデフォルトabsentを有効にし、インライン managed.roles スタンザで のみ 使用できます。DatabaseRoleはensureをサポートしていません。代わりに :ref:``delete` 再利用ポリシーを介した削除 <delete 再利用ポリシーを介した削除>` を介してロールの削除を表現します。inherit属性は、PostgreSQLの規則に従って、デフォルトでtrueです。connectionLimit属性は、PostgreSQLの規約に従って、デフォルトの-1に設定されます。inRolesのロールメンバーシップは、デフォルトでメンバーシップなしです。
DatabaseRole リソース
DatabaseRole
カスタムリソースは、PostgreSQLデータベースロールを管理する専用のKubernetesネイティブ方法を提供します。
これは、クラスターインフラストラクチャからロールのライフサイクルを分離するため、最新の環境とGitOpsワークフローに推奨されるアプローチです。
注釈
DatabaseRole は、仕様またはパスワードのSecretが変更されたときに適用されます。手動`ALTER ROLE` など、データベースに直接行われた変更は、次回リソースが適用されるまで検出または元に戻されません。対照的に、インライン管理ロールは定期的にデータベースカタログと比較され、仕様に戻されます。 ::
DatabaseRole
リソースへのアクセスを許可することのRBACの影響については、
CloudNativePGとCiliumを使用したポッド間のネットワークセキュリティ を参照してください。
DatabaseRole は名前空間スコープです。リソース、spec.cluster
を介して参照するCluster 、および消費するpasswordSecret
はすべて同じ名前空間に存在する必要があります。
マニフェストの例
apiVersion: postgresql.cnpg.io/v1
kind: DatabaseRole
metadata:
name: role-dante
spec:
cluster:
name: cluster-example
name: dante
comment: "Dante Alighieri"
login: true
superuser: false
createdb: true
databaseRoleReclaimPolicy: delete
inRoles:
- pg_monitor
passwordSecret:
name: cluster-example-dante
ロール定義のマニフェストの例は、ファイル role-examples.yaml にあります。
ロール再利用ポリシー
databaseRoleReclaimPolicy フィールドは、 DatabaseRole
カスタムリソースがKubernetes
APIから削除されるときのオペレーターの「最終動作」を定義します。これは、Kubernetesの永続ボリュームの動作を反映しています。
``retain`` デフォルト ロールはデータベースに残ります。これは運用環境にとって最も安全な設定であり、マニフェストが誤って削除された場合でも、データベースユーザーおよびその所有するオブジェクトは変更されないままです。
``delete`` : オペレーターは、Kubernetesオブジェクトがファイナライズされる前に、PostgreSQLで
DROP ROLEを実行しようとします。これは、一時的な環境または自動化された環境に最適です。
注釈
ロールがオブジェクトテーブル、スキーマなどを所有している場合、DROP ROLE は失敗し、DatabaseRole は`Terminating` に残り、これらのオブジェクトが再割り当てまたは削除されるまで定期的に再試行されます。オペレーターは、あなたに代わって所有オブジェクトをドロップすることはありません。PostgreSQLでそれらを再割り当てまたはドロップするか、retain に切り替えて、削除を完了します。 ::
ロールの削除
ロールを削除する方法は、ロールの作成方法によって異なります。
``DatabaseRole`` によって作成されます リソースを削除します。ロールがPostgreSQLから削除されるかどうかは、その :ref:``delete` 再利用ポリシーを介した削除 <delete 再利用ポリシーを介した削除>` によって制御されます。
既存の、または他の場所で管理されている
DatabaseRoleは、ドロップするツールではありません。インライン managed.roles を介してabsentを宣言します
スタンザを削除するか、 DROP ROLE を直接実行します。
警告
既に存在するロールの`DatabaseRole` を作成する adopts it:オペレーターは、**すべての**属性がマニフェストと一致するように既存のロールを変更します。省略した属性を含み、デフォルトに強制的に戻されます。特に、inRoles にリストされていないメンバーシップは取り消され、省略された`connectionLimit` は`-1` 無制限にリセットされ、ロールに有効期限がある場合、省略された`validUntil` は`infinity` になります。ロールを採用する前に、ロールの現在の属性とメンバーシップを確認し、削除する前に変更されるため、ドロップするだけのロールで`DatabaseRole` をポイントしないでください。
DatabaseRole リソースのステータス
DatabaseRole
リソースには、ロールごとの可観測性のための専用のstatus
セクションが含まれています。
status:
applied: true
observedGeneration: 3
conditions:
- lastTransitionTime: "2026-04-04T15:06:23Z"
message: "2051"
reason: ChangeDetected
status: "True"
type: PasswordSecretChange
PasswordSecretChange
条件は、インスタンスマネージャーの内部信号としてオペレーターによって維持されます。そのメッセージには、オペレーターが最後に観察したパスワードシークレットのresourceVersion
が含まれ、その値の変更がパスワードの再適用をトリガーします。この条件は、パスワードシークレットが使用されると表示され、
passwordSecret が仕様から削除されると削除されます。
DatabaseRole
がクラスター仕様で既に管理されている名前をターゲットとしている場合
共存と優先 を参照してください、 applied フィールドはfalse
になり、次のメッセージが表示されます。
database role is already managed by the CNPG cluster
レプリカクラスター では、ロールはプライマリクラスターが所有し、ローカルにリコンサイルされません。その場合、インスタンスマネージャーは、ロールをfailedではなく_unknown_として報告します。applied
フィールドは説明メッセージとともに設定されないnil
のままです。クラスターがプライマリに昇格すると、ロールは通常調整されます。
クライアント証明書の生成
DatabaseRole
リソースは、クラスターのクライアントCAによって署名され、Kubernetes
Secretに保存されているTLSクライアント証明書のオプトイン生成をサポートしています。これにより、 PostgreSQL `cert authentication <https://www.postgresql.org/docs/current/auth-cert.html>`_ が有効になります
パスワードの代替として パスワードを手動でローテーションする必要はなく、プライベートキーはKubernetes Secretとして保存され、クラスターの外部に送信されることはありません。
これを有効にするには、clientCertificate
ブロックを仕様に追加します。
apiVersion: postgresql.cnpg.io/v1
kind: DatabaseRole
metadata:
name: role-dante
spec:
cluster:
name: cluster-example
name: dante
login: true
clientCertificate:
enabled: true
databaseRoleReclaimPolicy: retain
ブロックが存在する場合、clientCertificate.enabled
はデフォルトのtrue になるため、 clientCertificate: {}
はそれを有効にすることと同じです。 enabled: false
を設定して、ブロックを維持したまま発行をオフにします。
重要
login: true は、 clientCertificate 発行が有効になっている場合に必要です。オペレーターは検証を介してこれを適用し、それ以外の場合はリソースを拒否します。
生成されたシークレット
オペレーターは、同じ名前空間に<databaserole-name>-client-cert
という名前のシークレットを作成します。これには2つのキーが含まれています。
Key |
Contents |
|---|---|
tls.crt |
PEM-encoded client certificate, signed by the cluster's client CA |
tls.key |
PEM-encoded private key |
証明書の有効期限はstatus.clientCertificate.expiration
に表示されます。
status:
clientCertificate:
expiration: "2026-07-01T12:00:00Z"
pg_hba.conf の構成
オペレーターは証明書を生成しますが、 pg_hba.conf
は自動的に変更されません**。ロールが認証できるようにするには、 cert
メソッドを使用してhostssl
ルールをクラスターに追加する必要があります。
spec:
postgresql:
pg_hba:
- hostssl all dante all cert
生成されたシークレットを使用した作業的な接続文字列は次のようになります。
psql "host=<cluster>-rw.<namespace>.svc port=5432 dbname=<db> user=dante \
sslcert=/path/to/tls.crt sslkey=/path/to/tls.key \
sslrootcert=/path/to/ca.crt sslmode=verify-full"
リニューアル
クライアント証明書は、オペレーターのグローバル証明書設定を継承します。デフォルトで
90日 の有効期間で発行され、有効期限から 7日
以内になると自動的に更新されます。どちらの値もオペレーター全体で、
CERTIFICATE_DURATION およびEXPIRING_CHECK_THRESHOLD
オペレーター設定を介して構成できます。 DatabaseRole
ごとに構成はできません。
更新はリコンサイルループによって駆動されます。オペレーターは、証明書の有効期限が近づいているかどうかを確認し、必要に応じて再署名します。
clientCertificate
発行が有効になっている場合、リコンサイルは少なくとも1時間に1回スケジュールされるため、トリガーイベントがなくても有効期限のかなり前に更新が発生します。現在の有効期限は常にstatus.clientCertificate.expiration
に反映されます。
削除とオプトアウト
Scenario |
Result |
|---|---|
clientCertificate.enabled set to false, or the clientCertificate block removed |
The cert Secret is deleted; status.clientCertificate is cleared |
DatabaseRole deleted |
The cert Secret is garbage-collected via owner reference, regardless of databaseRoleReclaimPolicy |
注釈
databaseRoleReclaimPolicy: retain は、生成されたシークレットではなく、PostgreSQLロールを保持します。シークレットは、オペレーターがロールを管理しているときにのみ意味があるため、削除時に常にクリーンアップされます。
Bring-your-own-CAの制限
クラスターのクライアントCAシークレットにプライベートキーが含まれていない場合つまり、
spec.certificates.clientCASecret
を介して独自のCAを指定した場合、オペレーターは新しい証明書に署名できません。
status.clientCertificate.message
に理由を記録し、再試行を停止します。
status:
clientCertificate:
message: client CA secret "my-ca" has no private key; bring-your-own-CA
clusters require manual certificate management
この場合、クライアント証明書を手動で発行および更新する必要があります。
注釈
CNPGは、証明書失効リストCRLを管理しません。証明書の有効期限が切れる前に無効にする必要がある場合は、クラスターのクライアントCAをローテーションします。次のリコンサイルで、オペレーターは、既存の証明書が現在のCAによって署名されていないことを検出し、すべての管理対象クライアント証明書を再発行します。または、証明書のシークレットを削除して、現在のCAによって署名された新しいものをオペレーターに発行させます。
インライン管理対象ロール
クラスター仕様のmanaged
スタンザを使用すると、CloudNativePGは.spec.managed.roles
で指定されたロールの管理を提供します。この機能により、既存のロールの宣言的管理と、新しいロールがまだ存在しない場合は作成が可能になります。
マニフェストの例
宣言的ロール管理を使用するクラスターのマニフェストの例は、ファイル cluster-example-with-roles.yaml にあります。
次に、そのファイルからの抜粋を示します。
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
spec:
managed:
roles:
- name: dante
ensure: present
comment: Dante Alighieri
login: true
superuser: false
inRoles:
- pg_monitor
- pg_signal_backend
インライン管理対象ロールのステータス
インラインメソッドを使用する場合、Cluster
ステータスには包括的な概要が含まれます。
status:
managedRolesStatus:
byStatus:
reconciled:
- dante
reserved:
- postgres
- streaming_replica
cannotReconcile:
petrarca:
- could not perform UPDATE_MEMBERSHIPS on role petrarca: role "poets" does not exist
データベースおよびCloudNativePGが受け入れられない操作、および人間の介入を必要とする操作用の特別なサブセクションcannotReconcile
に注意してください。
このセクションでは、オペレーター使用のために予約されているロールと、宣言的管理の下ではない**ロールをカバーし、データベースインスタンスのロールの包括的なビューを提供します。
Kubectl Plugin は、 status
サブコマンドで管理対象ロールのステータスも表示します。
Managed roles status
Status Roles
- ----- -----
pending-reconciliation petrarca
reconciled app,dante
reserved postgres,streaming_replica
Irreconcilable roles
Role Errors
- --- ------
petrarca could not perform UPDATE_MEMBERSHIPS on role petrarca: role "poets" does not exist
インライン管理ロールからDatabaseRole への移行
ロールをインラインmanaged.roles
スタンザからスタンドアロンのDatabaseRole
に中断せずに移動できます。
目的の仕様で
DatabaseRoleを作成します。両方のメソッドは同じを共有します RoleConfiguration
構造なので、スタンザをそのままコピーできます。
Clusterマニフェストの.spec.managed.rolesから一致するエントリーを削除します。オペレーターは変更を検出し、管理を
DatabaseRoleに引き継ぎます。
両方が存在する間はクラスター仕様が優先されるため 共存と優先 を参照してください、ハンドオーバーはインラインエントリがなくなったときにのみ発生するため、ロールが非管理のままになるウィンドウはありません。
インラインスタンザがensure: absent
で削除したロールを変換する場合、DatabaseRole
はensure: absent
をサポートしていないことに注意してください。代わりに :ref:delete` 再利用ポリシーを介した削除 <`delete` 再利用ポリシーを介した削除>` を介した高速削除。\ ``databaseRoleReclaimPolicy: delete
でリソースを削除してロールを削除するか、デフォルトのretain
をそのままにしておきます。完全な動作については、
ロールの削除 を参照してください。
パスワード管理
宣言的ロール管理機能 DatabaseRole
およびインラインmanaged.roles
スタンザの両方を使用する場合には、ロールパスワードの調整が含まれます。管理対象ロール構成では、オプションでユーザー名とパスワードが保存される
シークレット の名前を指定できます。
passwordSecret:
name: cluster-example-dante
シークレットのタイプはkubernetes.io/basic-auth
である必要があります。ユーザー名Kubernetesで通常のように_Base64_でエンコードされたは、パスワードを設定しているロールと一致する必要があります。例
apiVersion: v1
data:
username: ZGFudGU=
password: ZGFudGU=
kind: Secret
metadata:
name: cluster-example-dante
labels:
cnpg.io/reload: "true"
type: kubernetes.io/basic-auth
重要
上記のように、シークレットに`cnpg.io/reload: "true"` のラベルを付けます。ラベル付きシークレットのパスワードの変更はすぐに適用されますが、ラベルのないシークレットの変更は、後続の調整時、たとえば、オペレーターが内部キャッシュを更新するときのみに適用されます。
passwordSecret
が指定されない場合、インスタンスマネージャーはPostgreSQLの規約に従って、パスワードを使用してロールをCREATE/ALTER
しようとしません。
重要
passwordSecret を使用せずに作成された新しいロールは、PostgreSQL内に`NULL` パスワードがあります。
パスワードの無効化
PostgreSQLでパスワードをNULL
に明示的に設定するにはパスワードの更新を単に省略することと区別され、
disablePassword フィールドを使用します。
disablePassword: true
注釈
特定のロールで`passwordSecret` と`disablePassword` の両方を設定するのはエラーです。
パスワードの有効期限 VALID UNTIL
PostgreSQLのVALID UNTIL
ロール属性は、パスワードの有効期限を制御します。 VALID UNTIL
を指定せずに作成されたロールは、PostgreSQLでデフォルトでNULLを取得します。これは、パスワードの有効期限が無期限であることを意味します。
PostgreSQLは、 VALID UNTIL
のタイムスタンプタイプを使用します。これには、パスワードの有効期限が無期限であることを示す値'infinity'
のサポートが含まれます。 PostgreSQL documentation を参照してください。
参考までに。
宣言的ロール管理では、管理対象ロールのvalidUntil
属性がパスワードの有効期限を制御します。 validUntil
は以下のみを取ることができます。
Kubernetesタイムスタンプ、または
省略しますデフォルト
null
最初のケースでは、指定されたvalidUntil
タイムスタンプは、ロールのVALID UNTIL
属性としてデータベースに設定されます。
2番目のケースvalidUntil 省略
オペレーターは、パスワードの有効期限が決してないことを保証し、PostgreSQLの動作をミラーリングします。具体的には
新しいロールの場合、ロール作成ステートメントの
VALID UNTIL句を省略します既存のロールの場合、データベースで
VALID UNTILがNULLに設定されていない場合、VALID UNTILをinfinityに設定します。これは、PostgreSQLがALTER ROLESQLステートメントでVALID UNTIL NULLを許可していないためです。
事前ハッシュされたパスワード
MD5 / SCRAM-SHA-256ハッシュ形式でパスワードを指定することにより、事前に暗号化されたパスワードを提供することもできます。
kind: Secret
type: kubernetes.io/basic-auth
metadata:
name: cluster-example-cavalcanti
labels:
cnpg.io/reload: "true"
apiVersion: v1
stringData:
username: cavalcanti
password: SCRAM-SHA-256$<iteration count>:<salt>$<StoredKey>:<ServerKey>
警告
上記の例では、 stringData: を使用します。ここで、Kubernetesは値をエンコードします。これは、事前にハッシュされたパスワードの最も安全なパスです。 data: を使用する必要がある場合は、printf '%s' "$hash" | base64 または`echo -n "$hash" | base64` でバイトを正確にエンコードします。単純な`echo "$hash" | base64` の末尾の改行により、値はSCRAM / MD5シャドウフォーマットチェックをミスします。そのため、オペレーターはそれを平文として扱うことにフォールバックして再ハッシュし、ログインは機能を停止します。
クリアテキストパスワードを送信する際の安全性
ロールパスワードは、Kubernetesでシークレットを使用して安全に管理されますが、オペレーターとPostgreSQL間のSQLパスも懸念されます。 PostgreSQL documentation で述べたように
パスワードは平文でサーバーに送信され、 > クライアントのコマンド履歴またはサーバーログに記録される場合があります
CloudNativePGは、2つの補完的な方法でこのパスを保護します。
CREATE/ALTER ROLE ... PASSWORD '...'を発行する前に、オペレーターSCRAM-SHA-256は、クリアテキストパスワードをオペレーターサイドPostgreSQLの観点からクライアントサイドでエンコードします。これは、サーバーログとpg_stat_statementsまたはpgauditのような拡張機能からクリアテキストを保持するための標準のPostgreSQL実践であり、psql \passwordおよびlibpqのPQencryptPasswordConnが実行するエンコードと同じです。 PostgreSQLが受け取るリテラルは、pg_authid.rolpasswordに保存されているSCRAM-SHA-256ベリファイアです。 MD5またはSCRAM-SHA-256シャドウフォームで既に提供されているパスワードは、変更せずに転送されます。同じ
CREATE/ALTER ROLEステートメントは、ステートメントログlog_statementとエラーステートメントログlog_min_error_statementの両方を一時的に抑制するトランザクション内で実行され、成功と失敗の両方のシナリオでのPostgreSQLログへの漏洩を防ぎます。
クラスターのStatusセクションは、管理対象ロール操作のクエリステートメントを出力しません。
オペレーターサイドのエンコーディングのオプトアウト
パスワードをハッシュする方法を決定するために演算子ではなくPostgreSQLが必要な場合たとえば、
password_encryption = md5
を実行しているクラスターで、basic-authシークレットにアノテーションcnpg.io/passwordPassthrough: "enabled"
を設定します。オペレーターは、パスワード値をそのまま転送します。
警告
cnpg.io/passwordPassthrough アノテーションは、Cluster リソースではなく、**basic-auth Secret**自分自身に設定する必要があります。 Cluster に配置しても効果はなく、オペレーターはPostgreSQLに送信する前にパスワードにSCRAM-SHA-256エンコードを適用し続けます。
オプトインはシークレットごとであり、オペレーターが使用するすべての基本認証シークレット管理対象ロールシークレット、スーパーユーザーおよびアプリケーションユーザーシークレットにも適用されるため、単一のクラスターでパススルーシークレットとオペレーターエンコードされたシークレットを自由に混合できます。 。上記のステートメントロギング抑制レイヤーは、両方のモードに適用されます。
警告
cnpg.io/passwordPassthrough: "enabled" では、オペレーターはシークレットの`password` 値をそのまま転送します。その値がクリアテキストの場合 password_encryption = md5 クラスターでの一般的なケース pg_stat_statements や`pgaudit` などの拡張機能はそれを監視します。これは、PostgreSQLにハッシュ形式を選択させることで予想されるトレードオフです。
実現不可能なロール構成
PostgreSQLでは、場合によっては、コマンドはデータベースが受け入れられず、拒否されます。 PostgreSQL documentation on error codes を参照してください。
詳細については。
ロール操作では、このような基本的なエラーが発生する可能性があります。 2つの例
PostgreSQLに、ロールグループ
poetsのメンバーとしてロールpetrarcaを作成するように依頼しますが、poetsは存在しません。PostgreSQLにロール
danteを削除するように求めますが、ロールdanteはデータベースinfernoの所有者です。
これらの基本的なエラーは、人間の管理者の説明がない限り、データベースまたはCloudNativePGオペレーターによって修正できません。上記の2つの例は、それぞれロールpoets
を作成するか、データベースinferno
を削除することにより修正できますが、それらは人的エラーが原因で発生した可能性があり、そのような場合、提案された「修正」は間違ったものである可能性があります。
CloudNativePGは、 インライン管理対象ロールのステータス で説明しているように、このような基本的なエラーが発生したときを記録し、クラスターステータスに表示します。