Creating Clusters on VMware vSphere
This document explains how to create a VMware vSphere workload cluster by applying Cluster API manifests to the ACP global management cluster. The procedure does not create the global cluster itself. It covers a minimum supported topology with one datacenter, one NIC per node, and static IP allocation through VSphereMachineConfigPool. The provider behavior and fields on this page are validated against VMware vSphere Provider v1.0.16.
TOC
ScenariosHow to Use This PagePrerequisitesKey ObjectsClusterResourceSetvSphere CPI componentmachine config poolVM template requirementsLocal File LayoutStepsVerificationTroubleshootingCreation-Time Topology VariantsAdd a second NICMultiple datacenters and failure domainsAdd data disksVerify creation-time variantsNext StepsScenarios
Use this document in the following scenarios:
- You want to create the first baseline VMware vSphere workload cluster in your environment.
- You use one datacenter and one NIC per node for the initial validation.
- You want to keep the first deployment simple before enabling advanced placement or networking features.
This document applies to the following deployment model:
- CAPV connects directly to vCenter.
- Control plane and worker nodes both use
VSphereMachineConfigPoolfor static IP allocation and data disks. ClusterResourceSetdelivers the vSphere CPI component automatically.- The first validation uses one datacenter and one NIC per node.
This document does not apply to the following scenarios:
- A deployment that depends on vSphere Supervisor or
vm-operator. - A deployment that does not use
VSphereMachineConfigPool.
This document is written for the current platform environment. The kube-ovn delivery path depends on platform controllers that consume annotations on the Cluster resource, so this workflow is not intended to be a generic standalone CAPV deployment guide outside the platform context.
How to Use This Page
- Complete the infrastructure and parameter checklist.
- Prepare the baseline manifest files in the procedure below.
- Before applying them, add only the required creation-time topology variants.
- Apply the complete manifest set and finish the verification checks.
- After the cluster is running, use Managing Nodes on VMware vSphere for scale-out, immutable template replacement, and runtime topology changes.
The baseline is the validation reference. If the target cluster needs several optional topology features, introduce and validate one manifest change at a time before combining them.
Prerequisites
Before you begin, ensure the following conditions are met:
- You completed VMware vSphere Infrastructure Preparation.
- The
globalcluster can reach vCenter. - The target template, networks, datastores, and vCenter resource pool are available.
- The external control plane LoadBalancer satisfies the endpoint contract. VMware vSphere Provider
v1.0.16does not deploy a Self-built VIP. - All required static IP addresses are allocated and not in use.
ClusterResourceSet=trueis enabled.- The platform already has a valid
public-registry-credentialSecret, and the permanent Registry address is reachable from workload nodes. - The permanent platform Registry contains the required Kube-OVN, CoreDNS, and vSphere CPI tags.
- The platform can process the cluster annotations required to install the network plugin.
Key Objects
The top-level Cluster references VSphereCluster and the control-plane or worker controllers. Those controllers reference immutable VSphereMachineTemplate objects. Each template references one VSphereMachineConfigPool, whose slots provide hostnames, static network configuration, and persistent disks to the runtime Machine, VSphereMachine, and VSphereVM objects.
ClusterResourceSet
ClusterResourceSet is a Cluster API resource in the global cluster. After the workload API server becomes reachable, it applies the referenced ConfigMap and Secret resources to the workload cluster.
In this workflow, ClusterResourceSet is used to deliver the vSphere CPI resources automatically.
vSphere CPI component
The vSphere CPI component is delivered to the workload cluster through ClusterResourceSet. It connects workload nodes to the vSphere infrastructure so the cluster can report infrastructure identities and complete cloud-provider initialization.
machine config pool
The machine config pool is the VSphereMachineConfigPool custom resource. In the baseline workflow:
- One machine config pool is used for control plane nodes.
- One machine config pool is used for worker nodes.
Each node slot includes the hostname, datacenter, static IP assignment, and optional data disk definitions.
For network configuration, distinguish the following fields:
networkNameis the vCenter network or port group name.deviceNameis the NIC name inside the guest operating system.
If deviceName is set, CAPV writes that value into the generated guest-network metadata. If it is omitted, the current implementation typically uses NIC names such as eth0, eth1, and eth2 by NIC order.
Also distinguish the following value formats:
- A node IP address is used together with a prefix length, for example
10.10.10.11/24. - The gateway field contains only the gateway IP address, for example
10.10.10.1.
VM template requirements
The VM template used by this workflow should meet the following minimum requirements:
- It uses the required operating system for the target platform environment.
- It includes
cloud-init. - It includes VMware Tools or
open-vm-tools. - It includes
containerd. - It includes the baseline components required by kubeadm bootstrap.
- It includes pre-exported container image tar files under
/root/images/. These files are imported into containerd bycapv-load-local-images.shbefore kubeadm runs, so that node bootstrap does not depend on pulling images from a remote registry. - The tar files include the kubeadm control-plane images supplied with the OS template, including etcd and kube-apiserver, under the exact image references generated from
clusterConfiguration.imageRepository, the Kubernetes version, and the component image tags. Although etcd and kube-apiserver run as static Pods, they still require container images. A missing or mismatched local reference causes the runtime to try the configured Registry instead. - The
/root/images/*.tarfiles must include the sandbox (pause) image whose reference exactly matches thesandbox_imagevalue (containerd v1) orsandboxvalue (containerd v2) configured in/etc/containerd/config.toml. For example, if containerd is configured withsandbox_image = "registry.example.com/tkestack/pause:3.10", one of the tar files must contain that exact image reference. A mismatch causes containerd to pull the sandbox image from the network, which defeats the purpose of local preloading and fails in air-gapped environments.
Static IP configuration, hostname injection, and other initialization settings depend on cloud-init. Node IP reporting depends on guest tools.
Local File Layout
The workload cluster_name must not be global. That name is reserved for the global cluster, and reusing it causes the workload cluster's resources to collide with global cluster resources in cpaas-system. The global- prefix is reserved for resources owned by the global cluster's DR workflow; see Common Prerequisites. Do not use global- for workload-cluster resources, because failover operations can select those resources as if they belonged to the global cluster.
As a convention, keep the CAPI Cluster and provider cluster resource (VSphereCluster) named exactly <cluster_name>, and prefix non-root CAPI and provider resources (KubeadmControlPlane, KubeadmConfigTemplate, MachineDeployment, VSphereMachineTemplate, VSphereMachineConfigPool, etc.) with <cluster_name>- — for example, the example manifests use <cluster_name>-kcp and <cluster_name>-md-0. This is a recommendation rather than a controller-enforced rule, but it prevents same-namespace collisions when multiple workload clusters live in cpaas-system and makes resource ownership obvious during operations.
Create a local working directory and store the manifests with the following layout:
Use the following commands to create the directory:
Steps
Validate the environment
Run the following commands from the global cluster to verify the minimum prerequisites:
Export the permanent platform Registry address returned by the Cluster annotation and the image Registry used by the CPI and kubeadm manifests. If both placeholders identify the same Registry, use the same value for both variables.
The /v2/ segment is part of the Registry HTTP API URL only. In the workload Cluster manifest, set the Registry annotation to <registry_address> without a scheme or path.
Confirm the following results:
- The
globalcluster is reachable. - Alauda Container Platform Kubeadm Provider and Alauda Container Platform VMware vSphere Infrastructure Provider are running.
- The controller arguments include
ClusterResourceSet=true. - The
public-registry-credentialSecret exists; its contents are not printed by this procedure. - The permanent platform Registry contains the required Kube-OVN, CoreDNS, and vSphere CPI tags.
- The VM template passed the executable local-image validation, including exact etcd, kube-apiserver, and sandbox image references. Their static-Pod deployment does not remove the image requirement.
Before you continue, also verify the following items:
- The vCenter server address is reachable.
- The vCenter username and password are valid.
- The thumbprint is correct.
- The template name is correct.
- The template is resolvable in the target datacenter.
- If the VM is cloned as a
fullClone, the template system disk is not larger than thediskGiBvalue used later in the manifests. If CAPV completes alinkedClone, the system disk size stays at the template's size anddiskGiBis ignored. - VMware Tools or
open-vm-toolsis installed in the template. - The external LoadBalancer follows the Layer 4 listener, backend, health-check, reachability, and ownership requirements in Plan the Control Plane Endpoint.
Create the namespace and vCenter credential secret
Create the namespace that stores the workload cluster objects.
This workflow stores workload cluster objects in the cpaas-system namespace. In the manifests and commands below, replace every <namespace> placeholder with cpaas-system.
Create the vCenter credential secret referenced by VSphereCluster.spec.identityRef.
Apply both manifests:
Create the Cluster and VSphereCluster objects
Create the base cluster manifest with the workload cluster network settings, the control plane endpoint, and the vCenter connection settings. Set cpaas.io/registry-address to the permanent platform Registry in the form <registry_address> (<host>:<port> only).
Apply the manifest:
Create the vSphere CPI delivery resources
Create a ClusterResourceSet so the workload cluster receives the vSphere CPI configuration and manifests automatically after the workload API server becomes reachable.
In the baseline workflow VSphereCluster.spec.failureDomainSelector is intentionally not set and the CPI vsphere.conf does not include a [Labels] block. Both are required only after you enable failure domains; configure them together as described in Multiple datacenters and failure domains. Adding [Labels] to vsphere.conf without matching VSphereFailureDomain objects causes the CPI to look up zone and region tags that do not exist.
The vSphere CPI TLS bypass option is insecure-flag. Keep insecure-flag = "1" in the [Global] section of <cluster_name>-vsphere-cpi-config so the CPI can connect when the vCenter certificate is self-signed or not trusted by the workload cluster nodes. The CPI applies the global value to vCenter entries that do not set their own insecure-flag.
The CPI ConfigMap, Secret, and ClusterResourceSet resources must be created in the same namespace as the Cluster resource. In this guide that namespace is cpaas-system. A ClusterResourceSet can only match clusters within its own namespace; deploying it in a different namespace will silently prevent resource delivery.
The kube-ovn configuration in the Cluster annotations is consumed by platform controllers. This document does not install the network plugin directly.
This manifest is long and contains nested YAML inside data fields. Validate the manifest before applying: kubectl apply --dry-run=client -f 15-vsphere-cpi-clusterresourceset.yaml.
Apply the manifest:
Create the machine config pools
Create the control plane machine config pool.
Each node slot declares its NIC layout under network.primary (required) and network.additional (optional list). The primary NIC's networkName is required, and the provider derives the Kubernetes node name, the kubelet serving certificate DNS SAN, and the kubelet node-ip from hostname and the resolved primary NIC addresses. The hostname must be a valid DNS-1123 subdomain.
deviceName is optional. If you do not need to force the guest NIC name, remove the deviceName line from every node slot. The provider assigns NIC names such as eth0, eth1 by NIC order.
The dns entries in VSphereMachineConfigPool are kept in the static network configuration, but they might not update the guest operating system's /etc/resolv.conf reliably in affected VMware deployments. The control plane and worker bootstrap manifests below therefore also write /etc/resolv.conf explicitly through kubeadm files.
Create the worker machine config pool.
Apply both manifests:
Verify the pool binding and slot state before you create Machines:
The pool is also the authority for persistent-disk replacement state. When a VM is replaced, its slot changes from InUse to Released; a replacement Machine that references the same existing pool can reuse that slot and its VMDKs immediately. releaseDelayHours controls reclaim when the slot remains unused; it is not a reuse delay.
Do not create a new pool name as a routine retry for Machine replacement. A different VSphereMachineConfigPool.metadata.name creates independent slots and VMDKs, so repeated teardown and redeployment can temporarily consume multiple complete disk sets. Before another deployment on a capacity-constrained datastore, wait for earlier pools and their VMDKs to finish provider-managed deletion. See Persistent disk lifecycle for the teardown checks and status.configStatuses[].reclaimStatus fields.
Apply the optional failure-domain objects
Skip this step for the baseline single-datacenter topology.
If failure domains are enabled, complete Multiple datacenters and failure domains, then apply the failure-domain objects before creating the control plane:
Verify that every VSphereFailureDomain and VSphereDeploymentZone referenced by the cluster exists. Do not proceed until the deployment zones are available. Treat the following as one configuration set:
- The
VSphereFailureDomainandVSphereDeploymentZoneobjects in18-failure-domains.yaml VSphereCluster.spec.failureDomainSelectorin10-cluster.yaml- The CPI
[Labels]block in15-vsphere-cpi-clusterresourceset.yaml
Do not add failureDomainSelector or the CPI [Labels] block to the baseline manifests when failure domains are not enabled.
Create the control plane objects
Create the VSphereMachineTemplate and KubeadmControlPlane objects. Replace the placeholders in the following full template with the values collected in the checklist document.
The baseline control-plane and worker manifests omit imagePullCredentialsVerificationPolicy and are valid for Kubernetes 1.34 or earlier.
For Kubernetes 1.35 or later, add the following field to the KubeletConfiguration JSON in both 20-control-plane.yaml and 30-workers-md-0.yaml before applying either manifest:
cloneMode and diskGiB both remain present in the template because CAPV accepts both fields. In practice, diskGiB only affects the system disk when the actual clone operation is fullClone. If cloneMode is linkedClone and the template has a usable snapshot, CAPV completes a linked clone and the system disk size remains equal to the source template. If no usable snapshot exists, CAPV falls back to fullClone, and diskGiB applies again.
VSphereMachineTemplate.spec.template.spec.diskGiB sets only the VM system disk size. It is not the total capacity of all disks on the node.
Data disks are declared separately under VSphereMachineConfigPool.spec.configs[].persistentDisks[]. Do not add the persistent disk sizes to diskGiB; otherwise the VM can receive a larger system disk plus the separate data disks, which doubles the intended capacity.
For fullClone, diskGiB must be greater than or equal to the system disk size in the OS image template. For linkedClone, the system disk remains at the template size and diskGiB is ignored.
Apply the manifest:
Create the worker objects
Create the worker machine template, bootstrap template, and MachineDeployment.
The baseline worker kubelet patch omits the Kubernetes 1.35-only field. If the selected version is Kubernetes 1.35 or later, add imagePullCredentialsVerificationPolicy: NeverVerify here as well as in 20-control-plane.yaml, as described in the control-plane step.
Apply the manifest:
In the baseline workflow, note the following worker-specific rules:
failureDomainis not set by default in the main worker manifest because the baseline workflow assumes a single datacenter. If you need a workerMachineDeploymentto land in a specificVSphereDeploymentZone, addfailureDomainas described in Multiple datacenters and failure domains.- Some environments add extra runtime-image replacement commands or service-restart commands to
KubeadmConfigTemplate. Those commands are intentionally not included in the baseline sample. Add them only when the platform requirements in your environment explicitly require them.
Wait for the cluster to become ready
After all manifests are applied, the cluster creation is asynchronous. Monitor the progress with:
Wait until KubeadmControlPlane reports the expected number of ready replicas and all Machine objects reach the Running phase before proceeding to verification.
Verification
Use the following commands to verify the cluster creation workflow.
- Check the CPI delivery resources in the
globalcluster: - Export the workload kubeconfig:
- Check whether the vSphere CPI daemonset is created in the workload cluster:
- Check the
globalcluster objects: - Check the workload nodes:
Confirm the following results:
vsphere-cloud-controller-managerappears in the workload cluster.- Control plane and worker nodes are created.
- The nodes eventually become
Ready.
Troubleshooting
Use the following commands first when the workflow fails:
Prioritize the following checks:
- If the CPI resources are not delivered, verify
ClusterResourceSet=true,ClusterResourceSet, andClusterResourceSetBinding. - If
ClusterResourceSetexists but noClusterResourceSetBindingis created, check whether the controller has the required delete permission on the referencedConfigMapandSecretresources. - If the network plugin is not installed, verify that the required cluster annotations are present and that the platform controllers processed them.
- If the
cpaas.io/registry-addressannotation is missing or incorrect, verify that it is set to the permanent<registry_address>without a scheme or/v2/. Also verify thatpublic-registry-credentialexists and that the platform controller processed the annotation. - If a machine is stuck in
Provisioning, checkVSphereMachineconditions forMachineConfigPoolReady— it shows whether slot allocation failed due to pool binding or datacenter mismatch. - If a VM is waiting for IP allocation, verify VMware Tools, the static IP settings, and
VSphereVM.status.addresses. - If workload
Nodeobjects remain withoutspec.providerID, first verify the CPI delivery resources and then check for duplicate vCenter guest hostnames. When an old VM in the same datacenter still reports the same guest hostname as a new node,cloud-provider-vspherecan fall back to node-name lookup, cache the old VM, and reject the new node because the VM IP does not match the kubelet node IP. Check the leadervsphere-cloud-controller-managerlogs, the nodeSystemUUID, the real VM UUID, and vCenter guest hostname/IP values. After you fix or remove the duplicate hostname or old VM conflict, restart the workload cluster'svsphere-cloud-controller-managerPods to clear the bad in-memory cache: - If datastore space is exhausted, first list all current and terminating
VSphereMachineConfigPoolobjects and compare their names with everyVSphereMachineTemplate.spec.template.spec.machineConfigPoolRef.name. Different pool names own independent slots and VMDKs; repeated deployments can therefore accumulate multiple disk sets. Then inspectstatus.configStatuses[], includingstate,lastReleasedTime,reclaimStatus.state,volumePath,lastError, andretryAfter, together with related Events and the vCenter attachment state.insufficient disk availableconfirms a datastore capacity failure but does not by itself prove that reclaim failed. Do not manually delete a VMDK or remove a pool finalizer while reuse or provider-managed reclaim is pending. - If the template system disk size does not match the manifest values, first check the actual clone mode. When the VM was created as
linkedClone, the system disk stays at the template's size anddiskGiBis ignored. OnlyfullCloneusesdiskGiB, and in that casediskGiBmust not be smaller than the template disk size. - If the control plane endpoint does not come up, verify TCP
6443passthrough, all control-plane backends, HTTPS/healthzresults, DNS and certificate SANs, and reachability from theglobalcluster and control-plane nodes. - If the TLS connection to vCenter fails, verify the thumbprint, the vCenter address, and whether proxy settings interfere with the connection.
When you review controller logs, use the following rules:
deploy/capi-controller-managerruns in thecpaas-systemnamespace of theglobalcluster.- Do not use the workload-cluster kubeconfig to inspect
capi-controller-managerlogs. - If platform controllers process the cluster network annotations, also inspect the platform network-controller logs and the platform cluster-lifecycle-controller logs.
Creation-Time Topology Variants
The baseline manifest intentionally starts with one datacenter and one NIC. Before you create the cluster, use the following variants when the initial topology requires additional NICs, multiple datacenters, failure domains, or extra data disks. Apply one variant at a time and validate the complete manifest set before combining them.
Add a second NIC
When nodes require an additional management, storage, or service network, extend the manifests in the following resources:
16-vspheremachineconfigpool-control-plane.yaml17-vspheremachineconfigpool-worker.yaml20-control-plane.yaml30-workers-md-0.yaml18-failure-domains.yamlif failure domains are enabled
Each node slot declares its NIC layout under network.primary and network.additional. The primary NIC is used to derive the kubelet node-ip and remains the node's primary identity; additional NICs are merged after it in the order listed.
Add the second NIC to each control plane node slot in the machine config pools:
Apply the same pattern to the worker node slots:
Add the second NIC to the machine templates:
If the DNS server used by the node changes when you add the second NIC, update the /etc/resolv.conf file entries in both 20-control-plane.yaml and 30-workers-md-0.yaml. The dns values in the machine config pool network blocks do not replace the explicit /etc/resolv.conf bootstrap file entries.
If failure domains are enabled, update the network list in VSphereFailureDomain.spec.topology.networks:
When you define the second NIC values, prepare the following placeholders in the infrastructure checklist and manifests:
<master_01_nic2_ip><master_02_nic2_ip><master_03_nic2_ip><worker_01_nic2_ip><worker_02_nic2_ip>when you also expand the worker pool
For a running cluster, change all three network definitions together during immutable replacement. See Runtime Topology Changes.
Multiple datacenters and failure domains
Use multiple datacenters and failure domains when you need node placement across different vCenter datacenters or compute clusters.
The following principles apply:
- One cluster can define multiple
VSphereFailureDomainobjects. - Each
VSphereDeploymentZonereferences oneVSphereFailureDomain. - The control plane uses
VSphereCluster.spec.failureDomainSelector. - A worker
MachineDeploymentusesspec.template.spec.failureDomainwhen it must target a specific deployment zone.
Prepare the following placeholders for the first datacenter:
<compute_cluster_1><default_datastore_1><resource_pool_path_1><fd_name_1><dz_name_1>
Prepare the following placeholders for the second datacenter:
<dc_name_2><fd_name_2><dz_name_2><compute_cluster_2><default_datastore_2><resource_pool_path_2>
If you add a third datacenter, continue with the same placeholder pattern:
<dc_name_3><fd_name_3><dz_name_3><compute_cluster_3><default_datastore_3><resource_pool_path_3>
Create the failure-domain objects in 18-failure-domains.yaml. The first datacenter also needs a VSphereFailureDomain and VSphereDeploymentZone when failure domains are enabled:
Enable control plane selection across the available failure domains by adding failureDomainSelector to the VSphereCluster spec in 10-cluster.yaml:
An empty selector {} matches every VSphereDeploymentZone that has controlPlane: true. Use match labels to restrict the control plane to a subset of zones.
Also add the [Labels] block to the CPI ConfigMap so the vSphere CPI publishes the matching zone and region labels on workload nodes. The keys must match the tagCategory values used in VSphereFailureDomain.spec.zone.tagCategory and VSphereFailureDomain.spec.region.tagCategory. Update the vsphere.conf data in 15-vsphere-cpi-clusterresourceset.yaml:
failureDomainSelector and the CPI [Labels] block must be enabled together. Adding either one alone leaves the cluster in an inconsistent state: nodes get unresolved zone or region labels, or the control plane cannot select a deployment target.
Set a worker deployment zone when a worker MachineDeployment must be pinned to one deployment target. Add failureDomain to spec.template.spec in 30-workers-md-0.yaml:
Use a VSphereDeploymentZone name for <worker_failure_domain>, not a VSphereFailureDomain name.
Before you enable multiple datacenters, confirm all of the following prerequisites:
- The template is already synchronized to every target datacenter.
- The network names are resolvable in every target datacenter.
- The datastore names are resolvable in every target datacenter.
- The vSphere CPI datacenter list covers every target datacenter.
Add data disks
The baseline deployment includes the following required data disks:
- Control plane nodes:
var-cpaas,var-lib-containerd, andvar-lib-etcd(3 disks per node). Do not remove any of these disks. Thevar-lib-etcddisk must setwipeFilesystem: trueto allowkubeadm joinduring rolling updates. - Worker nodes:
var-cpaasandvar-lib-containerd(2 disks per node). Do not remove any of these disks.
VSphereMachineTemplate.spec.template.spec.diskGiB is the system disk size, not the total disk capacity of the VM. Keep additional persistent or data disks under VSphereMachineConfigPool.spec.configs[].persistentDisks[]. Do not add the persistent-disk sizes to diskGiB unless you intentionally want a larger system disk.
If a node needs additional data disks beyond the required set, append more entries to the same persistentDisks list in the corresponding VSphereMachineConfigPool node slot. The following optional fields are especially relevant here:
mountPath: If set, the disk is formatted and mounted at the specified path. If omitted, the disk is attached as a raw device with a symlink at/dev/disk/by-capv/<name>, allowing an external process to manage it at runtime.wipeFilesystem: Whentrue, disk content is wiped on the first boot of a new VM. Normal reboots and manual service restarts are not affected. Defaults tofalse.
To attach a raw disk without formatting or mounting, omit mountPath and fsFormat:
The disk is accessible inside the guest OS at /dev/disk/by-capv/app-data. On rolling updates, the same VMDK is re-attached to the new VM and the symlink is recreated. The disk is never formatted or mounted automatically; the application is responsible for managing it at runtime.
Verify creation-time variants
After you apply a topology variant, validate the cluster state with the following commands:
Confirm the following results:
- The placement, NIC, or disk definitions are reflected in the target resources.
- New nodes reach the
Readystate. - Existing nodes remain healthy after the change.
Next Steps
For worker scale-out and later template or runtime-topology changes, see Managing Nodes on VMware vSphere. Apply one change at a time and validate the result before you combine multiple changes in the same cluster.