KubernetesのhostPathを使ったDynamic Volume Provisioningテスト

経緯

Helmを使ってインストールしようとしたらpodが以下のメッセージでPendingになりました。

Events:
  Type     Reason            Age   From               Message
  ----     ------            ----  ----               -------
  Warning  FailedScheduling  21s   default-scheduler  0/1 nodes are available: 1 pod has unbound immediate PersistentVolumeClaims.

Kubernetesで永続化したボリュームを使うにはPersistentVolumeが必要なのですが、
自分で構築したKubernetesの場合、別途事前に作成する必要があります。
実際確認すると存在していませんでした。

$ kubectl get pv
No resources found

そこでPersistentVolumeを準備しようとしましたが、
Helmで提供されているchartはDynamic Provisioning前提となっているものがあるので、
それに対応したストレージクラスにする必要があるようです。
例えばbitnami/mysql

しかし対応しているProvisionerはクラウドばかりなので、
NFSiSCSI で 利用しようとするとexternal provisionersにする必要があるらしい。

ちょっとテストするだけでそれらを準備するのはちょっと億劫だなと思ったら、
こちら によると テストまたは開発目的用のhostPath Provisionerと言うのがあるらしいです。

これだ!と思ったら紹介されていたのはソースコードからビルドする方法だったので、
kubeadmで構築した環境でのやり方を調べてみました。

環境

ESXi上のUbuntuにkubeadmで構築したシングルノードクラスターです。

ubuntu@k8s:~$ kubectl get node
NAME   STATUS   ROLES                  AGE   VERSION
k8s    Ready    control-plane,master   22d   v1.20.2
ubuntu@k8s:~$ kubectl get all -n kube-system
NAME                              READY   STATUS    RESTARTS   AGE
pod/coredns-74ff55c5b-7w7kq       1/1     Running   1          22d
pod/coredns-74ff55c5b-bmdnw       1/1     Running   1          22d
pod/etcd-k8s                      1/1     Running   1          22d
pod/kube-apiserver-k8s            1/1     Running   1          22d
pod/kube-controller-manager-k8s   1/1     Running   1          22h
pod/kube-flannel-ds-95hkq         1/1     Running   1          22d
pod/kube-proxy-tgdm2              1/1     Running   2          22d
pod/kube-scheduler-k8s            1/1     Running   1          22d

NAME               TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)                  AGE
service/kube-dns   ClusterIP   10.96.0.10   <none>        53/UDP,53/TCP,9153/TCP   22d

NAME                             DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/kube-flannel-ds   1         1         1       1            1           <none>                   22d
daemonset.apps/kube-proxy        1         1         1       1            1           kubernetes.io/os=linux   22d

NAME                      READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/coredns   2/2     2            2           22d

NAME                                DESIRED   CURRENT   READY   AGE
replicaset.apps/coredns-74ff55c5b   2         2         2       22d

kube-controller-managerの設定変更

こちらのドキュメント によるとkube-controller-managerの
「–enable-hostpath-provisioner」オプションを有効化すると使えそうです。
変更の仕方はこちら を参考にさせていただきました。

以下のように1行追記すれば自動で反映されます。

ubuntu@k8s:~$ sudo cat /etc/kubernetes/manifests/kube-controller-manager.yaml
apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  labels:
    component: kube-controller-manager
    tier: control-plane
  name: kube-controller-manager
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-controller-manager
    - --allocate-node-cidrs=true
    - --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf
    - --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf
    - --bind-address=127.0.0.1
    - --client-ca-file=/etc/kubernetes/pki/ca.crt
    - --cluster-cidr=10.244.0.0/16
    - --cluster-name=kubernetes
    - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt
    - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key
    - --controllers=*,bootstrapsigner,tokencleaner
    - --kubeconfig=/etc/kubernetes/controller-manager.conf
    - --leader-elect=true
    - --port=0
    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt
    - --root-ca-file=/etc/kubernetes/pki/ca.crt
    - --service-account-private-key-file=/etc/kubernetes/pki/sa.key
    - --service-cluster-ip-range=10.96.0.0/12
    - --use-service-account-credentials=true
    - --enable-hostpath-provisioner=true

動作テスト

有効にしましたらこちら を 参考にストレージクラスを作成します。

ubuntu@k8s:~$ cat provisioner.yaml 
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: standard
  annotations:
    storageclass.beta.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/host-path
ubuntu@k8s:~$ kubectl create -f provisioner.yaml 
storageclass.storage.k8s.io/standard created

では bitnami/mysql をインストールしてみます。

ubuntu@k8s:~$ helm install my-release bitnami/mysql --set volumePermissions.enabled=true

※僕の場合以下のエラーが発生したので トラブルシュート に従って
「–set volumePermissions.enabled=true」を追加しています。

mkdir: cannot create directory '/bitnami/mysql/data': Permission denied

無事起動したようです。

ubuntu@k8s:~$ kubectl get all
NAME                     READY   STATUS    RESTARTS   AGE
pod/my-release-mysql-0   1/1     Running   0          6m14s

NAME                                TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
service/kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP    22d
service/my-release-mysql            ClusterIP   10.106.170.174   <none>        3306/TCP   6m14s
service/my-release-mysql-headless   ClusterIP   None             <none>        3306/TCP   6m14s

NAME                                READY   AGE
statefulset.apps/my-release-mysql   1/1     6m14s
ubuntu@k8s:~$ kubectl get sc,pv,pvc
NAME                                             PROVISIONER               RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
storageclass.storage.k8s.io/standard (default)   kubernetes.io/host-path   Delete          Immediate           false                  33m

NAME                                                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                             STORAGECLASS   REASON   AGE
persistentvolume/pvc-eb90dca8-103d-4ca1-b619-4804fa09d311   8Gi        RWO            Delete           Bound    default/data-my-release-mysql-0   standard                6m58s

NAME                                            STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/data-my-release-mysql-0   Bound    pvc-eb90dca8-103d-4ca1-b619-4804fa09d311   8Gi        RWO            standard       6m58s