Kubegresで任意のユーザ・データベースを作成しておく方法

Kubegresはコンテナ管理を自動化するKubernetesのOperatorのひとつで、PostgreSQLのHAクラスタを構築できるものです。

Kubegresを使ってPodをデフォルト設定で立ち上げると、管理者権限のpostgresユーザとpostgresデータベースが作成された状態でPostgreSQLが起動されます。

本記事では、Podの立ち上げ時に任意の一般ユーザ(user1)およびデータベース(testdb)を作成する方法を紹介します。  
また、minikubeで以前にKubegresを立ち上げたことがあると、前回の状態が影響して期待通りに動作しなかったので、その対処方法についても「[環境の準備](#環境の準備)」のところで触れています。

# 環境の準備
環境は[前回の記事](todo)と同様にminikubeを使用していて、Kubernetesクラスタを作り直しました。
初めての場合は、「```$ minikube start --driver=none```」のところから行ってください。

```shell
$ minikube delete
```
Kubegresは初回起動時（データベースディレクトリが存在しない場合）のみ初期化スクリプトが実行される作りになっていて、初期化スクリプトで任意のユーザ・データベースを作成しています。

前回の起動でPersistent Volumeがホストマシン上にマウントされていて、そのデータベースファイルがホストマシン上に残っている場合、それを削除しておく必要があります。そうしないと、初期化スクリプトが動きません。

私の場合は /tmp/hostpath-provisioner ディレクトリ以下にファイルがあったので、それを削除しました。

```shell
$ sudo rm -fr /tmp/hostpath-provisioner
```
どこにマウントされるかは[こちら](https://minikube.sigs.k8s.io/docs/handbook/persistent_volumes/)で確認することができます。

その後、minikubeを起動し、Operatorをインストールします。

```shell
$ minikube start --driver=none
$ kubectl apply -f https://raw.githubusercontent.com/reactive-tech/kubegres/v1.1/kubegres.yaml
```

# 設定ファイルの全体概要
[デフォルト設定](https://www.kubegres.io/doc/getting-started.html)（あるいは[前回記事](todo)）では、認証情報を設定する`my-postgres-secret.yaml`ファイルと、PotgreSQLのインスタンスを設定する`my-postgres.yaml`ファイルを作成しました。

それに加えて、カスタムの設定を行う`my-postgres-config.yaml`ファイルを作成します。  
デフォルトの設定からこの設定を読み込むように`my-postgres.yaml`を編集し、新たな認証情報は`my-postgres-secret.yaml`ファイルに追記します。

![図](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581362/7f10961a-bb19-0dd4-dce7-7bd77ac52d9c.png)

# 認証情報の設定ファイルの編集と適用
`my-postgres-secret.yaml`ファイルを編集し、追加するユーザのパスワードを記載します。
編集前のファイルは、[こちら](https://www.kubegres.io/doc/getting-started.html)の「2) Create a Secret resource」に記載のものを使用します。

末尾に`myDbUserPassword: user1Psw`を追記しました。今回作成するユーザのパスワードは`user1Psw`ということになります。

ファイル内容は以下になります。

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

編集後、適用します。

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

# カスタム設定ファイルの作成と適用
新たに`my-postgres-config.yaml`ファイルを作成して適用します。  
初期化スクリプトprimary_init_script.shをオーバーライドするものなのですが、このスクリプトの中で、作成するデータベース名`testdb`とユーザ名`user1`を指定します。 

1. まず、[こちら](https://www.kubegres.io/doc/set-config-map.html)の「Override primary_init_script.sh」を参考にファイルを作成します。
1. 次に、`customDatabaseName`と`customUserName`の行を編集して、今回作成するデータベース(testdb)とユーザ(user1)を指定します。
1. さらに、これまで使用してきたnamespaceはdefaultなので、`custom`の部分を`default`に変更します。

ファイル内容は以下になります。

```yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: mypostgres-conf
  namespace: default

data:

  primary_init_script.sh: |
    #!/bin/bash
    set -e

    # This script assumes that the env-var $POSTGRES_MY_DB_PASSWORD contains the password of the custom user to create.
    # You can add any env-var in your Kubegres resource config YAML.

    dt=$(date '+%d/%m/%Y %H:%M:%S');
    echo "$dt - Running init script the 1st time Primary PostgreSql container is created...";

    customDatabaseName="testdb"
    customUserName="user1"

    echo "$dt - Running: psql -v ON_ERROR_STOP=1 --username $POSTGRES_USER --dbname $POSTGRES_DB ...";

    psql -v ON_ERROR_STOP=1 --username "$POSTGRES_USER" --dbname "$POSTGRES_DB" <<-EOSQL
    CREATE DATABASE $customDatabaseName;
    CREATE USER $customUserName WITH PASSWORD '$POSTGRES_MY_DB_PASSWORD';
    GRANT ALL PRIVILEGES ON DATABASE "$customDatabaseName" to $customUserName;
    EOSQL

    echo "$dt - Init script is completed";
```

作成後、適用します。

```shell
$ kubectl apply -f my-postgres-config.yaml
```

# PotgreSQLインスタンスの設定ファイルの編集と適用
`my-postgres.yaml`ファイルを編集し、これまで行った設定を読み込むようにします。  
編集前のファイルは、[こちら](https://www.kubegres.io/doc/getting-started.html)の「3) Create a cluster of PostgreSql instances」に記載のものを使用します。

2箇所追記します。spec.customConfigの指定と、環境変数`POSTGRES_MY_DB_PASSWORD`の設定です。以下の内容を追記します。

```yaml
   customConfig: mypostgres-conf
```
customConfigの値は`my-postgres-config.yaml`ファイルで作成したConfigMapオブジェクトの名前`mypostgres-conf`を指定します。

```yaml
      - name: POSTGRES_MY_DB_PASSWORD
        valueFrom:
           secretKeyRef:
              name: mypostgres-secret
              key: myDbUserPassword
```
nameには`my-postgres-secret.yaml`ファイルで作成したSecretオブジェクトの名前`mypostgres-secret`を、Keyには`my-postgres-secret.yaml`ファイルで追記した項目のキー名`myDbUserPassword`を指定します。

最終的にファイル全体の内容は以下になります。

```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

   customConfig: mypostgres-conf

   env:
      - name: POSTGRES_PASSWORD
        valueFrom:
           secretKeyRef:
              name: mypostgres-secret
              key: superUserPassword
      - name: POSTGRES_REPLICATION_PASSWORD
        valueFrom:
           secretKeyRef:
              name: mypostgres-secret
              key: replicationUserPassword
      - name: POSTGRES_MY_DB_PASSWORD
        valueFrom:
           secretKeyRef:
              name: mypostgres-secret
              key: myDbUserPassword
```

作成後、適用します。

```shell
$ kubectl apply -f my-postgres.yaml
```

これで設定は終わりです。

# 確認
PostgreSQLに接続してみましょう。  
以下のコマンドを実行してPodの状態がRunningになっていることを確認しておきます。

```shell
$ 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>
```

前回の記事同様、アクセス用のPodからpsqlでアクセスしてみます。psqlの引数でユーザ(user1)とデータベース(testdb)を指定します。

```shell
$ kubectl exec -it psql-pod -- psql -h mypostgres -U user1 testdb
```

ここでパスワードを聞かれるので、`my-postgres-secret.yaml`ファイルで追加設定した`user1Psw`を入力します。
接続できればOKです。

また、以下のとおりPod内に入って確認することもできます。

```shell
$ kubectl exec -it mypostgres-1-0 -- /bin/bash
root@mypostgres-1-0:/# psql -U user1 testdb
```

# おわりに
KubegresでPod立ち上げ時にPostgreSQLの一般ユーザおよびデータベースを作成する方法を紹介しました。  
同様の方法でpostgres.confやpg_hba.confを上書きしてPostgreSQLの設定を変更できるので、[こちら](https://www.kubegres.io/doc/set-config-map.html)を参考にしてください。

# 参考文献
[https://www.kubegres.io/](https://www.kubegres.io/)
[https://kubernetes.io/](https://kubernetes.io/)
[https://minikube.sigs.k8s.io/](https://minikube.sigs.k8s.io/)