Zalando Postgres Operator を試してみた
ふとしたきっかけで、自宅ラボに 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 クラスタに接続することができました。
参考にさせていただいたサイト
今回 PostgreSQL as a Service を構築するにあたって情報を提供くださった @tzkb さんのスライドです。
そもそもの「Kubernetes 上でデータベースを動かす際の課題」から、より深い話まで説明されています。
仕事では SQL Server メインなのですが、Database on Kubernetes という観点では課題は同じはずですので、とても勉強になりました。
Zalando Postgres Operator の紹介をされている記事です。
今回のネタは、ほぼ上記記事の内容を元にしています。 フェイルオーバーなどのクラスタ構成の検証もされていて興味深かったです。
Patroni を試されている記事です。
自分は Patroni が何者か分からない状態だったので参考になりました。
さいごに
PostgreSQL as a Service のための Zalando Postgres Operator の使い方について確認しました。
PostgreSQL については本当に初心者なのですが、そのような状態でも Kubernetes クラスタがあれば簡単に PostgreSQL as a Service が実現できました。
もし手元に Kubernetes クラスタをお持ちなら、クラウドサービスではなく Zalando Postgres Operator も選択肢に入れてみると面白いかもしれません。