I created a VMware vSphere Kubernetes Service (VKS) cluster manually in my VCF 9.1.1 home lab, then connected from Windows PowerShell and deployed an Nginx web server. This walkthrough covers Supervisor activation with VPC networking, namespace preparation, VKS cluster creation through the vSphere Client, kubeconfig access, and exposing an application through a LoadBalancer Service.
The cluster uses one control-plane node and one worker. Both use the best-effort-small VM class. This is a compact test configuration: a single control-plane node does not provide control-plane high availability.
Example configuration
The resource names below are generic examples. Substitute your own vCenter, Supervisor, namespace, storage policy, and cluster names. The software versions describe the tested deployment; select releases supported by your installed Supervisor and Kubernetes Service.
| Setting | Example / value to select |
|---|---|
| Workload vCenter / cluster | vcenter.example.com / workload-cluster |
| NSX Manager | nsx.example.com |
| Supervisor | supervisor-01 |
| Supervisor version | v1.34.9+vmware.1-vsc9.1.1.0-25712839 |
| Kubernetes Service | 3.7.0-embedded+v1.36 |
| Local Consumption Interface | 9.1.2-embedded+fe6ddfd1 |
| vSphere namespace | vks-lab |
| VKS cluster | vks-demo |
| Kubernetes release in vCenter | v1.36.2—vmware.2-vkr.3 |
| Version reported by kubectl | v1.36.2+vmware.2 |
| Node configuration | 1 control-plane node + 1 worker; 2 vCPUs and 4 GB RAM each |
| Storage policy | Your namespace storage policy |
| Supervisor API address | Your Supervisor API address |
| VKS API endpoint | Endpoint from your downloaded kubeconfig |
The Supervisor and VKS cluster are separate Kubernetes environments. The Supervisor provides the platform used to provision the workload cluster. The downloaded VKS kubeconfig connects to the workload cluster where the Nginx application runs.
1. Prepare the Supervisor prerequisites
This walkthrough uses VCF Networking with VPC and a centralized Transit Gateway backed by NSX Edge. Start with an operational VCF workload domain, compatible vCenter and ESX versions, NSX host preparation, and sufficient compute and storage capacity. The distributed gateway and Foundation Load Balancer workflows have different prerequisites.
- Check the target cluster against the Supervisor requirements for VCF 9.1. Resolve cluster compatibility errors before activation, including host configuration, HA/DRS requirements, storage access, and NSX transport health.
- Prepare the placement model. For this example, use a single workload cluster and management zone. In vCenter, use vSphere Zones to prepare any required zone mapping; a three-zone design needs three eligible zones and a different placement plan.
- Create or select a storage policy with compatible shared storage for the Supervisor control-plane VMs. Confirm available capacity on the target datastore.
- Under Supervisor Management → Content Distribution, configure and assign the Supervisor release content library. Synchronize a compatible release through your supported online or offline depot workflow. Kubernetes node images for VKS are a separate content requirement.
- For the centralized networking path, prepare a healthy NSX Edge cluster, Tier-0 connectivity, and upstream routing. Confirm the intended NSX project and VPC connectivity profile, including its gateway connection, external IP block, private Transit Gateway pool, and Auto SNAT.
- Plan DNS, NTP, management IPs, workload address pools, and registry access. Reserve unused management addresses and verify that your workstation can route to the eventual Supervisor API endpoint.
These steps prepare existing infrastructure for Supervisor activation. Deploying the workload domain, NSX Edge appliances, and physical routing is a prerequisite rather than part of the activation wizard. For an offline environment, make both release content and required container images available before starting.
2. Check the VPC address plan
| Setting | Example / value to select |
|---|---|
| NSX project | Default |
| Connectivity profile | Default VPC Connectivity Profile |
| External IP block | Your external IP block |
| Private Transit Gateway block | Your private Transit Gateway block |
| Private VPC CIDR | Your private VPC CIDR |
| Supervisor Service CIDR | Your Supervisor Service CIDR |
These pools have different purposes. The external block supplies externally reachable addresses within the routed lab; it does not make a service public on the internet. The Supervisor Service CIDR is also separate from the workload cluster’s own Service network.
Keep the NSX transport networks, host and Edge TEP networks, Transit Gateway address pool, VPC ranges, and Kubernetes Service networks distinct. Check all allocations for overlap and verify routing, DNS, and Edge tunnel health. VLAN IDs and subnets must match your own network design.
3. Activate the Supervisor with VPC networking
The following sequence follows Broadcom’s Deploy a Supervisor with VPC Networking procedure. All names are examples. If you already have a healthy Supervisor, skip activation and continue with the namespace steps.
- Open Menu → Supervisor Management in the vSphere Client and choose Get Started to launch activation. If Supervisors already exist, use the available activation action on that page.
- On vCenter Server and Network, select the workload vCenter and choose VCF Networking with VPC.
- On Supervisor location, select Cluster Deployment, enter a name such as
supervisor-01, and select the intended datacenter and compatible cluster/management zone. Enable control-plane high availability for a resilient deployment. A single-control-plane configuration is a lab option where supported; it does not provide control-plane redundancy. - Select the storage policy for the Supervisor control-plane VMs. Confirm that the intended datastore is compatible.
- On Management Network, select the management port group and IP assignment mode. For a static HA deployment, reserve the documented block of five unused management IPs for the control-plane VMs, floating address, and replacement capacity. Enter the requested IP range, subnet mask, gateway, DNS servers, DNS search domain, and NTP settings. Follow the address count shown for your selected topology. If using DHCP, configure stable assignments and the required client-identifier support.
- On Workload Network, select the NSX project and VPC connectivity profile prepared earlier. Review the external and private Transit Gateway IP blocks, enter the private VPC CIDR and Supervisor Service CIDR, and supply the workload DNS and NTP settings. Check the network plan in the previous section before continuing.
- Under Advanced Setting, choose the Supervisor control-plane size. Small provides 4 vCPUs and 16 GB RAM per control-plane VM; select a size appropriate for the expected workload. This is separate from the VKS node VM class. The documented sizing change supports scaling up, not down.
- Enter an API server DNS name, such as
supervisor.example.com, if you intend to connect by name. This name is included in the generated certificate. Once the API address is known, configure DNS to resolve the name to that endpoint. - Review the settings and use Export Configuration to retain the activation JSON securely. Click Finish to begin deployment.
Plan the management addresses carefully: changing the control-plane and floating IPs after activation is not supported. Do not point the API DNS name at an arbitrary control-plane VM; use the API endpoint reported for the Supervisor.
Validate the Supervisor and install the services
- Monitor the activation task under Supervisor Management → Supervisors. Wait for the configuration and host configuration to report Running; inspect the configuration status details if activation fails.
- Verify that the expected control-plane VMs are powered on, that the selected storage is healthy, and that the Supervisor API endpoint is reachable from your administration network. Check DNS resolution using the configured API name.
- Under Supervisor Management → Services, verify that Kubernetes Service and Local Consumption Interface (LCI) are installed and healthy on this Supervisor. If either is absent, select a compatible registered version and use its installation action to target this Supervisor. Registering a service in vCenter alone does not install it on a Supervisor.
- Associate the compatible Kubernetes release content library under the Supervisor’s Configure → General → Kubernetes Service settings. Verify that the release needed for the VKS cluster is available.
- Proceed to create the namespace, assign its storage policy and VM classes, then deploy the VKS cluster. A Running Supervisor is the platform prerequisite; the later Nginx test validates a workload on the VKS cluster.
If activation stalls: check the reported failure first. Common causes include an incomplete VPC connectivity profile, missing external address blocks or gateway connectivity, management IP conflicts, DNS/NTP failures, incompatible storage, and unavailable release content. Resolve the prerequisite and inspect the task again before attempting another activation.
4. Prepare the vSphere namespace
- Open Supervisor Management → Namespaces. Select your existing namespace or choose New Namespace and place it on the intended Supervisor and zone. Use an example namespace such as
vks-lab. - Assign the storage policy that will hold the node VMs. Select the storage policy assigned to your namespace.
- Under the namespace’s VM Service settings, associate the required VM classes. For example, associate
best-effort-small,best-effort-medium, andbest-effort-large; the VKS nodes usebest-effort-small. - Confirm your account has namespace permissions to create and manage VKS clusters. Check available compute, storage, and namespace quotas before proceeding.
My test namespace has no CPU, memory, or storage limit. That is a lab setting, not a requirement. Best-effort classes do not reserve the full configured CPU and memory. Guaranteed classes introduce reservation requirements that can prevent placement when the resource pool lacks capacity. See Broadcom’s VM class and placement guidance.
5. Create the VKS cluster through the UI
Open the namespace’s Resources tab and select the Kubernetes cluster creation workflow provided by LCI. Labels and field order can differ between LCI releases. The settings below describe a small example deployment.
- Enter a cluster name. For example, name it
vks-demo; use a new name when deploying another cluster. - Select the available Kubernetes release. My cluster uses
v1.36.2---vmware.2-vkr.3. - Configure one control-plane node using
best-effort-small. - Configure one worker node in a worker node pool, also using
best-effort-small. - Select the storage policy assigned to the namespace for the node storage settings. Review networking and any additional disk settings exposed by your release.
- Review the configuration and any generated YAML shown by the wizard, then submit the cluster creation request. Save an export for future reference if the UI offers one.
I created this cluster manually; there is no original cluster-creation YAML in this walkthrough. The YAML later in this post deploys the test application into the existing cluster.
Wait for the cluster to become Available. You can inspect it under namespace → Compute → Kubernetes clusters. My cluster shows Available = True and Worker Count = 1. Under Compute → Virtual Machines, both node VMs are powered on and use best-effort-small. VM power state alone is not sufficient validation; check Kubernetes readiness next.
6. Download kubeconfig and connect from PowerShell
Open the cluster’s details in the LCI workflow and download its kubeconfig. Treat that file as a credential and keep it out of public repositories. Install a compatible kubectl client, then point the current PowerShell session at the downloaded file:
$env:KUBECONFIG = "$env:USERPROFILE\Downloads\vks-demo-kubeconfig.yaml"
kubectl config current-context
kubectl get --raw=/readyz
kubectl get nodes -o wide
kubectl get pods -A
kubectl get storageclassReplace the path with your own download location. Confirm that the current context belongs to the intended VKS cluster. The readiness check should return ok, and both nodes should report Ready. Use the API endpoint and authentication information provided in the downloaded kubeconfig.
Confirm that the StorageClasses made available by your assigned storage policy appear in the output. Listing them confirms availability, but does not itself prove a persistent volume can be provisioned.
7. Deploy the Nginx test application
Create an application namespace inside the VKS cluster. This nginx-demo namespace is different from the vks-lab vSphere namespace that contains the cluster.
kubectl create namespace nginx-demoSkip creation if that namespace already exists. Save the following as web.yaml. It contains the Deployment and a LoadBalancer Service:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
namespace: nginx-demo
spec:
replicas: 1
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
securityContext:
runAsNonRoot: true
runAsUser: 101
seccompProfile:
type: RuntimeDefault
containers:
- name: nginx
image: nginxinc/nginx-unprivileged:stable-alpine
ports:
- containerPort: 8080
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
---
apiVersion: v1
kind: Service
metadata:
name: web
namespace: nginx-demo
spec:
selector:
app: web
ports:
- port: 80
targetPort: 8080
type: LoadBalancerThe initial standard Nginx deployment was blocked by the namespace’s restricted Pod Security policy. This version uses an unprivileged image listening on port 8080, runs as a non-root user, disables privilege escalation, drops Linux capabilities, and selects the runtime’s default seccomp profile. See the Kubernetes security context documentation.
The worker must be able to pull the image. If your environment is offline, mirror it into an accessible registry and update the image reference and registry trust configuration first. The tag shown here matches the lab example; it can change over time.
kubectl apply -f .\web.yaml
kubectl rollout status deployment/web -n nginx-demo --timeout=120s
kubectl get pods -n nginx-demo
kubectl get service web -n nginx-demo --watch8. Verify access through the LoadBalancer
Wait for the web pod to show 1/1 Running and for the Service to receive an external address. Press Ctrl+C to stop the watch once the address appears. Use the address returned by your own Service on TCP port 80:
$webIP = kubectl get service web -n nginx-demo -o jsonpath="{.status.loadBalancer.ingress[0].ip}"
Test-NetConnection -ComputerName $webIP -Port 80
Invoke-WebRequest -Uri "http://$webIP"Open the same HTTP address in a browser to check the Nginx welcome page. A TCP test checks connectivity; the HTTP response verifies the application. The Service forwards port 80 to port 8080 in the container.
For a temporary local test, you can also run kubectl port-forward service/web 8080:80 -n nginx-demo and browse to http://localhost:8080. Port forwarding ends when you close that command. The Deployment and LoadBalancer Service remain in the cluster when you close PowerShell.
This example does not use a PersistentVolumeClaim. It validates cluster access, pod scheduling, image retrieval, and application exposure. A separate PVC test is needed to validate persistent application storage.
Troubleshooting from this lab
Resources tab missing or blank: confirm LCI is installed on the correct Supervisor, check its service health and browser connectivity, and refresh the vSphere session. The native Compute tab can still show existing clusters while you investigate the embedded Resources view.
LCI capability or networking errors: confirm the Supervisor uses the intended network stack. In my setup, the management DVPG is valid alongside NSX VPC workload networking. An earlier VDS setup without a load balancer did not provide the required service capabilities. Also verify the VPC connectivity profile’s Auto SNAT and address-block prerequisites.
Node placement failure: check namespace limits, host capacity, storage policy availability, and VM class reservations. For clusters created through LCI, make topology changes through the vSphere Client, as described in the Broadcom placement guidance linked above.
Deployment exists but no pod starts: inspect events. In this lab, the ReplicaSet reported restricted Pod Security violations. The corrected manifest above resolved the missing security settings.
kubectl get events -n nginx-demo --sort-by=.metadata.creationTimestamp
kubectl describe deployment web -n nginx-demo
kubectl get pods -n nginx-demo
kubectl logs deployment/web -n nginx-demoExternal IP stays pending: inspect kubectl describe service web -n nginx-demo and the platform’s service/network provisioning. If an IP is allocated but unreachable, check client routing, return routing, and firewall access to TCP 80. Do not assume an allocated address proves end-to-end connectivity.
What this test established
The manual VKS deployment produced an available two-node cluster, and kubeconfig authentication and API readiness checks succeeded. The Nginx test supplied a repeatable application manifest and a LoadBalancer endpoint. It also exposed a useful lesson: a successful cluster deployment is only the first check; security policy and network access still need validation with a real workload.
