今まではKubesprayを使ってKubernetesのインストールを行ってきました。今回は、Cluster APIを使ったKubernetesクラスタを作成を試してみました。
構成
- vCenter 7.0 U3
- ESXi 7.0 Update 3
- Kubespray
- kubernetes v1.25.5
- Cluster API v1.3.2
Cluster APIについて
Cluster APIは、Kubernetesの宣言型の機能を利用し、Kubernetesクラスタの作成や構成、管理をするプロジェクトになります。Kubesprayでは、masterノートやworkerノードの展開はgovcなど自身で行ってきましたが、Cluster APIではその作業も任せることができます。Cluster APIはパブリッククラウドなど様々なプラットフォームに対応しており、vSphereにも対応しており、vSphereの実装として、Cluster API Provider vSphere(CAPV)があります。CAPVはTanzu Kubernetes Grid(TKG)の中でも利用されているようです。
Cluster APIを利用すると、Kubernetesクラスタを管理するmanagement clusterと、management clusterで管理されたワークロードを実行するworkload clusterが作成されます。
workload cluster用のネットワークの準備
workload clusterはDHCPでIPアドレスを取得するため、workload clusterが接続するポートグループにDHCPでIPアドレスを取得できるようにしておきます。homelabでは、EdgeRouterのDHCP機能でIPアドレスを払い出ししています。
マシンイメージの展開
CAPV用のマシンイメージが配布されており、 ubuntu-2004-kube-v1.25.5.ova
をダウンロードし、vCenter上にデプロイします。
homelabでの利用なので、マシンイメージをそのまま利用しますが、production環境では独自ビルドが推奨なようです。
マシンイメージのビルド用のpackerテンプレートはこちらで管理されていました。
image-builder/images/capi/packer/ova at master · kubernetes-sigs/image-builder · GitHub
Cluster APIでマシンイメージを展開する際に、デフォルトだとlinked cloneが利用されるため、以下のようにlinked cloneを利用するためにスナップショットをとってから、テンプレート化しておきます。
$ govc snapshot.create -vm ubuntu-2004-kube-v1.25.5 root $ govc vm.markastemplate ubuntu-2004-kube-v1.25.5
haproxyのマシンイメージについては、kube-vipを使うように変更となったため、非推奨となってようなので、利用はしていません。
management clusterのインストール
通常の手順ですと、kindを利用して、docker上にKubernetesをインストールして、bootstrap clusterを作成し、そこにclusterctlを使ってmanagement clusterをインストールします。
今回は、KubesprayですでにKubernetesクラスタがあるため、Kubesprayで作成したKubernetesクラスタにmanagement clusterをインストールしていきます。
clusterctlをインストールします。
$ curl -L https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.3.2/clusterctl-linux-amd64 -o clusterctl $ sudo install -o root -g root -m 0755 clusterctl /usr/local/bin/clusterctl $ clusterctl version
clusterctlを実行するために、以下のように ~/.cluster-api/clusterctl.yaml
に定義ファイルを用意します。
$ vi ~/.cluster-api/clusterctl.yaml ## -- Controller settings -- ## VSPHERE_USERNAME: "vCenterのログインユーザ" VSPHERE_PASSWORD: "パスワード" ## -- Required workload cluster default settings -- ## VSPHERE_SERVER: "vCenterのFQDN" VSPHERE_DATACENTER: "データセンター名" VSPHERE_DATASTORE: "データストア名" VSPHERE_NETWORK: "DHCPが利用可能なポートグループ名" VSPHERE_RESOURCE_POOL: "<クラスタ名 or リソースプール名>/Resources" VSPHERE_FOLDER: "vm" VSPHERE_TEMPLATE: "ubuntu-2004-kube-v1.25.5" CONTROL_PLANE_ENDPOINT_IP: "workload clusterのkubectlで接続するコントロールプレーンのIPアドレス" VIP_NETWORK_INTERFACE: "eth0" VSPHERE_TLS_THUMBPRINT: "vCenterのthumbprint" EXP_CLUSTER_RESOURCE_SET: "true" VSPHERE_SSH_AUTHORIZED_KEY: "sshのための公開鍵" VSPHERE_STORAGE_POLICY: ""
vCenterのthumbprintは、vCenterにsshでログインし、以下のコマンドで取得します。
# openssl x509 -in /etc/vmware-vpx/ssl/rui.crt -fingerprint -sha1 -noout
vCenterのログイン情報や、workload clusterを作成するために必要なリソースプールやデータストア名などを入力します。
上記の設定で困ったことは、 CONTROL_PLANE_ENDPOINT_IP
と VIP_NETWORK_INTERFACE
の設定になります。
CONTROL_PLANE_ENDPOINT_IP
はkube-vipで利用するworkload clusterのコントロールプレーンのIPアドレスになり、DHCPのIP帯以外のstaticなIPアドレスを指定する必要があります。ここのIPアドレスの指定を間違えると、コントロールプレーンにアクセスできないとエラーが出て、workload clusterの作成に失敗します。
$ kubectl logs capi-kubeadm-control-plane-controller-manager-785c94c5d4-sh9fg -n capi-kubeadm-control-plane-system -f "Failed to update KubeadmControlPlane Status" err="failed to create remote cluster client: failed to create cluster accessor: error creating dynamic rest mapper for remote cluster \"default/vsphere-quickstart\": Get \"https://10.0.50 .30:6443/api?timeout=10s\": x509: certificate signed by unknown authority (possibly because of \"crypto/rsa: verification error\" while trying to verify candidate authority certificate \"kubernetes\")" controller="kubeadmcontrolplane" controllerGroup="controlplane.cluster.x-k8s.io" controllerKind="KubeadmControlPlane" KubeadmControlPlane="default/vsphere-quickstart" namespace="default" name="vsphere-quickstart" reconcileID=fa7159b4-97ff-45cd-b1ba-29a4d5f11548 Cluster="default/vsphere-quickstart"
VIP_NETWORK_INTERFACE
は、コントロールプレーンのkube-vipで利用するインターフェイスの設定となりますが、公式のマシンイメージでは、インターフェイスにeth0を利用しており、サンプルではens192だったため、コントロールプレーンにアクセスできず、workload clusterの作成に失敗します。
~/.cluster-api/clusterctl.yaml
が出来たところで、以下のコマンドで、management clusterのインストールを行います。
$ clusterctl init --infrastructure vsphere Fetching providers Installing cert-manager Version="v1.10.1" Waiting for cert-manager to be available... Installing Provider="cluster-api" Version="v1.3.2" TargetNamespace="capi-system" Installing Provider="bootstrap-kubeadm" Version="v1.3.2" TargetNamespace="capi-kubeadm-bootstrap-system" Installing Provider="control-plane-kubeadm" Version="v1.3.2" TargetNamespace="capi-kubeadm-control-plane-system" Installing Provider="infrastructure-vsphere" Version="v1.5.1" TargetNamespace="capv-system" Your management cluster has been initialized successfully! You can now create your first workload cluster by running the following: clusterctl generate cluster [name] --kubernetes-version [version] | kubectl apply -f -
以下のような、podが起動してきます。
$ kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE capi-kubeadm-bootstrap-system capi-kubeadm-bootstrap-controller-manager-78c76cd689-flgtb 1/1 Running 0 3d capi-kubeadm-control-plane-system capi-kubeadm-control-plane-controller-manager-785c94c5d4-sh9fg 1/1 Running 0 3d capi-system capi-controller-manager-8665f47486-thlh4 1/1 Running 0 3d capv-system capv-controller-manager-dfb77fcc6-tz7t8 1/1 Running 0 2d19h cert-manager cert-manager-74d949c895-v4g52 1/1 Running 0 3d cert-manager cert-manager-cainjector-d9bc5979d-ktwrz 1/1 Running 0 3d cert-manager cert-manager-webhook-84b7ddd796-fdj8l 1/1 Running 0 3d
workload clusterのインストール
次に、workload clusterのインストールをしていきます。
workload clusterのKubernetsのバージョンや、コントロールプレーンのVM数、wokerノードのVM数を指定して、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
必要に応じて、cluster.yamlを編集します。
以下のコマンドで、workload clusterのインストールを行います。
$ kubectl apply -f cluster.yaml
以下のコマンドで、workload clusterが起動してきかたを確認できます。10分ぐらいで立ち上がってくるように見えています。
$ kubectl get machines NAME CLUSTER NODENAME PROVIDERID PHASE AGE VERSION vsphere-quickstart-md-0-5c5849c5b9-5wbv8 vsphere-quickstart vsphere-quickstart-md-0-5c5849c5b9-5wbv8 vsphere://42080fa2-7dab-7285-444a-7b0ecc66a35e Running 7m15s v1.25.5 vsphere-quickstart-md-0-5c5849c5b9-95595 vsphere-quickstart vsphere-quickstart-md-0-5c5849c5b9-95595 vsphere://4208d8b7-8297-c452-26f9-e7061d023e8a Running 7m15s v1.25.5 vsphere-quickstart-md-0-5c5849c5b9-s4rz9 vsphere-quickstart vsphere-quickstart-md-0-5c5849c5b9-s4rz9 vsphere://4208246c-a347-1f39-51c3-3907b502f884 Running 7m15s v1.25.5 vsphere-quickstart-sxfqt vsphere-quickstart vsphere-quickstart-sxfqt vsphere://4208aad8-d2e7-42bf-00ac-70511419ff77 Running 7m14s v1.25.5
workload clusterにアクセスするためのconfigファイルを以下のように生成します。
$ kubectl get secret/vsphere-quickstart-kubeconfig -o json \ | jq -r .data.value \ | base64 --decode \ > ./vsphere-quickstart.kubeconfig
workload clusterのノードを確認すると、NotReadyとなっています。こちらはCNIがインストールされていないため、利用ができない状態となっています。
$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl get node NAME STATUS ROLES AGE VERSION vsphere-quickstart-md-0-5c5849c5b9-5wbv8 NotReady <none> 10m v1.25.5 vsphere-quickstart-md-0-5c5849c5b9-95595 NotReady <none> 10m v1.25.5 vsphere-quickstart-md-0-5c5849c5b9-s4rz9 NotReady <none> 10m v1.25.5 vsphere-quickstart-sxfqt NotReady control-plane 11m v1.25.5
以下のようにcalicoをインストールします。
$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl apply -f https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml
Readyになったことを確認し、workload clusterのインストールは完了になります。
$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl get node NAME STATUS ROLES AGE VERSION vsphere-quickstart-md-0-5c5849c5b9-5wbv8 Ready <none> 28h v1.25.5 vsphere-quickstart-md-0-5c5849c5b9-95595 Ready <none> 28h v1.25.5 vsphere-quickstart-md-0-5c5849c5b9-s4rz9 Ready <none> 28h v1.25.5 vsphere-quickstart-sxfqt Ready control-plane 28h v1.25.5
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
スモークテスト
動作確認を行います。
テスト用のpodを2台作成し、pod間で疎通が取れるか確認します。
$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl run myshell1 -it --rm --image busybox -- sh / # hostname -i 192.168.136.2 / # ping 192.168.82.67 PING 192.168.82.67 (192.168.82.67): 56 data bytes 64 bytes from 192.168.82.67: seq=0 ttl=62 time=0.615 ms 64 bytes from 192.168.82.67: seq=1 ttl=62 time=3.218 ms ^C --- 192.168.82.67 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.615/1.916/3.218 ms
$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl run myshell2 -it --rm --image busybox -- sh / # hostname -i 192.168.82.67 / # ping 192.168.136.2 PING 192.168.136.2 (192.168.136.2): 56 data bytes 64 bytes from 192.168.136.2: seq=0 ttl=62 time=0.918 ms 64 bytes from 192.168.136.2: seq=1 ttl=62 time=0.316 ms ^C --- 192.168.136.2 ping statistics --- 2 packets transmitted, 2 packets received, 0% packet loss round-trip min/avg/max = 0.316/0.617/0.918 ms
podの状態は以下の通りです。
$ KUBECONFIG=vsphere-quickstart.kubeconfig kubectl get pod -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES myshell1 1/1 Running 0 50s 192.168.136.2 vsphere-quickstart-md-0-5c5849c5b9-5wbv8 <none> <none> myshell2 1/1 Running 0 28s 192.168.82.67 vsphere-quickstart-md-0-5c5849c5b9-95595 <none> <none>
おわりに
KubesprayだとKubernetesクラスタのインストールに30分ぐらいかかりましたが、Cluster APIだと10分程度で利用ができるので、効率がよさそうでした。ただ、Kubesprayだとクラスタの初期設定(CNIやMetalLB)もある程度対応できたり、マシンイメージのビルドが楽だったり、構築中の動作やどのような設定を行っているかが分かりやすいということもあり、homelabだとKubesprayのほうが使いやすそうには見えています。用途によって使い分けるのがよさそうに見えました。