[Kubernetes]PersistentVolume/PersistentVolumeClaimの動作を確認する 1

#はじめに
今回はPersistentVolume（PV）とPersistentVolumeClaim（PVC）の動作を確認してみたいと思います。
[前回](https://qiita.com/dingtianhongjie/items/cead36bedffbd57ce100)確認したVolumeは、workerノードのファイルシステムやConfigMapなどのリソースをコンテナ上で利用するものでしたが、PVはリソースとしてあらかじめ作成して、それをコンテナ上で利用するものです。

#PVの作成
PVとして利用できるものにはNFSやiSCSIなどお馴染？のものから、Cephやクラウドサービスのリソースなどいろいろとあります。今回は環境の都合上、NFSを使用します。

>[永続ボリュームの種類](https://kubernetes.io/ja/docs/concepts/storage/persistent-volumes/#%e6%b0%b8%e7%b6%9a%e3%83%9c%e3%83%aa%e3%83%a5%e3%83%bc%e3%83%a0%e3%81%ae%e7%a8%ae%e9%a1%9e)

以下のマニフェストを作成して、applyします。

```PV.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 500Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /share
    server: k8s-client
```
```
$ kubectl apply -f PV.yaml
persistentvolume/pv0003 created
$ kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv0003   500Mi      RWX            Recycle          Available           slow                    14m
```

##PVのパラメータ
|パラメータ|概要
|:---|:---
|capacity|ストレージの容量を指定します。現在設定できるのはストレージサイズのみですが、将来的にはIOPS、スループットなどが含まれます。
|volumeMode|ブロックデバイスを使用する場合は「block」、ファイルシステムを使用する場合は「filesystem」を指定します。デフォルト値は「filesystem」です。
|accessModes|「ReadWriteOnce」「ReadOnlyMany」「ReadWriteMany 」の三種類があります。Once/Manyは1回/複数ではなく、「単一ノード/複数ノード」の意味で、ReadWriteOnceであれば、「単一ノードからRead/Write可能」となります。また、PVの種類によって設定できるモードが異なります。
|persistentVolumeReclaimPolicy|PVの利用が終わった後の処理を指定します。（削除/保持など）
|storageClassName|マニュアルを読んでもよくわからず
|mountOptions|PVの種類に応じてマウントオプションを指定します。今回は別サーバ（k8s-client）の/shareをNFSであらかじめShareしています。

>[永続ボリューム](https://kubernetes.io/ja/docs/concepts/storage/persistent-volumes/#%e6%b0%b8%e7%b6%9a%e3%83%9c%e3%83%aa%e3%83%a5%e3%83%bc%e3%83%a0)

#PVCの設定
PVを作成したら、PVCを設定します。PVを利用する際は、PVを直接Podのマニフェストなどで指定するのではなく、PVCを経由して利用します。

以下のマニフェストを作成しました。
PVCは「このPV」とPV名を指定するのではなく、「こういうPV」とスペックを指定して、それに該当するPVを割り当てる動作になります。

```PVC.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Mi
  storageClassName: slow
```

このマニフェストをapplyして確認します。

```
$ kubectl apply -f PVC.yaml
persistentvolumeclaim/myclaim created
$ kubectl get pvc
NAME      STATUS   VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
myclaim   Bound    pv0003   500Mi      RWX            slow           6s
$ kubectl get pv
NAME     CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM             STORAGECLASS   REASON   AGE
pv0003   500Mi      RWX            Recycle          Bound    default/myclaim   slow                    31m
```

pv0003がmyclaimに割り当てられていることが確認できます。

#Podでの利用
ここまで準備ができて、PodでPVを利用できるようになります。
以下のマニフェストをapplyして動作を確認します。

```nginx-dep.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-dep
spec:
  replicas: 4
  selector:
    matchLabels:
      app: nginx-dep
  template:
    metadata:
      labels:
        app: nginx-dep
    spec:
      containers:
      - image: nginx:latest
        name: nginx-container
        volumeMounts:
        - mountPath: /cache
          name: cache-pv
      volumes:
      - name: cache-pv
        persistentVolumeClaim:
          claimName: myclaim
          readOnly: false
```

```
$ kubectl apply -f nginx-dep.yaml
deployment.apps/nginx-dep created
$ kubectl exec -it nginx-dep-54b4455fbd-7pqjw /bin/bash
root@nginx-dep-54b4455fbd-7pqjw:/# df -h
Filesystem               Size  Used Avail Use% Mounted on
overlay                   17G  6.1G   11G  36% /
tmpfs                     64M     0   64M   0% /dev
tmpfs                    1.4G     0  1.4G   0% /sys/fs/cgroup
k8s-client:/share        8.0G  5.1G  3.0G  63% /cache
/dev/mapper/centos-root   17G  6.1G   11G  36% /etc/hosts
shm                       64M     0   64M   0% /dev/shm
tmpfs                    1.4G   12K  1.4G   1% /run/secrets/kubernetes.io/serviceaccount
tmpfs                    1.4G     0  1.4G   0% /proc/acpi
tmpfs                    1.4G     0  1.4G   0% /proc/scsi
tmpfs                    1.4G     0  1.4G   0% /sys/firmware
```

指定したマウントポイント（/cache）にPVで指定したファイルシステムがマウントされていますね。

##動作の確認
ファイルを作成したりして動作を確認してみたいと思います。

```
$ kubectl exec -it nginx-dep-54b4455fbd-7pqjw /bin/bash
root@nginx-dep-54b4455fbd-7pqjw:/# echo hello > /cache/testfile
root@nginx-dep-54b4455fbd-7pqjw:/# exit
exit
$ kubectl exec -it nginx-dep-54b4455fbd-vb6t2 /bin/bash
root@nginx-dep-54b4455fbd-vb6t2:/# echo nihao >> /cache/testfile
root@nginx-dep-54b4455fbd-vb6t2:/# exit
exit
$ kubectl exec -it nginx-dep-54b4455fbd-vhm7h cat /cache/testfile
hello
nihao
```

別々のコンテナからPV上のファイルシステムに対して、一つのファイルの編集/参照ができますね。

NFSサーバからも参照ができます。

```
[k8s-client ~]$ cat /share/testfile
hello
nihao
```
---

今度は指定した容量（500MiB）以上のファイル（1GiB）が作成できるかどうか確認してみます。

```
$ kubectl exec -it nginx-dep-54b4455fbd-7whcv /bin/bash
root@nginx-dep-54b4455fbd-7whcv:/# dd if=/dev/zero of=/cache/tmpfile2 bs=1M count=1024
1024+0 records in
1024+0 records out
1073741824 bytes (1.1 GB, 1.0 GiB) copied, 12.0081 s, 89.4 MB/s
root@nginx-dep-54b4455fbd-7whcv:/# ls -l /cache/tmpfile2
-rw-r--r--. 1 root root 1073741824 Apr 28 13:49 /cache/tmpfile2
```

あれ？作れちゃいましたね。
調べてみると、NFSだと制限が無視されるようです。。。

>また、通常のNFSなどではNFSの仕組み上Quotaがかかっておらず、PersistentVolume作成時の容量が実質無視されてしまう点にも注意が必要です。
>[KubernetesのConfig＆Storageリソース（その2）](https://thinkit.co.jp/article/14195?page=0%2C1)

---
最後にすべて削除してみます。

```
$ kubectl delete -f nginx-dep.yaml
deployment.apps "nginx-dep" deleted
$ kubectl delete -f PVC.yaml
persistentvolumeclaim "myclaim" deleted
$ kubectl delete -f PV.yaml
persistentvolume "pv0003" deleted
```

削除すると、コンテナから作成したファイルも削除されていますね。

```
[k8s-client ~]$ cat /share/testfile
cat: /share/testfile: そのようなファイルやディレクトリはありません
```

#まとめ
今回はPV/PVCの動作を確認しました。
正直、まだ「とりあえずできました」レベルで、マニュアルを見てもよくわからないところがあります。また、オプションも色々とありますので、これからPV/PVCの動作を細かく確認してみたいと思います。