動かざることバグの如し

近づきたいよ 君の理想に

Kubernatesでstorageclass.storage.k8s.io "standard" not foundエラー

PersistentVolumeを作成したらエラーになる

公式チュートリアルでPersistentVolumeを使ったWordPressのデプロイをやっていたところ

kubernetes.io

いつまで経ってもPVCがPendingのまま。。。

kubectl get pvc
NAME             STATUS    VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
wp-pv-claim      Pending                                                                        standard      15s

詳細を見てみると「storageclass.storage.k8s.io "standard" not found」とエラーになる。。

kubectl describe pvc wp-pv-claim
Name:          wp-pv-claim
Namespace:     test
StorageClass:  standard
Status:        Pending
Volume:        
Labels:        app=wordpress
Annotations:   <none>
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:      
Access Modes:  
VolumeMode:    Filesystem
Used By:       wordpress-5d96f87b44-tvg4m
Events:
  Type     Reason              Age                   From                         Message
  ----     ------              ----                  ----                         -------
  Warning  ProvisioningFailed  12s (x12 over 2m47s)  persistentvolume-controller  storageclass.storage.k8s.io "standard" not found

あとから分かったことだが、StorageClassというリソースがKubernetesにはあり、 それがなかったのが直接的な原因

kubectl get pv
No resources found

それを解決するまでの道筋をメモしておく

PVの作成まで

まず、StorageClassがなくてもPVもPVCも作成することはできる。

試しにPVを作成してみる。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv01
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteOnce
  persistentVolumeReclaimPolicy: Delete
  storageClassName: standard
  hostPath:
    path: /data
    type: DirectoryOrCreate

accessModes

  • ReadWriteOnce(RWO) 単一ノードからRead/Writeされる
  • ReadOnlyMany(ROX) 単一ノードからWrite、複数ノードからReadされる
  • ReadWriteMany(RWX) 複数ノードからRead/Writeされる

persistentVolumeReclaimPolicy

Reclaim Policyは、PersistentVolumeを利用し終わった後の処理方法を制御するポリシー

  • Retain PersistentVolumeのデータも消さずに保持する。また、他のPersistentVolumeClaimによって、このPersistentVolumeが再度マウントされることはない
  • Recycle PersistentVolumeのデータを削除し、再利用可能な状態にする よって他のPersistentVolumeClaimによって再度マウントされる
  • Delete PersistentVolumeが削除されます GCE、AWSなど外部ボリュームの際に利用する

確認

kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS    REASON   AGE
pv01   1Gi        RWO            Delete           Available           standard            41s

よさそうなのでPVCも作成してみる

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc01
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  storageClassName: standard

これも無事に作成されている

kubectl get pvc                                                          
NAME             STATUS    VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS    AGE
pvc01         Bound     pv01   1Gi        RWO            standard   50s

試しにマウント用のPodを作成して確認してみる

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: pvc01
  terminationGracePeriodSeconds: 0

これでShellの中に入るとたしかにマウント可能

/data # ls -l
total 0
-rw-r--r--    1 root     root             0 Jul 19 23:35 aaaaaaaaa

PVが削除されたら中身も削除されるのでPodを消して再生成しても中身は残る

が、Podを立てるたびにPVCを指定しなければならないのはダルすぎる

ってことでPVCの要件を指定したら自動でいい感じにKubernetes側に選んでマウントしてもらいたい

それがStorageClassってリソース

StorageClassの作成

ようやく本題に入るが実はセキュリティ上の理由からデフォルトではホストのマウントする形のStorageClassの作成が許可されていない

のでその許可を先に行う

hostPath provisionerを有効化する

/etc/kubernetes/manifests/kube-controller-manager.yaml を開いて --enable-hostpath-provisioner=true を追加する。

編集保存した瞬間にcontroller-managerのpodが再起動&反映されるので注意

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.100.0.0/16
    - --cluster-name=myhome
    - --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
    - --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 # ← ココ!

いざStorageClassを作成 デフォルトではStorageClassは「standard」らしいのでそれに従う

kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: standard
  annotations:
    storageclass.beta.kubernetes.io/is-default-class: "true"
provisioner: kubernetes.io/host-path

確認

kubectl get sc              
NAME                 PROVISIONER               RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
standard (default)   kubernetes.io/host-path   Delete          Immediate           false                  67m

あとはチュートリアルの kustomization.yaml を再反映すれば無事に

kubectl get pvc                                                          
NAME             STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
mysql-pv-claim   Bound    pvc-7a1040f1-3867-44fc-be04-9b980e269a96   20Gi       RWO            standard       5m53s
wp-pv-claim      Bound    pvc-c303dff4-3327-4df9-b0b1-e73d9b00cdd1   20Gi       RWO            standard       5m53s

となる

volumeBindingModeについて

後で調べる

参考リンク