Create custom images

You can create custom images from existing source disks and use them to create and start virtual machines (VMs). Custom images are ideal for use when you have created and modified a persistent boot disk to a certain state and need to save that state for creating VMs. Creating and saving a custom image to use as a new VM image in future VM creation prevents duplicating your setup steps later.

Before you begin

To use gdcloud command-line interface (CLI) commands, ensure that you have downloaded, installed, and configured the gdcloud CLI. All commands for Distributed Cloud Hosted use the gdcloud or kubectl CLI, and require an operating system (OS) environment.

Get the kubeconfig file paths

  1. Run gdcloud auth login to the admin cluster.

    1. Record the path to the generated file, as in this example:
      /tmp/admin-kubeconfig-with-user-identity.yaml.

    2. Use the path to replace ORG_ADMIN_KUBECONFIG in these instructions.

Permissions required for this task

To create a custom image, you must have project-level VM image access. Follow the steps given to assign the Project VirtualMachine Image Admin role. If you are using the GDCH console to create an image, you also need the VM Admin role and the Project Viewer role.

Create a custom image

This section describes how to create a custom image on a VM.

Prepare your VM for an image

You can create an image from a disk while it is attached to a running VM. However, your image is more reliable if you put the VM into a state for the image to capture.

Minimize writing data to the persistent disk

Use one of the following processes to reduce disk writes. Either stop the VM, or minimize writes to the disk:

  • Stop the VM so that it can shut down and stop writing any data to the persistent disk.

If you can't stop your VM before you create the image, minimize the writes to the disk and sync your file system. To minimize writes to your persistent disk, follow these steps:

  1. Pause apps or OS processes that write data to that persistent disk. Run an app flush to disk, if necessary. Other apps might have similar processes.
  2. Stop your apps from writing to your persistent disk.
  3. Run sudo sync.

Create the image

Follow these steps to create disk images from a persistent disk, even while that disk is attached to a VM:

Console

  1. Select a project.

  2. In the navigation menu, click Virtual Machines > Images.

  3. Click Create Image.

  4. Enter a unique name for the image. The name must be no longer than 35 characters.

  5. Enter a version to add to the image name.

  6. In the Source Disk field, select a disk.

  7. In the Minimum Disk Size field, enter a disk size.

  8. Enter a description of the image.

  9. Click Create.

The image appears in the list of images.

API

  1. List all VirtualMachineDisk objects:

    kubectl --kubeconfig ORG_ADMIN_KUBECONFIG \
       get virtualmachinedisks.virtualmachine.gdc.goog --namespace PROJECT
    
  2. Select a VirtualMachineDisk object to use as source disk for the new image.

  3. Check whether the VM disk is attached to a VM:

      kubectl --kubeconfig ORG_ADMIN_KUBECONFIG \
          get virtualmachinedisks.virtualmachine.gdc.goog --namespace PROJECT \
          DISK_NAME -o jsonpath='{.status.virtualMachineAttachments}'
    

    Example output showing a disk is attached to a VM:

      [{"autoDelete":true,"nameRef":{"name":"vm1"},"uid":"...."}]
    
    1. Check the VM's running status. If the status is not Stopped, Stop the VM and proceed with creating the VirtualMachineImage.
  4. Get the size of VirtualMachineDisk to create the image:

    kubectl --kubeconfig ORG_ADMIN_KUBECONFIG \
        get virtualmachinedisks.virtualmachine.gdc.goog --namespace PROJECT \
        DISK_NAME -o jsonpath='{.spec.size}'
    
  5. Create a VirtualMachineImageImport object in the org admin cluster:

    kubectl --kubeconfig ORG_ADMIN_KUBECONFIG \
        apply -n PROJECT -f - <<EOF
    apiVersion: virtualmachine.gdc.goog/v1
    kind: VirtualMachineImageImport
    metadata:
      name: VM_IMAGE_IMPORT_NAME
    spec:
      source:
        diskRef:
          name: DISK_NAME
      imageMetadata:
        name: IMAGE_NAME
        operatingSystem: OS_NAME
        minimumDiskSize: MINIMUM_DISK_SIZE
    EOF
    
  6. Verify that the image import has finished and the status is Ready:

    kubectl --kubeconfig ORG_ADMIN_KUBECONFIG \
        get virtualmachineimageimports.virtualmachine.gdc.goog --namespace PROJECT \
        VM_IMAGE_IMPORT_NAME -o jsonpath='{.status}'
    

    The status should look like this when the import is complete:

    {
      "conditions": [
        {
          "lastTransitionTime": "",
          "message": "",
          "observedGeneration": 1,
          "reason": "ImportJobComplete",
          "status": "True",
          "type": "Ready"
        }
      ],
      "imageName": IMAGE_NAME
    }
    
  7. Verify the image has been created:

    kubectl --kubeconfig ORG_ADMIN_KUBECONFIG \
        get virtualmachineimages.virtualmachine.gdc.goog --namespace PROJECT \
        CREATED_IMAGE_NAME
    

    Replace the variables, using the following definitions.

    VariableDefinition
    ADMIN_KUBECONFIG The admin cluster kubeconfig file path.
    PROJECT The GDCH project in which to create the image.
    DISK_NAME The name of the source disk, such as vm1-boot-disk.
    VM_IMAGE_IMPORT_NAME The name of the VM image import. The name must be no longer than 35 characters.
    IMAGE_NAME The name of the created image, such as custom-image.
    OS_NAME The name of the image OS, must be one of these three:
    ubuntu-2004, windows-2019, or rhel-8.
    MINIMUM_DISK_SIZE The minimum disk size in the VM image import, such as 20G:
    minimumDiskSize must always be greater than or equal to the source boot disk size.
    CREATED_IMAGE_NAME The name of the created image. The created image name must be unique; it cannot be an image name that already exists in the project.