8.6. Kubernetesの設定例

この章では、Kubernetes上でPgpool-IIをデプロイし、 読み取りクエリの負荷分散とコネクションプーリングを実現する方法について説明します。

8.6.1. はじめに

PostgreSQLはステートフルなアプリケーションであり、 またPostgreSQLの運用ではバックアップ、リカバリ、 障害対策などの管理が必要になります。 Kubernetesの標準的な機能ではこれらの機能を実現できません。 そのために、Kubernetesを使ってPostgreSQLを運用するには、 Kubernetesの本来の機能を拡張するためのOperatorが必要になります。

代表的なPostgreSQL Operatorとしては、 Crunchy PostgreSQL OperatorZalando PostgreSQL OperatorKubeDBがあります。 しかし、これらのPostgreSQL Operatorには読み取りクエリの負荷分散機能はありません。

この章では、PostgreSQL OperatorをPgpool-IIと組み合わせて、 Kubernetes上で読み取りクエリの負荷分散とコネクションプーリング機能を備えたPostgreSQLクラスタの構築方法について説明します。 Pgpool-IIは、上記PostgreSQL Operatorのいずれかと組み合わせることができます。

8.6.2. 全体構成図

図 8-2. 全体構成図

8.6.3. 前提条件

Pgpool-IIをデプロイする前に、以下の設定を行ってください。

8.6.4. Pgpool-IIのデプロイ

Kubernetesを利用する場合は、PostgreSQLおよびPgpool-IIの状態はKubernetesによって管理されますので、 Pgpool-IIのヘルスチェック、自動フェイルオーバ、 Watchdogおよびオンラインリカバリ機能はKubernetes環境では必要ありません。 読み取りクエリの負荷分散とコネクションプーリング機能のみを有効にすれば良いです。

Kubernetes上でPgpool-IIを動かすために、以下の設定が必要最低限の設定です。

backend_hostname0 = '<プライマリService名>'
backend_hostname1 = '<レプリカService名>'
backend_port0 = '5432'
backend_port1 = '5432'
backend_flag0 = 'ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER'
backend_flag1 = 'DISALLOW_TO_FAILOVER'

failover_on_backend_error = off

sr_check_period = 10                        (ストリーミングレプリケーションチェック機能を利用する場合のみ)
sr_check_user='username of PostgreSQL user' (ストリーミングレプリケーションチェック機能を利用する場合のみ)

load_balance_mode = on
connection_cache = on
listen_addresses = '*'
  

Pgpool-IIを構成する方法は2つあります。

  1. 環境変数を利用する

  2. ConfigMapを利用する

プロダクション環境では、クライアント認証、または多くのパラメーターを設定する必要があります。 設定パラメータごとにそれぞれの環境変数を設定すると、マニフェストが冗長な記述になってしまうデメリットがあります。 プロダクション環境の場合は、ConfigMapを使用したPgpool-IIのインストール方法(項8.6.4.2)をお勧めします。

ここからは、環境変数とConfigMapをそれぞれ使用してPgpool-II を設定およびデプロイする方法を説明します。 この設定例では、必要最低限のパラメータを設定しています。 Pgpool-IIの各機能の詳細設定については、 項8.6.5をご参照ください。 Pgpool-IIのデプロイに使用される各種マニフェストファイルは、 ここからダウンロードできます。

8.6.4.1. 環境変数を使用したPgpool-IIの設定

Kubernetesの環境変数は、Pod内のコンテナに渡すことができるので、 Pgpool-IIのデプロイマニフェストで環境変数を定義することで、 Pgpool-IIのパラメータを設定することができます。 pgpool-deploy-minimal.yamlPgpool-IIKubernetes上で動かすための最小限の環境変数を定義している サンプルYAMLファイルです。このファイルをダウンロードし、PostgreSQL クラスタの情報に合わせて各環境変数のvalueを設定します。

$ curl -LO https://raw.githubusercontent.com/pgpool/pgpool2_on_k8s/master/pgpool-deploy-minimal.yaml
   

PGPOOL_PARAMS_で始まる環境変数は、Pgpool-IIの設定パラメータに変換され、 デフォルトの設定値を上書きすることができます。

Kubernetes環境では、2つのバックエンドノードのみを指定すれば良いです。 backend_hostname0にプライマリのservice名、 backend_hostname1にレプリカのservice名を指定します。 自動フェイルオーバがKubernetesによって管理されているので、両方のノードのbackend_flagに DISALLOW_TO_FAILOVERフラグを指定します。 backend_flag0にALWAYS_PRIMARYフラグを指定します。 backend_data_directoryを設定する必要はありません。

例えば、マニフェストで定義されている以下の環境変数は、

env:
- name: PGPOOL_PARAMS_BACKEND_HOSTNAME0
  value: "mypostgres"
- name: PGPOOL_PARAMS_BACKEND_HOSTNAME1
  value: "mypostgres-replica"
- name: PGPOOL_PARAMS_BACKEND_FLAG0
  value: "ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER"
- name: PGPOOL_PARAMS_BACKEND_FLAG1
  value: "DISALLOW_TO_FAILOVER"
   

これらの設定パラメータに変換され、pgpool.confに追記されます。

backend_hostname0 = 'mypostgres'
backend_hostname1 = 'mypostgres-replica'
backend_flag0 = 'ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER'
backend_flag1 = 'DISALLOW_TO_FAILOVER'
   

クライアント認証を行うために、PostgreSQLのユーザ名とパスワードを表す環境変数を設定します。 詳細については項8.6.5.3をご参照ください。

env:
- name: <任意の文字列>_USERNAME
  valueFrom:
     secretKeyRef:
     ...
- name: <任意の文字列>_PASSWORD
  valueFrom:
     secretKeyRef:
     ...
   

上記設定完了後、Pgpool-IIをデプロイします。

kubectl apply -f pgpool-deploy-minimal.yaml
   

8.6.4.2. ConfigMapを使用したPgpool-IIの設定

KubernetesのConfigMapを使用し、 pgpool.confpool_hba.confファイル全体を保存することができます。 また、ConfigMapは、ボリュームとしてはPgpool-IIのコンテナにマウントすることができます。

ConfigMapとPgpool-IIをデプロイするためのサンプルYAMLファイルは ここからダウンロードできます。

curl -LO https://raw.githubusercontent.com/pgpool/pgpool2_on_k8s/master/pgpool-configmap.yaml
curl -LO https://raw.githubusercontent.com/pgpool/pgpool2_on_k8s/master/pgpool-deploy.yaml
   

サンプルのConfigMapは以下のような形式で定義されています。必要に応じてパラメータの設定値を更新してください。 Pgpool-IIはクライアント認証に pool_hba.confを使用するために、 enable_pool_hbaonにする必要があります。 デフォルトでは、offとなります。

apiVersion: v1
kind: ConfigMap
metadata:
  name: pgpool-config
  labels:
    name: pgpool-config
data:
  pgpool.conf: |-
    listen_addresses = '*'
    port = 9999
    socket_dir = '/var/run/pgpool'
    pcp_listen_addresses = '*'
    pcp_port = 9898
    pcp_socket_dir = '/var/run/pgpool'
    backend_hostname0 = 'mypostgres'
...
  pool_hba.conf: |-
    local   all         all                               trust
    host    all         all         127.0.0.1/32          trust
    host    all         all         ::1/128               trust
    hostssl all         all         0.0.0.0/0             md5
   

クライアント認証を行うために、PostgreSQLの各ユーザのユーザ名とパスワードを表す環境変数を設定します。 PostgreSQLユーザのユーザ名とパスワードを表す環境変数のフォーマットや設定方法については 項8.6.5.3をご参照ください。

env:
- name: <任意の文字列>_USERNAME
  valueFrom:
     secretKeyRef:
     ...
- name: <任意の文字列>_PASSWORD
  valueFrom:
     secretKeyRef:
     ...
   

設定後、Pgpool-IIをデプロイします。

kubectl apply -f pgpool-configmap.yaml
kubectl apply -f pgpool-deploy.yaml
   

Pgpool-IIをデプロイした後、kubectl get podkubectl get svcコマンドを使用してPgpool-IIのPodとServiceを確認できます。

8.6.5. Pgpool-IIの詳細設定

8.6.5.1. バックエンド接続

Kubernetes環境では、2つのバックエンドノードのみを指定すれば良いです。 KubernetesではServiceを経由してアプリケーションに接続するのが一般的です。 そのため、backend_hostname0にプライマリService名、 backend_hostname1にレプリカService名を指定します。

backend_hostname0 = '<プライマリService名>'
backend_hostname1 = '<レプリカService名>'
backend_port0 = '5432'
backend_port1 = '5432'
   

8.6.5.2. PostgreSQLの自動フェイルオーバ

Pgpool-IIには定期的にPostgreSQLを状態をチェックし、 障害を検知するとフェイルオーバさせる機能はありますが、Kubernetesでは、 PostgreSQLの状態はKubernetesによって管理されるので、 Pgpoo-IIの自動フェイルオーバ機能を無効にします。

また、PostgreSQL Podが再作成されたり、 Kubernetesによってフェイルオーバしても、 プライマリService名とレプリカService名が変更されないので、 PostgreSQLノード0をプライマリとして固定するために、 backend_flag0ALWAYS_PRIMARYを指定します。

backend_flag0 ='ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER'
backend_flag1 ='DISALLOW_TO_FAILOVER'
failover_on_backend_error = off
   

8.6.5.3. パスワードファイルの生成

Pgpool-IIでは、パスワードファイルpool_passwdを用いて、 認証を行います。

Pgpool-II Pod起動時に、自動的にpg_md5コマンドを実行し、 <任意の文字列>_USERNAME<任意の文字列>_PASSWORD フォーマットで定義した環境変数を元に、 パスワードファイルpool_passwdを生成しています。

PostgreSQLのユーザ名とパスワードを表す環境変数のフォーマットは以下の通りです。 同一ユーザのユーザ名とパスワードの<任意の文字列>部分は一致する必要があります。

ユーザ名   : <任意の文字列>_USERNAME
パスワード : <任意の文字列>_PASSWORD
   

セキュリティ上の理由で、パスワードは平文で記述せず、Secretを利用した方法をお勧めします。 ほとんどのPostgreSQL Operatorでは、PostgreSQLクラスタを作成するときに、 PostgreSQLユーザのusernameおよび passwordを保存しているいくつかのSecretが自動的に作成されます。 kubectl get secretコマンドを実行し、既存のSecretを確認します。 例えば、mypostgres-postgres-secretpostgres ユーザのusernamepasswordを保存しています。 環境変数の設定方法は以下の通りです。

env:
- name: POSTGRES_USERNAME
  valueFrom:
     secretKeyRef:
       name: mypostgres-postgres-secret
       key: username
- name: POSTGRES_PASSWORD
  valueFrom:
     secretKeyRef:
       name: mypostgres-postgres-secret
       key: password
   

Pgpool-II Podが起動すると、 pool_passwdおよびpcp.confが自動的に /opt/pgpool-II/etc配下に生成されます。

$ kubectl exec <pgpool pod> -it -- cat /opt/pgpool-II/etc/pool_passwd
postgres:md53175bce1d3201d16594cebf9d7eb3f9d

$ kubectl exec <pgpool pod> -it -- cat /opt/pgpool-II/etc/pcp.conf
postgres:e8a48653851e28c69d0506508fb27fc5
   

8.6.5.4. ストリーミングレプリケーションチェック

Pgpool-IIが定期的に各PostgreSQLに接続し、 レプリケーション遅延をチェックすることができます。 この機能を利用するには、sr_check_usersr_check_passwordPostgreSQLユーザのユーザ名とそのパスワードを設定する必要があります。 Pgpool-IIでは、sr_check_passwordが空文字の場合、 pool_passwdファイルからsr_check_userに指定したユーザのパスワードを取得します。

ここでは、sr_check_passwordを設定せず、pod起動時に自動的に生成されるpool_passwdから取得する方法を説明します。 例えば、postgresユーザを利用し、 10秒間隔でストリーミングレプリケーションチェックを行う場合、 以下のように設定します。

sr_check_period = 10
sr_check_user = 'postgres'
   

Pgpool-IIをデプロイするためのYAMLファイルで、 ストリーミングレプリケーションチェックで利用するユーザ名とパスワードを表す環境変数を設定します。 sr_check_userに指定したユーザの情報を格納しているSecretを事前に作成しておき、 環境変数として参照するように設定します。 ほとんどのPostgreSQL Operatorでは、PostgreSQLクラスタを作成するときに、 PostgreSQLユーザのusernameおよび passwordを保存しているいくつかのSecretが自動的に作成されます。 kubectl get secretコマンドを実行し、既存のSecretを確認します。

以下の環境変数では、mypostgres-postgres-secretというSecretを参照しています。

env:
- name: POSTGRES_USERNAME
  valueFrom:
     secretKeyRef:
       name: mypostgres-postgres-secret
       key: username
- name: POSTGRES_PASSWORD
  valueFrom:
     secretKeyRef:
       name: mypostgres-postgres-secret
       key: password
   

しかし、Kubernetes環境では、Pgpool-IIはすべてのレプリカに接続するのではなく、 レプリカSerivceを経由して、いずれかのレプリカに接続します。 レプリカが複数存在しても、Pgpool-IIが1台のレプリカとして管理しています。 そのため、レプリカServiceにぶら下がっている複数のレプリカのうち、 どのレプリカが遅延しているのかはPgpool-IIが正確に判断できません。 この機能を無効にするには、以下のパラメータを設定します。

sr_check_period = 0
   

8.6.5.5. SSL接続

クライアントとPgpool-IIの間のSSL接続を有効にするために、 sslをonに設定する必要があります。

ssl = on
   

ssl = onを設定すると、Pgpool-II Pod起動時に、 秘密鍵および証明書ファイルが自動的に/opt/pgpool-II/certs/配下に作成されます。 また、Pgpool-IIのパラメータssl_keyssl_cert も秘密鍵および証明書ファイルのパスに合わせて自動的に設定されます。

さらに、クライアントがPgpool-IIに接続する際に、SSL接続のみを許可するには、 pool_hba.confにてTCP/IPを使用した接続に対応するレコードを以下のように設定します。 pool_hba.confの設定方法については、 項8.6.4.2をご参照ください。

hostssl    all         all         0.0.0.0/0             md5
   

8.6.6. Pgpool-II Exporterによる監視

Pgpool-II ExporterPgpool-IIの各種メトリクスを収集し、 Prometheusフォーマットで出力するツールです。

Pgpool-II Exporterを利用する場合は、サンプルのYAMLファイル pgpool-deploy-metrics.yamlを利用します。 pgpool-deploy-metrics.yamlでは、 Pgpool-IIのPodにPgpool-IIのコンテナと Pgpool-II Exporterのコンテナを作成しています。

spec:
  containers:
  - name: pgpool
    image: pgpool/pgpool
  ...
  - name: pgpool-stats
    image: pgpool/pgpool2_exporter
  ...
   

サンプルのYAMLファイルpgpool-deploy-metrics.yamlをダウンロードします。

$ curl -LO https://raw.githubusercontent.com/pgpool/pgpool2_on_k8s/master/pgpool-deploy-metrics.yaml
   

Pgpool-IIおよびPgpool-II Exporterの設定を行います。 Pgpool-IIの設定は前述の項8.6.4をご参照ください。 Pgpool-II ExporterからPgpool-IIに接続するための環境変数の設定は以下の通りです。

env:
- name: POSTGRES_USERNAME
  valueFrom:
    secretKeyRef:
      name: mypostgres-postgres-secret
      key: username
- name: POSTGRES_PASSWORD
  valueFrom:
    secretKeyRef:
      name: mypostgres-postgres-secret
      key: password
- name: PGPOOL_SERVICE
  value: "localhost"
- name: PGPOOL_SERVICE_PORT
  value: "9999"
   

Pgpool-IIおよびPgpool-II Exporterの設定が完了したら、Pgpool-IIのPodをデプロイします。

kubectl apply -f pgpool-configmap.yaml
kubectl apply -f pgpool-deploy-metrics.yaml