永続ボリュームを設定する
最初に
まずはドキュメントに目を通してみる。
併せて参考としたサイトをいくつか。
Minecraft の World データの保存場所としては、
- Minecraft の World ��ータが消えるのは困るから、pod 内の一時的な記憶領域では困る。
- Node が動作しているディスク領域を利用すると、Node に障害が発生したときに World データが利用できないから困る。
- iSCSI や NFS による、クラスター外のストレージを利用すれば Node に障害が発生しても何とかなる。
ということで、Master Node にディスクを追加する。もし Master Node が動作しているPVE のホストが落ちてもデータは大丈夫なハズ。
NFS 関係のマニフェストはhttps://github.com/kubernetes/examples/tree/master/staging/volumes/nfsを参考にした。NFS-Server そのものをデプロイするためのマニフェストもあるけれど、なれたところで普通に Master Node で NFS Server を動作させることにした。
オンプレミスの kubernetes クラスターでも、ローカルディレクトリや NFS を利用する StorageClass を設定することができるらしい。ただ、自分の場合は World データの保存先を確実に把握したいからそこまでは不要。そのうち気が向いたら試してみよう。
Minecraft をデプロイしたあと、kubectl -n minecraft describe pod minecraft-76d4c555c-lxk59 で様子を確認したところ Warning があったから、この際に StorageClass も設定する。使用するかどうかは別の話。
Node で NFS を動作させる
Proxmox 管理画面からディスクを追加する。Minecraft 用に 16G とした。
disk イメージの保存先は ceph。
/mnt/disk 等のマウントポイントを作って、gdisk でパーティションを初期化して、mkfs.ext4 でフォーマットして、/etc/fstab に mount 情報を追加する(色々省略)。
続いて NFS server をインストールする。
sudo apt install nfs-kernel-server
ファイル exports を編集(最終行を追加)する。
Kubernetes クラスタが接続できるよう CIDR は 10.1.0.0/16 としている。
$ sudo vi /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
# to NFS clients. See exports(5).
#
# Example for NFSv2 and NFSv3:
# /srv/homes hostname1(rw,sync,no_subtree_check) hostname2(ro,sync,no_subtree_check)
#
# Example for NFSv4:
# /srv/nfs4 gss/krb5i(rw,sync,fsid=0,crossmnt,no_subtree_check)
# /srv/nfs4/homes gss/krb5i(rw,sync,no_subtree_check)
#
/media/disk2 10.1.0.0/16(async,rw,no_root_squash,no_subtree_check)
exports の設定を反映させて、サービスを再起動する。
sudo exportfs -ra
sudo systemctl restart nfs-server.service
ここまでの手順で Master Node に NFS server を設置できた。
永続ボリュームを準備する
PersistentVolume(PV)
PV 用に、Master Node の /media/disk2 の下にサブディレクトリを用意する。
今回は Minecraft の java 版と bedrock 版に分けることを前提として2つとする。
mkdir /media/disk2/java
mkdie /media/disk2/bedrock
こちら(nfs-pv.yaml)を参考に PV のマニフェストを作る。
PVC が削除されても PV 内のデータが残るよう、persistentVolumeReclaimPolicy: Retain としている。
$ vi ./nfs-pv-java.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
name: nfs-pv-java
spec:
capacity:
storage: 5Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
nfs:
server: 10.1.1.3
path: /media/disk2/java-version
mountOptions:
- nfsvers=4.2
PV をデプロイする。
$ kubectl apply -f ./nfs-pv-java.yaml
persistentvolume/nfs-pv-java created
確認する。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv-java 5Gi RWX Retain Available 9s
PersistentVolumeClaim(PVC)
こちら(nfs-pvc.yaml)を参考に PVC のマニフェストを作る。
World のデータ保存先を固定するため、volumeName: nfs-pv-java として pv を指定している。
$ vi ./nfs-pvc-java.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-pvc-java
spec:
accessModes:
- ReadWriteMany
storageClassName: ""
resources:
requests:
storage: 5Gi
volumeName: nfs-pv-java
PVC をデプロイする。
$ kubectl apply -f ./nfs-pvc-java.yaml
persistentvolumeclaim/nfs-pvc-java created
pv と pvc を確認する。
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv-java 5Gi RWX Retain Bound default/nfs-pvc-java 12m
$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc-java Bound nfs-pv-java 5Gi RWX 42s
Kubernetes Dashboard で見てみる。
テストしてみる
次のサイトをもとに、マニフェストを作って pod をデプロイする。
$ vi ./mount-pvc.yaml
apiVersion: v1
kind: Pod
metadata:
name: pvc-test
spec:
containers:
- image: alpine
name: alpine
command: ["tail", "-f", "/dev/null"]
volumeMounts:
- name: claim-volume
mountPath: /data
volumes:
- name: claim-volume
persistentVolumeClaim:
claimName: nfs-pvc-java
terminationGracePeriodSeconds: 0
実行してみる。
$ kubectl exec pvc-test -- ls -l /
total 60
drwxr-xr-x 2 root root 4096 Sep 28 11:18 bin
drwxrwxr-x 3 1000 1000 4096 Oct 31 13:06 data
drwxr-xr-x 5 root root 360 Oct 31 13:15 dev
drwxr-xr-x 1 root root 4096 Oct 31 13:15 etc
drwxr-xr-x 2 root root 4096 Sep 28 11:18 home
drwxr-xr-x 7 root root 4096 Sep 28 11:18 lib
drwxr-xr-x 5 root root 4096 Sep 28 11:18 media
drwxr-xr-x 2 root root 4096 Sep 28 11:18 mnt
drwxr-xr-x 2 root root 4096 Sep 28 11:18 opt
dr-xr-xr-x 208 root root 0 Oct 31 13:15 proc
drwx------ 2 root root 4096 Sep 28 11:18 root
drwxr-xr-x 1 root root 4096 Oct 31 13:15 run
drwxr-xr-x 2 root root 4096 Sep 28 11:18 sbin
drwxr-xr-x 2 root root 4096 Sep 28 11:18 srv
dr-xr-xr-x 13 root root 0 Oct 31 13:15 sys
drwxrwxrwt 2 root root 4096 Sep 28 11:18 tmp
drwxr-xr-x 7 root root 4096 Sep 28 11:18 usr
drwxr-xr-x 12 root root 4096 Sep 28 11:18 var
$ kubectl exec pvc-test -- ls -l /data
total 8
drwxr-xr-x 2 root root 4096 Oct 31 13:04 test
-rw-r--r-- 1 root root 192 Oct 31 13:06 test.txt
$ kubectl delete -f ./mount-pvc.yaml
pod "pvc-test" deleted
無事、/data にマウントできている。
ファイル test.txt やディレクトリ test は、前もって直接 /media/disk2/jiava-version に書き込んだもの。
NFS の StorageClass を定義する
永続ボリュームを使用するだけなら StorageClass は必要ないけれど、動的プロビジョニング(必要に応じてリソースを提供すること)の準備ができていないと Warning が出るから設定する。
NFS CSI Deiver のインストール
Kubernetes 公式ドキュメントによると、StorageClass には、PV のプロビジョニングに使用するボリュームプラグインを決定するプロビジョナーがあって、このフィールド(provisioner)を指定しないといけない。表では内部用 NFS の Provisioner は「 - 」になっているけど、CSI Driver を使うと動的プロビジョニングが可能。
ということで、Install CSI driver with Helm 3 のとおり Helm でインストールする。
バージョンは 4.4.0。
helm repo add csi-driver-nfs https://raw.githubusercontent.com/kubernetes-csi/csi-driver-nfs/master/charts
helm install csi-driver-nfs csi-driver-nfs/csi-driver-nfs --namespace kube-system --version v4.4.0
確認する。namespace は default ではなく kube-system なので、オプション --namespace=kube-system を付けている。
-n namespace でも OK。
$ kubectl --namespace=kube-system get pods --selector="app.kubernetes.io/instance=csi-driver-nfs"
NAME READY STATUS RESTARTS AGE
csi-nfs-controller-c544c88c-k5hdt 4/4 Running 4 (94m ago) 7h2m
csi-nfs-node-cvvfx 3/3 Running 0 7h2m
csi-nfs-node-tv7sc 3/3 Running 0 7h2m
csi-nfs-node-x6shz 3/3 Running 0 7h2m
csi-nfs-node-xzqjm 3/3 Running 0 7h2m
StrageClass nfs-csi を設定する
vi sc-nfs.yaml とかでマニフェストを作ってデプロイする。
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: nfs-csi
provisioner: nfs.csi.k8s.io
parameters:
server: 10.1.1.3
share: /media/disk2
mountPermissions: "775"
reclaimPolicy: Delete
volumeBindingMode: Immediate
mountOptions:
- hard
- nfsvers=4.2
確認する。
$ kubectl apply -f sc-nfs.yaml
storageclass.storage.k8s.io/nfs-csi created
$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
nfs-csi nfs.csi.k8s.io Delete Immediate false 12s
問題なさそう。
Dynamic volume provisioning を試す
動的プロビジョニング用の test-pvc.yaml を作る。
namespace に minecraft を指定しているが、なければ default が適用される。
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim1
namespace: minecraft
spec:
accessModes:
- ReadWriteOnce
storageClassName: nfs-csi
resources:
requests:
storage: 1Gi
デプロイする。
$ kubectl apply -f ./test-pvc-dynamic.yaml
persistentvolumeclaim/claim1 created
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv-java 5Gi RWX Retain Bound minecraft/nfs-pvc-java 8h
pvc-9a714dfe-e409-4001-a116-2cada4194f55 1Gi RWO Delete Bound minecraft/claim1 nfs-csi 4s
$ kubectl get pvc -n minecraft
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
claim1 Bound pvc-9a714dfe-e409-4001-a116-2cada4194f55 1Gi RWO nfs-csi 4m29s
nfs-pvc-java Bound nfs-pv-java 5Gi RWX 8h
pvc をデプロイしたら、pv「pvc-9a714dfe-e409-4001-a116-2cada4194f55」ができている。権限は設定どおり ReadWriteOnce。
pvc を削除する。
$ kubectl delete pvc -n minecraft claim1
persistentvolumeclaim "claim1" deleted
$ kubectl get pvc -n minecraft
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE
nfs-pvc-java Bound nfs-pv-java 5Gi RWX 9h
$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS REASON AGE
nfs-pv-java 5Gi RWX Retain Bound minecraft/nfs-pvc-java 9h
pvc「claim1」を削除すると、動的に確保されていた pv「pvc-9a714dfe-e409-4001-a116-2cada4194f55」も削除されることが確認できた。
次回に向けて
永続ボリュームもできたし、いよいよ Minecraft のデプロイに進めよう。
コメント