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.

Prerequisites

  • 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.

Procedure

  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 vmoperator.vmware.com/v1alpha1.
    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.
    apiVersion: vmoperator.vmware.com/v1alpha1
    kind: VirtualMachine
    metadata:
      name: vmsvc-centos-vm
      namespace: my-ns-centos
    spec:
      imageName: centos-stream-8-vmservice-v1alpha1-xxxxxxxxxxxxx
      className: custom
      powerState: poweredOn
      storageClass: wcpglobal-storage-profile
      networkInterfaces:
      - networkName: "primary"
        networkType: vsphere-distributed
      vmMetadata:
          configMapName: vmsvc-centos-nginx-cm
          transport: OvfEnv
    ---
    apiVersion: v1
    kind: ConfigMap
    metadata:
        name: vmsvc-centos-nginx-cm
        namespace: my-ns-centos
    data:
      user-data: >-
        I2Nsb3VkLWNvbmZpZwoKcGFzc3dvcmQ6IFZNV0FSRQpzc2hfcHdhdXRoOiB0cnVlCgp1c2VyczoKICAtIG5hbWU6IHZtd2FyZQogICAgc3VkbzogQUxMPShBTEwpIE5PUEFTU1dEOkFMTAogICAgbG9ja19wYXNzd2Q6IGZhbHNlCiAgICAjIFBhc3N3b3JkIHNldCB0byBBZG1pbiEyMwogICAgcGFzc3dkOiAnJDEkc2FsdCRTT0MzM2ZWYkEvWnhlSXdENXl3MXUxJwogICAgc2hlbGw6IC9iaW4vYmFzaAoKd3JpdGVfZmlsZXM6CiAgLSBjb250ZW50OiB8CiAgICAgIFZNU1ZDIFNheXMgSGVsbG8gV29ybGQKICAgIHBhdGg6IC9oZWxsb3dvcmxkCg==
    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:
    #cloud-config
    password: VMWARE
    ssh_pwauth: true
    users:
      - name: vmware
        sudo: ALL=(ALL) NOPASSWD:ALL
        lock_passwd: false
        passwd: '$1$salt$SOC33fVbA/ZxeIwD5yw1u1'
        shell: /bin/bash
    write_files:
      - content: |
          VMSVC Says Hello World
        path: /helloworld
    For more information about cloud-config specifications, see https://cloudinit.readthedocs.io/en/latest/topics/examples.html.
  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:  vmoperator.vmware.com/image-supported-check: disabled
    API Version:  vmoperator.vmware.com/v1alpha1
    Kind:         VirtualMachine
    Metadata:
      Creation Timestamp:  2021-03-23T19:07:36Z
      Finalizers:
        virtualmachine.vmoperator.vmware.com
      Generation:  1
      Managed Fields:
     ...  
     ... 
    Spec:
      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
    Status:
      Bios UUID:              4218ec42-aeb3-9491-fe22-19b6f954ce38
      Change Block Tracking:  false
      Conditions:
        Last Transition Time:  2021-03-23T19:08:59Z
        Status:                True
        Type:                  VirtualMachinePrereqReady
      Host:                    10.185.240.10
      Instance UUID:           50180b3a-86ee-870a-c3da-90ddbaffc950
      Phase:                   Created
      Power State:             poweredOn
      Unique ID:               vm-73
      Vm Ip:                   10.161.75.162
    Events:                    <none>
    ...
    
  5. Verify that the VM IP is reachable.
    ping 10.161.75.162
    PING 10.161.75.162 (10.161.75.162): 56 data bytes
    64 bytes from 10.161.75.162: icmp_seq=0 ttl=59 time=43.528 ms
    64 bytes from 10.161.75.162: icmp_seq=1 ttl=59 time=53.885 ms
    64 bytes from 10.161.75.162: icmp_seq=2 ttl=59 time=31.581 ms

Results

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.