hidemium's blog

日々学んだことをアウトプットする。

Cluster API Provider vSphereでvSphere CSI ControllerがCrashLoopBackOffとなる事象を追ってみる

前回、Cluster API Provider vSphereを使ってKubernetesクラスタを作成してみました。今回は、Kubernetesクラスタを作成した際にvSphere CSI ControllerがCrashLoopBackOffとなる事象について原因を追ってみたので書いてみようと思います。

hidemium.hatenablog.com

構成

  • vCenter 7.0 U3
  • ESXi 7.0 Update 3
  • Kubespray
  • kubernetes v1.25.5
  • Cluster API v1.3.2
    • clusterctl v1.3.2
    • cluster-api-provider-vsphere v1.5.1
    • ubuntu-2004-kube-v1.25.5.ova
  • vSphere CPI v1.18.1
  • vSphere CSI v2.1.0

発生した事象について

前回、Cluster APIを使ってKubernetesクラスタを作成し、calicoのインストールが完了後のpodの状態がこちらです。vsphere-csi-controller が CrashLoopBackOff となっています。

$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl get pod -A
NAMESPACE     NAME                                               READY   STATUS             RESTARTS      AGE
kube-system   calico-kube-controllers-74677b4c5f-m77w8           1/1     Running            0             16m
kube-system   calico-node-7bcpz                                  1/1     Running            0             16m
kube-system   calico-node-w7fs9                                  1/1     Running            0             16m
kube-system   calico-node-wckhz                                  1/1     Running            0             16m
kube-system   calico-node-zlc5b                                  1/1     Running            0             16m
kube-system   coredns-565d847f94-chn5z                           1/1     Running            0             21m
kube-system   coredns-565d847f94-dn4zq                           1/1     Running            0             21m
kube-system   etcd-vsphere-quickstart-d7r7k                      1/1     Running            0             21m
kube-system   kube-apiserver-vsphere-quickstart-d7r7k            1/1     Running            0             21m
kube-system   kube-controller-manager-vsphere-quickstart-d7r7k   1/1     Running            0             21m
kube-system   kube-proxy-br9fn                                   1/1     Running            0             20m
kube-system   kube-proxy-cvfzq                                   1/1     Running            0             20m
kube-system   kube-proxy-qxlj2                                   1/1     Running            0             20m
kube-system   kube-proxy-rmzww                                   1/1     Running            0             21m
kube-system   kube-scheduler-vsphere-quickstart-d7r7k            1/1     Running            0             21m
kube-system   kube-vip-vsphere-quickstart-d7r7k                  1/1     Running            0             21m
kube-system   vsphere-cloud-controller-manager-ctkr7             1/1     Running            0             20m
kube-system   vsphere-cloud-controller-manager-hl5w2             1/1     Running            0             20m
kube-system   vsphere-cloud-controller-manager-r9dhk             1/1     Running            0             20m
kube-system   vsphere-csi-controller-5d6484644d-nqwlh            4/5     CrashLoopBackOff   8 (37s ago)   21m
kube-system   vsphere-csi-node-h9p2x                             3/3     Running            0             21m
kube-system   vsphere-csi-node-hbgsl                             3/3     Running            0             20m
kube-system   vsphere-csi-node-tr99v                             3/3     Running            0             20m
kube-system   vsphere-csi-node-xk2jq                             3/3     Running            0             20m

ログの確認

まずは、vsphere-csi-controllerの状態について以下のコマンドで確認してみます。ログを見ると、以下のようなエラーが発生します。エラーは、vCenter名の証明書が不明な認証局によって署名されているためです。デフォルトでは、vCenterは証明書を発行する認証局(VMCA)があり、自己署名証明書を作成しています。

$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl logs vsphere-csi-controller-5d6484644d-nqwlh -c vsphere-csi-controller -n kube-system
level=fatal msg="grpc failed" error="Post https://vcsa-1.home.lab:443/sdk: x509: certificate signed by unknown authority"

自己署名証明書を使うオプションががあり、csi-vsphere.conf で insecure-flag を利用する必要があります。

Create a Kubernetes Secret for vSphere Container Storage Plug-in

Cluster APIを使ってKubernetesクラスタで、vSphere CSIcsi-vsphere.confの設定がどのようになっているかを確認するには、以下のコマンドを実行します。

$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl edit secret csi-vsphere-config -n kube-system
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  csi-vsphere.conf: <設定値>
kind: Secret
metadata:
  creationTimestamp: "<date>"
  name: csi-vsphere-config
  namespace: kube-system
  resourceVersion: "3908"
  uid: 2b96cb9c-5444-425a-a625-f1b6c4ca5754
type: Opaque

csi-vsphere.confにbase64エンコードされた設定値が入っており、値を確認してみます。設定値を見ると、 insecure-flag が設定されていないことが分かります。

$ echo "設定値" | base64 -d
[Global]
cluster-id = "default/vsphere-quickstart"

[VirtualCenter "vcsa-1.home.lab"]
user = "vCenter username"
password = "vCenter password"
datacenters = "datacenter name"

[Network]
public-network = "portgroup name"

csi-vsphere.confの定義ファイルに、 insecure-flag = "true" を追加し、base64でデコードします。

$ vi csi-vsphere.conf
[Global]
cluster-id = "default/vsphere-quickstart"

[VirtualCenter "vcsa-1.home.lab"]
insecure-flag = "true"
user = "vCenter username"
password = "vCenter password"
datacenters = "datacenter name"

[Network]
public-network = "portgroup name"
$ base64 csi-vsphere.conf
<出力値>

base64でデコードした値をsecretのcsi-vsphere.confに入力し、保存します。

$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl edit secret csi-vsphere-config -n kube-system
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  csi-vsphere.conf: <値を入れ替え>
kind: Secret
metadata:
  creationTimestamp: "<date>"
  name: csi-vsphere-config
  namespace: kube-system
  resourceVersion: "3908"
  uid: 2b96cb9c-5444-425a-a625-f1b6c4ca5754
type: Opaque

podを再起動し、vsphere-csi-controllerが起動してくることを確認します。

$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl rollout restart deploy vsphere-csi-controller -n kube-system

再起動後のpodの状態はこちらです。

$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl get pod -A
NAMESPACE     NAME                                               READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-74677b4c5f-87sdx           1/1     Running   0          66m
kube-system   calico-node-26nls                                  1/1     Running   0          66m
kube-system   calico-node-kgnzr                                  1/1     Running   0          66m
kube-system   calico-node-qhmm6                                  1/1     Running   0          66m
kube-system   calico-node-rpsbk                                  1/1     Running   0          66m
kube-system   coredns-565d847f94-drphk                           1/1     Running   0          68m
kube-system   coredns-565d847f94-qc66x                           1/1     Running   0          68m
kube-system   etcd-vsphere-quickstart-9nzbv                      1/1     Running   0          68m
kube-system   kube-apiserver-vsphere-quickstart-9nzbv            1/1     Running   0          68m
kube-system   kube-controller-manager-vsphere-quickstart-9nzbv   1/1     Running   0          68m
kube-system   kube-proxy-9ntsx                                   1/1     Running   0          68m
kube-system   kube-proxy-dqrpj                                   1/1     Running   0          67m
kube-system   kube-proxy-v5j24                                   1/1     Running   0          67m
kube-system   kube-proxy-zqp7h                                   1/1     Running   0          67m
kube-system   kube-scheduler-vsphere-quickstart-9nzbv            1/1     Running   0          68m
kube-system   kube-vip-vsphere-quickstart-9nzbv                  1/1     Running   0          68m
kube-system   vsphere-cloud-controller-manager-4fmp2             1/1     Running   0          67m
kube-system   vsphere-cloud-controller-manager-r7sq7             1/1     Running   0          67m
kube-system   vsphere-cloud-controller-manager-z6dcx             1/1     Running   0          67m
kube-system   vsphere-csi-controller-d695747dc-qhjqs             5/5     Running   0          35s
kube-system   vsphere-csi-node-98z65                             3/3     Running   0          67m
kube-system   vsphere-csi-node-jjx8r                             3/3     Running   0          67m
kube-system   vsphere-csi-node-rfg6w                             3/3     Running   0          67m
kube-system   vsphere-csi-node-stlbj                             3/3     Running   0          68m

起動はできましたが、vsphere-csi-controllerのバージョンを確認してみると、v2.1.0を利用していることが分かります。

VMware vSphere Container Storage Plug-inのリリースノートを見ると、v2.1.0はKubernetes v1.19までしかサポートしていないことが分かります。

VMware vSphere Container Storage Plug-in 2.1 Release Notes

この問題については、こちらのissueでも議論されているようでした。

CAPV CSI driver isn't passing TLS thumbprint · Issue #1162 · kubernetes-sigs/cluster-api-provider-vsphere · GitHub

vSphere CSI Controllerがデプロイされる動作

Cluster API Provider vSphereで、vSphere CSI Controllerが自動的にデプロイされている理由としては、ClusterResourceSetが利用されています。

ClusterResourceSetは、workload clusterを作成した際に、workload clusterに追加のコンポーネントを自動的にインストールできるようにする実験的な機能です。

CNIを毎回コマンドでインストールしているため、自動でインストールされると便利ではあります。

ClusterResourceSetの設定内容について確認してみようと思います。

workload clusterを作成する際に、cluster.yamlを作成しましたが、こちらの中身を見てみます。

$ clusterctl generate cluster vsphere-quickstart \
    --infrastructure vsphere \
    --kubernetes-version v1.25.5 \
    --control-plane-machine-count 1 \
    --worker-machine-count 3 > cluster.yaml

ClusterResourceSetのリソースの中に、csi-vsphere-configがあることが分かります。csi-vsphere-configの中身には、insecure-flag が設定されていないことが分かります。

$ vi cluster.yaml
---
apiVersion: addons.cluster.x-k8s.io/v1beta1
kind: ClusterResourceSet
metadata:
  labels:
    cluster.x-k8s.io/cluster-name: vsphere-quickstart
  name: vsphere-quickstart-crs-0
  namespace: default
spec:
  clusterSelector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: vsphere-quickstart
  resources:
  - kind: Secret
    name: vsphere-csi-controller
  - kind: ConfigMap
    name: vsphere-csi-controller-role
  - kind: ConfigMap
    name: vsphere-csi-controller-binding
  - kind: Secret
    name: csi-vsphere-config
  - kind: ConfigMap
    name: csi.vsphere.vmware.com
  - kind: ConfigMap
    name: vsphere-csi-node
  - kind: ConfigMap
    name: vsphere-csi-controller
  - kind: Secret
    name: cloud-controller-manager
  - kind: Secret
    name: cloud-provider-vsphere-credentials
  - kind: ConfigMap
    name: cpi-manifests
:
---
apiVersion: v1
kind: Secret
metadata:
  name: csi-vsphere-config
  namespace: default
stringData:
  data: |
    apiVersion: v1
    kind: Secret
    metadata:
      name: csi-vsphere-config
      namespace: kube-system
    stringData:
      csi-vsphere.conf: |+
        [Global]
        cluster-id = "default/vsphere-quickstart"

        [VirtualCenter "vcsa-1.home.lab"]
        user = "vCenter username"
        password = "vCenter password"
        datacenters = "datacenter name"

        [Network]
        public-network = "portgroup name"

    type: Opaque
type: addons.cluster.x-k8s.io/resource-set

cluster.yamlcsi-vsphere-configを書き換えても、vsphere-csi-controllerが起動してくることが分かりました。

また、csi-vsphere-configにthumbprintオプションを追加し、vCenterのサーバー証明書のthumbprintやvCenterのCAのthumbprintを指定してみましたが、エラーは解消しませんでした。

現状は、csi-vsphere-configを書き換えても、vSphere CSIはサポートされない組み合わせとなってしまうため、ClusterResourceSetを使う場合でもバージョンの更新が課題になってきそうに見えています。

Continuous ClusterResourceSetStrategy · Issue #4807 · kubernetes-sigs/cluster-api · GitHub

また、clusterctl.yamlEXP_CLUSTER_RESOURCE_SET を false にしても、Taintの設定上podが起動してこないため、現状は一度vSphere CSIを削除し、最新バージョンのvSphere CSIをインストールし直さないといけないようには見えており、他にいい方法がないか気になっています。

参考