User Tools

Site Tools


zededa:workshop:06_persistent_volumes_content_trees

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

zededa:workshop:06_persistent_volumes_content_trees [2026/07/22 15:52] – old revision restored (2026/05/31 17:21) mczededa: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 ''zedcloud_volume_instance'' resources in Terraform but serving very different purposes. 
- 
-  * **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 ^ 
-| ''VOLUME_INSTANCE_TYPE_BLOCKSTORAGE'' | Blank block storage | READWRITE | No | App data, databases, persistent state, Node-RED flows | 
-| ''VOLUME_INSTANCE_TYPE_CONTENT_TREE'' | Image-backed read-only volume | READONLY (default) | Yes | Pre-stage a VM image, distribute a dataset, deliver a base OS | 
- 
-===== Key Fields ===== 
- 
-^ Field ^ Description ^ 
-| ''type'' | ''VOLUME_INSTANCE_TYPE_BLOCKSTORAGE'' or ''VOLUME_INSTANCE_TYPE_CONTENT_TREE'' | 
-| ''accessmode'' | ''VOLUME_INSTANCE_ACCESS_MODE_READWRITE'' or ''VOLUME_INSTANCE_ACCESS_MODE_READONLY'' | 
-| ''size_bytes'' | Size of the volume in bytes. For BLOCKSTORAGE: the allocated size. For CONTENT_TREE: set to ''0'' (size comes from the image). | 
-| ''image'' | Image name to back the volume. Required for CONTENT_TREE, not used for BLOCKSTORAGE. | 
-| ''cleartext'' | ''false'' = volume is encrypted at rest using EVE-OS full-disk encryption. ''true'' = unencrypted. Always use ''false'' in production. | 
-| ''label'' | Optional label for the volume. Used when referencing it in app bundle drive definitions. | 
-| ''device_id'' | Assign to a specific standalone edge node (mutually exclusive with ''edge_node_cluster''). | 
-| ''edge_node_cluster.id'' | Assign to an EVE-k cluster (mutually exclusive with ''device_id''). | 
- 
-===== 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 | ''zedcloud_volume_instance'' resource (separately) | 
- 
-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 "zedcloud_volume_instance" "tf_demo_vol1_persist" { 
-    edge_node_cluster { 
-      id = zedcloud_edgenode_cluster.demo_edgenode_cluster_1.id 
-    } 
-    accessmode = "VOLUME_INSTANCE_ACCESS_MODE_READWRITE" 
-    cleartext  = false 
-    label      = "nodered-vol1-persist" 
-    name       = "nodered-vol1-persist" 
-    size_bytes = 1073741824 
-    title      = "nodered-vol1-persist" 
-    type       = "VOLUME_INSTANCE_TYPE_BLOCKSTORAGE" 
-  } 
- 
-Notes: 
-  * ''size_bytes = 1073741824'' is exactly 1 GB (1024 * 1024 * 1024) 
-  * ''cleartext = false'' enables EVE-OS encryption at rest -- the volume key is sealed to the TPM via measured boot attestation 
-  * ''edge_node_cluster'' targets the cluster instead of a specific node. ZEDEDA creates the volume on each node in the cluster. 
-  * ''label'' is used when referencing this volume in an app bundle ''drives'' block 
- 
-==== 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 "zedcloud_volume_instance" "tf_demo_vol1_ub_ct" { 
-    edge_node_cluster { 
-      id = zedcloud_edgenode_cluster.demo_edgenode_cluster_1.id 
-    } 
-    accessmode = "VOLUME_INSTANCE_ACCESS_MODE_READONLY" 
-    cleartext  = false 
-    image      = zedcloud_image.demo_atl_ub_image_1.name 
-    label      = "" 
-    name       = "UBUNTU-24-CT" 
-    size_bytes = 0 
-    title      = "UBUNTU-24-CT" 
-    type       = "VOLUME_INSTANCE_TYPE_CONTENT_TREE" 
-  } 
- 
-Notes: 
-  * ''image'' references the image **name** (not ID) of a registered app image -- in this case the Ubuntu 24.04 QCOW2 registered earlier 
-  * ''size_bytes = 0'' -- for content trees the size is determined by the image itself, not declared here 
-  * ''accessmode = READONLY'' is standard for content trees; the image data is not modified at runtime 
-  * ''label = ""'' -- no label needed since the image name is the identifier 
-  * 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 ''device_id'' instead of ''edge_node_cluster'': 
- 
-  resource "zedcloud_volume_instance" "tf_demo_vol1_persist_nocl" { 
-    device_id  = zedcloud_edgenode.demo_en_advantech_1.id 
-    accessmode = "VOLUME_INSTANCE_ACCESS_MODE_READWRITE" 
-    cleartext  = false 
-    label      = "nodered-vol1-persist-nocl" 
-    name       = "nodered-vol1-persist-nocl" 
-    size_bytes = 1073741824 
-    title      = "nodered-vol1-persist" 
-    type       = "VOLUME_INSTANCE_TYPE_BLOCKSTORAGE" 
-  } 
- 
-The only structural difference is ''device_id'' vs ''edge_node_cluster.id''. Everything else is identical. ''device_id'' and ''edge_node_cluster'' are mutually exclusive -- you cannot specify both. 
- 
-==== 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**: on (recommended) 
-  - 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="nodered-vol1-persist" 
- 
-  # 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="UBUNTU-24-CT" 
- 
-  # 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 
-  { 
-    "name": "nodered-vol1-persist-nocl", 
-    "type": "VOLUME_INSTANCE_TYPE_BLOCKSTORAGE", 
-    "accessMode": "VOLUME_INSTANCE_ACCESS_MODE_READWRITE", 
-    "sizeBytes": 1073741824, 
-    "clearText": false, 
-    "deviceId": "<device_id>", 
-    "projectId": "<project_id>" 
-  } 
- 
-  # Content tree 
-  POST /v1/volumes 
-  { 
-    "name": "UBUNTU-24-CT", 
-    "type": "VOLUME_INSTANCE_TYPE_CONTENT_TREE", 
-    "accessMode": "VOLUME_INSTANCE_ACCESS_MODE_READONLY", 
-    "sizeBytes": 0, 
-    "clearText": false, 
-    "image": "TF-ATL-UBUNTU-24-IMAGE", 
-    "deviceId": "<cluster_id>", 
-    "projectId": "<project_id>" 
-  } 
- 
-===== 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's local volume pool 
-  - 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 ''cleartext = false'', the volume is encrypted at rest using EVE-OS's full-disk encryption: 
- 
-  * 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 ''cleartext = false'' for production workloads that store sensitive data. 
- 
-===== 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