最近(2021年4月)Kubegresがリリースされたので使ってみました。本記事では、minikube上でKubegresをインストールして設定する手順をまとめました。
Kubegresはコンテナ管理を自動化するKubernetesのOperatorのひとつで、PostgreSQLのHAクラスタを構築できるものです。また、minikubeはローカルマシン上に簡単にKubernetesクラスタを構築できるツールです。
これらを使ってPostgreSQLを冗長化してみます。Podの構成は以下の図のようになっています。
PostgreSQLは、まずは1台のPRIMARYと2台のREPLICAで構成し、あとでREPLICAを1台追加します。アプリケーションを想定したPodを用意し、そこからPostgreSQLにアクセスしてみます。
また、自動フェイルオーバー、Dockerイメージのアップデートの確認も行いました。
今回使用したツールのバージョンは以下のとおりです。
- kubegres v1.1 (postgres 13.2)
- minikube v1.18.1
- kubectl v1.20
- Docker v20.10.6
minikubeのインストールと起動
-
必要なパッケージをインストールします。
$ sudo apt install conntrack
-
minikube本体を公式サイトの手順に従ってインストールします。例えば、
$ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 $ sudo install minikube-linux-amd64 /usr/local/bin/minikube
-
minikube用にシステムのプロキシを設定します(参考)。プロキシを使わない場合はスキップしてください。
-
10.96.0.0/12,192.168.99.0/24,192.168.39.0/24
をNO_PROXYに設定する。 - HTTPプロキシだけでなく、HTTPS_PROXYの設定をお忘れなく。
-
-
起動します。
$ minikube start --driver=none
-
確認します。以下のように表示されればOKです。
$ minikube profile list |----------|-----------|---------|-----------|------|---------|---------|-------| | Profile | VM Driver | Runtime | IP | Port | Version | Status | Nodes | |----------|-----------|---------|-----------|------|---------|---------|-------| | minikube | none | docker | 10.0.2.15 | 8443 | v1.20.2 | Running | 1 | |----------|-----------|---------|-----------|------|---------|---------|-------|
kubectlのインストール
-
公式サイトの手順に従ってインストールします。バイナリをダウンロードし、パスの通ったところに配置します。
$ curl -LO "https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/linux/amd64/kubectl" $ chmod +x ./kubectl $ sudo mv ./kubectl /usr/local/bin/kubectl
-
確認します。以下のようにバージョンが表示されればOKです。
$ kubectl version --client Client Version: version.Info{Major:"1", Minor:"20", GitVersion:"v1.20.5", GitCommit:"6b1d87acf3c8253c123756b9e61dac642678305f", GitTreeState:"clean", BuildDate:"2021-03-18T01:10:43Z", GoVersion:"go1.15.8", Compiler:"gc", Platform:"linux/amd64"}
Kubegresのインストール
こちらも公式サイトの手順に従ってインストールします。
Operatorのインストール
-
以下のコマンドを実行します。
$ kubectl apply -f https://raw.githubusercontent.com/reactive-tech/kubegres/v1.1/kubegres.yaml
-
確認します。以下のように4つのリソースが表示されればOKです。
$ kubectl get all -n kubegres-system NAME READY STATUS RESTARTS AGE pod/kubegres-controller-manager-5b6797895c-ph9gj 2/2 Running 0 4m48s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubegres-controller-manager-metrics-service ClusterIP 10.99.241.122 <none> 8443/TCP 4m48s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/kubegres-controller-manager 1/1 1 1 4m48s NAME DESIRED CURRENT READY AGE replicaset.apps/kubegres-controller-manager-5b6797895c 1 1 1 4m48s
PostgreSQLの管理者ユーザの認証情報の設定と適用
-
my-postgres-secret.yaml
ファイルを作成し、以下の内容を記述します。apiVersion: v1 kind: Secret metadata: name: mypostgres-secret namespace: default type: Opaque stringData: superUserPassword: postgresSuperUserPsw replicationUserPassword: postgresReplicaPsw
superUserPassword
で指定する部分がpostgresユーザのパスワード、replicationUserPassword
で指定する部分がレプリケーション用ユーザのパスワードです。 -
ファイルが作成できたら、以下のコマンドで適用します。
$ kubectl apply -f my-postgres-secret.yaml
PostgreSQLのサーバ構成の設定と適用
-
my-postgres.yaml
ファイルを作成し、以下の内容を記述します。apiVersion: kubegres.reactive-tech.io/v1 kind: Kubegres metadata: name: mypostgres namespace: default spec: replicas: 3 image: postgres:13.2 database: size: 200Mi storageClassName: standard env: - name: POSTGRES_PASSWORD valueFrom: secretKeyRef: name: mypostgres-secret key: superUserPassword - name: POSTGRES_REPLICATION_PASSWORD valueFrom: secretKeyRef: name: mypostgres-secret key: replicationUserPassword
replicas: 3
として、3台のPostgreSQLを起動するように指定します。 -
ファイルが作成できたら、以下のコマンドで適用します。
$ kubectl apply -f my-postgres.yaml
これで、PostgreSQLが自動で立ち上がり、レプリケーションが開始されます。
動作確認
動作確認のために、PostgreSQLにアクセスするためのPodを別途用意しました。
そのPodからplsqを使いPRIMARY/REPLICAに接続してみます。
plsq用のPodの作成
-
今回、psqlが使えるPodを用意するために、postgres:13.2のイメージを使いました。
以下の内容をpsql.yaml
ファイルに記述します。apiVersion: v1 kind: Pod metadata: name: psql-pod namespace: default spec: containers: - name: psql image: postgres:13.2 env: - name: POSTGRES_PASSWORD value: pgpwd
-
ファイルが作成できたら、以下のコマンドで適用します。
$ kubectl apply -f psql.yaml
PostgreSQLへのアクセス
-
まず以下のコマンドを実行してPodの状態を確認します。3台のPodのステータスがRunningになっていればOKです。
$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mypostgres-1-0 1/1 Running 0 3m 172.17.0.6 hostname <none> <none> mypostgres-2-0 1/1 Running 0 2m46s 172.17.0.7 hostname <none> <none> mypostgres-3-0 1/1 Running 0 2m34s 172.17.0.8 hostname <none> <none>
-
PRIMARYに接続してみます。
PRIMARYにはmypostgres
というホスト名でアクセスできます。
以下のコマンドでPostgreSQLに接続します。$ kubectl exec -it psql-pod -- psql -h mypostgres -U postgres
ここでパスワードを聞かれるので、
my-postgres-secret.yaml
ファイルで設定したpostgresSuperUserPsw
を入力します。
レプリケーション状態を確認します。postgres=# SELECT pg_is_in_recovery(); pg_is_in_recovery ------------------- f (1 row)
f
が返っているのはPRIMARYとして動作しているということです。
PRIMARY上でテーブルを作成してみます。postgres=# CREATE TABLE tbl(a integer, b text); postgres=# INSERT INTO tbl VALUES(1, 'AAA');
-
次にREPLICAに接続してみます。
やり方はPRIMARYのときと同様です。REPLICAにはmypostgres-replica
というホスト名でアクセスできます。REPLICAは複数台ありますが、Kubegresがそのうちのひとつを自動で選択してくれます。$ kubectl exec -it psql-pod -- psql -h mypostgres-replica -U postgres
レプリケーション状態を確認すると、
t
が返りREPLICAとして動作していることが確認できます。postgres=# SELECT pg_is_in_recovery(); pg_is_in_recovery ------------------- t (1 row)
PRIMARY上で作成したテーブルをSEELCTしてみると、REPLICA上でも見ることができます。
postgres=# SELECT * FROM tbl; a | b ---+----- 1 | AAA (1 row)
自動フェイルオーバーの確認
ふたつの方法でPRIMARYに異常を発生させてみます。
- PRIMARYのPodを落とす方法
- PRIMARYのPostgreSQLのプロセスを終了させる方法
PRIMARYのPodを落としてみる
-
まずPRIMARYのPodを特定します。
以下のコマンドを実行すると、Endpoints
が172.17.0.6
になっています。$ kubectl describe services mypostgres Name: mypostgres Namespace: default Labels: app=mypostgres replicationRole=primary Annotations: <none> Selector: app=mypostgres,replicationRole=primary Type: ClusterIP IP Families: <none> IP: None IPs: None Port: <unset> 5432/TCP TargetPort: 5432/TCP Endpoints: 172.17.0.6:5432 Session Affinity: None Events: <none>
「PostgreSQLへのアクセス」の冒頭で確認したPod状態と照らし合わせると、PRIMARYのPodはmypostgres-1-0であることがわかります。
-
次のコマンドでPodを落とします。
$ kubectl delete pod mypostgres-1-0 pod "mypostgres-1-0" deleted
-
Podの状態を確認します。
mypostgres-1-0を落とした直後は、mypostgres-2-0とmypostgres-3-0のみしかありませんが、しばらくするとmypostgres-4-0が自動で立ち上がります。$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mypostgres-2-0 1/1 Running 0 16s 172.17.0.6 hostname <none> <none> mypostgres-3-0 1/1 Running 0 69m 172.17.0.8 hostname <none> <none> mypostgres-4-0 1/1 Running 0 16s 172.17.0.7 hostname <none> <none>
-
PRIMARYを確認します。
これまでと同様に、ホスト名にmypostgres
を指定してPRIMARYに接続してみます。$ kubectl exec -it psql-pod -- psql -h mypostgres -U postgres postgres=# SELECT pg_is_in_recovery(); pg_is_in_recovery ------------------- f (1 row)
このようにPodが終了する前と同じ手段でアクセスできることが確認できました。
以下のように、mypostgres-2-0が新しくPRIMARYになっていました。$ kubectl describe services mypostgres | grep Endpoints Endpoints: 172.17.0.6:5432
このように、自動フェイルオーバー・自動フェイルバックが行われることが確認できました。
PostgreSQLへのアクセスのときの状態と比べてると分かるように、PRIMARYのPod名は変わるものの、以前と変わらず同じホスト名mypostgres
でアクセスできます。
PRIMARYのPostgreSQLのプロセスを終了させてみる
-
次のコマンドでPod内のプロセスを終了させます。
$ kubectl exec -it mypostgres-2-0 -- /bin/bash root@mypostgres-2-0:/# kill 1
-
Podの状態を確認します。
プロセスをキルすると、以下のように自動的にPodが終了します。$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mypostgres-2-0 0/1 Terminating 1 5m14s 172.17.0.6 hostname <none> <none> mypostgres-3-0 1/1 Running 0 74m 172.17.0.8 hostname <none> <none> mypostgres-4-0 1/1 Running 0 5m1s 172.17.0.7 hostname <none> <none>
しばらくすると、mypostgres-5-0が自動で立ち上がります。
$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mypostgres-3-0 1/1 Running 0 31s 172.17.0.6 hostname <none> <none> mypostgres-4-0 1/1 Running 0 5m48s 172.17.0.7 hostname <none> <none> mypostgres-5-0 1/1 Running 0 19s 172.17.0.8 hostname <none> <none>
この方法でも自動フェイルオーバーが行われることが確認できました。
REPLICAの追加
「PostgreSQLのサーバ構成の設定と適用」で使用した、my-postgres.yaml
ファイルを編集します。
このファイルでreplicas: 4
としてPostgreSQLサーバ数を4に変更します。
$ kubectl apply -f my-postgres.yaml
$ kubectl get pods -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
mypostgres-3-0 1/1 Running 0 12m 172.17.0.6 hostname <none> <none>
mypostgres-4-0 1/1 Running 0 17m 172.17.0.7 hostname <none> <none>
mypostgres-5-0 1/1 Running 0 11m 172.17.0.8 hostname <none> <none>
mypostgres-6-0 1/1 Running 0 14s 172.17.0.9 hostname <none> <none>
mypostgres-6-0というPodが立ち上がり、4台構成とすることができました。
Dockerイメージのアップデート
稼働中のPostgreSQLのバージョン(PodのDockerイメージ)を更新してみます。
準備
まず、現在使用しているDockerイメージを確認します。postgres:13.2であることがわかりました。
$ kubectl get pods -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |sort
mypostgres-3-0: postgres:13.2,
mypostgres-4-0: postgres:13.2,
mypostgres-5-0: postgres:13.2,
mypostgres-6-0: postgres:13.2,
今回は新しいイメージとしてpostgres:myversion
を作成して、Podに反映させてみます。
DockerイメージのIDを確認し、
$ docker images | grep postgres
postgres 13.2 26c8bcd8b719 2 weeks ago 314MB
postgres latest 26c8bcd8b719 2 weeks ago 314MB
新しくタグを切ります。
$ docker tag 26c8bcd8b719 postgres:myversion
アップデートの実施
-
my-postgres.yaml
で、image: postgres:myversion
に変更し、適用します。$ kubectl apply -f my-postgres.yaml
-
Podの状態を確認すると、Podがひとつずつ終了して再起動されます。
$ kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES mypostgres-3-0 1/1 Running 0 27m 172.17.0.6 hostname <none> <none> mypostgres-4-0 1/1 Running 0 32m 172.17.0.7 hostname <none> <none> mypostgres-5-0 1/1 Running 0 26m 172.17.0.8 hostname <none> <none> mypostgres-6-0 0/1 Terminating 0 15m 172.17.0.9 hostname <none> <none>
-
すべてのPodが再起動されたあと、Dockerイメージを確認します。
$ kubectl get pods -o=jsonpath='{range .items[*]}{"\n"}{.metadata.name}{":\t"}{range .spec.containers[*]}{.image}{", "}{end}{end}' |sort mypostgres-3-0: postgres:myversion, mypostgres-4-0: postgres:myversion, mypostgres-5-0: postgres:myversion, mypostgres-6-0: postgres:myversion,
すべてのPodのDockerイメージがpostgres:myversion
となり、ローリングアップデートが行われることが確認できました。
おわりに
Kubegresを使ってPostgreSQL4台でHAクラスタを簡単に構成することができました。
また、Kubegresで自動フェイルオーバー・自動フェイルバック、REPLICA追加およびローリングアップデートを行えることを確認しました。
今回のデフォルトの設定では、PostgreSQL上にはpostgresユーザ、postgresデータベースが作成されます。
任意のユーザあるいはデータベースを作成して起動させる方法は、別途紹介したいと思います。
参考文献
https://www.kubegres.io/
https://kubernetes.io/
https://minikube.sigs.k8s.io/
https://www.sraoss.co.jp/tech-blog/pgsql/kubernetes-postgres-operator/
https://qiita.com/Esfahan/items/f5c846088281c39f73a4