Lab: Deploy Virtual Machine via VM Service (kubectl apply)
Objectives
- Configure VM classes and content library for VM Service
- Create a VirtualMachine manifest (YAML) and deploy via kubectl
- Verify VM creation in both kubectl and vCenter UI
- Understand VM class types: best-effort vs guaranteed reservations
- Manage VM lifecycle through Kubernetes API (power on/off, delete)
Prerequisites
Supervisor enabled on VVF cluster (Lab 10 completed). Namespace 'dev-team' exists with resource quotas.
Prior labs: vvf-admin-10
Required skills:
- YAML syntax
- kubectl basics (apply, get, describe, delete)
- Content Library concepts
Lab Environment
Holodeck VVF pod with Supervisor running. HAProxy providing load balancing. Namespace 'dev-team' available.
Credentials
| System | Username | Password |
|---|---|---|
| vCenter | administrator@vsphere.local | Set during VCSA deployment |
| Supervisor | administrator@vsphere.local | Same as vCenter |
Tasks
Task 1 Configure VM Classes and Content Library
manageabilityVM classes define resource profiles (CPU/memory) that developers can request. Content library provides VM images. Both must be configured before VM Service can provision VMs.
vCenter → Workload Management → VM Service → VM Classes. Review built-in classes:
- best-effort-xsmall (2 vCPU, 2GB)
- best-effort-small (2 vCPU, 4GB)
- best-effort-medium (4 vCPU, 8GB)
- guaranteed-small (2 vCPU, 4GB, 100% reservation)
- guaranteed-medium (4 vCPU, 8GB, 100% reservation)
Create a custom VM class: Click 'Create VM Class' → Name='lab-small', vCPUs=2, Memory=4096 MB, Reservation: CPU=0, Memory=0 (best-effort).
Assign VM classes to namespace: Workload Management → Namespaces → 'dev-team' → VM Service → Add VM Class. Select 'best-effort-small' and 'lab-small'.
Create Content Library with VM image: vCenter → Content Libraries → Create Library → Name='vm-service-images', Type=Local.
Import VM image: In the content library, click 'Import Item' → select a VM image OVF (e.g., Photon OS 5.0 OVA or Ubuntu Server 22.04 cloud image).
Associate content library with namespace: Workload Management → Namespaces → 'dev-team' → VM Service → Add Content Library → select 'vm-service-images'.
Validation Gate
Check: Workload Management → Namespaces → dev-team → VM Service tab
Expected: VM Classes (best-effort-small, lab-small) and Content Library (vm-service-images) associated with namespace
Task 2 Deploy VM Using kubectl apply
manageabilityThis is the core VM Service workflow — infrastructure-as-code for VMs using Kubernetes API. Exam objective 4.4 explicitly tests this capability.
Authenticate to Supervisor:
kubectl vsphere login --server=<supervisor-api-ip> --vsphere-username=administrator@vsphere.local --insecure-skip-tls-verify
Switch to dev-team namespace:
kubectl config use-context dev-team
Create VM manifest file (my-vm.yaml):
apiVersion: vmoperator.vmware.com/v1alpha1
kind: VirtualMachine
metadata:
name: test-vm-01
namespace: dev-team
spec:
className: best-effort-small
imageName: photon-5-server
storageClass: vsan-default-storage-policy
powerState: poweredOn
networkInterfaces:
- networkType: vsphere-distributed
Apply the manifest:
kubectl apply -f my-vm.yaml
Monitor VM creation:
kubectl get virtualmachines -n dev-team -w
Get detailed VM status:
kubectl describe virtualmachine test-vm-01 -n dev-team
Verify in vCenter: Navigate to cluster → VMs → find 'test-vm-01'. Confirm it appears as a regular VM managed by Supervisor.
Validation Gate
Check: kubectl get virtualmachines -n dev-team && vCenter shows test-vm-01 in inventory
Expected: VM test-vm-01 in poweredOn state visible in both kubectl and vCenter
Common Errors
Task 3 Manage VM Lifecycle via kubectl
manageabilityDay-2 VM operations through kubectl demonstrate the Kubernetes-native management model — the self-service experience developers get with VM Service.
Power off VM:
kubectl patch virtualmachine test-vm-01 -n dev-team --type merge -p '{"spec":{"powerState":"poweredOff"}}'
Verify power state:
kubectl get vm test-vm-01 -n dev-team
Power on:
kubectl patch virtualmachine test-vm-01 -n dev-team --type merge -p '{"spec":{"powerState":"poweredOn"}}'
Delete VM:
kubectl delete vm test-vm-01 -n dev-team
Verify deletion in vCenter: VM 'test-vm-01' no longer appears in inventory.
Validation Gate
Check: kubectl get vm -n dev-team
Expected: No resources found in dev-team namespace (VM deleted)
Final Validation
VM classes and content library configured, VM deployed via kubectl, lifecycle operations (power on/off/delete) demonstrated.
✓ VM classes assigned to dev-team namespace → best-effort-small and lab-small visible
✓ Content library associated with dev-team namespace → vm-service-images library listed
✓ VM Service workflow complete: create → verify → power cycle → delete → All kubectl operations succeeded without errors
Cleanup / Restore
Snapshot: post-vm-service-lab
• Ensure test-vm-01 is deleted (kubectl delete vm test-vm-01 -n dev-team)
• Take snapshot 'post-vm-service-lab'
Design Reflection (VCDX)
Panelist: When should a customer use VM Service vs traditional VM provisioning? What guardrails prevent resource sprawl? How do you handle Windows VMs in VM Service (guest customization, licensing)?
Requirements
- Developer self-service VM provisioning
- Resource governance via quotas
- Infrastructure-as-code for VMs
- Integration with CI/CD pipelines
Constraints
- VM images must be in content library (no ad-hoc ISO installs)
- VM classes predefine allowed sizes (no arbitrary sizing)
- vDS networking limits to VLAN-based isolation
- No VM snapshot support through kubectl (vSphere-only feature)
Assumptions
- Developers understand YAML and kubectl
- Content library images are pre-hardened and approved
- Namespace quotas prevent resource exhaustion
Risks
- Uncontrolled VM sprawl if quotas not enforced
- Image drift if content library not regularly updated
- Developer confusion between kubectl VM and vCenter VM management
Self-Assessment Discussion Prompts
- How do VM Service VMs differ from traditional vCenter VMs in backup, monitoring, and lifecycle?
- What's the right VM class strategy — few standardized classes or many custom classes?
- How would you integrate VM Service with a GitOps workflow?
References
- VM Service in vSphere with TanzuTier 1 — Official
- VirtualMachine CRD ReferenceTier 1 — Official