As a DevOps engineer, use the kubectl command to review available VM resources and provision a stand-alone Linux or Windows VM in a namespace on a Supervisor. If the VM includes a PCI device configured for vGPU, after you create and boot the VM in your vSphere with Tanzu environment, you can install the NVIDIA vGPU graphics driver to enable GPU operations.


To be able to deploy a stand-alone VM in vSphere with Tanzu, a DevOps engineer must have access to specific VM resources. Make sure that a vSphere administrator has performed these steps to make VM resources available:

If you plan to use NVIDIA vGPU or other PCI devices for your VMs, you must follow additional requirements. For information, see Deploying a VM with PCI Devices in vSphere with Tanzu.

View VM Resources Available on a Namespace in vSphere with Tanzu

As a DevOps engineer, verify that you can access VM resources on your namespace, and view VM classes and VM templates available in your environment. You can also list storage classes and other items you might need to self-service a VM.

This task covers commands you use to access resources available for a deployment of a stand-alone VM. For information about resources necessary to deploy Tanzu Kubernetes Grid clusters and VMs that make up the clusters, see Virtual Machine Classes for TKG Clusters in the Using Tanzu Kubernetes Grid 2 with vSphere with Tanzu documentation.


  1. Access your namespace in the Kubernetes environment.
  2. To view VM classes available in your namespace, run the following command.
    kubectl get virtualmachineclassbindings
    You can see the following output.
    Note: Because the best effort VM class type allows resources to be overcommitted, you can run out of resources if you have set limits on the namespace where you are provisioning the VMs. For this reason, use the guaranteed VM class type in the production environment.
    NAME                       VIRTUALMACHINECLASS        AGE
    best-effort-large          best-effort-large          44m
    best-effort-medium         best-effort-medium         44m
    best-effort-small          best-effort-small          44m
    best-effort-xsmall         best-effort-xsmall         44m
    custom                     custom                     44m
  3. To view details of a specific VM class, run the following commands.
    • kubectl describe virtualmachineclasses name_vm_class

      If a VM class includes a vGPU device, you can see its profile under spec: hardware: devices: vgpuDevices.

          cpus: 4
            - profileName: grid_v100-q4
    • kubectl get virtualmachineclasses -o wide

      If the VM class includes a vGPU or a passthrough device, the output shows it in the VGPUDevicesProfileNames or PassthroughDeviceIDs column.

  4. View the VM images.
    kubectl get virtualmachineimages​
    The output you see is similar to the following. The image name, such as vmi-xxxxxxxxxxxxx is auto-generated by the system.
    NAME                                              VERSION  OSTYPE                FORMAT  IMAGESUPPORTED  AGE
    vmi-xxxxxxxxxxxxx                                          centos8_64Guest       ovf     true            4d3h
  5. To describe a specific image, use the following command.
    kubectl describe virtualmachineimage/vmi-xxxxxxxxxxxxx

    VMs with vGPU devices require images that have boot mode set to EFI, such as CentOS. Make sure to have access to these images.

  6. Verify that you can access storage classes.
    kubectl get resourcequotas
    NAME                        AGE   REQUEST                                                                                         LIMIT
    my-ns-ubuntu-storagequota   24h 0/9223372036854775807
  7. If you are using vSphere Distributed Switch for your workload networking, obtain the name of the network.
    Note: You use this information to specify the networkName parameter in the VM YAML file when the networkType is vsphere-distributed. You do not need to obtain and specify the network name if you use VMware NSX.
    kubectl get network
    NAME      AGE
    primary   7d2h

Deploy a Virtual Machine in vSphere with Tanzu

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


If you use NVIDIA vGPU or other PCI devices for your VMs, see Deploying a VM with PCI Devices in vSphere with Tanzu.


  1. Prepare a 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 virtual machine image resource name in Kubernetes cluster.
    spec.storageClass​ Specifies the storage class to be used for storage of the persistent volumes.
    spec.className Specifies the name of the VM class that describes the virtual hardware settings to be used.
    spec.networkInterfaces Specifies network-related settings for the VM.
    • networkType. Values for this key can be nsx-t or vsphere-distributed.
    • networkName. If needed, specify the name or leave the default name.
    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.

    For additional information, including details on how to bootstrap and customize Windows VMs using the Microsoft System Preparation tool (Sysprep), see Customizing a Guest. Controls the VM placement on a three-zone Supervisor. For example, zone-a02.
    The following example VM YAML file my-vm uses CloudInit as a bootstrapping method. The example shows a VirtualMachine resource that specifies user data in a Secret resource my-vm-bootstrap-data. The Secret will be used to bootstrap and customize the guest OS.

    The data in the Secret includes the CloudInit cloud-config. For more information on the cloud-config format, see the Cloud config examples official documentation.

    For examples with Sysprep as a bootstrapping method, see Sysprep.
    kind: VirtualMachine
      name:      my-vm
      namespace: my-namespace
      className:    small
      imageName:    vmi-xxxxxxxxxxxxx
      storageClass: iscsi
        transport: CloudInit
        secretName: my-vm-bootstrap-data
    apiVersion: v1
    kind: Secret
      name:      my-vm-bootstrap-data
      namespace: my-namespace
      user-data: |
        - default
        - name: xyz..
          primary_group: xyz..
          groups: users
          - ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDSL7uWGj...
        - "ls /"
        - [ "ls", "-a", "-l", "/" ]
        - path: /etc/my-plaintext
          permissions: '0644'
          owner: root:root
          content: |
            Hello, world.

    Use the following example if you are deploying a VM in an environment with zones.

    To get the values for ZONE_NAME, run the kubectl get vspherezones command.

    kind: VirtualMachine
      name: <vm-name>
      namespace: <vm-ns>
      labels: ZONE_NAME
  2. Deploy the VM.
    kubectl apply -f my-vm.yaml
  3. Verify that the VM has been created.
    kubectl get vm
    NAME              AGE
    my-vm             28s
  4. Check the VM details and its status.
    kubectl describe virtualmachine my-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:         my-vm
    Namespace:    my-namespace
    API Version:
    Kind:         VirtualMachine
      Creation Timestamp:  2021-03-23T19:07:36Z
      Generation:  1
      Managed Fields:
      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.