[HLF] docker-composeからMinikubeへ移行(#1) PostgreSQL編

# 前回までのAssetシステムをKubernetesへ移行します
今まで`docker-compose`で構築してきたAssetシステムを`Kubernetes`(以下`k8s`)へ移行します。
途中で放り投げるかもしれませんが、ボチボチやっていきます。
いきなり`k8s`も面倒なので先ずは`minikube`上で構築して、動作確認ができたらどこかのクラウドベンダーに`k8s`で構築しようと思います。

# 何はなくともダミーデータ
今回は`minikube`上で`PostgreSQL`を稼働させ、ダミーデータの登録とDBの永続化まで実施します。
架空の車1万台分の`CVS`ファイルは[こちら](https://github.com/settembre21/asset/tree/master/data)に置いてあります。

# 環境について
動作環境は次の通りです。

| SW | Version |
|:--|:--|
| Ubuntu | 18.04.4 LTS |
| minikube | 1.18.3 |
| kubectl | 1.18.4 |
| docker | 19.03.12 |
| PostgreSQL | 12.3 |

# 環境構築します
### minikubeのインストール
本家の[こちら](https://kubernetes.io/ja/docs/tasks/tools/install-minikube/)を参考にインストールします。
丁寧に書かれているので分かりやすいと思います。下記は転記しているだけです;-)

```bash
# curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64
# chmod +x minikube
# install minikube /usr/local/bin/
```
VMはインストールせず`none`でやります。
起動方法は次の通りです。初回は`minikube`の`docker`イメージをダウンロードするので遅いです。

```bash
# minikube start --vm-driver=none
```

### kubectlのインストール
[こちら](https://kubernetes.io/ja/docs/tasks/tools/install-kubectl/#install-kubectl-on-linux)を参考にインストールします。

```bash
# 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
# install kubectl /usr/local/bin
```

### その他
`docker`と`PostgreSQL`のインストール手順は省略します。メモを取り忘れてます、スミマセン。
私もググってインストールしたので、ググってください。私はggrksです ;-)

# `minikube`用に`yaml`ファイルを修正
`docker-compose`用に作った`PostgreSQL`のyamlファイルを`minikube`用に修正します。
その前に、毎回`minikube`を再起動した時に`PostgreSQL`のDB作成＆TABLE定義をするのが面倒過ぎるので、DBストレージの永続化を設定します。

### DB用ストレージの永続化
`k8s`には`PersistentVolume`と`PersistentVolumeClaim`という仕組みがあるのでこれを使います。`PersistentVolume`で領域を確保して、`PersistentVolumeClaim`がその領域からサイズを要求して割り当てる、みたいな理解です。割り当てる領域は、今回はホスト側のディレクトリ(`hostPath`設定)を使います。`k8s`の場合は`NFS`かクラウドベンダーが提供しているストレージを使うことになるでしょう(AWSのS3みたいなやつ？)。

```yaml:pgsql-ppvc.yaml
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pgsql-pv
  labels:
    name: pgsqlvolume
spec:
  capacity:
    storage: 3Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /tank/minikube/pgsql # ホスト側の任意なディレクトリを指定してください
  storageClassName: slow
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pgsql-pvc
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  storageClassName: slow
```

`PersistentVolume`でホストの`/tank/minikube/pgsql`から3GBを確保して、`PersistentVolumeClaim`がそのうち1GBを要求・割り当てする設定です。さっそく適用してみましょう！
（その前に`minikube`の起動を忘れずに）

```bash
# kubectl apply -f pgsql-ppvc.yaml
persistentvolume/pgsql-pv created
persistentvolumeclaim/pgsql-pvc created
```

適用できたようです。ちゃんとストレージの割り当てが出来ているか確認します。

```bash
# kubectl get pv,pvc
NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM               STORAGECLASS   REASON   AGE
persistentvolume/pgsql-pv   3Gi        RWO            Retain           Bound    default/pgsql-pvc   slow                    101s

NAME                              STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/pgsql-pvc   Bound    pgsql-pv   3Gi        RWO            slow           101s
```

割り当て成功したみたいです。pv(`persistentvolume`)、pvc(`persistentvolumeclaim`)共に`CAPACITY`が3Giになってますが、気にしないことにします。

### PostgreSQLのでぷろい
`PostgreSQL`のyamlファルを作成します。必要最低限しか書かないようにします。yamlは難しいので…

```yaml:pgsql-sv.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql
  labels:
    app: pgsql
spec:
  strategy:
    type: Recreate
  replicas: 1
  selector:
    matchLabels:
      name: pgsql
  template:
    metadata:
      labels:
        name: pgsql
    spec:
      containers:
        - image: postgres:latest
          name: postgresql
          env:
            - name: POSTGRES_PASSWORD
              value: secret
          volumeMounts:
            - name: pgsqlclime
              mountPath: /var/lib/postgresql/data
      volumes:
        - name: pgsqlclime
          persistentVolumeClaim:
            claimName: pgsql-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql
  labels:
    app: pgsql
spec:
  ports:
    - port: 5432
  selector:
    app: pgsql
```
`---`はブロックの区切りを表していて、確かマルチブロックとか言います。1つのyamlファイルに2以上の項目を定義する場合に使います。行頭の`---`も必要です。ここでは、`PostgreSQL`の設定と、`PostgreSQL`を利用できるようにする`Service`を定義しています。`volumes`の項目に上記で設定したクライムを指定しています。`PostgreSQL`のデフォルトDB置き場`/var/lib/postgresql/data`にマウントしています。
では、適用してみましょう！

```bash
# kubectl apply -f pgsql-sv.yaml 
deployment.apps/postgresql created
service/postgresql created
```

適用できたようです。`pod`の状態を見てみましょう。

```bash
# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
postgresql-5cf88f5767-vmjzt   1/1     Running   0          76s
```
ちゃんと`Running`になっています！`Name`にあるのは`pod`の名前です。ユニーク名になっていると思います。
`kubectl`へはこの名前を指定して`pod`を操作します。

# DBの構築
ここまでできたらDBを構築します。手順としては、

　1. minikubeのPostgreSQLコンテナへダミーデータをコピー
　2. minikubeのPostgreSQLコンテナへログインする
　3. postgresへスイッチユーザー(su - postgres)
　4. psqlコマンドでDB作成＆TABLE定義
　5. 3で作ったTABLEへCSVデータを流し込み

となります。
ダミーデータをコピーしましょう。

```bash
# kubectl cp data.csv postgresql-5cf88f5767-vmjzt:/tmp
```
あっけなくコピーできます。中へ入って確認してみます。

```bash
# kubectl exec -it postgresql-5cf88f5767-vmjzt /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@postgresql-5cf88f5767-vmjzt:/#
```
これもあっけなく入れました。`/tmp`を見てみましょう。

```bash
# ls -l /tmp
total 396
-rw-r--r-- 1 root root 405488 Jun 26 23:26 data.csv
```
ダミーデータ用の`CSV`ファイルを確認できました。中身も確認しておきましょう。

```bash
root@postgresql-5cf88f5767-vmjzt:/# more /tmp/data.csv 
"JXT4EGSP0AX100001","2010","04",33880,78
"JXT5EGSP0AX100002","2010","02",6360,96
"JXT4EGSP0AX100003","2010","09",41040,73
"JXT4EGSP0AX100004","2010","03",15330,90
"JXT4EGSP0AX100005","2010","06",43680,71
"JXT4EGSP0AX100006","2010","04",17800,89
"JXT4EGSP0AX100007","2010","03",14850,91
"JXT4EGSP0AX100008","2010","09",23220,85
"JXT5EGSP0AX100009","2010","08",22960,85
"JXT4EGSP0AX100010","2010","07",1050,100
"JXT4EGSP0AX100011","2010","01",3870,98
"JXT5EGSP0AX100012","2010","10",35600,77
"JXT4EGSP0AX100013","2010","08",38800,75
"JXT4EGSP0AX100014","2010","02",1800,99
"JXT4EGSP0AX100015","2010","04",17320,89
"JXT4EGSP0AX100016","2010","11",35640,77
"JXT5EGSP0AX100017","2010","10",95700,37
"JXT4EGSP0AX100018","2010","10",19900,87
"JXT4EGSP0AX100019","2010","02",17760,89
"JXT4EGSP0AX100020","2010","08",28400,82
"JXT4EGSP0AX100021","2010","07",42350,72
"JXT5EGSP0AX100022","2010","11",91080,40
"JXT4EGSP0AX100023","2010","03",23490,85
"JXT4EGSP0AX100024","2010","08",30080,80
"JXT4EGSP0AX100025","2010","03",13410,92
"JXT4EGSP0AX100026","2010","02",9260,94
"JXT5EGSP0AX100027","2010","09",56070,63
"JXT4EGSP0AX100028","2010","02",2660,99
"JXT4EGSP0AX100029","2010","08",2640,99
"JXT4EGSP0AX100030","2010","12",240,100
"JXT5EGSP0AX100031","2010","05",27300,82
"JXT4EGSP0AX100032","2010","01",5030,97
"JXT4EGSP0AX100033","2010","04",8200,95
"JXT5EGSP0AX100034","2010","10",35100,77
"JXT5EGSP0AX100035","2010","06",41220,73
"JXT4EGSP0AX100036","2010","11",31350,80
"JXT5EGSP0AX100037","2010","05",4900,97
"JXT4EGSP0AX100038","2010","08",46560,69
--More--(0%)
```
ちゃんとコピーできていますね。

### DBの作成とTABLEの定義
`PostgreSQL`のコンテナへ入れたので、早速DBの作成とTABLEの定義をします。
`postgres`へsuします。

```bash
root@postgresql-5cf88f5767-vmjzt:/# su - postgres
postgres@postgresql-5cf88f5767-vmjzt:~$
```
su出来ました。ここから一気にいきます。

```bash
postgres@postgresql-5cf88f5767-vmjzt:~$ psql
psql (12.3 (Debian 12.3-1.pgdg100+1))
Type "help" for help.
```

```sql
postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------+----------+----------+------------+------------+-----------------------
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 | 
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
(3 rows)
postgres=# create database asset; /* DBの作成 */
postgres=# \l
                                 List of databases
   Name    |  Owner   | Encoding |  Collate   |   Ctype    |   Access privileges   
-----------+----------+----------+------------+------------+-----------------------
 asset     | postgres | UTF8     | en_US.utf8 | en_US.utf8 | 
 postgres  | postgres | UTF8     | en_US.utf8 | en_US.utf8 | 
 template0 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
 template1 | postgres | UTF8     | en_US.utf8 | en_US.utf8 | =c/postgres          +
           |          |          |            |            | postgres=CTc/postgres
(4 rows)

postgres=# \c asset /* DBの選択 */
You are now connected to database "asset" as user "postgres".
asset=# create table asset ( /* TABLEの定義 */
asset(# id char(17) NOT NULL, 
asset(# year char(4) NOT NULL,
asset(# month char(2) NOT NULL,
asset(# mileage integer,
asset(# battery integer,
asset(# primary key(id)); 
CREATE TABLE
asset=# \copy asset from /tmp/data.csv with csv /* CSVファイルをインポート */
COPY 10000

asset=# select * from asset;
        id         | year | month | mileage | battery 
-------------------+------+-------+---------+---------
 JXT4EGSP0AX100001 | 2010 | 04    |   33880 |      78
 JXT5EGSP0AX100002 | 2010 | 02    |    6360 |      96
 JXT4EGSP0AX100003 | 2010 | 09    |   41040 |      73
 JXT4EGSP0AX100004 | 2010 | 03    |   15330 |      90
 JXT4EGSP0AX100005 | 2010 | 06    |   43680 |      71
 JXT4EGSP0AX100006 | 2010 | 04    |   17800 |      89
 JXT4EGSP0AX100007 | 2010 | 03    |   14850 |      91
 JXT4EGSP0AX100008 | 2010 | 09    |   23220 |      85
 JXT5EGSP0AX100009 | 2010 | 08    |   22960 |      85
 JXT4EGSP0AX100010 | 2010 | 07    |    1050 |     100
 JXT4EGSP0AX100011 | 2010 | 01    |    3870 |      98
 JXT5EGSP0AX100012 | 2010 | 10    |   35600 |      77
 JXT4EGSP0AX100013 | 2010 | 08    |   38800 |      75
 JXT4EGSP0AX100014 | 2010 | 02    |    1800 |      99
 JXT4EGSP0AX100015 | 2010 | 04    |   17320 |      89
 JXT4EGSP0AX100016 | 2010 | 11    |   35640 |      77
 JXT5EGSP0AX100017 | 2010 | 10    |   95700 |      37
 JXT4EGSP0AX100018 | 2010 | 10    |   19900 |      87
 JXT4EGSP0AX100019 | 2010 | 02    |   17760 |      89
 JXT4EGSP0AX100020 | 2010 | 08    |   28400 |      82
 JXT4EGSP0AX100021 | 2010 | 07    |   42350 |      72
 JXT5EGSP0AX100022 | 2010 | 11    |   91080 |      40
 JXT4EGSP0AX100023 | 2010 | 03    |   23490 |      85
 JXT4EGSP0AX100024 | 2010 | 08    |   30080 |      80
 JXT4EGSP0AX100025 | 2010 | 03    |   13410 |      92
 JXT4EGSP0AX100026 | 2010 | 02    |    9260 |      94
 JXT5EGSP0AX100027 | 2010 | 09    |   56070 |      63
 JXT4EGSP0AX100028 | 2010 | 02    |    2660 |      99
 JXT4EGSP0AX100029 | 2010 | 08    |    2640 |      99
 JXT4EGSP0AX100030 | 2010 | 12    |     240 |     100
 JXT5EGSP0AX100031 | 2010 | 05    |   27300 |      82
 JXT4EGSP0AX100032 | 2010 | 01    |    5030 |      97
 JXT4EGSP0AX100033 | 2010 | 04    |    8200 |      95
 JXT5EGSP0AX100034 | 2010 | 10    |   35100 |      77
 JXT5EGSP0AX100035 | 2010 | 06    |   41220 |      73
 JXT4EGSP0AX100036 | 2010 | 11    |   31350 |      80
--More--
/* 'q'で抜ける */
asset=# \q /* psqlから抜ける */
postgres@postgresql-5cf88f5767-vmjzt:~$
```
ここまでで`PostgreSQL`の設定は終わりです。

### ストレージ永続化の確認
ちゃんとDBが永続化できているかを確認します。
コンテナを削除します。

```bash
# kubectl delete -f pgsql-sv.yaml
deployment.apps "postgresql" deleted
service "postgresql" deleted
# kubectl delete -f pgsql-ppvc.yaml 
persistentvolume "pgsql-pv" deleted
persistentvolumeclaim "pgsql-pvc" deleted
```

`minikube`でstartした環境を削除します。

```bash
# minikube delete
* Uninstalling Kubernetes v1.18.3 using kubeadm ...
* Deleting "minikube" in none ...
* Removed all traces of the "minikube" cluster.
```
消えたようです。念のため`get pods`してみます。

```bash
# kubectl get pods
The connection to the server localhost:8080 was refused - did you specify the right host or port?
```
怒られ(？)ました。
再スタート。

```bash
minikube start --vm-driver=none
* minikube v1.11.0 on Ubuntu 18.04
* Using the none driver based on user configuration
* Starting control plane node minikube in cluster minikube
* Running on localhost (CPUs=4, Memory=15859MB, Disk=111657MB) ...
* OS release is Ubuntu 18.04.4 LTS
* Preparing Kubernetes v1.18.3 on Docker 19.03.12 ...
  - kubelet.resolv-conf=/run/systemd/resolve/resolv.conf
* Configuring local host environment ...
* 
! The 'none' driver is designed for experts who need to integrate with an existing VM
* Most users should use the newer 'docker' driver instead, which does not require root!
* For more information, see: https://minikube.sigs.k8s.io/docs/reference/drivers/none/
* 
! kubectl and minikube configuration will be stored in /root
! To use kubectl or minikube commands as your own user, you may need to relocate them. For example, to overwrite your own settings, run:
* 
  - sudo mv /root/.kube /root/.minikube $HOME
  - sudo chown -R $USER $HOME/.kube $HOME/.minikube
* 
* This can also be done automatically by setting the env var CHANGE_MINIKUBE_NONE_USER=true
* Verifying Kubernetes components...
* Enabled addons: default-storageclass, storage-provisioner
* Done! kubectl is now configured to use "minikube"
```
`minikube`を再起動しました。
`PostgreSQL`のデプロイ。

```bash
# kubectl apply -f pgsql-ppvc.yaml
persistentvolume/pgsql-pv created
persistentvolumeclaim/pgsql-pvc created
# kubectl apply -f pgsql-sv.yaml 
deployment.apps/postgresql created
service/postgresql created
```
`PostgreSQL`のコンテナIDを確認。

```bash
# kubectl get pods
NAME                          READY   STATUS    RESTARTS   AGE
postgresql-5cf88f5767-w29ww   1/1     Running   0          8s
```
ちゃんと動いています。ここからコンテナへ入ってTABLEの内容まで確認します。

```bash
# kubectl exec -it postgresql-5cf88f5767-w29ww /bin/bash
kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.
root@postgresql-5cf88f5767-w29ww:/# su - postgres
postgres@postgresql-5cf88f5767-w29ww:~$ psql
psql (12.3 (Debian 12.3-1.pgdg100+1))
Type "help" for help.
```

```sql
postgres=# \c asset
You are now connected to database "asset" as user "postgres".
asset=# select * from asset;
        id         | year | month | mileage | battery 
-------------------+------+-------+---------+---------
 JXT4EGSP0AX100001 | 2010 | 04    |   33880 |      78
 JXT5EGSP0AX100002 | 2010 | 02    |    6360 |      96
 JXT4EGSP0AX100003 | 2010 | 09    |   41040 |      73
 JXT4EGSP0AX100004 | 2010 | 03    |   15330 |      90
 JXT4EGSP0AX100005 | 2010 | 06    |   43680 |      71
 JXT4EGSP0AX100006 | 2010 | 04    |   17800 |      89
 JXT4EGSP0AX100007 | 2010 | 03    |   14850 |      91
 JXT4EGSP0AX100008 | 2010 | 09    |   23220 |      85
 JXT5EGSP0AX100009 | 2010 | 08    |   22960 |      85
 JXT4EGSP0AX100010 | 2010 | 07    |    1050 |     100
 JXT4EGSP0AX100011 | 2010 | 01    |    3870 |      98
 JXT5EGSP0AX100012 | 2010 | 10    |   35600 |      77
 JXT4EGSP0AX100013 | 2010 | 08    |   38800 |      75
 JXT4EGSP0AX100014 | 2010 | 02    |    1800 |      99
 JXT4EGSP0AX100015 | 2010 | 04    |   17320 |      89
 JXT4EGSP0AX100016 | 2010 | 11    |   35640 |      77
 JXT5EGSP0AX100017 | 2010 | 10    |   95700 |      37
 JXT4EGSP0AX100018 | 2010 | 10    |   19900 |      87
 JXT4EGSP0AX100019 | 2010 | 02    |   17760 |      89
 JXT4EGSP0AX100020 | 2010 | 08    |   28400 |      82
 JXT4EGSP0AX100021 | 2010 | 07    |   42350 |      72
 JXT5EGSP0AX100022 | 2010 | 11    |   91080 |      40
 JXT4EGSP0AX100023 | 2010 | 03    |   23490 |      85
 JXT4EGSP0AX100024 | 2010 | 08    |   30080 |      80
 JXT4EGSP0AX100025 | 2010 | 03    |   13410 |      92
 JXT4EGSP0AX100026 | 2010 | 02    |    9260 |      94
 JXT5EGSP0AX100027 | 2010 | 09    |   56070 |      63
 JXT4EGSP0AX100028 | 2010 | 02    |    2660 |      99
 JXT4EGSP0AX100029 | 2010 | 08    |    2640 |      99
 JXT4EGSP0AX100030 | 2010 | 12    |     240 |     100
 JXT5EGSP0AX100031 | 2010 | 05    |   27300 |      82
 JXT4EGSP0AX100032 | 2010 | 01    |    5030 |      97
 JXT4EGSP0AX100033 | 2010 | 04    |    8200 |      95
 JXT5EGSP0AX100034 | 2010 | 10    |   35100 |      77
 JXT5EGSP0AX100035 | 2010 | 06    |   41220 |      73
 JXT4EGSP0AX100036 | 2010 | 11    |   31350 |      80
asset=# \q
```
DBもTABLEも残っていることが確認できました。永続化できていますね。

# 最後に
`docker-compose`はあまり関係無かったですね。`PostgreSQL`を`minikube`上で初期設定する説明になりました。
これから`Hyperledger Fabric`のコンテナを`minikube`に立てていこうと思います。
ボチボチね。