As a DevOps engineer, you can provision a VM and its guest OS in a declarative manner by writing VM deployment specifications in a Kubernetes YAML file.


  • Verify that you have available resources to deploy a VM in your namespace. See View VM Resources Available on a Namespace in vSphere with Tanzu.
  • If you use NVIDIA vGPU or other PCI devices for your VMs, the following considerations apply:
    • Make sure to use appropriate VM class with PCI configuration. See Add PCI Devices to a VM Class in vSphere with Tanzu.
    • VMs with vGPU devices require images that have boot mode set to EFI, such as CentOS. Make sure to have access to these images. For information about supported images, search for VM Service image on the VMware Cloud Marketplace web site.
    • VMs with vGPU devices that are managed by VM Service are automatically powered off when an ESXi host enters maintenance mode. This might temporarily affect workloads running in the VMs. The VMs are automatically powered on after the host exists the maintenance mode.


  1. Prepare the VM YAML file.
    In the file, specify the following parameters:
    Option Description
    apiVersion Specifies the version of the VM Service API. Such as
    kind Specifies the type of Kubernetes resource to create. The only available value is VirtualMachine.
    spec.imageName Specifies the content library image the VM should use. For example, centos-stream-8-vmservice-v1alpha1-xxxxxxxxxxxxx.
    spec.storageClass​ Identifies the storage class to be used for storage of the persistent volumes. For example, wcpglobal-storage-profile.
    spec.className Specifies the name of the VM class that describes the virtual hardware settings to be used. For example, custom.
    spec.networkInterfaces Specifies network-related settings for the VM.
    • networkType. Values for this key can be nsx-t or vsphere-distributed.
    • networkName. Specify the name only if networkType is vsphere-distributed. You can obtain this information using the kubectl get network command.

      If networkType is nsx-t, you do not need to indicate networkName.

    spec.vmMetadata Includes additional metadata to pass to the VM. You can use this key to customize the guest OS image and set such items as the hostname of the VM and user-data, including passwords, ssh keys, and so on. The example YAML below uses ConfigMap to store the metadata.
    Use the following as an example of a YAML file vmsvc-centos-vm.yaml.
    kind: VirtualMachine
      name: vmsvc-centos-vm
      namespace: my-ns-centos
      imageName: centos-stream-8-vmservice-v1alpha1-xxxxxxxxxxxxx
      className: custom
      powerState: poweredOn
      storageClass: wcpglobal-storage-profile
      - networkName: "primary"
        networkType: vsphere-distributed
          configMapName: vmsvc-centos-nginx-cm
          transport: OvfEnv
    apiVersion: v1
    kind: ConfigMap
        name: vmsvc-centos-nginx-cm
        namespace: my-ns-centos
      user-data: >-
    ConfigMap contains the cloud-config blob that specifies the username and password for the guest OS. In this example, user-data in vmsvc-centos-nginx-cm ConfigMap represents the following snippet in base64 format:
    password: VMWARE
    ssh_pwauth: true
      - name: vmware
        sudo: ALL=(ALL) NOPASSWD:ALL
        lock_passwd: false
        passwd: '$1$salt$SOC33fVbA/ZxeIwD5yw1u1'
        shell: /bin/bash
      - content: |
          VMSVC Says Hello World
        path: /helloworld
    For more information about cloud-config specifications, see
  2. Deploy the VM.
    kubectl apply -f vmsvc-centos-vm.yaml
  3. Verify that the VM has been created.
    kubectl get vm -n my-ns-centos
    NAME              AGE
    vmsvc-centos-vm   28s
  4. Check the status of the VM and associated events.
    kubectl describe virtualmachine vmsvc-centos-vm

    The output is similar to the following. From the output, you can also obtain the IP address of the VM, which appears in the Vm Ip field.

    Name:         vmsvc-centos-vm
    Namespace:    my-ns-centos
    Annotations: disabled
    API Version:
    Kind:         VirtualMachine
      Creation Timestamp:  2021-03-23T19:07:36Z
      Generation:  1
      Managed Fields:
      Class Name:  custom
      Image Name:  vmservice-centos-20-10-server-cloudimg-amd64
      Network Interfaces:
        Network Name:  primary
        Network Type:  vsphere-distributed
      Power State:     poweredOn
      Storage Class:   wcpglobal-storage-profile
      Vm Metadata:
        Config Map Name:  vmsvc-centos-nginx-cm
        Transport:        OvfEnv
      Bios UUID:              4218ec42-aeb3-9491-fe22-19b6f954ce38
      Change Block Tracking:  false
        Last Transition Time:  2021-03-23T19:08:59Z
        Status:                True
        Type:                  VirtualMachinePrereqReady
      Instance UUID:           50180b3a-86ee-870a-c3da-90ddbaffc950
      Phase:                   Created
      Power State:             poweredOn
      Unique ID:               vm-73
      Vm Ip:         
    Events:                    <none>
  5. Verify that the VM IP is reachable.
    PING ( 56 data bytes
    64 bytes from icmp_seq=0 ttl=59 time=43.528 ms
    64 bytes from icmp_seq=1 ttl=59 time=53.885 ms
    64 bytes from icmp_seq=2 ttl=59 time=31.581 ms


A VM created through the VM Service can be managed only by DevOps from the Kubernetes namespace. Its life cycle cannot be managed from the vSphere Client, but vSphere administrators can monitor the VM and its resources. For more information, see Monitor Virtual Machines Available in vSphere with Tanzu.

What to do next

For additional details, see the Introducing Virtual Machine Provisioning blog.

If the VM includes a PCI device configured for vGPU, install the NVIDIA display driver. See Install the NVIDIA Guest Driver in a VM in vSphere with Tanzu.