@@ -61,7 +61,7 @@ a target [management cluster] on the selected [infrastructure provider].
61
61
The installation procedure depends on the version of kind; if you are planning to use the Docker infrastructure provider,
62
62
please follow the additional instructions in the dedicated tab:
63
63
64
- {{#tabs name:"install-kind" tabs:"Default,Docker"}}
64
+ {{#tabs name:"install-kind" tabs:"Default,Docker,KubeVirt "}}
65
65
{{#tab Default}}
66
66
67
67
Create the kind cluster:
@@ -93,6 +93,57 @@ a target [management cluster] on the selected [infrastructure provider].
93
93
Then follow the instruction for your kind version using ` kind create cluster --config kind-cluster-with-extramounts.yaml`
94
94
to create the management cluster using the above file.
95
95
96
+ {{# /tab }}
97
+ {{#tab KubeVirt}}
98
+
99
+ #### Create the Kind Cluster
100
+ [KubeVirt][KubeVirt] is a cloud native virtualization solution. The virtual machines we're going to create and use for
101
+ the workload cluster's nodes, are actually running within pods in the management cluster. In order to communicate with
102
+ the workload cluster's API server, we'll need to expose it. We are using Kind which is a limited environment. The
103
+ easiest way to expose the workload cluster's API server (a pod within a node running in a VM that is itself running
104
+ within a pod in the management cluster, that is running inside a docker container), is to use a LoadBalancer service.
105
+
106
+ To allow using a LoadBalancer service, we can't use the kind's default CNI (kindnet), but we'll need to install
107
+ another CNI, like Calico. In order to do that, we'll need first to initiate the kind cluster with two modifications:
108
+ 1. Disable the default CNI
109
+ 2. Add the docker credentials to the cluster, to avoid the docker hub pull rate limit of the calico images; read more
110
+ about it in the [docker documentation](https://docs.docker.com/docker-hub/download-rate-limit/), and in the
111
+ [kind documentation](https://kind.sigs.k8s.io/docs/user/private-registries/#mount-a-config-file-to-each-node).
112
+
113
+ Create a configuration file for kind. Please notice the docker config file path, and adjust it to your local setting:
114
+ ` ` ` bash
115
+ cat <<EOF > kind-config.yaml
116
+ kind: Cluster
117
+ apiVersion: kind.x-k8s.io/v1alpha4
118
+ networking:
119
+ # the default CNI will not be installed
120
+ disableDefaultCNI: true
121
+ nodes:
122
+ - role: control-plane
123
+ extraMounts:
124
+ - containerPath: /var/lib/kubelet/config.json
125
+ hostPath: <YOUR DOCKER CONFIG FILE PATH>
126
+ EOF
127
+ ` ` `
128
+ Now, create the kind cluster with the configuration file:
129
+ ` ` ` bash
130
+ kind create cluster --config=kind-config.yaml
131
+ ` ` `
132
+ Test to ensure the local kind cluster is ready:
133
+ ` ` ` bash
134
+ kubectl cluster-info
135
+ ` ` `
136
+
137
+ # ### Install the Calico CNI
138
+ Now we' ll need to install a CNI. In this example, we' re using calico, but other CNIs should work as well. Please see
139
+ [calico installation guide](https://projectcalico.docs.tigera.io/getting-started/kubernetes/self-managed-onprem/onpremises#install-calico)
140
+ for more details (use the " Manifest" tab). Below is an example of how to install calico version v3.24.4.
141
+
142
+ Use the Calico manifest to create the required resources; e.g.:
143
+ ` ` ` bash
144
+ kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.24.4/manifests/calico.yaml
145
+ ` ` `
146
+
96
147
{{# /tab }}
97
148
{{#/tabs }}
98
149
@@ -202,7 +253,7 @@ Additional documentation about experimental features can be found in [Experiment
202
253
Depending on the infrastructure provider you are planning to use, some additional prerequisites should be satisfied
203
254
before getting started with Cluster API. See below for the expected settings for common providers.
204
255
205
- {{# tabs name:"tab-installation-infrastructure" tabs:"AWS,Azure,CloudStack,DigitalOcean,Docker,Equinix Metal,GCP,Hetzner,IBM Cloud,KubeKey,Kubevirt ,Metal3,Nutanix,OCI,OpenStack,Outscale,VCD,vcluster,Virtink,vSphere"}}
256
+ {{# tabs name:"tab-installation-infrastructure" tabs:"AWS,Azure,CloudStack,DigitalOcean,Docker,Equinix Metal,GCP,Hetzner,IBM Cloud,KubeKey,KubeVirt ,Metal3,Nutanix,OCI,OpenStack,Outscale,VCD,vcluster,Virtink,vSphere"}}
206
257
{{# tab AWS}}
207
258
208
259
Download the latest binary of ` clusterawsadm` from the [AWS provider releases].
@@ -442,9 +493,61 @@ clusterctl init --infrastructure kubekey
442
493
` ` `
443
494
444
495
{{# /tab }}
445
- {{# tab Kubevirt}}
496
+ {{# tab KubeVirt}}
497
+
498
+ Please visit the [KubeVirt project][KubeVirt provider] for more information.
446
499
447
- Please visit the [Kubevirt project][Kubevirt provider].
500
+ As described above, we want to use a LoadBalancer service in order to expose the workload cluster' s API server. In the
501
+ example below, we will use [MetalLB](https://metallb.universe.tf/) solution to implement load balancing to our kind
502
+ cluster. Other solution should work as well.
503
+
504
+ #### Install MetalLB for load balancing
505
+ Install MetalLB, as described [here](https://metallb.universe.tf/installation/#installation-by-manifest); for example:
506
+ ```bash
507
+ METALLB_VER=$(curl "https://api.github.com/repos/metallb/metallb/releases/latest" | jq -r ".tag_name")
508
+ kubectl apply -f "https://raw.githubusercontent.com/metallb/metallb/${METALLB_VER}/config/manifests/metallb-native.yaml"
509
+ kubectl wait pods -n metallb-system -l app=metallb,component=controller --for=condition=Ready --timeout=10m
510
+ kubectl wait pods -n metallb-system -l app=metallb,component=speaker --for=condition=Ready --timeout=2m
511
+ ```
512
+
513
+ Now, we' ll create the ` IPAddressPool` and the ` L2Advertisement` custom resources. The script below creates the CRs with
514
+ the right addresses, that match to the kind cluster addresses:
515
+ ` ` ` bash
516
+ GW_IP=$( docker network inspect -f ' {{range .IPAM.Config}}{{.Gateway}}{{end}}' kind)
517
+ NET_IP=$( echo ${GW_IP} | sed -E ' s|^([0-9]+\.[0-9]+)\..*$|\1|g' )
518
+ cat << EOF | sed -E "s|172.19|${NET_IP} |g" | kubectl apply -f -
519
+ apiVersion: metallb.io/v1beta1
520
+ kind: IPAddressPool
521
+ metadata:
522
+ name: capi-ip-pool
523
+ namespace: metallb-system
524
+ spec:
525
+ addresses:
526
+ - 172.19.255.200-172.19.255.250
527
+ ---
528
+ apiVersion: metallb.io/v1beta1
529
+ kind: L2Advertisement
530
+ metadata:
531
+ name: empty
532
+ namespace: metallb-system
533
+ EOF
534
+ ` ` `
535
+
536
+ # ### Install KubeVirt on the kind cluster
537
+ ` ` ` bash
538
+ # get KubeVirt version
539
+ KV_VER=$( curl " https://api.github.com/repos/kubevirt/kubevirt/releases/latest" | jq -r " .tag_name" )
540
+ # deploy required CRDs
541
+ kubectl apply -f " https://github.com/kubevirt/kubevirt/releases/download/${KV_VER} /kubevirt-operator.yaml"
542
+ # deploy the KubeVirt custom resource
543
+ kubectl apply -f " https://github.com/kubevirt/kubevirt/releases/download/${KV_VER} /kubevirt-cr.yaml"
544
+ kubectl wait -n kubevirt kv kubevirt --for=condition=Available --timeout=10m
545
+ ` ` `
546
+
547
+ # ### Initialize the management cluster with the KubeVirt Provider
548
+ ` ` ` bash
549
+ clusterctl init --infrastructure kubevirt
550
+ ` ` `
448
551
449
552
{{# /tab }}
450
553
{{# tab Metal3}}
@@ -601,7 +704,7 @@ before configuring a cluster with Cluster API. Instructions are provided for com
601
704
Otherwise, you can look at the ` clusterctl generate cluster` [command][clusterctl generate cluster] documentation for details about how to
602
705
discover the list of variables required by a cluster templates.
603
706
604
- {{# tabs name:"tab-configuration-infrastructure" tabs:"AWS,Azure,CloudStack,DigitalOcean,Docker,Equinix Metal,GCP,IBM Cloud,KubeKey,Kubevirt ,Metal3,Nutanix,OpenStack,Outscale,VCD,vcluster,Virtink,vSphere"}}
707
+ {{# tabs name:"tab-configuration-infrastructure" tabs:"AWS,Azure,CloudStack,DigitalOcean,Docker,Equinix Metal,GCP,IBM Cloud,KubeKey,KubeVirt ,Metal3,Nutanix,OpenStack,Outscale,VCD,vcluster,Virtink,vSphere"}}
605
708
{{# tab AWS}}
606
709
607
710
` ` ` bash
@@ -820,15 +923,14 @@ export CONTROL_PLANE_ENDPOINT_IP=<your-control-plane-virtual-ip>
820
923
Please visit the [KubeKey provider] for more information.
821
924
822
925
{{# /tab }}
823
- {{#tab Kubevirt}}
824
-
825
- A ClusterAPI compatible image must be available in your Kubevirt image library. For instructions on how to build a compatible image
826
- see [image-builder](https://image-builder.sigs.k8s.io/capi/capi.html).
926
+ {{#tab KubeVirt}}
827
927
828
- To see all required Kubevirt environment variables execute:
829
928
` ` ` bash
830
- clusterctl generate cluster --infrastructure kubevirt --list-variables capi-quickstart
929
+ export CAPK_GUEST_K8S_VERSION=" v1.23.10"
930
+ export CRI_PATH=" /var/run/containerd/containerd.sock"
931
+ export NODE_VM_IMAGE_TEMPLATE=" quay.io/capk/ubuntu-2004-container-disk:${CAPK_GUEST_K8S_VERSION} "
831
932
` ` `
933
+ Please visit the [KubeVirt project][KubeVirt provider] for more information.
832
934
833
935
{{# /tab }}
834
936
{{#tab Metal3}}
@@ -1007,7 +1109,7 @@ For more information about prerequisites, credentials management, or permissions
1007
1109
1008
1110
For the purpose of this tutorial, we'll name our cluster capi-quickstart.
1009
1111
1010
- {{#tabs name:"tab-clusterctl-config-cluster" tabs:"Docker, vcluster, others..."}}
1112
+ {{#tabs name:"tab-clusterctl-config-cluster" tabs:"Docker, vcluster, KubeVirt, others..."}}
1011
1113
{{#tab Docker}}
1012
1114
1013
1115
<aside class="note warning">
@@ -1042,6 +1144,22 @@ clusterctl generate cluster ${CLUSTER_NAME} \
1042
1144
--target-namespace ${CLUSTER_NAMESPACE} | kubectl apply -f -
1043
1145
` ` `
1044
1146
1147
+ {{# /tab }}
1148
+ {{#tab KubeVirt}}
1149
+
1150
+ As we described above, in this tutorial, we will use a LoadBalancer service in order to expose the API server of the
1151
+ workload cluster, so we want to use the load balancer (lb) template (rather than the default one). We'll use the
1152
+ clusterctl's ` --flavor` flag for that:
1153
+ ` ` ` bash
1154
+ clusterctl generate cluster capi-quickstart \
1155
+ --infrastructure=" kubevirt" \
1156
+ --flavor lb \
1157
+ --kubernetes-version ${CAPK_GUEST_K8S_VERSION} \
1158
+ --control-plane-machine-count=1 \
1159
+ --worker-machine-count=1 \
1160
+ > capi-quickstart.yaml
1161
+ ` ` `
1162
+
1045
1163
{{# /tab }}
1046
1164
{{#tab others...}}
1047
1165
@@ -1151,7 +1269,7 @@ Note: To use the default clusterctl method to retrieve kubeconfig for a workload
1151
1269
1152
1270
Calico is used here as an example.
1153
1271
1154
- {{#tabs name:"tab-deploy-cni" tabs:"Azure,vcluster,others..."}}
1272
+ {{#tabs name:"tab-deploy-cni" tabs:"Azure,vcluster,KubeVirt, others..."}}
1155
1273
{{#tab Azure}}
1156
1274
1157
1275
Azure [does not currently support Calico networking](https://docs.projectcalico.org/reference/public-cloud/azure). As a workaround, it is recommended that Azure clusters use the Calico spec below that uses VXLAN.
@@ -1173,6 +1291,126 @@ kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes
1173
1291
1174
1292
Calico not required for vcluster.
1175
1293
1294
+ {{#/tab }}
1295
+ {{#tab KubeVirt}}
1296
+
1297
+ Before deploying the Calico CNI, make sure the VMs are running:
1298
+ ` ` ` bash
1299
+ kubectl get vm
1300
+ ` ` `
1301
+
1302
+ If our new VMs are running, we should see a response similar to this:
1303
+
1304
+ ` ` ` text
1305
+ NAME AGE STATUS READY
1306
+ capi-quickstart-control-plane-7s945 167m Running True
1307
+ capi-quickstart-md-0-zht5j 164m Running True
1308
+ ` ` `
1309
+
1310
+ We can also read the virtual machine instances:
1311
+ ` ` ` bash
1312
+ kubectl get vmi
1313
+ ` ` `
1314
+ The output will be similar to:
1315
+ ` ` ` text
1316
+ NAME AGE PHASE IP NODENAME READY
1317
+ capi-quickstart-control-plane-7s945 167m Running 10.244.82.16 kind-control-plane True
1318
+ capi-quickstart-md-0-zht5j 164m Running 10.244.82.17 kind-control-plane True
1319
+ ` ` `
1320
+
1321
+ Since our workload cluster is running within the kind cluster, we need to prevent conflicts between the kind
1322
+ (management) cluster' s CNI, and the workload cluster CNI. The following modifications in the default Calico settings
1323
+ are enough for these two CNI to work on (actually) the same environment.
1324
+
1325
+ * Change the CIDR to a non-conflicting range
1326
+ * Change the value of the `CLUSTER_TYPE` environment variable to `k8s`
1327
+ * Change the value of the `CALICO_IPV4POOL_IPIP` environment variable to `Never`
1328
+ * Change the value of the `CALICO_IPV4POOL_VXLAN` environment variable to `Always`
1329
+ * Add the `FELIX_VXLANPORT` environment variable with the value of a non-conflicting port, e.g. `"6789"`.
1330
+
1331
+ The following script downloads the Calico manifest and modifies the required field. The CIDR and the port values are examples.
1332
+ ```bash
1333
+ curl https://raw.githubusercontent.com/projectcalico/calico/v3.24.4/manifests/calico.yaml -o calico-workload.yaml
1334
+
1335
+ sed -i -E ' s| ^( +)# (- name: CALICO_IPV4POOL_CIDR)$|\1\2|g;'\
1336
+ 's|^( +)# ( value: )"192.168.0.0/16"|\1\2"10.243.0.0/16"|g;'\
1337
+ '/- name: CLUSTER_TYPE/{ n; s/( +value: ").+/\1k8s"/g };'\
1338
+ '/- name: CALICO_IPV4POOL_IPIP/{ n; s/value: "Always"/value: "Never"/ };'\
1339
+ '/- name: CALICO_IPV4POOL_VXLAN/{ n; s/value: "Never"/value: "Always"/};'\
1340
+ '/# Set Felix endpoint to host default action to ACCEPT./a\ - name: FELIX_VXLANPORT\n value: "6789"' \
1341
+ calico-workload.yaml
1342
+ ` ` `
1343
+ Now, deploy the Calico CNI on the workload cluster:
1344
+ ` ` ` bash
1345
+ kubectl --kubeconfig=./capi-quickstart.kubeconfig create -f calico-workload.yaml
1346
+ ` ` `
1347
+
1348
+ After a short while, our nodes should be running and in ` Ready` state, let’s check the status using ` kubectl get nodes` :
1349
+
1350
+ ` ` ` bash
1351
+ kubectl --kubeconfig=./capi-quickstart.kubeconfig get nodes
1352
+ ` ` `
1353
+
1354
+ < aside class=" note" >
1355
+
1356
+ < h1> Troubleshooting< /h1>
1357
+
1358
+ If the nodes don' t become ready after a long period, read the pods in the `kube-system` namespace
1359
+ ```bash
1360
+ kubectl --kubeconfig=./capi-quickstart.kubeconfig get pod -n kube-system
1361
+ ```
1362
+
1363
+ If the Calico pods are in image pull error state (`ErrImagePull`), it' s probably because of the docker hub pull rate limit.
1364
+ We can try to fix that by adding a secret with our docker hub credentials, and use it;
1365
+ see [here](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/# registry-secret-existing-credentials)
1366
+ for details.
1367
+
1368
+ First, create the secret. Please notice the docker config file path, and adjust it to your local setting.
1369
+ ` ` ` bash
1370
+ kubectl --kubeconfig=./capi-quickstart.kubeconfig create secret generic docker-creds \
1371
+ --from-file=.dockerconfigjson=< YOUR DOCKER CONFIG FILE PATH> \
1372
+ --type=kubernetes.io/dockerconfigjson \
1373
+ -n kube-system
1374
+ ` ` `
1375
+
1376
+ Now, if the ` calico-node` pods are with status of ` ErrImagePull` , patch their DaemonSet to make them use the new secret to pull images:
1377
+ ` ` ` bash
1378
+ kubectl --kubeconfig=./capi-quickstart.kubeconfig patch daemonset \
1379
+ -n kube-system calico-node \
1380
+ -p ' {"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"docker-creds"}]}}}}'
1381
+ ` ` `
1382
+
1383
+ After a short while, the calico-node pods will be with ` Running` status. Now, if the calico-kube-controllers pod is also
1384
+ in ` ErrImagePull` status, patch its deployment to fix the problem:
1385
+ ` ` ` bash
1386
+ kubectl --kubeconfig=./capi-quickstart.kubeconfig patch deployment \
1387
+ -n kube-system calico-kube-controllers \
1388
+ -p ' {"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"docker-creds"}]}}}}'
1389
+ ` ` `
1390
+
1391
+ Read the pods again
1392
+ ` ` ` bash
1393
+ kubectl --kubeconfig=./capi-quickstart.kubeconfig get pod -n kube-system
1394
+ ` ` `
1395
+
1396
+ Eventually, all the pods in the kube-system namespace will run, and the result should be similar to this:
1397
+ ` ` ` text
1398
+ NAME READY STATUS RESTARTS AGE
1399
+ calico-kube-controllers-c969cf844-dgld6 1/1 Running 0 50s
1400
+ calico-node-7zz7c 1/1 Running 0 54s
1401
+ calico-node-jmjd6 1/1 Running 0 54s
1402
+ coredns-64897985d-dspjm 1/1 Running 0 3m49s
1403
+ coredns-64897985d-pgtgz 1/1 Running 0 3m49s
1404
+ etcd-capi-quickstart-control-plane-kjjbb 1/1 Running 0 3m57s
1405
+ kube-apiserver-capi-quickstart-control-plane-kjjbb 1/1 Running 0 3m57s
1406
+ kube-controller-manager-capi-quickstart-control-plane-kjjbb 1/1 Running 0 3m57s
1407
+ kube-proxy-b9g5m 1/1 Running 0 3m12s
1408
+ kube-proxy-p6xx8 1/1 Running 0 3m49s
1409
+ kube-scheduler-capi-quickstart-control-plane-kjjbb 1/1 Running 0 3m57s
1410
+ ` ` `
1411
+
1412
+ < /aside>
1413
+
1176
1414
{{# /tab }}
1177
1415
{{# tab others...}}
1178
1416
@@ -1244,7 +1482,8 @@ See the [clusterctl] documentation for more detail about clusterctl supported ac
1244
1482
[Metal3 getting started guide]: https://github.com/metal3-io/cluster-api-provider-metal3/blob/master/docs/getting-started.md
1245
1483
[Metal3 provider]: https://github.com/metal3-io/cluster-api-provider-metal3/
1246
1484
[KubeKey provider]: https://github.com/kubesphere/kubekey
1247
- [Kubevirt provider]: https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt/
1485
+ [KubeVirt provider]: https://github.com/kubernetes-sigs/cluster-api-provider-kubevirt/
1486
+ [KubeVirt]: https://kubevirt.io/
1248
1487
[oci-provider]: https://oracle.github.io/cluster-api-provider-oci/#getting-started
1249
1488
[Equinix Metal getting started guide]: https://github.com/kubernetes-sigs/cluster-api-provider-packet#using
1250
1489
[provider]:../reference/providers.md
0 commit comments