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

#はじめに
今回はPersistentVolume（PV）のパラメータの「Reclaim Policy」の動作を確認してみたいと思います。Reclaim PolicyはPVを利用し終わった後の処理を指定します。
Reclaim Policyには以下の3つがあります。

|Reclaim Policy|概要
|:---|:---
|Delete|PVの実体を削除する。
|Retain|PVの実体を保持する。
|Recycle|PVのデータを削除し、再利用可能な状態にする。

#Delete
まずはDeleteの動作を確認します。

##環境準備

以下のPV/PVC/Podのマニフェストをapplyします。

```pv-delete.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-delete-0001
spec:
  capacity:
    storage: 500Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /share
    server: k8s-client
```

```pvc-delete01.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim-dlt01
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Mi
  storageClassName: slow
```

```nginx-delete01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-dlt01
spec:
  containers:
  - image: nginx:latest
    name: nginx-dlt01
    volumeMounts:
    - mountPath: /cache
      name: cache-pv01
  volumes:
  - name: cache-pv01
    persistentVolumeClaim:
      claimName: claim-dlt01
```


```
$ kubectl apply -f pv-delete.yaml
persistentvolume/pv-delete-0001 created
$ kubectl apply -f pvc-delete01.yaml
persistentvolumeclaim/claim-dlt01 created
$ kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-delete-0001   500Mi      RWX            Delete           Bound    default/claim-dlt01   slow                    2m40s
$ kubectl get pvc
NAME          STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-dlt01   Bound    pv-delete-0001   500Mi      RWX            slow           9s
$ kubectl apply -f nginx-delete01.yaml
pod/nginx-dlt01 created
```

##動作確認
PodのPVの領域にファイルを作って書き込みます。

```
$ kubectl exec -it nginx-dlt01 /bin/bash
root@nginx-dlt01:/# echo `hostname` > /cache/testfile
root@nginx-dlt01:/# cat /cache/testfile
nginx-dlt01
root@nginx-dlt01:/# exit
exit
```

###Podの削除
Podだけ削除して、再作成してみます。

```
$ kubectl delete -f nginx-delete01.yaml
pod "nginx-dlt01" deleted
$ kubectl apply -f nginx-delete01.yaml
pod/nginx-dlt01 created
$ kubectl exec -it nginx-dlt01 cat /cache/testfile
nginx-dlt01
```
Podを再作成しても、PVに書き込んだファイルは残ってますね。

###PVCの削除
今度はPVCまで削除してみます。

```
$ kubectl delete -f nginx-delete01.yaml
pod "nginx-dlt01" deleted
$ kubectl delete -f pvc-delete01.yaml
persistentvolumeclaim "claim-dlt01" deleted
$ kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-delete-0001   500Mi      RWX            Delete           Failed   default/claim-dlt01   slow                    16m
```

PVのSTATUSが「Failed」になりました。

このときのNFS Server側でファイルを確認してみます。

```
[k8s-client ~]$ cat /share/testfile
nginx-dlt01
```
ファイルは残ってますね。

ここでPVCを再作成してみます。

```
$ kubectl apply -f pvc-delete01.yaml
persistentvolumeclaim/claim-dlt01 created
$ kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-delete-0001   500Mi      RWX            Delete           Failed   default/claim-dlt01   slow                    18m
$ kubectl get pvc
NAME          STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-dlt01   Pending                                      slow           11s
$ kubectl describe pvc claim-dlt01
Name:          claim-dlt01
・・・
Events:
  Type     Reason              Age                From                         Message
  ----     ------              ----               ----                         -------
  Warning  ProvisioningFailed  11s (x3 over 30s)  persistentvolume-controller  storageclass.storage.k8s.io "slow" not found
```

PVCの再作成はできましたが、Pendingの状態ですね。

###PVの削除
今度はPVまで削除してみたいと思います。

```
$ kubectl delete -f nginx-delete01.yaml
pod "nginx-dlt01" deleted
$ kubectl delete -f pvc-delete01.yaml
persistentvolumeclaim "claim-dlt01" deleted
$ kubectl delete -f pv-delete.yaml
persistentvolume "pv-delete-0001" deleted
```
再作成します。

```
$ kubectl apply -f pv-delete.yaml
persistentvolume/pv-delete-0001 created
$ kubectl apply -f pvc-delete01.yaml
persistentvolumeclaim/claim-dlt01 created
$ kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-delete-0001   500Mi      RWX            Delete           Bound    default/claim-dlt01   slow                    30s
$ kubectl get pvc
NAME          STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-dlt01   Bound    pv-delete-0001   500Mi      RWX            slow           15s
$ kubectl apply -f nginx-delete01.yaml
pod/nginx-dlt01 created
```
PVの領域を確認します。

```
$ kubectl exec -it nginx-dlt01 cat /cache/testfile
nginx-dlt01
```
残ってますね。

マニュアルには以下のように記載されています。

>AWS EBS、GCE PD、Azure Disk、もしくはOpenStack Cinderボリュームに関連するストレージアセットを削除

確かにNFSだと実体のファイルシステムを削除されても困ると思いますので、NFSだとこういう動作になるのかもしれないですね。
AWSなどで確認する機会ができたら、確認してみたいと思います。


#Retain
次にRetainの動作を確認します。

##環境準備
以下のマニフェストのPV/PVC/Podをapplyします。

```pv-retain01.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-retain-0001
spec:
  capacity:
    storage: 500Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Retain
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /share
    server: k8s-client
```
```pvc-retain01.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim-rtn01
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Mi
  storageClassName: slow
```
```nginx-retain01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-rtn01
spec:
  containers:
  - image: nginx:latest
    name: nginx-rtn01
    volumeMounts:
    - mountPath: /cache
      name: cache-pv01
  volumes:
  - name: cache-pv01
    persistentVolumeClaim:
      claimName: claim-rtn01
```
```
$ kubectl apply -f pv-retain01.yaml
persistentvolume/pv-retain-0001 created
$ kubectl apply -f pvc-retain01.yaml
persistentvolumeclaim/claim-rtn01 created
$ kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-retain-0001   500Mi      RWX            Retain           Bound    default/claim-rtn01   slow                    13s
$ kubectl get pvc
NAME          STATUS   VOLUME           CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-rtn01   Bound    pv-retain-0001   500Mi      RWX            slow           9s
$ kubectl apply -f nginx-retain01.yaml
pod/nginx-rtn01 created
```

##動作確認

同様にPodのPVの領域にファイルを作って書き込んでおきます。

```
$ kubectl exec -it nginx-rtn01 cat /cache/testfile
nginx-rtn01
```

###PVCの削除
PodとPVCを削除してみます。

```
$ kubectl delete -f nginx-retain01.yaml
pod "nginx-rtn01" deleted
$ kubectl delete -f pvc-retain01.yaml
persistentvolumeclaim "claim-rtn01" deleted
$ kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                 STORAGECLASS   REASON   AGE
pv-retain-0001   500Mi      RWX            Retain           Released   default/claim-rtn01   slow                    10m
```
STATUSが「Released」となりました。

なお、この時NFS Server側では、作成したファイルは保持されています。

```
[k8s-client ~]$ cat /share/testfile
nginx-rtn01
```

---

PVCを再作成してみます。

```
$ kubectl apply -f pvc-retain01.yaml
persistentvolumeclaim/claim-rtn01 created
$ kubectl get pv
NAME             CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                 STORAGECLASS   REASON   AGE
pv-retain-0001   500Mi      RWX            Retain           Released   default/claim-rtn01   slow                    12m
$ kubectl get pvc
NAME          STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-rtn01   Pending                                      slow           10s
$ kubectl describe pvc claim-rtn01
Name:          claim-rtn01
・・・
Events:
  Type     Reason              Age               From                         Message
  ----     ------              ----              ----                         -------
  Warning  ProvisioningFailed  9s (x4 over 46s)  persistentvolume-controller  storageclass.storage.k8s.io "slow" not found
```

PVのSTATUSは「Released」のままで、PVCがPendingになってますね。

###PVの削除
PVまで削除し、PV/PVCを再作成することで、保持されているPVおよびファイルを再利用することができます。
RetainはPVの利用が終わった後（PVCを削除した後）にPVの実体を保持しますが、そのPVを再度利用する際は、PVを再作成する必要があります。

#Recycle
最後にRecycleの動作を確認します。

##環境準備

以下のマニフェストのPV/PVC/Podをapplyします。

```pv-recycle01.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-recycle-0001
spec:
  capacity:
    storage: 500Mi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteMany
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /share
    server: k8s-client
```

```pvc-recycle01.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: claim-rcc01
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 500Mi
  storageClassName: slow
```

```nginx-recycle01.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-rcc01
spec:
  containers:
  - image: nginx:latest
    name: nginx-rcc01
    volumeMounts:
    - mountPath: /cache
      name: cache-pv01
  volumes:
  - name: cache-pv01
    persistentVolumeClaim:
      claimName: claim-rcc01
```

```
$ kubectl get pv
NAME              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-recycle-0001   500Mi      RWX            Recycle          Bound    default/claim-rcc01   slow                    13s
$ kubectl get pvc
NAME          STATUS   VOLUME            CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-rcc01   Bound    pv-recycle-0001   500Mi      RWX            slow           7s
$ kubectl get pod
NAME                  READY   STATUS      RESTARTS   AGE
nginx-rcc01           1/1     Running     0          3m6s
```

##動作確認
同様にPodのPVの領域にファイルを作って書き込んでおきます。

```
$ kubectl exec -it nginx-rcc01 cat /cache/testfile
nginx-rcc01
```

##PVCの削除
PodとPVCを削除してみます。

```
$ kubectl delete -f nginx-recycle01.yaml
pod "nginx-rcc01" deleted
$ kubectl delete -f pvc-recycle01.yaml
persistentvolumeclaim "claim-rcc01" deleted
$ kubectl get pv
NAME              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
pv-recycle-0001   500Mi      RWX            Recycle          Available           slow                    8m21s
```

DeleteやRetainと違って、STATUSが「Available」に戻ってますね。

この時のNFS Server側のファイルを確認します。

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

PVのSTATUSが「Available」ですので、PVを再作成しなくてもPVCを再設定できます。

```
$ kubectl apply -f pvc-recycle01.yaml
persistentvolumeclaim/claim-rcc01 created
$ kubectl get pv
NAME              CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                 STORAGECLASS   REASON   AGE
pv-recycle-0001   500Mi      RWX            Recycle          Bound    default/claim-rcc01   slow                    12m
$ kubectl get pvc
NAME          STATUS   VOLUME            CAPACITY   ACCESS MODES   STORAGECLASS   AGE
claim-rcc01   Bound    pv-recycle-0001   500Mi      RWX            slow           8s
```

#まとめ
Deleteは想定した動きにはなりませんでしたが、Reclaim Policyの動きをまとめると以下になります。

##PVCを削除したとき

||Delete|Retain|Recycle
|:---|:---|:---|:---
|PV中のファイル|削除される※|保持される|削除される
|PV|削除される※|保持される|保持される
|PVの実体|削除される※|保持される|保持される

※Deleteは今回の検証では違う動き。本やマニュアルを見るとこうなる模様。

##PVを再利用するとき

||Delete|Retain|Recycle
|:---|:---|:---|:---
|PVC|再設定|再設定|再設定
|PV|再設定|再設定|再設定不要
|PVの実体|再設定？|再設定不要|再設定不要