Import an image
If you already have a VM disk — as a GCP Compute Engine image, or as a file on your machine — you can import it rather than rebuilding it. The import converts the disk, prepares it for reuse and registers it in your team’s catalog as a new image at team-slug/name, with its first version tagged v1.
Imports run headless. There is no VM to attach to and nothing to drive: you start one and watch it in Drafts on the images list.
An import keeps running server-side once it starts, so you can close the tab and check back later. Each step has its own limit: three hours for the GCP export, and thirty minutes per attempt for preparing the image, with up to three attempts.
Import a GCP Compute Engine image
Section titled “Import a GCP Compute Engine image”- In the sidebar, click Building blocks → Images.
- Click Import → GCP Image.
- Enter an Image name. This becomes
team-slug/name, and it has to be free within your team. - Enter the GCP image reference — either a self-link, or
projects/<project>/global/images/<image>. - Click Import.
Pin a specific image. Image families (projects/<project>/global/images/family/<family>) are refused, because the whole point of an import is that you know what you imported.
Import a private image
Section titled “Import a private image”A private image needs two things before your team can import it. The Import image dialog shows both commands with your team ID filled in. Paste the image reference, and the commands fill in its project and image too. Copy the commands from there, or run them by hand:
-
Give Instruqt’s importer read access to the image:
Terminal window gcloud compute images add-iam-policy-binding <image> \--project=<project> \--member=serviceAccount:image-import-copy@instruqt-prod.iam.gserviceaccount.com \--role=roles/compute.imageUser -
Label the image with your team’s ID, in lowercase:
Terminal window gcloud compute images add-labels <image> \--project=<project> \--labels=instruqt-team=<team-id>
All Instruqt teams share the importer service account. The label is what limits the import to your team: an import from any other team fails. Only someone who can change the image can set its labels.
If the label is missing or has another value, the import fails and shows the exact label to set.
Images in Google’s public OS image projects (e.g. debian-cloud, ubuntu-os-cloud) need neither step. To import an image you cannot label, copy it into a project you own first (gcloud compute images create --source-image=...).
Import a disk file
Section titled “Import a disk file”- In the sidebar, click Building blocks → Images.
- Click Import → Image File.
- Enter an Image name.
- Drop a disk onto the upload area, or click Choose a disk. qcow2, raw and VMDK are supported, up to 150 GB.
- Click Import.
The file does not pass through the Instruqt API — your browser uploads it straight to storage, and the import is pointed at what landed. Keep the dialog open while it uploads; for a real disk that is minutes, and the progress bar is in the dialog. The upload is resumable, and Cancel upload stops it without starting anything.
What an import does to the disk
Section titled “What an import does to the disk”Both paths prepare the disk before registering it, so it behaves like a base image rather than like a clone of one particular machine:
- Cloud-init state is reset, so every lab that boots from it gets a clean first boot.
- On images with cloud-init, cloud-init is set to use only the NoCloud datasource, which is how Instruqt hands it the VM’s configuration.
- GCE guest services (e.g.
google-guest-agent) are disabled, so the disk does not wait for GCE’s metadata server. - Machine-specific identity — the machine ID, SSH host keys — is cleared.
- Users’
.sshdirectories, includingauthorized_keys, are removed, along with log files, shell history, users’ cron and at jobs, DHCP leases, temporary files and package manager caches. - Network configuration tied to the source machine is removed: files in
/etc/netplanand/etc/systemd/network, the network configuration cloud-init wrote, udev persistent network rules, andHOSTNAMEandDHCP_HOSTNAMEsettings in network interface files. It names the source machine’s network interfaces, which don’t exist here. The VM gets its addresses from Instruqt at boot instead. See Images without cloud-init. - The Instruqt agent is installed as a systemd service.
- On images with SELinux, SELinux is set to permissive. No SELinux relabel is scheduled, so the VM does not relabel its filesystem and reboot when it boots.
- The GRUB menu timeout is set to 0, so the VM boots its default entry without waiting at the menu.
State that your own software created on the source machine is kept, such as a Kubernetes cluster’s datastore and certificates. Reset it before you create the source image, as described in Before you publish.
A raw or VMDK disk is converted to qcow2 along the way.
BIOS and UEFI disks
Section titled “BIOS and UEFI disks”An imported disk can be installed for BIOS, for UEFI, or for both. Each time a VM starts, in a build session or in a lab, Instruqt reads the disk’s partition table to pick the firmware:
- A disk with boot code in its master boot record boots with BIOS. This includes disks installed for both, which also have an EFI System Partition.
- A disk with no boot code in its master boot record and with an EFI System Partition boots with UEFI.
There is no setting to choose the firmware. UEFI VMs boot without Secure Boot. UEFI variables, such as boot entries, are not saved with the image: every VM starts with an empty set. With no boot entries, the firmware boots the fallback loader at \EFI\BOOT\BOOTX64.EFI on the EFI System Partition, so a disk installed for UEFI only must have that file. The import does not add it.
Images without cloud-init
Section titled “Images without cloud-init”Cloud-init is optional. Instruqt’s base images have it, and so do most cloud images, but an image exported from another hypervisor (e.g. VMware) often does not.
The Instruqt agent runs the startup_script, task scripts, exec health checks and terminals, mounts disk and volume blocks, and sets the environment variables. None of these need cloud-init. What cloud-init does in a VM is configure the network, and set the hostname in a lab:
- Network, in a build session: The agent configures the network. Instruqt reaches the agent without using the network, so this works with or without cloud-init.
- Network, in a lab: With cloud-init installed and not disabled (no
/etc/cloud/cloud-init.disabled), cloud-init configures the network, as on Instruqt’s base images. If it has not configured every network interface within 60 seconds, e.g. because the image turns off cloud-init’s network configuration, the agent configures them instead, and the VM is ready about a minute later. Without cloud-init, or with cloud-init disabled, the agent configures each interface’s address, the default route and the DNS resolver, and keeps NetworkManager from changing those interfaces and/etc/resolv.conf. - Hostname: With cloud-init, a lab VM’s hostname is its resource name. Without it, the hostname is whatever is on the disk. The agent in a build session sets the hostname to
buildand writes it to/etc/hostname, and publishing keeps it, so a lab VM booted from a published version is calledbuild. Thev1an import creates keeps the hostname the source machine had. Either way, other resources in the lab reach the VM by its resource name.
If the image has cloud-init, keep it: networking in a lab is set up the same way as on Instruqt’s base images, and the VM’s hostname matches its resource name.
Firewalls
Section titled “Firewalls”A lab reaches the agent over the VM’s network, with or without cloud-init, so the image’s firewall must let the agent’s port through. The agent opens its port in firewalld, the default firewall on e.g. RHEL. It does not open it in any other firewall, such as ufw, or nftables or iptables rules: if one of those blocks incoming connections, the lab fails waiting for the VM’s agent. Ports your lab itself uses, e.g. for a service tab, must also be open in the image’s firewall.
Watching an import
Section titled “Watching an import”The import appears in Drafts above the catalog with an Importing badge and a line saying where it is:
| Phase | What is happening |
|---|---|
| Copying source image… | The source is being copied into Instruqt’s export project. GCP imports only. |
| Exporting disk… | The image is being exported to a disk file. GCP imports only. |
| Preparing image… | The disk is being converted and prepared. |
| Publishing… | The result is being pushed to the registry. |
When it finishes, the draft row disappears and the image is in the catalog as Published. A failed import stays as a Failed row with its error; Dismiss clears it.
Opening an importing session’s URL directly tells you there is nothing to drive — the drafts list is where an import is watched.
After importing
Section titled “After importing”An imported image is an ordinary team image. From there you can:
- Boot labs from it by referencing
team-slug/name. See Use an image in a lab. - Build on top of it with New version, the same as any other image.
- Write its readme, so the rest of the team knows what is in it. See Manage images and versions.
Limits
Section titled “Limits”| Limit | Value |
|---|---|
| Upload size | 150 GB |
| Disk formats | qcow2, raw, VMDK |
| GCP sources | A specific Compute Engine image. A private image must be shared with the importer and labeled for your team. Image families are not supported. |
| Name | Must be free within your team. A collision is refused before the import starts. |
