LoginSignup
5
0

More than 3 years have passed since last update.

Kubernetes operator "Kubegres"で、PostgreSQLのクラスタ化を検証

Posted at

最近(2021年4月)Kubegresがリリースされたので使ってみました。本記事では、minikube上でKubegresをインストールして設定する手順をまとめました。

Kubegresはコンテナ管理を自動化するKubernetesのOperatorのひとつで、PostgreSQLのHAクラスタを構築できるものです。また、minikubeはローカルマシン上に簡単にKubernetesクラスタを構築できるツールです。

これらを使ってPostgreSQLを冗長化してみます。Podの構成は以下の図のようになっています。
PostgreSQLサーバ構成

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のインストールと起動

  1. 必要なパッケージをインストールします。

    $ sudo apt install conntrack
    
  2. minikube本体を公式サイトの手順に従ってインストールします。例えば、

    $ curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
    $ sudo install minikube-linux-amd64 /usr/local/bin/minikube
    
  3. minikube用にシステムのプロキシを設定します(参考)。プロキシを使わない場合はスキップしてください。

    • 10.96.0.0/12,192.168.99.0/24,192.168.39.0/24 をNO_PROXYに設定する。
    • HTTPプロキシだけでなく、HTTPS_PROXYの設定をお忘れなく。
  4. 起動します。

    $ minikube start --driver=none
    
  5. 確認します。以下のように表示されれば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のインストール

  1. 公式サイトの手順に従ってインストールします。バイナリをダウンロードし、パスの通ったところに配置します。

    $ 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
    
  2. 確認します。以下のようにバージョンが表示されれば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のインストール

  1. 以下のコマンドを実行します。

    $ kubectl apply -f https://raw.githubusercontent.com/reactive-tech/kubegres/v1.1/kubegres.yaml
    
  2. 確認します。以下のように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の管理者ユーザの認証情報の設定と適用

  1. my-postgres-secret.yamlファイルを作成し、以下の内容を記述します。

    apiVersion: v1
    kind: Secret
    metadata:
      name: mypostgres-secret
      namespace: default
    type: Opaque
    stringData:
      superUserPassword: postgresSuperUserPsw
      replicationUserPassword: postgresReplicaPsw
    

    superUserPasswordで指定する部分がpostgresユーザのパスワード、replicationUserPasswordで指定する部分がレプリケーション用ユーザのパスワードです。

  2. ファイルが作成できたら、以下のコマンドで適用します。

    $ kubectl apply -f my-postgres-secret.yaml
    

PostgreSQLのサーバ構成の設定と適用

  1. 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を起動するように指定します。

  2. ファイルが作成できたら、以下のコマンドで適用します。

    $ kubectl apply -f my-postgres.yaml
    

これで、PostgreSQLが自動で立ち上がり、レプリケーションが開始されます。

動作確認

動作確認のために、PostgreSQLにアクセスするためのPodを別途用意しました。
そのPodからplsqを使いPRIMARY/REPLICAに接続してみます。

plsq用のPodの作成

  1. 今回、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
    
  2. ファイルが作成できたら、以下のコマンドで適用します。

    $ 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に異常を発生させてみます。

  1. PRIMARYのPodを落とす方法
  2. PRIMARYのPostgreSQLのプロセスを終了させる方法

PRIMARYのPodを落としてみる

  1. まずPRIMARYのPodを特定します。
    以下のコマンドを実行すると、Endpoints172.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であることがわかります。

  2. 次のコマンドでPodを落とします。

    $ kubectl delete pod mypostgres-1-0
    pod "mypostgres-1-0" deleted
    
  3. 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>
    
  4. 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のプロセスを終了させてみる

  1. 次のコマンドでPod内のプロセスを終了させます。

    $ kubectl exec -it mypostgres-2-0 -- /bin/bash
    root@mypostgres-2-0:/# kill 1
    
  2. 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

アップデートの実施

  1. my-postgres.yamlで、image: postgres:myversionに変更し、適用します。

    $ kubectl apply -f my-postgres.yaml
    
  2. 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>
    
  3. すべての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

5
0
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
0