ふとしたきっかけで、自宅ラボに PostgreSQL as a Service が欲しくなったので Zalando Postgres Operator を試してみました。
Zalando Postgres Operator とは
Zalando Postgres Operator(以下、Postgres Operator)とは、Kubernetes クラスタに HA 構成の PostgreSQL クラスタを簡単に構築してくれる Operator です。
Postgres Operator を Kubernetes クラスタにデプロイすると、postgresql
というカスタムリソースを宣言したマニフェストを使うだけで簡単に PostgreSQL クラスタを構築できます。
また、専用の Web UI を使って PostgreSQL クラスタを管理することもできます。
この Postgres Operator を自宅ラボの Kubernetes クラスタにデプロイして PostgreSQL as a Service として利用します。
Zalando SE
Zalando SE とは、ヨーロッパを中心に展開するオンラインファッションプラットフォームを運営する企業です(日本で言うところの ZOZO でしょうか?)。
Zalando SE は GitHub で複数のオープンソースのプロジェクトを公開しています。
Zalando Postgres Operator も Zalando が開発しているプロジェクトの一つです。
構成
公式ドキュメント の画像を拝借させてもらうのですが、
Postgres Operator デプロイ後に postgresql
カスタムリソースをデプロイすると、下図のリソースが Postgres Operator によって作成されます。
HA 構成の PostgreSQL クラスタを構築するため、Pod には Spilo というコンテナイメージが使用されます。
Spilo コンテナの中では PostgreSQL と Patroni というサービスが動いています。
Patroni は PostgreSQL クラスタのノードを監視して、マスタが故障した際に自動フェイルオーバーを実現するためのサービスです。
Spilo と Patroni は共に Zalando のプロジェクトとなっています。
今回初めて Zalando を知りましたが、ほとんど自分たちで開発していてすごいですね…。
インストール
Postgres Operator のインストール方法には以下の3通りあります。
- マニュアル
- Kustomize
- Helm
今回はマニュアル、つまりマニフェストをデプロイする方法で Postgres Operator をインストールします。
公式リポジトリ内のマニフェストを kubectl apply
するだけで Operator と Web UI をインストールできます。
$ git clone https://github.com/zalando/postgres-operator.git
$ cd postgres-operator/
$ kubectl create namespace zalando-postgres
# Postgres Operator
$ kubectl apply -f manifests/configmap.yaml
$ kubectl apply -f manifests/operator-service-account-rbac.yaml # namespace: defualt のものがあるので注意
$ kubectl apply -f manifests/postgres-operator.yaml
$ kubectl apply -f manifests/api-service.yaml
# UI
$ kubectl apply -f ui/manifests/
# 確認
$ kubectl get all -n zalando-postgres
NAME READY STATUS RESTARTS AGE
pod/postgres-operator-f6bfcd5b4-zsh2n 1/1 Running 0 3d7h
pod/postgres-operator-ui-6dc47bbbc6-phdvw 1/1 Running 0 4d9h
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/postgres-operator ClusterIP 10.96.100.47 <none> 8080/TCP 6d23h
service/postgres-operator-ui LoadBalancer 10.104.183.177 192.168.2.252 80:31363/TCP 14d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/postgres-operator 1/1 1 1 6d23h
deployment.apps/postgres-operator-ui 1/1 1 1 14d
NAME DESIRED CURRENT READY AGE
replicaset.apps/postgres-operator-f6bfcd5b4 1 1 1 6d23h
replicaset.apps/postgres-operator-ui-6dc47bbbc6 1 1 1 13d
postgres-operator
と postgres-operator-ui
の Pod がデプロイされました。
注意点 1
manifests/operator-service-account-rbac.yaml には namespace: default
と指定されているため、Postgres Operator 用の namespace を default 以外にする場合には変更が必要です。
# manifests/operator-service-account-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: postgres-operator
namespace: zalando-postgres
注意点 2
Web UI のマニフェストはそのままでは namespace: default
しか管理対象となりません。
全 namespace を対象とする場合は、ui/manifests/deployment.yaml の TARGET_NAMESPACE
に "*" を指定します。
# ui/manifests/deployment.yaml
env:
- name: "TARGET_NAMESPACE"
value: "default" # "*" に変更
以上で Postgres Operator のインストールは完了です。
PostgreSQL クラスタ構築
Postgres Operator の準備ができたので、PostgreSQL クラスタを構築していきます。 クラスタ構築には2通りあります。
- Web UI
- マニュアル
Web UI
さきほど作成した postgres-operator-ui
に Service または Ingress 経由でアクセスすると、クラスタ作成画面が表示されます。
必要な項目を入力して「Create Cluster」を押すと PostgreSQL クラスタが作成されます。
マニュアル
マニュアルの場合は、postgresql リソースを宣言したマニフェストを準備します。
公式リポジトリのサンプルや、Web UI のクラスタ作成画面に表示されるマニフェストが参考になります。
以下は自宅ラボの k8s クラスタにデプロイしたお試しマニフェストです。 Rook で用意した storageClass を追加しています。
# postgres.yaml
apiVersion: acid.zalan.do/v1
kind: postgresql
metadata:
name: acid-example
namespace: default
labels:
team: acid
spec:
teamId: acid
postgresql:
version: "13" # note: String
numberOfInstances: 1
volume:
size: 1Gi
storageClass: rook-ceph-block
users:
example: []
databases:
example: example
allowedSourceRanges:
resources:
requests:
cpu: 100m
memory: 100Mi
limits:
cpu: 500m
memory: 500Mi
postgresql リソースのデプロイが完了すると、Postgres Operator により StatefulSet や Service の各種リソースが作成されます。
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/acid-example-0 1/1 Running 0 164m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/acid-example ClusterIP 10.98.124.54 <none> 5432/TCP 7d
service/acid-example-config ClusterIP None <none> <none> 7d
service/acid-example-repl ClusterIP 10.106.121.165 <none> 5432/TCP 7d
NAME READY AGE
statefulset.apps/acid-example 1/1 7d
NAME TEAM VERSION PODS VOLUME CPU-REQUEST MEMORY-REQUEST AGE STATUS
postgresql.acid.zalan.do/acid-example acid 13 1 1Gi 100m 100Mi 7d Running
注意点
Web UI の注意点として、volume.storageClass の指定ができません。
そのため、Rook Ceph で作成した storageClass などを指定する場合はマニフェストを使う必要があります。
Web UI では基本的な情報を埋め込んだマニフェストを作成し、細かい設定はマニフェストに直接記述するのが良さそうです。
接続確認
kubectl port-forward
を使い、ローカル環境から PostgreSQL クラスタへ接続できるか確認します。
本当はフェイルオーバーなど HA 構成の特性を検証してみたかったのですが、PostgreSQL について勉強不足のため実施していません。
Postgres Operator によりログイン用のパスワードが Secret として作成されています。
$ export PGMASTER=$(kubectl get pods -o jsonpath={.items..metadata.name} -l application=spilo)
$ kubectl port-forward $PGMASTER 6432:5432 &
$ kubectl get secret postgres.acid-example.credentials -o 'jsonpath={.data.password}' | base64 -d
$ export PGSSLMODE=require
$ psql -U postgres -h localhost -p 6432
Handling connection for 6432
ユーザ postgres のパスワード:
Handling connection for 6432
psql (13.1)
SSL 接続 (プロトコル: TLSv1.2、暗号化方式: ECDHE-RSA-AES256-GCM-SHA384、ビット長: 256、圧縮: オフ)
"help"でヘルプを表示します。
postgres=#
無事に Postgres Operator で作成した PostgreSQL クラスタに接続することができました。
参考にさせていただいたサイト
-
https://speakerdeck.com/tzkoba/kubernetesdetukurupostgresql-as-a-service
今回 PostgreSQL as a Service を構築するにあたって情報を提供くださった @tzkb さんのスライドです。
そもそもの「Kubernetes 上でデータベースを動かす際の課題」から、より深い話まで説明されています。 仕事では SQL Server メインなのですが、Database on Kubernetes という観点では課題は同じはずですので、とても勉強になりました。
-
https://www.sraoss.co.jp/tech-blog/pgsql/zalando-postgres-operator/
Zalando Postgres Operator の紹介をされている記事です。 今回のネタは、ほぼ上記記事の内容を元にしています。 フェイルオーバーなどのクラスタ構成の検証もされていて興味深かったです。
-
https://recruit.gmo.jp/engineer/jisedai/blog/postgresql12-patroni-cluster/
Patroni を試されている記事です。 自分は Patroni が何者か分からない状態だったので参考になりました。
さいごに
PostgreSQL as a Service のための Zalando Postgres Operator の使い方について確認しました。
PostgreSQL については本当に初心者なのですが、そのような状態でも Kubernetes クラスタがあれば簡単に PostgreSQL as a Service が実現できました。
もし手元に Kubernetes クラスタをお持ちなら、クラウドサービスではなく Zalando Postgres Operator も選択肢に入れてみると面白いかもしれません。