こんにちは、ナナオです。
k8sを運用していて、永続ストレージが欲しくなるケース、ありますよね。
今回はそんな時に役立つ動的プロビジョニングを実施してみたいと思います。
動的プロビジョニングとは
k8sで永続ストレージを使用するには、PVとPVCを作成する必要があります。
PVはストレージの接続方法やディレクトリパスを指定するリソースで、PVCはストレージとデプロイメントやポッドを繋ぐためのインターフェースのような役割を果たすリソースです。
ただ、ストレージが必要になるたびに毎回PVを作ってPVCを作って…とするのは面倒です。
その手間を減らしてくれるのが動的プロビジョニングになります。
動的プロビジョニングでは、一度ストレージの接続方法とディレクトリパスを指定してあげれば、あとは勝手にそのディレクトリ内でPVを作ってPVCと紐づけてくれます。
実践
早速実践してみましょう。
動的プロビジョニングを行うために以下のツールをhelmを使用してインストールします。
helmは以下のコマンドでダウンロード可能です。
brew install helm
また、helmによるインストールの管理にはhelmfileというツールを使用します。
こちらもダウンロードはbrewコマンドで一発で行えます。
brew install helmfile
準備が整いました。
以下のようにプロビジョナーを設定します。
nfs:
server: 192.168.0.94
path: /k8s-data
storageClass:
name: nfs-client
defaultClass: true # デフォルトのストレージクラスにする
reclaimPolicy: Retain # PVC削除時にNASのデータを残すか(Retainなら残る)
先ほど実装したプロビジョナーの設定を参照するhelmfileを実装します。
repositories:
- name: nfs-subdir-external-provisioner
url: https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
releases:
- name: nfs-provisioner
namespace: kube-system
chart: nfs-subdir-external-provisioner/nfs-subdir-external-provisioner
version: 4.0.18
values:
- ./values/nfs-provisioner.yaml
実装したhelmfileを適用します。
helmfile apply -f helm/helmfile.yaml
実行したところエラーになりました。
❯ helmfile apply -f helm/helmfile.yaml
Adding repo nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
"nfs-subdir-external-provisioner" has been added to your repositories
Comparing release=nfs-provisioner, chart=nfs-subdir-external-provisioner/nfs-subdir-external-provisioner, namespace=kube-system
in helm/helmfile.yaml: command "/home/linuxbrew/.linuxbrew/bin/helm" exited with non-zero status:
PATH:
/home/linuxbrew/.linuxbrew/bin/helm
ARGS:
0: helm (4 bytes)
1: diff (4 bytes)
2: upgrade (7 bytes)
3: --allow-unreleased (18 bytes)
4: nfs-provisioner (15 bytes)
5: nfs-subdir-external-provisioner/nfs-subdir-external-provisioner (63 bytes)
6: --version (9 bytes)
7: 4.0.18 (6 bytes)
8: --kube-version (14 bytes)
9: 1.34.3+k3s1 (11 bytes)
10: --namespace (11 bytes)
11: kube-system (11 bytes)
12: --values (8 bytes)
13: /tmp/helmfile247608998/kube-system-nfs-provisioner-values-66cd9877fc (68 bytes)
14: --reset-values (14 bytes)
15: --detailed-exitcode (19 bytes)
ERROR:
exit status 1
EXIT STATUS
1
STDERR:
Error: unknown command "diff" for "helm"
Run 'helm --help' for usage.
COMBINED OUTPUT:
Error: unknown command "diff" for "helm"
Run 'helm --help' for usage.
helm diffコマンドが存在しないといわれています。
どうやら以下のプラグインを導入する必要があるようです。
以下のコマンドでプラグインをインストールします。
helm plugin install https://github.com/databus23/helm-diff --verify=false
再度実行してみます。
❯ helmfile apply -f helm/helmfile.yaml
Adding repo nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
"nfs-subdir-external-provisioner" already exists with the same configuration, skipping
Comparing release=nfs-provisioner, chart=nfs-subdir-external-provisioner/nfs-subdir-external-provisioner, namespace=kube-system
kube-system, leader-locking-nfs-provisioner-nfs-subdir-external-provisioner, Role (rbac.authorization.k8s.io) has been added:
-
+ # Source: nfs-subdir-external-provisioner/templates/role.yaml
+ kind: Role
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ labels:
+ chart: nfs-subdir-external-provisioner-4.0.18
+ heritage: Helm
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ name: leader-locking-nfs-provisioner-nfs-subdir-external-provisioner
+ rules:
+ - apiGroups: [""]
+ resources: ["endpoints"]
+ verbs: ["get", "list", "watch", "create", "update", "patch"]
kube-system, leader-locking-nfs-provisioner-nfs-subdir-external-provisioner, RoleBinding (rbac.authorization.k8s.io) has been added:
-
+ # Source: nfs-subdir-external-provisioner/templates/rolebinding.yaml
+ kind: RoleBinding
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ labels:
+ chart: nfs-subdir-external-provisioner-4.0.18
+ heritage: Helm
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ name: leader-locking-nfs-provisioner-nfs-subdir-external-provisioner
+ subjects:
+ - kind: ServiceAccount
+ name: nfs-provisioner-nfs-subdir-external-provisioner
+ namespace: kube-system
+ roleRef:
+ kind: Role
+ name: leader-locking-nfs-provisioner-nfs-subdir-external-provisioner
+ apiGroup: rbac.authorization.k8s.io
kube-system, nfs-client, StorageClass (storage.k8s.io) has been added:
-
+ # Source: nfs-subdir-external-provisioner/templates/storageclass.yaml
+ apiVersion: storage.k8s.io/v1
+ kind: StorageClass
+ metadata:
+ labels:
+ chart: nfs-subdir-external-provisioner-4.0.18
+ heritage: Helm
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ name: nfs-client
+ annotations:
+ storageclass.kubernetes.io/is-default-class: "true"
+ provisioner: cluster.local/nfs-provisioner-nfs-subdir-external-provisioner
+ allowVolumeExpansion: true
+ reclaimPolicy: Retain
+ volumeBindingMode: Immediate
+ parameters:
+ archiveOnDelete: "true"
kube-system, nfs-provisioner-nfs-subdir-external-provisioner, Deployment (apps) has been added:
-
+ # Source: nfs-subdir-external-provisioner/templates/deployment.yaml
+ apiVersion: apps/v1
+ kind: Deployment
+ metadata:
+ name: nfs-provisioner-nfs-subdir-external-provisioner
+ labels:
+ chart: nfs-subdir-external-provisioner-4.0.18
+ heritage: Helm
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ spec:
+ replicas: 1
+ strategy:
+ type: Recreate
+ selector:
+ matchLabels:
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ template:
+ metadata:
+ annotations:
+ labels:
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ spec:
+ serviceAccountName: nfs-provisioner-nfs-subdir-external-provisioner
+ securityContext:
+ {}
+ containers:
+ - name: nfs-subdir-external-provisioner
+ image: "registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2"
+ imagePullPolicy: IfNotPresent
+ securityContext:
+ {}
+ volumeMounts:
+ - name: nfs-subdir-external-provisioner-root
+ mountPath: /persistentvolumes
+ env:
+ - name: PROVISIONER_NAME
+ value: cluster.local/nfs-provisioner-nfs-subdir-external-provisioner
+ - name: NFS_SERVER
+ value: 192.168.0.94
+ - name: NFS_PATH
+ value: /k8s-data
+ volumes:
+ - name: nfs-subdir-external-provisioner-root
+ nfs:
+ server: 192.168.0.94
+ path: /k8s-data
kube-system, nfs-provisioner-nfs-subdir-external-provisioner, ServiceAccount (v1) has been added:
-
+ # Source: nfs-subdir-external-provisioner/templates/serviceaccount.yaml
+ apiVersion: v1
+ kind: ServiceAccount
+ metadata:
+ labels:
+ chart: nfs-subdir-external-provisioner-4.0.18
+ heritage: Helm
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ name: nfs-provisioner-nfs-subdir-external-provisioner
kube-system, nfs-provisioner-nfs-subdir-external-provisioner-runner, ClusterRole (rbac.authorization.k8s.io) has been added:
-
+ # Source: nfs-subdir-external-provisioner/templates/clusterrole.yaml
+ kind: ClusterRole
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ labels:
+ chart: nfs-subdir-external-provisioner-4.0.18
+ heritage: Helm
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ name: nfs-provisioner-nfs-subdir-external-provisioner-runner
+ rules:
+ - apiGroups: [""]
+ resources: ["nodes"]
+ verbs: ["get", "list", "watch"]
+ - apiGroups: [""]
+ resources: ["persistentvolumes"]
+ verbs: ["get", "list", "watch", "create", "delete"]
+ - apiGroups: [""]
+ resources: ["persistentvolumeclaims"]
+ verbs: ["get", "list", "watch", "update"]
+ - apiGroups: ["storage.k8s.io"]
+ resources: ["storageclasses"]
+ verbs: ["get", "list", "watch"]
+ - apiGroups: [""]
+ resources: ["events"]
+ verbs: ["create", "update", "patch"]
kube-system, run-nfs-provisioner-nfs-subdir-external-provisioner, ClusterRoleBinding (rbac.authorization.k8s.io) has been added:
-
+ # Source: nfs-subdir-external-provisioner/templates/clusterrolebinding.yaml
+ kind: ClusterRoleBinding
+ apiVersion: rbac.authorization.k8s.io/v1
+ metadata:
+ labels:
+ chart: nfs-subdir-external-provisioner-4.0.18
+ heritage: Helm
+ app: nfs-subdir-external-provisioner
+ release: nfs-provisioner
+ name: run-nfs-provisioner-nfs-subdir-external-provisioner
+ subjects:
+ - kind: ServiceAccount
+ name: nfs-provisioner-nfs-subdir-external-provisioner
+ namespace: kube-system
+ roleRef:
+ kind: ClusterRole
+ name: nfs-provisioner-nfs-subdir-external-provisioner-runner
+ apiGroup: rbac.authorization.k8s.io
Upgrading release=nfs-provisioner, chart=nfs-subdir-external-provisioner/nfs-subdir-external-provisioner, namespace=kube-system
Release "nfs-provisioner" does not exist. Installing it now.
NAME: nfs-provisioner
LAST DEPLOYED: Tue Jan 13 00:54:01 2026
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None
Listing releases matching ^nfs-provisioner$
nfs-provisioner kube-system 1 2026-01-13 00:54:01.223708054 +0900 JST deployed nfs-subdir-external-provisioner-4.0.18 4.0.2
UPDATED RELEASES:
NAME NAMESPACE CHART VERSION DURATION
nfs-provisioner kube-system nfs-subdir-external-provisioner/nfs-subdir-external-provisioner 4.0.18 2s
今度は成功しました!
感想
とても簡単にプロビジョナーを導入できました。
今後はPVCを作るだけになるので、作業がますます捗ります。