PostgreSQL Role management

CloudNativePGは、当初から、PostgreSQLインスタンスで必要な特定のロールの作成を管理してきました。

  • postgres スーパーユーザー、streaming_replicacnpg_pooler_pgbouncer などの一部の予約済みユーザーPgBouncer Pooler を使用する場合

  • アプリケーションデータベースの低特権の所有者として設定されたアプリケーションユーザー

このプロセスは、 Bootstrap セクションで説明しています。

クラスター仕様の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

.spec.managed.roles のロール仕様は、 PostgreSQL structure and naming conventions に従います。ロールごとに定義できる属性の完全なリストについては、 API Reference を参照してください。

いくつかの点に注意してください。

  1. ensure 属性はPostgreSQLの ではありません 。これにより、宣言的なロール管理でロールを作成および削除できます。 2つの値は、present デフォルトとabsent です。

  2. inherit 属性は、PostgreSQLの規則に従って、デフォルトでtrueです。

  3. connectionLimit 属性は、PostgreSQLの規約に従って、デフォルトの-1に設定されます。

  4. inRoles のロールメンバーシップは、デフォルトでメンバーシップなしです。

宣言的ロール管理により、PostgreSQLインスタンスが仕様に準拠していることが保証されます。ユーザーがデータベースでロール属性を直接変更した場合、CloudNativePGオペレーターは、次の調整サイクル中にこれらの変更を元に戻します。

パスワード管理

宣言的ロール管理機能には、ロールパスワードの調整が含まれます。パスワードはKubernetesの世界とPostgreSQLでは根本的に異なる方法で管理されており、その結果、いくつかの注意事項があります。

管理対象ロール構成は、オプションでユーザー名とパスワードが保存される シークレット の名前を指定できます。Kubernetesで通常のようにBase64でエンコードされます。例

managed:
  roles:
  - name: dante
    ensure: present
    [… snipped …]
    passwordSecret:
      name: cluster-example-dante

これは、ユーザー名とパスワードを含むcluster-example-dante と呼ばれるシークレットの存在を前提としています。ユーザー名は、パスワードを設定しているロールと一致する必要があります。例

apiVersion: v1
data:
  username: ZGFudGU=
  password: ZGFudGU=
kind: Secret
metadata:
  name: cluster-example-dante
  labels:
    cnpg.io/reload: "true"
type: kubernetes.io/basic-auth

ロールにpasswordSecret が指定されていない場合、インスタンスマネージャーはパスワードを使用してロールを作成/変更しようとしません。これは、 WITH PASSWORD で指示されない限り、ALTERがパスワードを更新しないPostgreSQL規約に従います。

ロールが最初にパスワードを使用して作成され、PostgreSQLでパスワードをNULLに設定したい場合、これはCloudNativePGのユーザー側で明示的にする必要があります。 「仕様で提供されているパスワードなし」と「パスワードをNULLに設定する」を区別するには、フィールド DisablePassword を使用する必要があります。

データベースのdante ロールにパスワードを設定しないことにしたとします。このような場合、次を指定します。

managed:
  roles:
  - name: dante
    ensure: present
    [… snipped …]
    disablePassword: true

注特定のロールでpasswordSecretdisablePassword の両方を設定することはエラーとみなされます。この構成は、検証Webhookによって拒否されます。

パスワードの有効期限 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 UNTILNULL に設定されていない場合、VALID UNTILinfinity に設定します。これは、PostgreSQLがALTER ROLE SQLステートメントでVALID UNTIL NULL を許可していないためです。

警告

passwordSecret を使用せずに作成された新しいロールは、PostgreSQL内に`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>

実現不可能なロール構成

PostgreSQLでは、場合によっては、コマンドはデータベースが受け入れられず、拒否されます。 PostgreSQL documentation on error codes を参照してください。

詳細については。

ロール操作では、このような基本的なエラーが発生する可能性があります。 2つの例

  • PostgreSQLに、ロールグループpoets のメンバーとしてロールpetrarca を作成するように依頼しますが、 poets は存在しません。

  • PostgreSQLにロールdante を削除するように求めますが、ロールdante はデータベースinferno の所有者です。

これらの基本的なエラーは、人間の管理者の説明がない限り、データベースまたはCloudNativePGオペレーターによって修正できません。上記の2つの例は、それぞれロールpoets を作成するか、データベースinferno を削除することにより修正できますが、それらは人的エラーが原因で発生した可能性があり、そのような場合、提案された「修正」は間違ったものである可能性があります。

CloudNativePGは、このような基本的なエラーが発生すると記録し、クラスターステータスに表示します。どちらが続くか…

管理対象ロールのステータス

クラスターステータスには、以下に示すように、管理対象ロールのステータスのセクションが含まれます。

status:
  […snipped…]
  managedRolesStatus:
    byStatus:
      not-managed:
      - app
      pending-reconciliation:
      - dante
      - petrarca
      reconciled:
      - ariosto
      reserved:
      - postgres
      - streaming_replica
    cannotReconcile:
      dante:
      - could not perform DELETE on role dante: owner of database inferno
      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

注釈

下位互換性の観点から、宣言的ロール管理は、データベースには存在するが仕様に含まれていないロールを無視するように設計されています。これらのロールのライフサイクルは、引き続きPostgreSQL内で管理されるため、CloudNativePGユーザーは自分の都合に合わせてこの機能を採用できます。