LoginSignup
69
43

More than 5 years have passed since last update.

Kubernetes: Local Volumeの検証

Last updated at Posted at 2018-06-25

Kubernetes Local Volume の概要

 Kubernetesではv1.10からBetaとしてLocal Volumeがサポートされました。Local Volumeとは、KubernetesのNodeのサーバ内蔵ディスク(SSD含む)をPodから利用する機能です。これにより、Podが削除されても、データを削除することなくNodeのサーバ内蔵ディスクに、データを保存し続けることが可能となります。
 外部ストレージを準備できない環境や、内蔵ディスクに余力がある方は使ってみると良いかと思います。ただし、あくまで内蔵ディスクですので、外部ストレージと異なりRAIDやErasure Codingなどのデータ保護は出来ませんので、Node障害でデータが消えてしまったり、アクセスできなくなって困るようなデータの格納には向かないので注意してください。
 Kubernetes v1.10での制限としては、StatefulSetなどと一緒に用いることの多いPod生成時に自動でVolumeを生成してくれる機能Dynamic Provisioningが非サポートとなっています。その代わり、Dynamic Provisioningほど強力ではありませんが、実際にPodにVolumeが割り当てられるまでVolumeを使用しないようにする設定が可能です。

検証

検証環境

  • Kubernetes環境: Kubernetes v1.10.5 (kubeadmを使いVirtual Box上に構築したMaster, WorkerNode x 2VMの合計3VMのクラスタ環境)

Local Volumeの準備

はじめに workerノード(k8s-node1)に、sshでログインし、local volumeとして利用するディレクトリを作成します。
今回は、k8s-node1のLocal Volumeのみ割り当てます。

$ kubectl get node
NAME        STATUS    ROLES     AGE       VERSION
k8s         Ready     master    56d       v1.10.5
k8s-node1   Ready     <none>    56d       v1.10.5
k8s-node2   Ready     <none>    56d       v1.10.5
$ ssh k8s-node1
$ sudo mkdir -p /mnt/disks/vol1
$ sudo chmod 777 /mnt/disks/vol1
$ exit

StorageClass の定義

次に、Local Volumeに対応したStorageClassをsc-lv.yamlファイルに定義します。

sc-lv.yaml
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer
  • provisionerは、Dynamic Provisioningが非サポートとのため、kubernetes.io/no-provisionerを指定します。
  • volumeBindingModeは、WaitForFirstConsumerを設定することで、実際にPodにVolumeが割り当てられるまでVolumeを使用しないようになります。

StorageClass のデプロイ

kubectlを使ってStorageClassをデプロイします。

$ kubectl create -f sc-lv.yaml 
storageclass.storage.k8s.io "local-storage" created

StorageClassがデプロイされていることを確認します。

$ kubectl get sc        
NAME            PROVISIONER                    AGE
local-storage   kubernetes.io/no-provisioner   1m

PersistentVolume の定義

続いて、PersistenvVolumeをpv-lv.yamlファイルに定義します。

pv-lv.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: local-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  local:
    path: /mnt/disks/vol1
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-node1
  • spec.accessModesは、Local Volumeは他のPodから共有で利用することが出来ず、1つのPodからしかRead/Writeができないため、ReadWriteOnceを指定します。
  • persistentVolumeReclaimPolicyは、PersistentVolumeClaimが削除された時にデータ削除のポリシーを指定できます。Local Volumeの場合はRetainを指定してください。persistentVolumeReclaimPolicy にはデータを削除するRecycle、Volumeを同時に削除するDeleteが指定可能です。しかし、Recycleはデータを削除するのであれば、そもそもLocal Volumeを使う理由がありませんし、DeleteはDynamic Provisioningが非サポートのため、指定してもPersistentVolumeClaimされるとPersistetVolumeのステータスがFAILになります。
  • storageClassNameは、先ほどデプロイしたStorageClassのnameのlocal-storageを指定します
  • spec.local.pathは、Local Volumeの準備で作成したディレクトリ/mnt/disks/vol1を指定します。
  • nodeAffinityは、どのNodeを使うかの条件を指定します。今回は、Nodeのk8s-node1のみ選択されるようにkubernetes.io/hostnameをキーとして指定しています。

PersistentVolume のデプロイ

kubectlを使ってPersistentVolumeをデプロイします。

$ kubectl create -f pv-lv.yaml
persistentvolume "local-pv" created

PersistentVolumeがデプロイされていることを確認します。

$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM     STORAGECLASS    REASON    AGE
local-pv   1Gi        RWO            Retain           Available             local-storage             29s

PersistentVolumeClaim の定義

次に、ユーザがVolumeを要求するための定義PersistentVolumeClaimをpvc-lv.yamlファイルに定義します。

pvc-lv.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: local-claim
spec:
  accessModes:
  - ReadWriteOnce
  storageClassName: local-storage
  resources:
    requests:
      storage: 1Gi
  • spec.storageClassName には、先に定義したStorageClassのnameであるlocal-storageを指定します。

PersistentVolumeClaim のデプロイ

kubectlを使ってPersistentVolumeClaimをデプロイします。

$ kubectl create -f pvc-lv.yaml 
persistentvolumeclaim "local-claim" created

PersistentVolumeClameがデプロイされていることを確認します。
この段階では、STATUSはPendingとなります。

$ kubectl get pvc
NAME          STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS    AGE
local-claim   Pending                                       local-storage   52s

Local Volumeを使ったPodの定義

定義したPersistentVolumeClaimのlocal-claimを使い、PodへLocal Volumeを割り当てます。
ここでは、nginx-lv.yamlとしてPodを定義します。

nginx-lv.yaml
apiVersion: v1
kind: Pod
metadata:
  name: my-nginx-pod
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 80
    volumeMounts:
    - mountPath: "/usr/share/nginx/html"
      name: mydata
  volumes:
    - name: mydata
      persistentVolumeClaim:
        claimName: local-claim
  • spec.containers.volumeMounts.mountPathに、Pod内のLocal Volumeのマウント先を指定します。
  • spec.volumes.persistentVolumeClaimに、先に定義したPersistentVolumeClaimのnameであるlocal-claimを指定します。

Local Volumeを使ったPodのデプロイ

kubectlを使ってLocal Volumeを使ったPodをデプロイします。

$ kubectl create -f nginx-lv.yaml 
pod "my-nginx-pod" created

Local Volumeを使ったPodがデプロイされていることを確認します。
このPodがPersistentVolumeClaimを経由しPersistentVolumeをマウントした段階で、PersistentVolumeClaimのSTATUSがBoundに変わります。
さらに、そのPersistentVolumeClaimから選出されたPersistentVolumeのSTATUSがBoundに変わり、CLAIMにdefault/local-claimが設定されます。
つまり、StorageClassにて定義したvolumeBindingModeのWaitForFirstConsumerの指定通り、PodがLocal Volumeをマウントした際に、初めてPersistentVolumeが使用され始めます。

$ kubectl get pvc
NAME          STATUS    VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS    AGE
local-claim   Bound     local-pv   1Gi        RWO            local-storage   3m
$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS    CLAIM                 STORAGECLASS    REASON    AGE
local-pv   1Gi        RWO            Retain           Bound     default/local-claim   local-storage             5m

クリーンアップ

デプロイしたPod, PersistentVolumeClaimを削除します。

$ kubectl delete -f nginx-lv.yaml 
pod "my-nginx-pod" deleted
$ kubectl delete -f pvc-lv.yaml 
persistentvolumeclaim "local-claim" deleted

PersistentVolumeClaimを削除したことで、PersistentVolumeのSTAUTSがReleasedに変わります。

$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS     CLAIM                 STORAGECLASS    REASON    AGE
local-pv   1Gi        RWO            Retain           Released   default/local-claim   local-storage             6m

続いて、PersistentVolumeとStorageClassを削除します。

$ kubectl delete -f pv-lv.yaml 
persistentvolume "local-pv" deleted
$ kubectl delete -f sc-lv.yaml 
storageclass.storage.k8s.io "local-storage" deleted

最後に、K8s-node1のNodeにsshでログインし、/mnt/disksディレクトリ配下を削除します。

$ ssh k8s-node1
$ cd /mnt
$ sudo rm -rf disks/
$ exit

まとめ

 今回、Local Volumeを検証しました。Local Volumeは、データの重要性は低いが、Podと一緒に削除されて欲しくない、そういうデータを保存するのに向いています。そういうケースはなんでしょうか?たとえば、データベースのSlaveノードなどには向いているかと思います。Slaveノードは、Masterノードが生きていれば、Slaveノードのデータは障害などでデータが削除したとしても復旧可能です。また、Slaveノードがバージョンアップによるローリングアップデートなどで再作成する場合には、データは保持されたままなので、MasterとSlave間の同期は短時間で完了します。
 その他、Local Volumeのユースケースはなにかあるでしょうか?感の良い人ならば思いつくかと思います。Kubernetesに対応していないレガシーの外部ストレージを利用するのに利用できます。つまり、レガシーの外部ストレージのVolumeをNodeにマウントし、そのマウントしたVolumeを、今回紹介したLocal Volumeとして利用します。これにより、レガシーの外部ストレージのVolumeをPodで使用することが可能となります。ただし、Nodeのサーバに外部ストレージのVolumeを割り当てないといけないため、管理者の負担は増えてしまいます。レガシーの外部ストレージをPod(コンテナ)で利用する場合の奥の手として持っておくのには、有効な方法かと思います。

参考情報

69
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
69
43