LoginSignup
5
4

More than 5 years have passed since last update.

#14 PostgreSQLコンテナの紹介

Last updated at Posted at 2018-12-13

本記事は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公式のものを使っています。

pg-rook-sf.yaml(image部分抜粋)
    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を作りました。

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を与えています。

pg-rook-sf.yaml(コンフィグ部分を抜粋)
          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が起動できません。

pg-rook-sf.yaml(env部分を抜粋)
          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。
pg-rook-sf.yaml(volumeMount部分の抜粋)
          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で該当ディレクトリの書き込み権限を付与をしています。

pg-rook-sf.yaml(postStart部分の抜粋)
          lifecycle:
            postStart:
              exec:
                command:
                  - sh
                  - -c
                  - chmod a+w /mnt/postgresql/xlog/

これもファイルストレージを事前に用意しておけば、回避することができるはずです。

Probeの設定

最後にliveness/readinessProbeの設定です。
ここではPostgreSQLが使う5432ポートに対して、tcpソケットでヘルスチェックを投げる設定を入れています。

pg-rook-sf.yaml(postStart部分の抜粋)
          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を書いてみて下さい。

よろしくお願いします。

5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4