この章では、Kubernetes上でPgpool-IIをデプロイし、 読み取りクエリの負荷分散とコネクションプーリングを実現する方法について説明します。
PostgreSQLはステートフルなアプリケーションであり、 またPostgreSQLの運用ではバックアップ、リカバリ、 障害対策などの管理が必要になります。 Kubernetesの標準的な機能ではこれらの機能を実現できません。 そのために、Kubernetesを使ってPostgreSQLを運用するには、 Kubernetesの本来の機能を拡張するためのOperatorが必要になります。
代表的なPostgreSQL Operatorとしては、 Crunchy PostgreSQL Operatorや Zalando PostgreSQL Operator、 KubeDBがあります。 しかし、これらのPostgreSQL Operatorには読み取りクエリの負荷分散機能はありません。
この章では、PostgreSQL OperatorをPgpool-IIと組み合わせて、 Kubernetes上で読み取りクエリの負荷分散とコネクションプーリング機能を備えたPostgreSQLクラスタの構築方法について説明します。 Pgpool-IIは、上記PostgreSQL Operatorのいずれかと組み合わせることができます。
Pgpool-IIをデプロイする前に、以下の設定を行ってください。
Kubernetesクラスタを構築し、kubectlをインストールしておきます。
KubernetesクラスタにPostgreSQL Operatorをインストールし、PostgreSQLクラスタを1つ作成しておきます。
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つあります。
プロダクション環境では、クライアント認証、または多くのパラメーターを設定する必要があります。 設定パラメータごとにそれぞれの環境変数を設定すると、マニフェストが冗長な記述になってしまうデメリットがあります。 プロダクション環境の場合は、ConfigMapを使用したPgpool-IIのインストール方法(項8.6.4.2)をお勧めします。
ここからは、環境変数とConfigMapをそれぞれ使用してPgpool-II を設定およびデプロイする方法を説明します。 この設定例では、必要最低限のパラメータを設定しています。 Pgpool-IIの各機能の詳細設定については、 項8.6.5をご参照ください。 Pgpool-IIのデプロイに使用される各種マニフェストファイルは、 ここからダウンロードできます。
Kubernetesの環境変数は、Pod内のコンテナに渡すことができるので、 Pgpool-IIのデプロイマニフェストで環境変数を定義することで、 Pgpool-IIのパラメータを設定することができます。 pgpool-deploy-minimal.yamlはPgpool-II をKubernetes上で動かすための最小限の環境変数を定義している サンプル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
KubernetesのConfigMapを使用し、 pgpool.confやpool_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_hbaをonにする必要があります。 デフォルトでは、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 podや kubectl get svcコマンドを使用してPgpool-IIのPodとServiceを確認できます。
Kubernetes環境では、2つのバックエンドノードのみを指定すれば良いです。 KubernetesではServiceを経由してアプリケーションに接続するのが一般的です。 そのため、backend_hostname0にプライマリService名、 backend_hostname1にレプリカService名を指定します。
backend_hostname0 = '<プライマリService名>' backend_hostname1 = '<レプリカService名>' backend_port0 = '5432' backend_port1 = '5432'
Pgpool-IIには定期的にPostgreSQLを状態をチェックし、 障害を検知するとフェイルオーバさせる機能はありますが、Kubernetesでは、 PostgreSQLの状態はKubernetesによって管理されるので、 Pgpoo-IIの自動フェイルオーバ機能を無効にします。
また、PostgreSQL Podが再作成されたり、 Kubernetesによってフェイルオーバしても、 プライマリService名とレプリカService名が変更されないので、 PostgreSQLノード0をプライマリとして固定するために、 backend_flag0にALWAYS_PRIMARYを指定します。
backend_flag0 ='ALWAYS_PRIMARY|DISALLOW_TO_FAILOVER' backend_flag1 ='DISALLOW_TO_FAILOVER' failover_on_backend_error = off
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-secretにpostgres ユーザのusernameとpasswordを保存しています。 環境変数の設定方法は以下の通りです。
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
Pgpool-IIが定期的に各PostgreSQLに接続し、 レプリケーション遅延をチェックすることができます。 この機能を利用するには、sr_check_userとsr_check_password にPostgreSQLユーザのユーザ名とそのパスワードを設定する必要があります。 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
クライアントとPgpool-IIの間のSSL接続を有効にするために、 sslをonに設定する必要があります。
ssl = on
ssl = onを設定すると、Pgpool-II Pod起動時に、 秘密鍵および証明書ファイルが自動的に/opt/pgpool-II/certs/配下に作成されます。 また、Pgpool-IIのパラメータssl_keyやssl_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
Pgpool-II Exporter はPgpool-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