環境
- ubuntu:22.0.4.1 LTS
- kubernetes:1.28.2
- containerd:1.6.24
StorageClassについて
StorageClassを用いずにPersistentVolumeを使用するには、クラスターの管理者が事前にPersistentVolumeを作成して、ユーザーがPersistentVolumeClaimを作成する流れになると思います。
ですが、もう少し運用を楽にしたい。クラスターの管理者を介さずに、PersistentVolumeを作成したいといった要件があると思います。
そこで、使えるのがStorageClassです。
今回、オンプレ環境でStorageClassを利用するための外部プロビジョナー(対する「内部プロビジョナー」はデフォルトで使用できるプロビジョナーを指す)を用いて、NFS使った動的プロビジョンについて書いていきます。
NFSサーバーの準備
NFSサーバーを構築していきます。詳細は「nfs-kernel-server」で検索していただきたいですが、以下の通り、インストールします。
# sudo apt-get update
# sudo apt-get install nfs-kernel-server
インストールが完了したら公開するディレクトリの作成および権限設定をします。
今回は、/export/nfsという公開用のディレクトリを作成し、然る権限を付与します。
# sudo mkdir /export/nfs
# sudo chmod 1777 /export/nfs/.
次に、NFSの設定をします。
/export/nfs/ 172.21.0.0/24(rw,sync,no_subtree_check,no_root_squash,no_all_squash
最後に設定を反映させるためにNFSサービスを再起動させます。
# sudo systemctl reload nfs-kernel-server
これで準備完了です。
NFSクライアントのインストール
ワーカーノードすべてでNFSクライアントをインストールする。
# sudo apt-get update
# sudo apt-get install nfs-common
NFSクライアントの確認
NFSクライアントが正常に動作することを確認する。
# sudo mount -t nfs 172.21.0.50:/export /mnt
# ls /mnt/nfs
<show something>
# sudo umount /mnt
プロビジョナーの導入
プロビジョナーの導入をしていきます。
以下のレポジトリのREADME通りに実施しています。HelmやKustomizeでの導入も可能ですが、今回は、マニュアルで導入していきます。
gitクローンするディレクトリを作成する。
# mkdir dynamic-provisioner-nfs && cd dynamic-provisioner-nfs
# git init --initial-branch main
# Initialized empty Git repository in /dynamic-provisioner-nfs/.git/
gitの設定
/deployディレクトリのみ必要なので、特定のディレクトリのみクローンできるように設定していきます。併せてリモートレポジトリを追加します。
# git config core.sparsecheckout true
# git config --list
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
+ core.sparsecheckout=true
# git remote add origin https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner.git
# echo /deploy >> .git/info/sparse-checkout
gitクローン
それでは、/deployディレクトリをクローンします。
# git pull origin master
From https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner
* branch master -> FETCH_HEAD
# ls
deploy
これで準備が完了しました。
次に各yamlファイルの作成・修正をしていきます。
namespaceの作成
まずは、プロビジョナー用Namespaceのマニフェストを作成します。
ここではNamespace名をdynamic-provisioner-nfs
とします。
sioner-nfs.yaml
apiVersion: v1
kind: Namespace
metadata:
name: dynamic-provisioner-nfs
spec: {}
status: {}
上記で作成したマニフェストを'apply'します。
# kubectl apply -f namespace-dynamic-provisioner-nfs.yaml
namespace/dynamic-provisioner-nfs created
rbac.yaml、deployment.yamlの修正
/deployには、それぞれDeployment、ServiceAccount、StorageClass、テスト用PVC、テスト用Podのマニフェストが入っております。rbac.yamlやdeployment.yamlはデフォルトでNamespaceがdefault
になっているので、上記で作成したNamespace dynamic-provisioner-nfs
に変更します。
# NAMESPACE=dynamic-provisioner-nfs
# echo $NAMESPACE
dynamic-provisioner-nfs
# sed -i "s/default/$NAMESPACE/g" ./deploy/rbac.yaml ./deploy/deployment.yaml
ServiceAccountの作成
ここで、rbac.yamlの中身をみてみます。
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: dynamic-provisioner-nfs
---
kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: nfs-client-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"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: run-nfs-client-provisioner
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: dynamic-provisioner-nfs
roleRef:
kind: ClusterRole
name: nfs-client-provisioner-runner
apiGroup: rbac.authorization.k8s.io
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: dynamic-provisioner-nfs
rules:
- apiGroups: [""]
resources: ["endpoints"]
verbs: ["get", "list", "watch", "create", "update", "patch"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: leader-locking-nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: dynamic-provisioner-nfs
subjects:
- kind: ServiceAccount
name: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: dynamic-provisioner-nfs
roleRef:
kind: Role
name: leader-locking-nfs-client-provisioner
apiGroup: rbac.authorization.k8s.io
Node、PVC、PVを管理するための権限と、上記で作成したnameSpaceのEndpointsを管理するための権限を付与したServiceAccountを作成しています。Endpointsの権限はなぜ必要なのかわからないですが、一旦そのままにしておきます。
このServiceAccountを、後で作成するDeploymentに渡して、上記のリソースを管理するPodをデプロイします。
では、'apply'します。
# kubectl create -f deploy/rbac.yaml
serviceaccount/nfs-client-provisioner created
clusterrole.rbac.authorization.k8s.io/nfs-client-provisioner-runner created
clusterrolebinding.rbac.authorization.k8s.io/run-nfs-client-provisioner created
role.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
rolebinding.rbac.authorization.k8s.io/leader-locking-nfs-client-provisioner created
Deploymentの作成
では、先に修正したDeployment.yamlをさらに修正していきます。
デフォルトでNFSサーバーのアドレスと、ディレクトリがサンプルのパラメータとして記載されています。
ここでは、以下のように修正します。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-client-provisioner
labels:
app: nfs-client-provisioner
# replace with namespace where provisioner is deployed
namespace: dynamic-provisioner-nfs
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app: nfs-client-provisioner
template:
metadata:
labels:
app: nfs-client-provisioner
spec:
serviceAccountName: nfs-client-provisioner
containers:
- name: nfs-client-provisioner
image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
env:
- name: PROVISIONER_NAME
value: k8s-sigs.io/nfs-subdir-external-provisioner
- name: NFS_SERVER
- value: 10.3.243.101
+ value: 172.21.0.50
- name: NFS_PATH
- value: /ifs/kubernetes
+ value: /export/nfs
volumes:
- name: nfs-client-root
nfs:
- server: 10.3.243.101
+ server: 172.21.0.50
- path: /ifs/kubernetes
+ path: /export/nfs
では、'apply'します。
# kubectl apply -f deploy/deployment.yaml
deployment.apps/nfs-client-provisioner created
これで、対象のPodが立ち上がるのを待ちます。
少しだけ時間がかかった気がします。
# kubectl get pods -n dynamic-provisioner-nfs
NAME READY STATUS RESTARTS AGE
nfs-client-provisioner-85975c94c6-lpxnt 1/1 Running 0 6m46s
StrageClassの作成
最後にStorageClassの作成をしていきます。
必要に応じてマニフェストの修正が必要になりますが、用意されているclass.yamlをそのまま'apply'してみます。
# kubectl apply -f deploy/class.yaml
storageclass.storage.k8s.io/nfs-client created
# kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-client k8s-sigs.io/nfs-subdir-external-provisioner Delete Immediate false 2m16s
これで準備が整いました。
それでは、PersistentVolumeClaimを作成していきます。
動作確認
このGitでは親切にもテスト用のマニフェストが用意されていますので、そのまま使用してみたいと思います。用意されているPod、PVCマニフェストのNamespaceはdefault
となっています。
# kubectl apply -f deploy/test-pod.yaml -f deploy/test-claim.yaml
pod/test-pod created
persistentvolumeclaim/test-claim created
# kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
test-claim Bound pvc-b1888a30-6361-4dd9-bfe4-77649c095733 1Mi RWX nfs-client 42s
# kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
pvc-b1888a30-6361-4dd9-bfe4-77649c095733 1Mi RWX Delete Bound default/test-claim nfs-client 71s
# kubectl get pods
NAME READY STATUS RESTARTS AGE
test-pod 0/1 Completed 0 82s
上記でtest-claim
というPVCと、それに対応するpvc-b1888a30-6361-4dd9-bfe4-77649c095733
というPVが作成されます。
NFSサーバーには、以下のようなディレクトリが作成されます。
${namespace}-${pvcName}-${pvName}
ここでは「default
-test-claim
-pvc-b1888a30-6361-4dd9-bfe4-77649c095733
」といったディレクトリが公開ディレクトリに作成されます。
加えて、Pod test-pod
で先に作成されたPVC test-claim
をマウントします。
ここで、NFSサーバーにアクセスし、公開ディレクトリを確認してみます。
# ls /export/nfs/default-test-claim-pvc-b1888a30-6361-4dd9-bfe4-77649c095733/
SUCCESS
「SUCCESS」ファイルが作成されていれば完了です。
動作確認出来たら、先のPVCとPodを削除します。
# kubectl delete -f deploy/test-pod.yaml -f deploy/test-claim.yaml
pod "test-pod" deleted
persistentvolumeclaim "test-claim" deleted
これでクラスター管理者を介さずにPersistentVolumeを作成できるようになりました。
今回は以上です。