🐷

kubernetesのボリュームを調べる

2021/03/12に公開

はじめに

くーばねてすを倒すために今回はkubernetesのストレージを調べた!(^^)!

概要

■kubernetesのいろんなボリューム
■kubernetesで指定できる外部ボリューム例

■kubernetesクラスタ外にボリュームをあてることでなにができるか

をまとめた(^^)/

■kubernetesのいろんなボリューム

Kubernetes上のPodはざっくり分けると以下の3つの方法でデータをディスクに書き込むことができる。
pod内のディスクを利用
Pod内で一時的に利用可能なディスク領域を使用する方法。Podを削除すると保存されていたデータも一緒に削除されるため、データは永続化できない。
Nodeのディスクを利用
Podを動かしているKubernetes Nodeのディスク領域をPodにマウントする方法。Podを削除してもデータはNodeに残るため、データの永続化が可能です。しかし、 Pod が別ノードで動作した場合にはデータの再利用ができないデメリットがある。
外部ストレージを利用
コンテナを動かしているKubernetes Nodeとは別にiSCSIやNFS、クラウドプロバイダーの外部ストレージを利用する方法です。Podを削除してもデータは外部ストレージに残るため、データの永続化が可能です。また、Pod が別ノードで動作したとしてもデータが外部に存在するためデータの再利用が可能。

■kubernetesで指定できる外部ボリューム例

Kubernetes上のPodは以下の4タイプのオブジェクトを利用してKubernetesの外部ストレージの利用が可能だ。
Volume
Persistent Volume (PV)
Persistent Volume Claim (PVC)
Storage Class (SC)

Volume

Volume は予め用意されたボリュームをマニュフェストに直接指定することで利用可能となる。マニュフェストの特性上、Kubernetes 上で新規にボリュームを作成したり、既存のボリュームを削除することは出来ない。 Node 上の任意のパスでマウントすることができる。
https://kubernetes.io/docs/concepts/storage/volumes/#types-of-volumes
ボリューム例↓

emptyDir(pod内のディスクを利用)

Nodeのディスクを一時的に利用する仕組み。単一のpodのコンテナ間でボリュームを共有できるがその他のpodでは共有できない。podが終了するとボリュームも削除される。
マニフェスト例

emptyDir.yml
apiVersion: v1
kind: Pod
metadata:
  name: redis
spec:
  containers:
  - name: redis
    image: redis
    volumeMounts:
    - name: redis-storage
      mountPath: /data/redis
  volumes:
  - name: redis-storage
    emptyDir: {}

hostPass(Node内のディスクを利用)

emptyDirと同様Nodeのディスクを使用するが同一Node内であれば異なるpodでもボリュームを共有できる。異なるNodeのpodはボリュームを共有できない。またpodが終了してもボリュームは削除されない。Nodeが停止するとボリュームも削除される。hostPassは外部ストレージを用意できないときの簡易的手段として利用されたりする。
マニフェスト例

hostPath.yml
apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: k8s.gcr.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /test-pd
      name: test-volume
  volumes:
  - name: test-volume
    hostPath:
      # directory location on host
      path: /data
      # this field is optional
      type: Directory


|ディスク名|概要|
| --- | --- | --- |
|emptyDir|単一のpodでしか共有できない。podが終了するとボリュームも削除|
|hostPass|異なるpodでもボリュームを共有できる。Nodeが終了するとボリュームも削除|

PersistentVolume(PV)

PersistentVolume(以降 PV) は永続化領域として確保される Volume。
PV は個別にリソースを作成して利用する必要があり、 PersistentVolumeClaim(PVC)経由で利用する。
PVにはボリュームサイズやアクセスモードを指定することができる。
PersistentVolumeオブジェクトの名前は、有効な DNSサブドメイン名である必要がある。
マニフェスト例

persistentVolume.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2`

永続ボリュームの種類
PersistentVolumeの種類はプラグインとして実装されます。Kubernetesは現在次のプラグインに対応しています。
GCEPersistentDisk
AWSElasticBlockStore
AzureFile
AzureDisk
CSI
FC (Fibre Channel)
FlexVolume
Flocker
NFS
iSCSI
RBD (Ceph Block Device)
CephFS
Cinder (OpenStack block storage)
Glusterfs
VsphereVolume
Quobyte Volumes
HostPath (テスト用の単一ノードのみ。ローカルストレージはどのような方法でもサポートされておらず、またマルチノードクラスターでは動作しません)
Portworx Volumes
ScaleIO Volumes
StorageOS

PersistentVolumeClaim(PVC)

Claim(要求する)という意味の通り、作成された PV から利用請求するためのリソース。PV はクラスタにボリュームを登録するだけのオブジェクトなので Pod から利用する場合には PVC を定義する必要がある。
Dynamic プロビジョニングを行うことで事前に PV を作成せず、PVC が作成された際に動的に PV を作成する事ができる。
マニフェスト例

PersistentVolumeClaim.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 8Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

PersistentVolumeClaim(PVC)の拡大
PersistentVolumeClaim(PVC)の拡大はデフォルトで有効だ。次のボリュームの種類が指定することができる。
https://kubernetes.io/ja/docs/concepts/storage/persistent-volumes/
そのストレージクラスのallowVolumeExpansionフィールドがtrueとなっている場合のみ、PVCを拡大できる。

次のボリュームの種類で拡大できます。
gcePersistentDisk
awsElasticBlockStore
Cinder
glusterfs
rbd
Azure File
Azure Disk
Portworx
FlexVolumes
CSI

StorageClass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: gluster-vol-default
provisioner: kubernetes.io/glusterfs
parameters:
  resturl: "http://192.168.10.100:8080"
  restuser: ""
  secretNamespace: ""
  secretName: ""
allowVolumeExpansion: true

PVCオブジェクトを編集してより大きなサイズを指定することによりPersistentVolumeを受け持つ基盤にボリュームの拡大がトリガーされる。新規にPersistentVolumeが作成されることはなく代わりに既存のボリュームがリサイズされる。

Storage Class (SC)

このオブジェクトはプラグインを使い、メタデータを追加する。ストレージがバックエンドでどのように扱われるかを設定する。
https://kubernetes.io/ja/docs/concepts/storage/dynamic-provisioning/
Dynamic Provisioning
DynamicProvisioningを使用する際にはStorageClass のProvisionerにCSIに対応したCSI Volume Pluginを指定することでボリュームの作成・削除の自動化を実現できます
DynamicProvisioningなしで設定する場合、管理者はクラウドプロバイダーまたはストレージプロバイダーに対して新規のストレージ用のボリュームとPersistentVolumeオブジェクトを作成するように手動で指示しなければならない。
DynamicProvisioningの機能によって、管理者がストレージを事前にプロビジョンする必要がなくなり、ユーザーによってリクエストされたときに自動でストレージが作成される。

StorageClassマニフェスト例

StorageClass.yml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate

DynamicProvisioningを利用してストレージサービスを利用する例

■kubernetesクラスタ外にボリュームをあてることでなにができるか

永続的にボリュームを保存するだけでなく、各Nodeに外部ストレージへのアクセス経路を設定することで、Node停止時でもすべてのコンテナはボリュームを共有しているのでpodをほかのNodeに退避させることでコンテナの稼働状態を継続させることができる。(ボリュームの種類によって共有できないものもある)

まとめ

HostPathがVolumeとPersistentVolumeにあるのが謎(>_<)
ややこしいのでまだまだ調べる!

Discussion