本番で稼働しているkubernetes環境と同じk8sをローカルにも構築したくて奮闘したお話です。
簡単に纏めるとmanifestで実在しないstorageClassを指定していたことが原因でした。
$ kubectl get pod -n logging
NAME READY STATUS RESTARTS AGE
kafka-0 0/1 Pending 0 3h33m
これだと何が原因か分かりづらいので詳細を確認します。
$ 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の準備に失敗している感じがします。
$ 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を利用するように変更します。
$ kubectl get sc
NAME PROVISIONER RECLAIMPOLICY VOLUMEBINDINGMODE ALLOWVOLUMEEXPANSION AGE
hostpath (default) docker.io/hostpath Delete Immediate false 7m48s
defaultが設定されているのでPVCでは、StorageClassを指定しなくても使用することができます。
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
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もssdからローカルのdefaultに変更するため、削除しておきます。
$ kubectl delete pvc -n logging data-kafka-0
persistentvolumeclaim "data-kafka-0" deleted
$ 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
manifestにvolumeClaimTemplatesを定義しておくと、勝手にPVも作ってくれる優れものです。
annotationsを定義することでStorageClassを指定することができ
ます。
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を勝手に作るボリューム定義書と覚えればいいでしょう。
このブログではインフラや情シスのさりげない日常を記録しています。
お困りごとも相談にのりますので、お問い合わせフォームからお気軽にお問い合わせください。