データベースロール管理

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

  • postgres スーパーユーザー、streaming_replica 、cnpg_pooler_pgbouncer などの一部の予約ユーザー(PgBouncer Pooler を使用する場合)

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

このプロセスについては、 BootstrapConfiguration セクションで説明されています。

クラスター仕様のmanaged スタンザにより、CloudNativePGは、 .spec.managed.roles で指定されたロールの完全なライフサイクル管理を提供するようになりました。

この機能により、既存のロールの宣言的管理と、新しいロールがデータベースにまだ存在しない場合は作成できます。ロールの作成は、データベースのブートストラップが完了した 後に 発生します。

宣言的なロール管理を備えたクラスターのマニフェストの例は、次のファイルにあります。

apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
  name: cluster-example-with-roles
spec:
  instances: 3
  storage:
    size: 1Gi

  managed:
    roles:
    - name: app
      createdb: true
      login: true
    - name: dante
      ensure: present
      comment: my database-side comment
      login: true
      superuser: false
      createdb: true
      createrole: false
      inherit: false
      replication: false
      bypassrls: false
      connectionLimit: 4
      validUntil: "2053-04-12T15:04:05Z"
      inRoles:
        - pg_monitor
        - pg_signal_backend
      passwordSecret:
        name: cluster-example-dante
- --
apiVersion: v1
data:
  username: ZGFudGU=
  password: ZGFudGU=
kind: Secret
metadata:
  name: cluster-example-dante
type: kubernetes.io/basic-auth

。

これはそのファイルからの抜粋です。

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リファレンス を参照してください。

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

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

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

  3. PostgreSQLの規則に従って、 connectionLimit 属性のデフォルトは-1です。

  4. inRoles を持つロールメンバーシップは、デフォルトでメンバーシップなしになります。

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

パスワード管理

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

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

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

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

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 が指定されていない場合、インスタンスマネージャーはパスワードを使用してロールを作成/変更しようとしません。これはPostgreSQLの慣習に従っており、 WITH PASSWORD で指示されない限りALTERはパスワードを更新しません。

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

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

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

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

パスワードの有効期限、VALID UNTIL

PostgreSQLのVALID UNTIL ロール属性は、パスワードの有効期限を制御します。 PostgreSQLでは、 VALID UNTIL を指定せずに作成されたロールはデフォルトで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 ROLE SQLステートメントでVALID UNTIL NULL を許可していないためです)

警告

宣言的なロール管理機能は、初期バージョン(1.20.0)から動作が変更されました。 1.20.0では、 passwordSecret のないロールは、PostgreSQLでパスワードをNULLに設定することになりました。実際には1.20.0とほとんど違いはありません。 passwordSecret なしで作成された新しいロールには、NULL パスワードがあります。関連する変更は、管理対象ロールを使用して、以前に作成されたロールを管理する場合です。 1.20.0では、これを行うと、誤って既存のパスワードを`NULL` に設定する可能性があります。

実現不可能なロール構成

PostgreSQLでは、場合によっては、データベースがコマンドを受け入れることができず、拒否されます。

PostgreSQL documentation on error codes を参照してください

詳細については。

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

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

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

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

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

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

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

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 に注意してください。

このセクションでは、オペレーターの使用のために予約されているロールと、宣言管理下にないロールについて説明し、データベースインスタンス内のロールの包括的なビューを提供します。

重要

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