GKEの中で永続ディスク（Persistent Disk）の利用方法

GKE使用時の課題

* どうやって、Podsの間にデータファイルを共有し、利用出来るか？
* どんな時に、Podがエラーとなったり、削除されたり、データに影響があるのか？

上記の課題は、Cloud Storageなどのストレージサービスを利用したら解決できますが、処理パフォーマンスが必要な場合Persistent Diskを利用しなければなりません。

Persistent Diskを使う方法を紹介いたします。

### 実施手順
* Persistent Disk作成
* Persistent Diskフォーマット
* 準備できたPersistent Diskを使ってGKE中にストレージを作成
* GKEのストレージマウントのPod作成

※本手順はGCPやgcloudを利用する経験がある前提とします。

## １．Persistent Disk作成

```
# Persistent Disk作成
gcloud compute disks create --size=10GB --zone=asia-northeast1-b sample-gce-nfs-disk
```
注意：利用されるGKEクラスタのZoneと同じ指定をしてください。

## ２．Persistent Diskフォーマット
本記事は、GCEを使ってディスクをフォーマット化(初期化)する方法を紹介します。

```
# Persistentディスク付けのインスタンスを作成する
gcloud compute instances create work-vm --zone=asia-northeast1-b \
      --machine-type=f1-micro  --disk=name=sample-gce-nfs-disk

# GCEインスタンスにSSHする
gcloud compute ssh --zone=asia-northeast1-b work-vm

# 付けるディスク確認
$ sudo lsblk
> NAME   MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
> sda      8:0    0  10G  0 disk 
> `-sda1   8:1    0  10G  0 part /
> sdb      8:16   0  10G  0 disk 

# sdbは下記のコマンドに入れて、フォーマットする
sudo mkfs.ext4 -m 0 -F -E lazy_itable_init=0,lazy_journal_init=0,discard /dev/sdb

# フォーマットはこれで完了です。これからのコマンドの実施は任意
# マウント先のフォルダを作成
sudo mkdir -p /mnt/disks/sdb

# マウント実施
sudo mount -o discard,defaults /dev/sdb /mnt/disks/sdb

# 全てユーザに読み書きげ権限付与
sudo chmod a+w /mnt/disks/sdb
```

## ３．準備できたPersistent Diskを使ってGKE中にストレジを作成
ワークフォルダの構成

```
persistentvolume
├── README.md
├── postgres.deployment.yaml
└── pvc-demo.yaml
```

定義Yamlファイルを準備します。

```
pvc-demo.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: sample-volume-pv
spec:
  storageClassName: ""
  capacity:
    storage: 10G
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: sample-gce-nfs-disk
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: sample-volume-pvc
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10G
```

accessModesについては下記の３つがあります。

- ReadWriteOnce：読み書きできる１つマウント

- ReadOnlyMany：読み込み専用の権限で複数マウント可能

- ReadWriteMany：読み書きできる複数マウント。GCEのPersistent Diskはこのオプションを適用できない。このオプションを利用したい場合、[別の記事でNFSでマウントする方法を紹介](https://qiita.com/devs_hd/items/dbcafb54f6789280036a)します。

GKE中のストレージを作成

```
＃　ストレージ作成実施
kubectl apply -f pvc-demo.yaml
```

GKEのストレージ確認
<img width="1003" alt="gcp_gke_kubernetes_persistent_disk_devsamurai_001.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535698/90c36105-9b27-e01c-b538-34b3f397daf1.png">

## ４．GKEのストレジマウントのPod作成

postgres.deployment.yaml

```
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: postgres
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:latest
        imagePullPolicy: "IfNotPresent"
        ports:
        - containerPort: 5432
        env:
        - name: POSTGRES_USER
          value: postgres
        - name: POSTGRES_PASSWORD
          value: magicPass
        - name: PGDATA
          value: /var/lib/postgresql/data/pgdata
        volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: postgres-volume
      volumes:
      - name: postgres-volume
        persistentVolumeClaim:
          claimName: sample-volume-pvc
```
このデプロイメント定義は作成したPersistent Diskを使って、データベースの物理ファイルを保存する。

デプロイPostgres

```
＃　deploy postgres on gke
kubectl apply -f postgres.deployment.yaml
```

デプロイ後の確認
<img width="931" alt="gcp_gke_kubernetes_persistent_disk_devsamurai_002.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/535698/89b4a485-f941-d508-5574-254c18c33507.png">

## ５．Persistent Disk機能の確認

確認手順

* Postgresの中にテーブル作成
* Postgresのデプロイを削除
* Postgresを再デプロイ（以前のPersistent Disk付き）
* 作成したテーブルの確認

### Postgresの中にテーブル作成

```
# Podリスト表示
kubectl get pods
> NAME                                               READY   STATUS      RESTARTS   AGE
> nfs-server-c6d9c8755-pvjlz                         1/1     Running     0          147m
> postgres-55d84bc864-nwmgh                          1/1     Running     0          113s

# SSH to pod
kubeclt exec -it postgres-55d84bc864-nwmgh /bin/bash

# Connect to Postgres
psql --host=localhost --user=postgres

# Create a table
sql > CREATE TABLE account(
   user_id serial PRIMARY KEY,
   username VARCHAR (50) UNIQUE NOT NULL,
   password VARCHAR (50) NOT NULL,
   email VARCHAR (355) UNIQUE NOT NULL,
   created_on TIMESTAMP NOT NULL,
   last_login TIMESTAMP
);

sql > \d account;
                                           Table "public.account"
   Column   |            Type             | Collation | Nullable |                 Default                  
------------+-----------------------------+-----------+----------+------------------------------------------
 user_id    | integer                     |           | not null | nextval('account_user_id_seq'::regclass)
 username   | character varying(50)       |           | not null | 
 password   | character varying(50)       |           | not null | 
 email      | character varying(355)      |           | not null | 
 created_on | timestamp without time zone |           | not null | 
 last_login | timestamp without time zone |           |          | 
Indexes:
    "account_pkey" PRIMARY KEY, btree (user_id)
    "account_email_key" UNIQUE CONSTRAINT, btree (email)
    "account_username_key" UNIQUE CONSTRAINT, btree (username)
    
sql > \q;

# exit ssh
exit
```

### Postgresのデプロイ削除

```
kubectl delete deployment postgres
```

### Postgresを再デプロイ

```
＃　deploy postgres on gke
kubectl apply -f postgres.deployment.yaml
```

### 作成したテーブルの確認

```
# Podリスト表示
kubectl get pods
> NAME                                               READY   STATUS      RESTARTS   AGE
> nfs-server-c6d9c8755-pvjlz                         1/1     Running     0          147m
> postgres-55d84bc864-fpsv5                          1/1     Running     0          113s

# SSH to pod
kubeclt exec -it postgres-55d84bc864-fpsv5 /bin/bash

# Connect to Postgres
psql --host=localhost --user=postgres

-- 以前作成したテーブルの確認
sql > \d account;
                                           Table "public.account"
   Column   |            Type             | Collation | Nullable |                 Default                  
------------+-----------------------------+-----------+----------+------------------------------------------
 user_id    | integer                     |           | not null | nextval('account_user_id_seq'::regclass)
 username   | character varying(50)       |           | not null | 
 password   | character varying(50)       |           | not null | 
 email      | character varying(355)      |           | not null | 
 created_on | timestamp without time zone |           | not null | 
 last_login | timestamp without time zone |           |          | 
Indexes:
    "account_pkey" PRIMARY KEY, btree (user_id)
    "account_email_key" UNIQUE CONSTRAINT, btree (email)
    "account_username_key" UNIQUE CONSTRAINT, btree (username)
    
sql > \q;

# exit ssh
exit
```

本記事の利用ソースコードはこちら
[https://github.com/dssolutioninc/dss_gke/tree/master/persistentvolume](https://github.com/dssolutioninc/dss_gke/tree/master/persistentvolume)

 

最後まで読んで頂き、どうも有難う御座います!
DSS 橋本

関連記事[GKE上にNFSを構築する方法](https://qiita.com/dss_hashimoto/items/dbcafb54f6789280036a)