User Tools

Site Tools


zededa:workshop:03_images

This is an old revision of the document!


Images

An Image in ZEDEDA Cloud is a metadata record that describes where an application image lives, what format it is, and how to verify it. ZEDEDA Cloud does not store the image binary — the edge node pulls it directly from the referenced Datastore at deployment time. Images can reference VM disk images or OCI container images.

Every image belongs to a Datastore. Before creating an image record, the Datastore must already exist.

Image Types

image_type value GUI Label Used For
IMAGE_TYPE_APPLICATION Edge App Application images: VM disks (qcow2, raw, vmdk) and container images (OCI). The most common type.
IMAGE_TYPE_EVE EVE-OS EVE-OS firmware images for edge node onboarding and OS upgrades. See EVE-OS Images.

Image Formats

image_format Category Description
CONTAINER Container OCI container image pulled from a container registry by tag or digest
QCOW2 VM QEMU Copy-On-Write v2 disk image. The standard format for KVM VMs on EVE-KVM. Most common for Linux VMs.
RAW VM Raw disk image. Used for EVE-OS firmware and some VM images.
VMDK VM VMware disk format. Can be used on EVE-KVM with QEMU support.
VHD / VHDX VM Microsoft virtual disk formats.
OVA VM Open Virtualization Archive. A bundle containing a VMDK and descriptor.

For EVE-KVM workloads, QCOW2 is the recommended format for Linux VMs. It supports thin provisioning, snapshots, and compression.

Image Architecture

image_arch Meaning
AMD64 x86-64 nodes (Intel/AMD). The most common for edge servers and industrial PCs.
ARM64 64-bit ARM nodes (NVIDIA Jetson, Raspberry Pi 4/5, etc.).

An image record is tied to one architecture. You need separate image records for AMD64 and ARM64 variants of the same software.

Key Fields

Field Required Notes
name Yes Unique across the enterprise. Cannot be changed after creation.
title Yes Display name. Can be changed.
datastore_id Yes Must reference an existing Datastore.
image_type Yes IMAGE_TYPE_APPLICATION or IMAGE_TYPE_EVE
image_format Yes CONTAINER, QCOW2, RAW, VMDK, VHD, VHDX, OVA
image_arch Yes AMD64 or ARM64
image_rel_url Yes Path within the datastore to the image. For containers: the image name and tag (e.g. nodered/node-red:latest). For files: the filename relative to the datastore path.
image_sha256 Recommended SHA-256 hash of the image file. EVE-OS verifies this after download. Required for file-based images; optional for containers (digest is checked by the registry).
image_size_bytes Recommended Expected size in bytes. Used by ZEDEDA to track storage. Set to 0 for containers (size unknown until pull).
project_access_list No Which projects can use this image. Empty list = all projects.

Terraform Examples

Container Image (Docker Hub)

Pulling a Node-RED container image from Docker Hub via the Docker Hub datastore. No SHA or size needed — OCI layer integrity is handled by the registry.

resource "zedcloud_image" "demo_node_red_1" {
  datastore_id        = zedcloud_datastore.demo_docker_hub.id
  image_type          = "IMAGE_TYPE_APPLICATION"
  image_arch          = "AMD64"
  image_format        = "CONTAINER"
  image_size_bytes    = 0
  name                = "TF-NODE-RED-CONTAINER-IMAGE"
  title               = "TF-NODE-RED-CONTAINER-IMAGE"
  project_access_list = []
  image_rel_url       = "nodered/node-red:latest"
}

Notes:

  • image_rel_url is the image reference exactly as you would use in docker pull — <repo>/<image>:<tag>
  • image_size_bytes = 0 is correct for containers; EVE-OS does not need the size pre-declared
  • image_sha256 is omitted; OCI registries use their own layer digest verification
  • The datastore_id references the Docker Hub datastore (DATASTORE_TYPE_CONTAINERREGISTRY)
  • To pin to a specific digest instead of a floating tag: image_rel_url = “nodered/node-red@sha256:abc123…”

VM Image (QCOW2 from local HTTP)

Ubuntu 24.04 (Noble) cloud image served from a local HTTP datastore. SHA256 and size are both provided for integrity verification.

resource "zedcloud_image" "demo_atl_ub_image_1" {
  datastore_id        = zedcloud_datastore.demo_atl_ds.id
  image_type          = "IMAGE_TYPE_APPLICATION"
  image_arch          = "AMD64"
  image_format        = "QCOW2"
  image_sha256        = "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820"
  image_size_bytes    = 618925568
  name                = "TF-ATL-UBUNTU-24-IMAGE"
  title               = "TF-UBUNTU-24-IMAGE"
  project_access_list = []
  image_rel_url       = "noble-server-cloudimg-amd64.img"
}

Notes:

  • image_rel_url is the filename at the root of the HTTP server (combined with ds_path from the datastore to form the full URL)
  • image_sha256 — EVE-OS will verify the downloaded file against this hash. If the hash doesn't match, the download is rejected and the app instance errors
  • image_size_bytes — the size in bytes of the qcow2 file. Get this with: stat -c %s noble-server-cloudimg-amd64.img (Linux) or stat -f %z <file> (macOS)
  • image_sha256 — get this with: sha256sum noble-server-cloudimg-amd64.img (Linux) or shasum -a 256 <file> (macOS)
  • The Ubuntu cloud image is a sparse qcow2 — the file on disk (618 MB) is much smaller than the virtual disk size. EVE-OS expands it when creating the volume.

VM Image (Azure Blob)

Same Ubuntu image but sourced from Azure Blob Storage instead of a local server:

resource "zedcloud_image" "demo_az_ub_image" {
  datastore_id        = zedcloud_datastore.demo_az_blob_ds.id
  image_type          = "IMAGE_TYPE_APPLICATION"
  image_arch          = "AMD64"
  image_format        = "QCOW2"
  image_sha256        = "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820"
  image_size_bytes    = 618925568
  name                = "TF-AZ-UBUNTU-24-IMAGE"
  title               = "TF-AZ-UBUNTU-24-IMAGE"
  project_access_list = []
  image_rel_url       = "vms/noble-server-cloudimg-amd64.img"
}

The image_rel_url is the blob path within the container (the ds_path from the datastore definition). So the full resolved URL would be: https://<account>.blob.core.windows.net/<container>/vms/noble-server-cloudimg-amd64.img

Multiple Datastores (Fallback)

You can reference up to 3 datastores on a single image for redundancy. EVE-OS tries them in order — useful for hybrid environments where a cloud primary and local secondary exist:

resource "zedcloud_image" "demo_ub_with_fallback" {
  datastore_id        = zedcloud_datastore.demo_az_blob_ds.id
  image_type          = "IMAGE_TYPE_APPLICATION"
  image_arch          = "AMD64"
  image_format        = "QCOW2"
  image_sha256        = "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820"
  image_size_bytes    = 618925568
  name                = "TF-UBUNTU-24-WITH-FALLBACK"
  title               = "TF-UBUNTU-24-WITH-FALLBACK"
  project_access_list = []
  image_rel_url       = "noble-server-cloudimg-amd64.img"
  # Optional: additional datastores as fallback
  datastores = [
    zedcloud_datastore.demo_atl_ds.id  # local HTTP fallback
  ]
}

ZEDUI Walkthrough

  1. Navigate to Library > Images
  2. Click the + icon
  3. Identity: Name (permanent), Title, Description, Project scope
  4. Image Type: Edge App, Docker Compose, or Compose Runtime
  5. Image Format: Container, ISO, QCOW2, or RAW
  6. Image Architecture: AMD64 or ARM64
  7. Datastore: select up to 3 datastores (primary + fallback)
  8. Image URL: the relative path within the datastore (for files) or the image:tag (for containers)
  9. For file-based images: provide SHA256 and Size (bytes) — these can be entered manually or via Upload/Uplink
  10. Click Add

ZCLI

# Container image
zcli image create TF-NODE-RED-CONTAINER-IMAGE \
  --datastore-name=TF-ZED-DEMO-DOCKER-HUB \
  --arch=AMD64 \
  --image-format=container \
  --image-url=nodered/node-red:latest \
  --type=Application \
  --title=TF-NODE-RED-CONTAINER-IMAGE
# QCOW2 VM image (register the record)
zcli image create TF-ATL-UBUNTU-24-IMAGE \
  --datastore-name=TF-ATL-ZED-DEMO-DS \
  --arch=AMD64 \
  --image-format=qcow2 \
  --title=TF-ATL-UBUNTU-24-IMAGE \
  --type=Application
# Uplink (associate the file hash and size with the record)
zcli image uplink TF-ATL-UBUNTU-24-IMAGE \
  --datastore-name=TF-ATL-ZED-DEMO-DS \
  --image-sha=834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820 \
  --image-size=618925568

Note: for file-based images, image create registers the metadata and image uplink associates the SHA256 and size. These are two separate steps in ZCLI, but a single resource block in Terraform.

API

# Container image
POST /v1/images
{
  "name": "TF-NODE-RED-CONTAINER-IMAGE",
  "imageType": "IMAGE_TYPE_APPLICATION",
  "imageArch": "AMD64",
  "imageFormat": "CONTAINER",
  "datastoreId": "<docker_hub_datastore_id>",
  "imageRelUrl": "nodered/node-red:latest",
  "imageSizeBytes": 0
}
# QCOW2 VM image
POST /v1/images
{
  "name": "TF-ATL-UBUNTU-24-IMAGE",
  "imageType": "IMAGE_TYPE_APPLICATION",
  "imageArch": "AMD64",
  "imageFormat": "QCOW2",
  "datastoreId": "<http_datastore_id>",
  "imageRelUrl": "noble-server-cloudimg-amd64.img",
  "imageSha256": "834af9cd766d1fd86eca156db7dff34c3713fbbc7f5507a3269be2a72d2d1820",
  "imageSizeBytes": 618925568
}

What Happens on the Edge Node

The image record itself is never sent to the node — only the download instruction when an app instance referencing it is deployed:

  1. The controller sends the app instance config to EVE-OS including the resolved image URL, credentials, format, SHA256, and size
  2. For CONTAINER format: EVE-OS authenticates to the registry and pulls OCI layers using the standard OCI distribution protocol. Layers are stored in EVE-OS's containerd content store and deduped across images that share base layers.
  3. For QCOW2 / RAW / VMDK format: EVE-OS performs an HTTP(S)/S3/SFTP GET for the image file, streams it to the local volume pool, then verifies the SHA256 hash on completion. A mismatch aborts and marks the app instance as errored.
  4. Once downloaded, the image is cached in EVE-OS's local storage. If another app instance on the same node references the same image, it reuses the cached copy without re-downloading.
  5. For QCOW2 images, EVE-OS creates a copy-on-write overlay for each app instance so multiple VMs can share the same base image without writing to it.

Getting SHA256 and Size for a VM Image

Before creating a file-based image record, you need the SHA256 hash and byte size of the file:

# Linux
sha256sum noble-server-cloudimg-amd64.img
stat -c %s noble-server-cloudimg-amd64.img
# macOS
shasum -a 256 noble-server-cloudimg-amd64.img
stat -f %z noble-server-cloudimg-amd64.img
# PowerShell (Windows)
Get-FileHash noble-server-cloudimg-amd64.img -Algorithm SHA256
(Get-Item noble-server-cloudimg-amd64.img).length

Common VM Images for EVE-KVM

OS Format Source Notes
Ubuntu 24.04 (Noble) QCOW2 Ubuntu Cloud Images noble-server-cloudimg-amd64.img — cloud-init ready
Ubuntu 22.04 (Jammy) QCOW2 Ubuntu Cloud Images jammy-server-cloudimg-amd64.img
Debian 12 QCOW2 Debian Cloud Images debian-12-genericcloud-amd64.qcow2
Windows Server VHDX/VMDK Microsoft / your own Must convert to QCOW2 with qemu-img convert for EVE-KVM
Red Hat / RHEL QCOW2 Red Hat customer portal Must use VirtIO disk controller — change in VM settings before export

For Windows or RHEL VMs, the disk controller must be set to VirtIO before exporting the image, or the VM will fail to find its disk on EVE-KVM.

zededa/workshop/03_images.1780244897.txt.gz · Last modified: (external edit)