Statefulset を動かすために、kustomize で nfs-subdir-external-provisioner をセットアップする

自宅で動かしている k8s でも Statefulset を使ってデータベースをデプロイしてみたかったが、 Statefulset を使用する場合はストレージを Dynamic Volume Provisioning できるようにしておく必要があった。

プロビジョナー一覧を確認して最も簡単に用意できそうなのが nfs だったので、 kubernetes-sigs/nfs-subdir-external-provisioner を使ってセットアップしてみた。

kustomize の設定

おおよそ README.md の通りに進めて行けば良い。基本的な構成ファイルは こちらの GitHub リポジトリ にあり、これを resources で指定しつつ、必要部分だけ resourcespatch で上書きしていく。

provisioner を動かすネームスペースと、利用する nfs サーバーのパラメーターを指定するため、まずは namespace.yaml と deployment.yaml を用意していく。

# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: example-namespace # provisoner を動かす namespace 
# namespace.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: nfs-client-provisioner
  name: nfs-client-provisioner
spec:
  template:
    spec:
      containers:
        - name: nfs-client-provisioner
          env:
            - name: NFS_SERVER
              value: 192.0.2.254  # nfs サーバーのアドレス
            - name: NFS_PATH
              value: /kube/nfs # nfs サーバーのパス
      volumes:
        - name: nfs-client-root
          nfs:
            server:  192.0.2.254  # nfs サーバーのアドレス
            path: /kube/nfs # nfs サーバーのパス

env と volumes で同じ値を記述していくの二度手間だな...と思いつつ素直に真似しておく。

最後に kustomization.yaml を作成して、GitHub リポジトリにあるベース設定と、作成した namespaces.yaml、deployment.yaml を指定しておく。

# kustomization.yaml
namespace:  example-namespace
resources:
  - https://github.com/kubernetes-sigs/nfs-subdir-external-provisioner//deploy?ref=nfs-subdir-external-provisioner-4.0.18
  - namespace.yaml
patches:
  - path: deployment.yaml

resources に GitHub の URL を書けたりするのは知らなかった。remote targets と呼ぶらしい。README.md の例は Legacy URL format だったので読み替えたりした。

完成したら yaml を置いてあるディレクトリを指定して apply する。

kubectl -k ./nfs-provioner

終わったら provisioner の pod が起動しているか確認する

$ kubectl get pod -n example-namespace
NAME                                      READY   STATUS    RESTARTS   AGE
nfs-client-provisioner-6d6d6586d6-bzr2n   1/1     Running   0          52s

pod は無事起動しているようだ。

provisioner の動作確認

本当に動作するか PersistentVolumeClaim を記述した yaml ファイルを用意して確認する。

# pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: nfs-example
spec:
  storageClassName: nfs-client
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Mi

apply する

kubectl apply -f ./pvc.yaml

volume が作成されていることか確認。

$ kubectl get pvc
NAME                          STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS          AGE
nfs-example                   Bound    pvc-357aee94-d1fe-4e7a-962b-c41a429d65b2   100Mi      RWX            nfs-client            110s
$ kubectl describe pvc nfs-example
Name:          nfs-example
Namespace:     default
StorageClass:  nfs-client
Status:        Bound
Volume:        pvc-357aee94-d1fe-4e7a-962b-c41a429d65b2
Labels:        <none>
Annotations:   pv.kubernetes.io/bind-completed: yes
               pv.kubernetes.io/bound-by-controller: yes
               volume.beta.kubernetes.io/storage-provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
               volume.kubernetes.io/storage-provisioner: k8s-sigs.io/nfs-subdir-external-provisioner
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      100Mi
Access Modes:  RWX
VolumeMode:    Filesystem
Used By:       <none>
Events:
  Type    Reason                 Age   From                                                                                                                      Message
  ----    ------                 ----  ----                                                                                                                      -------
  Normal  ExternalProvisioning   121s   persistentvolume-controller                                                                                               waiting for a volume to be created, either by external provisioner "k8s-sigs.io/nfs-subdir-external-provisioner" or manually created by system administrator
  Normal  Provisioning           121s   k8s-sigs.io/nfs-subdir-external-provisioner_nfs-client-provisioner-6d6d6586d6-bzr2n_b29d68e1-cd9a-465e-b78a-a46a8e8e03fc  External provisioner is provisioning volume for claim "default/nfs-example"
  Normal  ProvisioningSucceeded  121s   k8s-sigs.io/nfs-subdir-external-provisioner_nfs-client-provisioner-6d6d6586d6-bzr2n_b29d68e1-cd9a-465e-b78a-a46a8e8e03fc  Successfully provisioned volume pvc-357aee94-d1fe-4e7a-962b-c41a429d65b2

無事に provision されてそう。これで Statefulset を使って Postgres や Redis をデプロイし放題になった。*1

*1:PostgreSQLNFS 上で動かす場合は注意事項が色々あるので気をつけよう