KubernetesのPersistent VolumeでDynamic Provisioningを試してみる

## はじめに

以下の手順は、KubernetesのPersistent Volumeが提供するDynamic Provisioningの機能を試したメモです。
Dynamic Provisioningを使うことで、Persistent Volume Claimを作成した際に、自動的にPersistent Volumeが作成され、またPVCを削除した際にも自動的にPVが削除されるようになります。


今回はhostPathプラグイン(Provisioner)を利用して当機能の動作を検証してみます。なお、hostPath Provisionerは、1ノード構成のみでしか動作しない(クラスタ不可)テスト目的用のプラグインとのことです。

## ローカルクラスタの起動
詳細な起動方法は、「[Kubernetesをソースコードからビルドしてローカル環境にkubernetes clusterを構築する](http://qiita.com/mittjp1129/items/aaba9c93086e7d598121)」を参照してください。hostPath ProvisionerでDynamic Provisioningを有効にするために、ENABLE_HOSTPATH_PROVISIONERをtrueとしてクラスタを起動しておきます。

```bash
# export ENABLE_HOSTPATH_PROVISIONER=true; ./hack/local-up-cluster.sh
```

## StorageClassの作成
Dynamic Provisioningを利用するためには、Provisioner用のStorageClassを事前に定義しておく必要があります。ここでは、前述の通り、hostPath Provisionerを利用するため、provisionerに"kubernetes.io/host-path"を指定したStorageClassを作成します。

```bash
% cat provisioner.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: standard
  annotations:
    storageclass.beta.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/host-path

% kubectl.sh create -f provisioner.yaml
storageclass "standard" created

% kubectl.sh get pv,pvc,storageclasses,pod
NAME                 TYPE
standard (default)   kubernetes.io/host-path   
```
PVCの作成には以下の定義を使います。

```bash
%cat pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: nginx-pvc01
  annotations:
    volume.beta.kubernetes.io/storage-class: "standard"
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 10Mi
```
続けて、PVCを作成し、作成状況を確認します。

```bash
% kubectl.sh create -f pvc.yaml
persistentvolumeclaim "nginx-pvc01" created

% kubectl.sh get pv,pvc,storageclasses,pod
NAME                                          CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                 STORAGECLASS   REASON    AGE
pv/pvc-2e36c3bd-13ff-11e7-a430-5254001f644e   10Mi       RWX           Delete          Bound     default/nginx-pvc01   standard                 3s

NAME              STATUS    VOLUME                                     CAPACITY   ACCESSMODES   STORAGECLASS   AGE
pvc/nginx-pvc01   Bound     pvc-2e36c3bd-13ff-11e7-a430-5254001f644e   10Mi       RWX           standard       3s

NAME                 TYPE
standard (default)   kubernetes.io/host-path

% sudo ls -l /tmp/hostpath_pv
total 0
drwxr-x--- 2 root root 40 Mar 28 17:40 2e389a13-13ff-11e7-983d-5254001f644e

```
pvc-2e36c3bd-13ff-11e7-a430-5254001f644eというPVが自動的に作成され、PVCにBoundされました。なお、hostPath用のディスク領域(PV名のフォルダ)は、ホストサーバーの/tmp/hostpath_pv以下に確保されるようになっています。

次に、このPVCをPodに割り当ててみます。

```bash
% kubectl.sh create -f nginx.yaml
pod "nginx-pod" created
% kubectl.sh get pv,pvc,storageclasses,pod
NAME                                          CAPACITY   ACCESSMODES   RECLAIMPOLICY   STATUS    CLAIM                 STORAGECLASS   REASON    AGE
pv/pvc-2e36c3bd-13ff-11e7-a430-5254001f644e   10Mi       RWX           Delete          Bound     default/nginx-pvc01   standard                 9m

NAME              STATUS    VOLUME                                     CAPACITY   ACCESSMODES   STORAGECLASS   AGE
pvc/nginx-pvc01   Bound     pvc-2e36c3bd-13ff-11e7-a430-5254001f644e   10Mi       RWX           standard       9m

NAME                 TYPE
standard (default)   kubernetes.io/host-path   

NAME           READY     STATUS    RESTARTS   AGE
po/nginx-pod   1/1       Running   0          4s

% kubectl.sh exec -it nginx-pod bash
root@nginx-pod:/# df -h
Filesystem                                                                                         Size  Used Avail Use% Mounted on
/dev/mapper/docker-253:0-1967460-9eab3d731c29da92924b11b11aa8620c227a15b66c842e3ec20fe90cc7c5a368   10G  231M  9.8G   3% /
tmpfs                                                                                              7.9G     0  7.9G   0% /dev
tmpfs                                                                                              7.9G     0  7.9G   0% /sys/fs/cgroup
/dev/mapper/fedora_dhcp--17--34-root                                                                49G   16G   31G  34% /etc/hosts
shm                                                                                                 64M     0   64M   0% /dev/shm
tmpfs                                                                                              7.9G  127M  7.8G   2% /usr/share/nginx/html
tmpfs                                                                                              7.9G   12K  7.9G   1% /run/secrets/kubernetes.io/serviceaccount

% kubectl.sh describe po/nginx-pod
Name:		nginx-pod
Namespace:	default
Node:		127.0.0.1/127.0.0.1
Start Time:	Tue, 28 Mar 2017 17:49:39 -0400
Labels:		<none>
Annotations:	<none>
Status:		Running
IP:		172.17.0.2
Controllers:	<none>
Containers:
  nginx-container:
    Container ID:	docker://34771096d1e95b3c6a1d1a9738feff29eec924355b93b90e0d4b34dec4c57951
    Image:		nginx
    Image ID:		docker-pullable://docker.io/nginx@sha256:52f84ace6ea43f2f58937e5f9fc562e99ad6876e82b99d171916c1ece587c188
    Port:		80/TCP
    State:		Running
      Started:		Tue, 28 Mar 2017 17:49:42 -0400
    Ready:		True
    Restart Count:	0
    Environment:	<none>
    Mounts:
      /usr/share/nginx/html from data (rw)
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-v46rn (ro)
Conditions:
  Type		Status
  Initialized 	True 
  Ready 	True 
  PodScheduled 	True 
Volumes:
  data:
    Type:	PersistentVolumeClaim (a reference to a PersistentVolumeClaim in the same namespace)
    ClaimName:	nginx-pvc01
    ReadOnly:	false
  default-token-v46rn:
    Type:	Secret (a volume populated by a Secret)
    SecretName:	default-token-v46rn
    Optional:	false
QoS Class:	BestEffort
Node-Selectors:	<none>
Tolerations:	node.alpha.kubernetes.io/notReady=:Exists:NoExecute for 300s
		node.alpha.kubernetes.io/unreachable=:Exists:NoExecute for 300s
Events:
  FirstSeen	LastSeen	Count	From			SubObjectPath				Type		Reason		Message
  ---------	--------	-----	----			-------------				--------	------		-------
  7m		7m		1	default-scheduler						Normal		Scheduled	Successfully assigned nginx-pod to 127.0.0.1
  7m		7m		1	kubelet, 127.0.0.1	spec.containers{nginx-container}	Normal		Pulling		pulling image "nginx"
  7m		7m		1	kubelet, 127.0.0.1	spec.containers{nginx-container}	Normal		Pulled		Successfully pulled image "nginx"
  7m		7m		1	kubelet, 127.0.0.1	spec.containers{nginx-container}	Normal		Created		Created container with id 34771096d1e95b3c6a1d1a9738feff29eec924355b93b90e0d4b34dec4c57951
  7m		7m		1	kubelet, 127.0.0.1	spec.containers{nginx-container}	Normal		Started		Started container with id 34771096d1e95b3c6a1d1a9738feff29eec924355b93b90e0d4b34dec4c57951
```
Podの/usr/share/nginx/htmlに、ホストの/tmp領域(tmpfs)がマウントされていることが確認できました。
この状態で、PVCを消してみます。(通常は、Podを削除してからが良いです)
PVCはPodにアタッチされている状態でも消すことが可能です。

```bash
% kubectl.sh delete -f pvc.yaml
persistentvolumeclaim "nginx-pvc01" deleted
% kubectl.sh get pv,pvc,storageclasses,pod
NAME                 TYPE
standard (default)   kubernetes.io/host-path   

NAME           READY     STATUS    RESTARTS   AGE
po/nginx-pod   1/1       Running   0          12m
```

PVCを削除すると、

-  紐付いているPVも自動的に削除される
-  ホストサーバー上に作成されていたPV用の/tmp/hostpath_pv/xxxのフォルダが削除される
-  Podからボリュームへアクセスできなくなる

といったボリュームのデタッチ処理が実行されることになります。