LoginSignup
91
51

More than 3 years have passed since last update.

hostPathとlocalのPersistentVolumeの違い

Last updated at Posted at 2018-12-29

PodにPersistentVolmueをマウントしたいとき、特にオンプレのKubernetesで、都合のいいNFSサーバーがなかったりすると、ノード上のローカルのファイルシステムをマウントしたいことがあります。その場合hostPathが使えますが、localというのもあります。違いがよくわからなかったので調べたメモです。

VolumeとPersistentVolume

わかりにくいですが、VolumeとPersistentVolumeは別です。VolumeとしてのhostPathと、PersistentVolumeとしてのhostPathがあります。

localについては、その説明がVolumeページにあるので混乱しますが、VolumeではなくPersistentVolumeです。以下のAPIドキュメントを確認すると、localというPesistentVolumeはありますが、localというVolumeはないことが確認できます。

hostPath(Volume)

hostPathのVolumeをPodのSpecに直接定義してコンテナにマウントできます。

mypod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
  - name: liberty
    image: websphere-liberty:18.0.0.4-kernel
    volumeMounts:
    - mountPath: /logs
      name: my-volume
  volumes:
  - name: my-volume
    hostPath:
      path: /data

単純なPodではなくDeployment等から管理されるPodの場合、PodのSpecは基本的には同じになるので、上記のようなPodTemplateを書いたとすると、各Podはスケジュールされたノードの/dataをマウントします。PodはnodeSelector等で指定していなければどのノードで稼働するかわかりません。また、1つのノードで複数のPodが稼働すると、同じhostPathをマウントしてしまいます。このためhostPathのVolumeをマウントしても問題がない状況はかなり限定されます。

hostPathのVolumeと相性がよいのは、各ノードで1つのみPodが稼働することが保証されるDaemonSetの場合です。IBM Cloud Privateの実装をみても、DaemonSetとして稼働しているコンテナからhostPathのVolumeをマウントしているケースが多くあります。

(補足)
以下のPersistentVolumeの場合も同様ですが、ノード上の/dataディレクトリーには適切な権限が必要です。上記のLibertyコンテナの場合は1001のUIDで起動するのでchown 1001:0 /dataしてあげる必要があります。

hostPath(PersistentVolume)

PersistentVolumeとしてhostPathはAPIドキュメントに以下のように記載されており、シングルノード環境でのテスト用としてのみ使うように記載されています。VolumeとしてのhostPathのAPIドキュメントにはこのような記載はありません。

This is useful for single-node development and testing only! On-host storage is not supported in any way and WILL NOT WORK in a multi-node cluster.

以下のようにhostPathのPersistentVolumeを定義できます。

my-pv-hostpath.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
  name: my-pv-hostpath
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  hostPath:
    path: /data
my-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: manual
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi

コンテナからはPersistentVolumeClaimをマウントします。

mypod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
  - name: liberty
    image: websphere-liberty:18.0.0.4-kernel
    volumeMounts:
    - mountPath: /logs
      name: my-volume
  volumes:
  - name: my-volume
    persistentVolumeClaim:
      claimName: my-pvc

単純なPodではなくDeployment/DaemonSetから管理されるPodの場合、全てのPodのSpecは基本的には同じになるので、上記のようなPodTemplateを書いたとすると、各Podが同じPersistentVolumeClaimをマウントしようとしてしまいます。しかしhostPathReadOnlyManyReadWriteManyサポートしていないため問題がありそうです(同じノード上で稼働する複数のPodからマウントするのもOKかもしれません)。このためDeploymentの場合はレプリカ数1でしか使えません。StatufulSetの場合はPersistentVolumeClaimTemplateを使ってPod毎に異なるPersistentVolumeClaimを定義できるので、各Podに異なるPersistentVolumeをアサインできます。

local

localはVolumeではなくPersistentVolumeです。hostPathとの違いはなんでしょうか。ドキュメントによると、hostPathと比べると、Node Affinityを使ってボリュームが実際に存在するノードを指定できるので、Podを手動でスケジュールする必要がないことが書かれています。

Compared to hostPath volumes, local volumes can be used in a durable and portable manner without manually scheduling Pods to nodes, as the system is aware of the volume’s node constraints by looking at the node affinity on the PersistentVolume.

試してみたところ、PersistentVolumeであればlocalだけでなくhostPathでもnfsでもNode Affinityは設定でき機能したので、上記の"Compared to hostPath volumes"という部分は、PersistentVolumeのhostPathではなくVolumeのhostPathを指しているように思われます。

localの場合はNode Affintyの設定が必要です。設定していないと下記のように怒られます。

$ kubectl apply -f pv-local-test.yaml
The PersistentVolume "my-pv-local-test" is invalid: metadata.annotations: Required value: Local volume requires node affinity
$

ただし、Node Affinityで例えば以下のように全てのノードにマッチするような表現を書くことも可能です。

  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: Exists

機能的にはNode Affinityの設定が必須であるくらいしか差異はなさそうですが、PersistentVolumeのhostPathはマルチノードがサポートされていないことが明確に書かれています。localのほうはv1.10からのBetaフィーチャーですが、以下のドキュメントに書かれているように、hostPathが持つ課題を解決するための新しい機能であり、精力的に開発がされているようなので、基本的にはこちらを使うべきと思います。

IBM Cloud Privateでの実装をみてみると、ローカルにデータを持つためにStatefulSetとして稼働しているコンテナからPersistentVolumeマウントする場合は、localのPersistentVolumeをマウントしています。

localのPersistentVolumeは以下のように使います。

my-pv-local.yaml
kind: PersistentVolume
apiVersion: v1
metadata:
  name: my-pv-local
spec:
  storageClassName: manual
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  local:
    path: /data
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - node1
my-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: my-pvc
spec:
  storageClassName: manual
  accessModes:
  - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
mypod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: mypod
spec:
  containers:
  - name: liberty
    image: websphere-liberty:18.0.0.4-kernel
    volumeMounts:
    - mountPath: /logs
      name: my-volume
  volumes:
  - name: my-volume
    persistentVolumeClaim:
      claimName: my-pvc

単純なPodではない場合、PersistentVolumeのhostPathの場合と同じく、レプリカ数1のDeploymentか、StatufulSetから使用する必要があります。

まとめ

PersistentVolumeとしてのhostPathlocalには明確な機能的な違いはなさそうですが、localはBetaフィーチャー(追記:1.14でGAとなりました)である一方、hostPathはマルチノード環境ではサポートされていないことが書かれています。利用方法についてまとめると以下です。

リソースタイプ ボリュームタイプ VolumeNodeAffinity 主な利用方法
Volume hostPath N/A DaemonSetを構成するPodから使う
PersistentVolume hostPath 設定可能 シングルノード環境でテスト目的でのみ使う
PersistentVolume local 設定必須 StatefulSetを構成するPodから使う

参考

91
51
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
91
51