zededa:workshop:06_persistent_volumes_content_trees
Differences
This shows you the differences between two versions of the page.
| zededa:workshop:06_persistent_volumes_content_trees [2026/07/22 15:52] – old revision restored (2026/05/31 17:21) mc | zededa:workshop:06_persistent_volumes_content_trees [2026/07/22 15:53] (current) – removed mc | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| - | ====== Persistent Volumes and Content Trees ====== | ||
| - | Volume instances are the storage layer for edge applications in ZEDEDA Cloud. There are two types, both created as '' | ||
| - | |||
| - | * **Persistent Volume (BLOCKSTORAGE)** -- blank block storage allocated on the edge node. Read-write. Data survives app restarts, app deletion, and node reboots. Used for stateful application data. | ||
| - | * **Content Tree (CONTENT_TREE)** -- a volume pre-populated from an existing image. Read-only by default. Used to deliver an OS image, dataset, or binary to the node before or alongside an app. | ||
| - | |||
| - | Both types are **node-scoped objects** -- they are created on a specific edge node or cluster, not in the project at large. If you want the same volume on five nodes, you create five volume instances. | ||
| - | |||
| - | ===== Volume Instance Types ===== | ||
| - | |||
| - | ^ Type value ^ Purpose ^ Access Mode ^ Image required ^ Typical use ^ | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | ===== Key Fields ===== | ||
| - | |||
| - | ^ Field ^ Description ^ | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | | '' | ||
| - | |||
| - | ===== Persistent Volume vs Standard Volume ===== | ||
| - | |||
| - | This is an important distinction in ZEDEDA: | ||
| - | |||
| - | ^ | Standard Volume | Persistent Volume | | ||
| - | | Owned by | The app instance | The edge node | | ||
| - | | Lifecycle | Deleted when the app instance is deleted | Survives app deletion | | ||
| - | | Purge & Update | Available | Not available (Purge is unchecked) | | ||
| - | | Shared across apps | No | Yes -- multiple apps on the same node can attach it | | ||
| - | | Created via | App bundle drive definition | '' | ||
| - | |||
| - | A standard volume is created implicitly when you deploy an app and define a drive in the app bundle. A persistent volume is created explicitly as its own resource, then referenced by the app. | ||
| - | |||
| - | ===== Terraform Examples ===== | ||
| - | |||
| - | ==== Persistent Block Volume -- EVE-k Cluster ==== | ||
| - | |||
| - | 1 GB blank block volume on an EVE-k cluster, encrypted at rest, read-write. Typical use: Node-RED flow storage, database files, application state. | ||
| - | |||
| - | resource " | ||
| - | edge_node_cluster { | ||
| - | id = zedcloud_edgenode_cluster.demo_edgenode_cluster_1.id | ||
| - | } | ||
| - | accessmode = " | ||
| - | cleartext | ||
| - | label = " | ||
| - | name = " | ||
| - | size_bytes = 1073741824 | ||
| - | title = " | ||
| - | type = " | ||
| - | } | ||
| - | |||
| - | Notes: | ||
| - | * '' | ||
| - | * '' | ||
| - | * '' | ||
| - | * '' | ||
| - | |||
| - | ==== Content Tree Volume -- EVE-k Cluster ==== | ||
| - | |||
| - | A read-only volume backed by the Ubuntu 24.04 image, used to pre-stage the OS on the cluster before deploying VMs. This avoids download delays when app instances are created. | ||
| - | |||
| - | resource " | ||
| - | edge_node_cluster { | ||
| - | id = zedcloud_edgenode_cluster.demo_edgenode_cluster_1.id | ||
| - | } | ||
| - | accessmode = " | ||
| - | cleartext | ||
| - | image = zedcloud_image.demo_atl_ub_image_1.name | ||
| - | label = "" | ||
| - | name = " | ||
| - | size_bytes = 0 | ||
| - | title = " | ||
| - | type = " | ||
| - | } | ||
| - | |||
| - | Notes: | ||
| - | * '' | ||
| - | * '' | ||
| - | * '' | ||
| - | * '' | ||
| - | * EVE-OS downloads the image from the datastore when this volume instance is created, caching it locally. Subsequent VMs using this image on the same node do not need to re-download it. | ||
| - | |||
| - | ==== Persistent Block Volume -- Standalone Edge Node ==== | ||
| - | |||
| - | The same 1 GB block volume but targeting a specific standalone node instead of a cluster. Use '' | ||
| - | |||
| - | resource " | ||
| - | device_id | ||
| - | accessmode = " | ||
| - | cleartext | ||
| - | label = " | ||
| - | name = " | ||
| - | size_bytes = 1073741824 | ||
| - | title = " | ||
| - | type = " | ||
| - | } | ||
| - | |||
| - | The only structural difference is '' | ||
| - | |||
| - | ==== Size Reference ==== | ||
| - | |||
| - | ^ Size ^ Bytes ^ | ||
| - | | 512 MB | 536870912 | | ||
| - | | 1 GB | 1073741824 | | ||
| - | | 5 GB | 5368709120 | | ||
| - | | 10 GB | 10737418240 | | ||
| - | | 20 GB | 21474836480 | | ||
| - | | 50 GB | 53687091200 | | ||
| - | |||
| - | ===== ZEDUI Walkthrough ===== | ||
| - | |||
| - | Volume instances can be created standalone in ZEDUI or as part of the app deployment wizard. | ||
| - | |||
| - | ==== Standalone (recommended for persistent volumes) ==== | ||
| - | |||
| - | - Navigate to **Library** > **Volume Instances** | ||
| - | - Click **+** | ||
| - | - Select the target **Edge Node** or **Edge Node Cluster** | ||
| - | - Select **Type**: Block Storage or Content Tree | ||
| - | - For Content Tree: select the **Image** | ||
| - | - Set **Size** (for Block Storage) or leave at 0 (Content Tree) | ||
| - | - Set **Access Mode**: Read-Write or Read-Only | ||
| - | - Set **Encryption**: | ||
| - | - Click **Add** | ||
| - | |||
| - | ==== As part of App Deployment ==== | ||
| - | |||
| - | When creating an App Bundle under **Edge Apps**, the **Drives** section lets you define volumes inline. These become standard (non-persistent) volumes tied to the app instance lifecycle unless you uncheck **Purge**. | ||
| - | |||
| - | To make a drive persistent: uncheck **Purge** in the Drives section. Note that Purge & Update will then be unavailable for that drive. | ||
| - | |||
| - | ===== ZCLI ===== | ||
| - | |||
| - | # Persistent block volume on a standalone node | ||
| - | zcli volume-instance create nodered-vol1-persist-nocl \ | ||
| - | --volume-type=BLOCKSTORAGE \ | ||
| - | --project=demo-project \ | ||
| - | --edge-node=demo-en-advantech-1 \ | ||
| - | --size=1073741824 \ | ||
| - | --access-mode=READWRITE \ | ||
| - | --title=" | ||
| - | |||
| - | # Content tree on a cluster | ||
| - | zcli volume-instance create UBUNTU-24-CT \ | ||
| - | --volume-type=CONTENT_TREE \ | ||
| - | --project=demo-project \ | ||
| - | --edge-node-cluster=demo-edgenode-cluster-1 \ | ||
| - | --image=TF-ATL-UBUNTU-24-IMAGE \ | ||
| - | --size=0 \ | ||
| - | --access-mode=READONLY \ | ||
| - | --title=" | ||
| - | |||
| - | # Show volume instances on a specific node | ||
| - | zcli volume-instance show \ | ||
| - | --project=demo-project \ | ||
| - | --edge-node=demo-en-advantech-1 | ||
| - | |||
| - | ===== API ===== | ||
| - | |||
| - | # Persistent block volume | ||
| - | POST /v1/volumes | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | } | ||
| - | |||
| - | # Content tree | ||
| - | POST /v1/volumes | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | } | ||
| - | |||
| - | ===== What Happens on the Edge Node ===== | ||
| - | |||
| - | ==== Block Storage (BLOCKSTORAGE) ==== | ||
| - | |||
| - | - EVE-OS receives the volume instance config at next heartbeat | ||
| - | - EVE-OS allocates the requested size from the node's data partition storage pool | ||
| - | - A raw block device or ext4 filesystem is created depending on how the app references it | ||
| - | - When an app instance references this volume in its drive definition, EVE-OS bind-mounts or block-attaches it into the VM or container at the specified mount path | ||
| - | - Data written by the app is stored on the node's local storage and is NOT automatically synced to the cloud | ||
| - | - The volume persists if the app is stopped, restarted, updated, or deleted -- it is owned by the node, not the app | ||
| - | |||
| - | ==== Content Tree (CONTENT_TREE) ==== | ||
| - | |||
| - | - EVE-OS receives the volume instance config referencing the image | ||
| - | - EVE-OS downloads the image from the registered datastore (same path as an app image download) | ||
| - | - The image is stored in EVE-OS' | ||
| - | - When an app instance references this volume, EVE-OS presents the image data as a read-only block device or mount point | ||
| - | - For QCOW2 images used as VM drives, EVE-OS creates a copy-on-write overlay so the app's writes go to a separate layer while the base image remains unchanged and reusable | ||
| - | |||
| - | ===== Encryption ===== | ||
| - | |||
| - | When '' | ||
| - | |||
| - | * The encryption key is generated per-volume on the node | ||
| - | * The key is sealed to the TPM using the measured boot PCR values | ||
| - | * If the node fails attestation (PCR values change -- indicating possible tampering), the key cannot be unsealed and the volume is inaccessible | ||
| - | * This means tampered or reflashed nodes cannot read encrypted volume data | ||
| - | |||
| - | Always use '' | ||
| - | |||
| - | ===== Common Patterns ===== | ||
| - | |||
| - | ^ Pattern ^ Type ^ Example ^ | ||
| - | | App data persistence | BLOCKSTORAGE | Node-RED flows, InfluxDB data, SQLite DB | | ||
| - | | Pre-stage VM image | CONTENT_TREE | Ubuntu 24.04 cached on node before app deployment | | ||
| - | | Shared data between apps | BLOCKSTORAGE (READWRITE) | Sensor data written by one app, read by another | | ||
| - | | Configuration delivery | CONTENT_TREE (READONLY) | Static config files packaged as a custom image | | ||
| - | | Log offload staging | BLOCKSTORAGE | App writes logs to volume; separate log shipper reads them | | ||
| - | |||
| - | ===== Related Resources ===== | ||
| - | |||
| - | * [[02_datastores|Datastores]] | ||
| - | * [[03_images|Images]] | ||
| - | * [[07_edge_apps|Edge Apps]] | ||
| - | * [[05_patch_envelopes|Patch Envelopes]] | ||
zededa/workshop/06_persistent_volumes_content_trees.1784735572.txt.gz · Last modified: by mc
