unbound immediate PersistentVolumeClaims

2021年10月05日2022年08月27日

本番で稼働しているkubernetes環境と同じk8sをローカルにも構築したくて奮闘したお話です。
簡単に纏めるとmanifestで実在しないstorageClassを指定していたことが原因でした。

環境

  • macos
  • docker-kubernetes v1.21.1

エラー内容


$ kubectl get pod -n logging
NAME     READY   STATUS  RESTARTS  AGE
kafka-0  0/1           Pending 0                  3h33m

これだと何が原因か分かりづらいので詳細を確認します。

PODを確認


$ kubectl describe pod -n logging kafka-0

~~~~~PODの情報が色々出力されている~~~~~

Events:
  Type     Reason            Age                From               Message
  ----     ------            ----               ----               -------
  Warning  FailedScheduling  33s (x2 over 35s)  default-scheduler  0/1 nodes are available: 1 pod has unbound immediate PersistentVolumeClaims.

最後にEventsが出力されていますが内容的には、PVCの準備に失敗している感じがします。

PVCを確認

$ kubectl get pvc -n logging
NAME           STATUS    VOLUME   CAPACITY   ACCESS MODES   STORAGECLASS   AGE
data-kafka-0   Pending                                      ssd            91s

こちらも同じようにPendingなので詳細を確認します。

$ kubectl describe pvc -n logging data-kafka-0

~~~~~PVCの情報が色々出力されている~~~~~
Events:
  Type     Reason              Age                 From                         Message
  ----     ------              ----                ----                         -------
  Warning  ProvisioningFailed  29s (x2 over 2m8s)  persistentvolume-controller  Failed to provision volume with StorageClass \"ssd\": failed to get GCE GCECloudProvider with error <nil>

ssdというStorageClassをmanifestで指定しているようですね。
今回はローカルで構築しているのでdefaultのStorageClassを利用するように変更します。

StorageClassを確認

$ kubectl get sc
NAME                 PROVISIONER            RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
hostpath (default)   docker.io/hostpath     Delete          Immediate           false                  7m48s

defaultが設定されているのでPVCでは、StorageClassを指定しなくても使用することができます。

修正

PVCのstorage-classの定義を削除

manifest
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: kafka
  namespace: logging

~~~~~PODの情報を色々定義している~~~~~

  volumeClaimTemplates:
    - metadata:
      name: data
-       annotations:
-         volume.beta.kubernetes.io/storage-class: "ssd"
    spec:
      accessModes: [ "ReadWriteOnce" ]
        resources:
          requests:
            storage: 1Gi

StatefulSetの削除

PVCの定義情報を変更したため、StatefulSetを削除しておきます。

$ kubectl delete sts -n logging kafka
statefulset.apps "kafka" deleted

ちなみにstsを削除せずにapplyだけすると怒られます。
怖いコワイ。

$ kubectl apply -f kafka/30-statefulset.yml
The StatefulSet "kafka" is invalid: spec: Forbidden: updates to statefulset spec for fields other than 'replicas', 'template', and 'updateStrategy' are forbidden

PVCの削除

PVCもssdからローカルのdefaultに変更するため、削除しておきます。

$ kubectl delete pvc -n logging data-kafka-0
persistentvolumeclaim "data-kafka-0" deleted

再apply

$ kubectl apply -f kafka.yml
statefulset.apps/kafka created

しばらくするとkafkaが立ち上がります。

$ kubectl get pod -n logging
NAME          READY   STATUS    RESTARTS   AGE
kafka-0       1/1     Running   4          4m57s
kafka-1       1/1     Running   4          4m51s
kafka-2       1/1     Running   5          4m43s

PVCとは

manifestにvolumeClaimTemplatesを定義しておくと、勝手にPVも作ってくれる優れものです。
annotationsを定義することでStorageClassを指定することができ
ます。

manifest
volumeClaimTemplates:
  - metadata:
      name: data
-       annotations:
-         volume.beta.kubernetes.io/storage-class: "ssd"
          spec:
            accessModes: [ "ReadWriteOnce" ]
            resources:
              requests:
                storage: 1Gi

PVの定義もmanifestに含めることができるのが利点ですね。

$ kubectl get pv
NAME                                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                      STORAGECLASS   REASON   AGE
pvc-9829216c-ea0d-49dc-bc9e-2d6ee4d7e2a7   1Gi        RWO            Delete           Bound    logging/data-kafka-1       hostpath                16m
pvc-abe043dc-e26f-4ce3-a3e5-0818b2ed5694   1Gi        RWO            Delete           Bound    logging/data-kafka-2       hostpath                15m
pvc-ef598b49-8924-4a3e-8ad3-3df62e9d0403   1Gi        RWO            Delete           Bound    logging/data-kafka-0       hostpath                16m

まとめ

なんかkubernetesのエラーハンドリングみたいになりましたが、ローカルではdefaultのStorageClassを使うのがいいなと思いました。
(provisionerをローカル用に変更すれば良いだけなんですけどね。)
PVCはPVを勝手に作るボリューム定義書と覚えればいいでしょう。
このブログではインフラや情シスのさりげない日常を記録しています。
お困りごとも相談にのりますので、お問い合わせフォームからお気軽にお問い合わせください。