本記事はPostgreSQL on Kubernetes Advent Calendar 2018の14日目です。
昨日は「Recap: PGConf.Asia 2018」ということで、3日間にかけて行われたカンファレンスの振り返りをしました。
12/25までのAdvent Calenderも今日でようやく半分を超えました。
本日からはPostgreSQL on Kubernetesの検証内容の投稿を再開します。
#TL;DR
- 公式のpostgresイメージを使って、コンフィグは外から与えるように設定するよ。
- データとアーカイブログは保存先を分けよう。
- Probe設定もわすれずに。
PostgreSQLのStatefulSet設定
これまで話している通り、今回のPostgreSQL on KubernetesではStatefulSetを使っています。
今回のPostgreSQL on Kubernetesで求められる要件は以下となります。
- postgresql.confを外出しして、設定を自由に変えられること。
- アーカイブログモードで動くこと。
- 外部ディスクとして、データとアーカイブログの領域を分けること。
実際にどのような設定で使っているかを順に記していきます。YAML全体はこちらをご覧下さい。
imageの指定
まずコンテナイメージですが、Docker Hub上のPostgres公式のものを使っています。
spec:
containers:
- name: pg-rook-sf
image: postgres:10.4
imagePullPolicy: "IfNotPresent"
PostgreSQLのバージョンは10.4、OSはDebianベースになります。公式のコンテナイメージとして提供されているのは2018年時点ではDebianとAlpineになっています。
postgresql.confの指定
公式のコンテナイメージでは、今回検証に必要なアーカイブログモードの設定がOFFになっています。さらにログ出力も少しカスタマイズしたかったので、事前にpg-rook-postgresql_conf.yamlを作りました。
archive_mode = on # enables archiving; off, on, or always
# (change requires restart)
archive_command = 'cp %p /mnt/postgresql/xlog/%f' # command to use to archive a logfile segment
# placeholders: %p = path of file to archive
# %f = file name only
archive_timeout = 60 # force a logfile segment switch after this
# number of seconds; 0 disables
さらに起動時にこのコンフィグをマウントしたConfigMapから与えるために、コンテナにargsを与えています。
args:
- -c
- config_file=/etc/postgresql/postgresql.conf
上記により、ConfigMapで指定したファイルがドキュメントにある以下の形で与えられ、想定したパラメータでPostgreSQLを起動することができます。
$ docker run -d --name some-postgres -v "$PWD/my-postgres.conf":/etc/postgresql/postgresql.conf postgres -c 'config_file=/etc/postgresql/postgresql.conf'
PGDATAディレクトリとTimeZoneの設定
公式のコンテナイメージでは環境変数:PGDATAでPostgreSQLのデータディレクトリを指定することができます。これを使うのはドキュメントにあるとおり、データディレクトリがマウントポイントになるケースです。
This optional environment variable can be used to define another location - like a subdirectory - for the database files. The default is /var/lib/postgresql/data, but if the data volume you're using is a fs mountpoint (like with GCE persistent disks), Postgres initdb recommends a subdirectory (for example /var/lib/postgresql/data/pgdata ) be created to contain the data.
(Google翻訳)
このオプションの環境変数を使用して、データベースファイルの別の場所(サブディレクトリなど)を定義することができます。デフォルトは/ var / lib / postgresql / dataですが、使用するデータボリュームがfsマウントポイント(GCE永続ディスクなど)の場合、Postgres initdbはサブディレクトリ(たとえば/ var / lib / postgresql / data / pgdata)を作成してデータを格納することができます。
今回のPostgreSQL on Rook構成でもPVでマウントした箇所が/var/lib/postgresql/dataとなるため、このPGDATAを指定しないと、PostgreSQLが起動できません。
env:
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
- name: TZ
value: Asia/Tokyo
さらに、TimeZoneについては今回検証するまで知らなかったのですが、コンテナの時刻はホストOSのそれを踏襲するのですね。TimeZoneを明示するために環境変数でTZ:Asia/Tokyoを与えています。
ボリュームのマウント
これまでの設定を踏まえて、今回のPostgreSQLコンテナでは3つのボリュームをマウントします。
- PGDATA、PostgreSQLのデータ格納ディレクトリ。Cephのブロックデバイス。
- アーカイブログの保存先。Cephのブロックデバイス。
- postgresql.conf。ConfigMap。
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: pg-rook-vol
- mountPath: /mnt/postgresql/xlog
name: pg-rook-vol-xlog
- mountPath: /etc/postgresql
readOnly: true
name: postgres-conf
データベースの設計としてはデータとアーカイブログの領域を分けて配置するのは当然のことです。後日、バックアップ/リストアのケースで詳細は確認しますが、リストアされるデータ領域と継続的に保管されるだけのアーカイブログ領域はライフサイクルが異なるためです。
今回はデータ、アーカイブログ領域のどちらもCephのブロックデバイスをマウントしていますが、アーカイブログ側は特にブロックデバイスである必要はありません。NFSのようなファイルストレージで十分なケースも多いので、いずれそこは修正できればと思います。
ただ、この構成で問題になってくるのがアーカイブログを出力する/mnt/postgresql/xlog
の権限です。コンテナを普通に起動するとPostgreSQLコンテナから権限不足で書き込みができなくなってしまいます。
これを避けるため、今回はpostStartで該当ディレクトリの書き込み権限を付与をしています。
lifecycle:
postStart:
exec:
command:
- sh
- -c
- chmod a+w /mnt/postgresql/xlog/
これもファイルストレージを事前に用意しておけば、回避することができるはずです。
Probeの設定
最後にliveness/readinessProbeの設定です。
ここではPostgreSQLが使う5432ポートに対して、tcpソケットでヘルスチェックを投げる設定を入れています。
livenessProbe:
tcpSocket:
port: 5432
initialDelaySeconds: 10
periodSeconds: 3
timeoutSeconds: 3
failureThreshold: 2
readinessProbe:
tcpSocket:
port: 5432
initialDelaySeconds: 5
periodSeconds: 3
timeoutSeconds: 1
successThreshold: 1
ただ、ポッド障害のケースで見たようにPostgreSQLのリカバリを待つケースなどでは上のヘルスチェックでは意味がないため、もう少し修正が必要そうです。
#まとめ
とりあえず動く形にはなりましたが、アーカイブログやProbe設定でまだまだ修正が必要な部分は残っています。PostgreSQL on Kubernetesしたいという方もこちらを参考に独自のYAMLを書いてみて下さい。
よろしくお願いします。