This is an old revision of the document!
Table of Contents
EVE-OS / ZEDEDA Application Volumes
Covers: what a volume is, what has to be configured in the GUI vs Terraform, how to deploy an app with a volume, and how to grow a volume after deployment. Primary examples use an image-backed HDD drive; HDD_EMPTY is covered as a separate use case at the end.
This page stays at the controller/app-instance config layer — the fields you set in the GUI, Terraform, or zcli. For what actually happens on the storage backend underneath (qcow2 vs. zvol, pool RAID vs. per-app resize), see the companion page: EVE-OS Volume Provisioning: Pool Layer vs. Per-App Layer.
Sources: lf-edge/eve, zededa/zedcloud Terraform provider docs, ZEDEDA Help Center (Storage Overview, Manage an Edge Application Instance, ZCLI volume-instance docs).
1. What a volume is
A volume instance is the storage object EVE-OS attaches to an app instance as a drive. It backs one of:
- The app's rootfs / OS disk (built from a Content Tree / image) — drive type HDD
- A blank data disk for app data — drive type HDD_EMPTY
- A shared/persistent data volume that can outlive the app instance or be shared between app instances on the same node
A volume can be:
- Implicit — created automatically as part of an app instance's drive list (defined inline on the app manifest)
- Explicit — created ahead of time as its own standalone object (Library > Volume Instances > +) and then referenced by label when the app is deployed
Standalone Volume Instance — Type options
When adding a standalone Volume Instance via the GUI, Type is one of:
- Content Tree — image-backed. An Image field appears (Select/Search Image) to pick the content tree. This is the standalone-object equivalent of an
HDDdrive. - Block Storage — blank. No Image field. Instead a Max Storage Size field appears (value + unit, e.g. Bytes). This is the standalone-object equivalent of
HDD_EMPTY.
Both types also require:
- Access Mode:
ReadorRead/Write - Edge Node: the target node the volume instance is delivered to (required either way — a standalone volume instance is still provisioned on a specific node, not floating free of one)
- Optional: Label, Encrypted (Block Storage), Deploy Edge Nodes Cluster toggle if targeting a cluster instead of a single node
Important layering note: everything on this page — maxsize, preserve, allow_storage_resize, drive type — is a controller-side config object (EVE's VolumeConfig, defined in pillar/types/volumes.go). It says nothing about how the volume is physically stored. EVE's volumemgr agent on the node reads this config and decides how to realize it on whatever persist backend the node has (ext4 or ZFS). That translation step is a completely separate layer — see the companion page.
2. Key fields (controller/app-instance layer)
| Field | Where it shows up | What it does |
|---|---|---|
Drive Type (drvtype) | GUI Drives pane / TF drvtype | HDD = image-backed. CDROM = read-only image, optical semantics. NET = network-backed. HDD_EMPTY = blank disk of maxsize (covered in section 6). |
Max Size (maxsize / maxsizebytes) | GUI Drives pane “Max Size” / TF maxsize | Capacity ceiling for the drive, as seen by the app-instance config. For HDD, this must be >= the image size; any headroom above the image size is usable, growable space on that same disk. This value is what volumemgr uses to size the actual backing object — see companion page for what that object is. |
Preserve (preserve) | GUI Drives pane “Preserve” | Whether this drive's data survives a purge/refresh of the app instance, vs. being rebuilt from the source image. |
Allow Storage Resize (allow_storage_resize / allowStorageResize) | App instance level, GUI/zcli/TF | Must be enabled before an existing app instance's drive size can be increased. Default: false. |
Volume Label (volumelabel) | GUI Drives pane / TF | References a pre-created (explicit) volume instance instead of an inline drive definition. |
Mount Path (mountpath) | GUI Drives pane / TF | Path inside the app where the drive is mounted. Empty or / defines the rootfs. |
3. What's required to configure — GUI vs Terraform
GUI
- Standalone volume instances: Library > Volume Instances > + (Add Volume Instance). Set Type (Content Tree or Block Storage), Access Mode, target Edge Node, and either Image (Content Tree) or Max Storage Size (Block Storage).
- Implicit volumes are created inline while adding a drive to an app instance instead — no separate object.
- On the app instance's Drives pane, define per drive: Drive Type, Image, Mount Path, Max Size, Preserve, Encrypted, and (for explicit volumes) Volume Label.
- Editing Drives on an existing app instance triggers a Purge & Update — the app purges and comes back online. Data on that drive is wiped unless Preserve was set.
Terraform (zededa/zedcloud provider)
- Resource:
zedcloud_application_instance(orzedcloud_deploymentfor policy-driven rollout). - Drive block fields:
drvtype,maxsize,preserve,mountpath,imagename/imvolname/mvolname,volumelabel. - App-instance-level field:
allow_storage_resize(bool, default false) — must betrueto permit a latermaxsizechange to apply. - Standalone volume instances can also be managed as their own resource/data source (
zedcloud_volume_instancefamily) and referenced by label from the app instance.
ZCLI
- Explicit volume:
zcli volume-instance create <name> –volume-type=<type> –project=<project> (–edge-node=<node> | –edge-node-cluster=<cluster>) –size=<size> –access-mode=<mode> - Update:
zcli volume-instance update <name> [–title=…] [–description=…] - App-instance-level resize permission is passed the same way as the GUI/TF flag, camelCase in JSON:
“allowStorageResize”: true
4. Step-by-step: Deploy an app with a volume (HDD)
This is the common case: a single image-backed drive that serves as both the app's rootfs and its data storage, sized larger than the image itself so there's room to grow later.
Via GUI
- Go to Edge Applications > Marketplace, select or create the edge app.
- Deploy the app: Edge Applications > Deploy, pick the target edge node.
- On the Drives pane, add the drive:
- Drive Type: HDD
- Image: select the app's image / content tree
- Mount Path:
/(or empty) to define the rootfs - Max Size: set this above the image's native size if you want growable headroom (e.g. image is 4 GB, set Max Size to 20 GB)
- Preserve: enable if this disk's contents should survive a future purge
- Complete networking/resources panes as normal and click Deploy.
- Confirm in Edge Node > App Instances that the instance reaches
RUNNINGand the drive shows the expected size under app instance details.
Via Terraform
resource "zedcloud_application_instance" "example" {
name = "my-app-instance"
app_id = zedcloud_application.example.id
device_id = data.zedcloud_edgenode.target.id
project_id = data.zedcloud_project.example.id
drives {
drvtype = "HDD"
imagename = "my-app-image"
mountpath = "/"
maxsize = "21474836480" # 20 GiB ceiling, even if the image itself is much smaller
preserve = true
}
allow_storage_resize = true
}
terraform plan/terraform apply.- Verify state:
terraform state show zedcloud_application_instance.exampleor check the GUI app instance detail page.
5. Step-by-step: Grow a volume (HDD)
Important: this is not a live/hot resize. Editing a drive on an existing app instance triggers a Purge & Update — the app purges and restarts. Data on that drive is lost unless preserve is set on it.
Via GUI
- Confirm the drive you're growing has Preserve set (if you need to keep its data).
- Go to Edge Applications > App Instances, select the instance, Edit.
- If not already enabled, enable Allow Storage Resize at the app instance level.
- On the Drives pane, raise the Max Size field for the HDD drive.
- Save. The GUI will show a Purge and update notification — confirm it.
- Wait for the app instance to purge and come back
RUNNING. - Log into the guest and grow the filesystem to use the new space (EVE resizes the backing volume, not the guest's partition/fs — see step below).
Via Terraform
resource "zedcloud_application_instance" "example" {
# ...unchanged config...
drives {
drvtype = "HDD"
imagename = "my-app-image"
mountpath = "/"
maxsize = "42949672960" # was 20 GiB, now 40 GiB
preserve = true
}
allow_storage_resize = true # must be true BEFORE the maxsize change is allowed to apply
}
terraform apply. Ifallow_storage_resizewasfalseon the last-applied state, apply that change first, then apply themaxsizechange (or in the same apply if the provider allows it — verify against current provider version behavior before assuming ordering).- Confirm the app instance purges and comes back up.
Guest-side step (both paths)
Raising maxsize enlarges the backing storage object (whatever volumemgr made it — see companion page); it does not grow the guest's partition or filesystem automatically. After the app instance comes back up:
- Linux ext4:
growpart /dev/xxx Nthenresize2fs /dev/xxxN - Linux xfs:
growpartthenxfs_growfs <mountpoint> - Windows: Disk Management > right-click volume > Extend Volume
6. Other use case: HDD_EMPTY (blank data disk)
HDD_EMPTY is a second, complementary pattern rather than an alternative to the above: a completely blank disk, not backed by any image or content tree, used as a separate data drive alongside an HDD rootfs drive.
- No image, no content tree, no hash to verify — the app-instance config just declares
maxsize, and volumemgr allocates raw space up to that. - Arrives to the guest as a raw, unformatted block device. The guest OS (or first-boot cloud-init) has to partition and format it itself.
- Typically mounted at a data path (e.g.
/data,/var/lib/mysql), separate from/. - Same
preserve,maxsize, andallow_storage_resizemechanics apply — grown the same way as described in section 5, just as a second drive block rather than the rootfs drive.
drives {
drvtype = "HDD_EMPTY"
maxsize = "10737418240" # 10 GiB blank data disk
preserve = true
mountpath = "/data"
}
Use this when you want the OS/app image to stay a fixed, replaceable artifact (rebuilt cleanly on every app update) while the data lives on its own drive that is never touched by an image update — as opposed to the HDD pattern in sections 4-5, where rootfs and data share one disk and the whole disk gets rebuilt from the image on update unless preserve is set.
7. Open questions / to verify before relying on this in production
- Exact ordering requirement between setting
allow_storage_resize=trueand applying amaxsizechange in a single Terraform apply — not confirmed from docs, test on a non-prod app instance first. - Whether any current EVE-OS version auto-grows the guest filesystem on boot after a resize (e.g., via cloud-init growpart module) — not confirmed; assume manual step is required unless verified for your specific image.
- How
maxsizeactually gets realized on disk (qcow2 vs. per-app zvol, thin vs. thick) — this is a different layer than anything on this page. See EVE-OS Volume Provisioning: Pool Layer vs. Per-App Layer. - This page is entirely about app instance drives. It does not cover the underlying
/persiststorage pool (ext4 disk or ZFS pool, RAID level) — that is an install-time/reinstall decision made via grub.cfg, not a controller-driven one. Covered on the EVE-OS Partitioning / ZFS wiki page.
