====== EVE-OS Images ====== EVE-OS Images are the operating system firmware for edge nodes. They are distinct from application images -- they are the OS itself, not a workload. ZEDEDA Cloud manages metadata, version tracking, and distribution; EVE-OS handles the update process on the node using an A/B partition scheme. Like application images, ZEDEDA Cloud does not store the EVE-OS binary. You upload the rootfs image to a datastore, then register a metadata record in ZEDEDA Cloud pointing to it. ===== EVE-OS Variants ===== The variant you choose determines what workloads the node can run and whether clustering is supported. You cannot switch between variants on a running node -- a variant change requires reinstallation. ^ Variant ^ Suffix ^ Workloads ^ Clustering ^ Notes ^ | **EVE-KVM** | kvm | VMs (KVM/QEMU) and OCI containers | No | Standard variant. Most common for industrial edge. Covered in this workshop. | | **EVE-k** | k | VMs and OCI containers | Yes (ZEDEDA managed) | Bare-metal Kubernetes support. Replaced EVE-Kubevirt in 16.0 LTS. Requires 12-core CPU, 16 GB RAM, NVMe. | | **EVE-Kubevirt** | kubevirt | VMs and OCI containers | Yes (ZEDEDA managed) | Legacy clustering variant from 14.5.0. Superseded by EVE-k in 16.0. | **You cannot update from EVE-KVM to EVE-k (or vice versa).** The rootfs partition layout differs. A variant change requires reflashing the node. ==== EVE-k is a Managed Kubernetes Infrastructure Layer ==== EVE-k embeds a k3s control plane inside EVE-OS to enable edge node clustering and the ZEDEDA Edge Kubernetes Service. It is important to understand what this means for operators: * The Kubernetes cluster is **managed entirely by ZEDEDA** -- you do not interact with it directly * You do **not** deploy pods, write Kubernetes manifests, or run kubectl to manage workloads * Apps are still deployed through the standard ZEDEDA Cloud API, ZEDUI, or Terraform -- exactly the same as on EVE-KVM * The k3s instance is part of the EVE-OS infrastructure layer, not an exposed API surface * What EVE-k enables is **node clustering for HA and scale** -- ZEDEDA uses the Kubernetes layer internally to schedule and manage workloads across clustered nodes * EdgeView does provide read-only kubectl access (get/list) for troubleshooting, but not for workload management In short: EVE-k gives you clustered infrastructure managed by ZEDEDA. Your workflow as an operator does not change -- you still define App Bundles and App Instances through ZEDEDA Cloud. ===== Image Naming Convention ===== EVE-OS image names follow the pattern: VERSION-lts-VARIANT-ARCH Examples: * ''16.0.0-lts-kvm-amd64'' -- version 16.0.0 LTS, KVM variant, x86-64 * ''16.8.0-k-amd64'' -- version 16.8.0, EVE-k variant, x86-64 (RC/custom, no lts tag) * ''14.5.2-lts-kvm-arm64'' -- version 14.5.2 LTS, KVM variant, ARM64 * ''16.0.0-rc6-kvm-amd64'' -- release candidate 6 of 16.0.0, KVM, x86-64 The ''-lts'' tag denotes an officially supported Long Term Support version. RC and custom builds omit it. **The ZEDEDA GUI only shows LTS images for upgrade. Custom, RC, and non-LTS images must be registered via Terraform or ZCLI.** ===== Terraform Examples ===== ==== EVE-KVM Release Candidate (custom datastore) ==== A pre-release or custom EVE-KVM image served from a local HTTP datastore. This is the pattern for testing RC builds before promoting to production nodes. resource "zedcloud_image" "demo_sjc_eve_OS_image_16" { name = "16.0.0-rc6-kvm-amd64" title = "16.0.0-rc6-kvm-amd64" datastore_id = zedcloud_datastore.demo_sjc_ds.id image_type = "IMAGE_TYPE_EVE" image_arch = "AMD64" image_format = "RAW" image_sha256 = "6fdefb5dee42429765403a3dfa40b5471ffd5a626944679da728de8a6d2ddbfc" image_size_bytes = 302092288 project_access_list = [] image_rel_url = "eve-16.0.0-rc6-kvm-amd64.img" } Notes: * ''image_type = "IMAGE_TYPE_EVE"'' -- this is what distinguishes an EVE-OS image from an app image * ''image_format = "RAW"'' -- EVE-OS rootfs images are always RAW format * ''image_size_bytes'' and ''image_sha256'' are required -- EVE-OS verifies the download before writing to the inactive partition * The name should match the version string exactly for clarity when managing multiple versions ==== EVE-k Image ==== The EVE-k variant (Kubernetes-enabled) uses the same structure. The only difference is the variant suffix in the name and image_rel_url: resource "zedcloud_image" "demo_sjc_eve_OS_image_16_k" { name = "16.8.0-k-amd64" title = "16.8.0-k-amd64" datastore_id = zedcloud_datastore.demo_atl_ds.id image_type = "IMAGE_TYPE_EVE" image_arch = "AMD64" image_format = "RAW" image_sha256 = "1d8170e4187e9c9342e59ff2db91c71b9d19fae1360eef3dc9c618b5ed9ed290" image_size_bytes = 394297344 project_access_list = [] image_rel_url = "16.8.0-k-amd64.rootfs" } Note the file extension: ''.rootfs'' vs ''.img'' -- both are valid RAW format rootfs images. The extension depends on how the image was generated and named when placed in the datastore. ===== Assigning an EVE-OS Image to an Edge Node (base_image) ===== Registering the image record is only step one. To actually upgrade a node, you assign the image via the ''base_image'' block on the edge node resource. ==== Terraform: base_image block ==== resource "zedcloud_edgenode" "demo_node" { name = "demo-edge-node-01" title = "Demo Edge Node 01" model_id = var.device_model_id project_id = zedcloud_project.demo_project.id base_image { image_name = "16.0.0-rc6-kvm-amd64" version = "16.0.0-rc6-kvm-amd64" activate = true } } Key fields in ''base_image'': ^ Field ^ Description ^ | ''image_name'' | Must exactly match the ''name'' field of a registered EVE-OS image record in your enterprise. | | ''version'' | The version string -- typically the same as image_name for EVE-OS images. | | ''activate'' | When true, ZEDEDA Cloud schedules the upgrade on the node at next heartbeat. Set to false to stage without activating. | The ''base_image'' block is commented out by default in many Terraform configs because it triggers an OS upgrade immediately when ''activate = true''. Uncomment and apply deliberately. ==== ZEDUI: Upgrade via GUI (LTS only) ==== The ZEDEDA GUI can upgrade nodes to LTS versions that are already registered in your enterprise or available in the ZEDEDA-managed catalog: - Navigate to **Edge Nodes** and select the target node - Click the **Software** tab - Under **EVE-OS Version**, click **Edit** - Select the target LTS version from the dropdown - Click **Save** -- the upgrade is scheduled for next heartbeat **Important: the GUI dropdown only shows LTS images.** RC builds, custom images, and non-LTS versions do not appear in the GUI. To upgrade to those, use Terraform or ZCLI. ==== ZCLI: Upgrade ==== # Assign an EVE-OS image to a specific edge node zcli edge-node update MY-EDGE-NODE \ --eve-image=16.0.0-rc6-kvm-amd64 # Or mark an image as the enterprise default for an architecture # (all nodes without an explicit assignment pick this up) zcli image mark-latest 16.0.0-lts-kvm-amd64 --image-arch=AMD64 ===== Upgrading an EVE-k Cluster ===== Upgrading a cluster is a single command that rolls the upgrade across all nodes sequentially. ZEDEDA handles the ordering -- it upgrades one node at a time, waits for it to check back in successfully, then moves to the next. This prevents the entire cluster from going offline simultaneously. ==== ZCLI: Upgrade ==== zcli edge-node-cluster upgrade ss-cluster1-pci --image=16.8.0-k-amd64 This targets the cluster by name and assigns the specified EVE-k image to all member nodes. The image must already be registered in ZEDEDA Cloud (see Terraform/ZCLI image registration above). ==== Monitor Progress ==== zcli edge-node-cluster show ss-cluster1-pci --upgrade Example output: NodeID UpgradeableEveOS Status UpdatedAt ------------------------------------ ---------------- ----------------- --------------------------- 60df8932-13de-4474-9853-25c9ef867a49 16.8.0-k-amd64 STATUS_COMPLETED 2026-02-27T12:11:04.077771Z 6c38a8ae-54e7-4f58-9e2c-23bc7b1f9e14 16.8.0-k-amd64 STATUS_COMPLETED 2026-02-27T12:26:22.208999Z 5e196606-bc80-4ea7-a01c-b16ea7136430 16.8.0-k-amd64 STATUS_COMPLETED 2026-02-27T12:41:43.899942Z The ''UpdatedAt'' timestamps show each node completing roughly 15 minutes apart -- that is the sequential per-node upgrade cadence. Each node downloads the new image, writes it to the standby partition, reboots, checks in, and only then does ZEDEDA trigger the next node in the cluster. Possible status values: ^ Status ^ Meaning ^ | ''STATUS_COMPLETED'' | Node has rebooted into the new version and checked in successfully | | ''STATUS_IN_PROGRESS'' | Download, write, or reboot in progress on this node | | ''STATUS_FAILED'' | Upgrade failed; node has auto-rolled back to the previous partition | ==== Terraform: Cluster Upgrade ==== Terraform cluster upgrade support via ''zedcloud_edge_node_cluster'' is not fully documented at the time of writing. The recommended approach for cluster upgrades is ZCLI (shown above) or the ZEDEDA API. The image registration itself (the ''zedcloud_image'' resource for the EVE-k image) is done in Terraform as shown in the examples above -- the upgrade trigger is then done via ZCLI referencing that image name. If you want to drive it from code, the API call is: POST /v1/edge-node-clusters/{cluster_id}/upgrade { "eveImageName": "16.8.0-k-amd64" } ==== Important Notes for Cluster Upgrades ==== * The image name passed to ''--image'' must match the ''name'' field of a registered ''IMAGE_TYPE_EVE'' image in your enterprise * All nodes in the cluster must be running the same EVE variant (EVE-k). You cannot mix EVE-KVM and EVE-k nodes in a cluster * The cluster remains operational during the rolling upgrade -- workloads on already-upgraded nodes continue running while remaining nodes upgrade * A 3-node cluster with 15-minute per-node cadence takes approximately 45 minutes to fully upgrade * Monitor with ''--upgrade'' flag until all nodes show ''STATUS_COMPLETED'' before considering the upgrade done ===== How to Get and Register a Custom EVE-OS Image ===== This is the full workflow for a custom or RC image -- required because the GUI upload is not supported for EVE-OS images. **Step 1: Pull the rootfs image from Docker Hub** # KVM variant, AMD64 docker run --rm lfedge/eve:16.0.0-rc6-kvm-amd64 rootfs > eve-16.0.0-rc6-kvm-amd64.img # EVE-k variant, AMD64 docker run --rm lfedge/eve:16.8.0-k-amd64 rootfs > 16.8.0-k-amd64.rootfs **Step 2: Get the SHA256 and size** sha256sum eve-16.0.0-rc6-kvm-amd64.img stat -c %s eve-16.0.0-rc6-kvm-amd64.img **Step 3: Upload to your datastore** (copy to your HTTP server, S3 bucket, or Azure container) **Step 4: Register the image in ZEDEDA Cloud via ZCLI** # Create the image record zcli image create 16.0.0-rc6-kvm-amd64 \ --arch=AMD64 \ --datastore-name=TF-ATL-ZED-DEMO-DS \ --type=Eve \ --image-format=RAW \ --title=16.0.0-rc6-kvm-amd64 # Uplink (associate SHA256 and size) zcli image uplink 16.0.0-rc6-kvm-amd64 \ --datastore-name=TF-ATL-ZED-DEMO-DS \ --image-sha=6fdefb5dee42429765403a3dfa40b5471ffd5a626944679da728de8a6d2ddbfc \ --image-size=302092288 Or do both steps in one Terraform apply using the resource block shown above. ===== How Upgrades Work on the Node ===== EVE-OS uses an **A/B partition scheme** -- two OS partitions, one active and one standby: - The controller delivers the desired EVE-OS version to the node at next heartbeat - EVE-OS compares the desired version to the currently running version - If different, EVE-OS downloads the new rootfs image from the datastore directly - The downloaded image is verified against the registered SHA256 hash - The verified image is written to the **inactive (standby) partition** - EVE-OS sets the standby partition as the next boot target and reboots - After reboot, the new version runs and checks in with the controller - If the node fails to check in within the timeout window, EVE-OS automatically rolls back to the previous partition and reports an error - The controller updates the node's recorded version after successful check-in This means upgrades are **atomic and self-healing**: a failed upgrade reverts automatically without manual intervention. ===== LTS vs Custom Images: Method Matrix ===== ^ Method ^ LTS Images ^ Custom / RC Images ^ Cluster Upgrade ^ | ZEDUI | Yes -- dropdown shows available LTS | No -- custom images do not appear | No | | ZCLI | Yes | Yes -- requires image create + uplink first | Yes -- ''zcli edge-node-cluster upgrade'' | | Terraform | Yes | Yes -- requires image resource + base_image block | Partial -- use ZCLI or API to trigger | | API | Yes | Yes -- requires POST /v1/images then PATCH /v1/devices | Yes -- POST /v1/edge-node-clusters/{id}/upgrade | ===== API ===== # Register a custom EVE-OS image POST /v1/images { "name": "16.0.0-rc6-kvm-amd64", "imageType": "IMAGE_TYPE_EVE", "imageArch": "AMD64", "imageFormat": "RAW", "datastoreId": "", "imageRelUrl": "eve-16.0.0-rc6-kvm-amd64.img", "imageSha256": "6fdefb5dee42429765403a3dfa40b5471ffd5a626944679da728de8a6d2ddbfc", "imageSizeBytes": 302092288 } # Assign to an edge node PATCH /v1/devices/{device_id} { "eveImageName": "16.0.0-rc6-kvm-amd64", "eveImageVersion": "16.0.0-rc6-kvm-amd64" } ===== Related Resources ===== * [[03_images|Images]] * [[01_projects|Projects]]