User Tools

Site Tools


zededa:sharing-persist-volume-by-two-apps

Differences

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

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
zededa:sharing-persist-volume-by-two-apps [2026/07/24 12:35] – mczededa:sharing-persist-volume-by-two-apps [2026/07/24 15:26] (current) – mc
Line 127: Line 127:
   * VMs mount the 9P share manually (''mount -t 9p ... share_dir''); containers auto-mount.   * VMs mount the 9P share manually (''mount -t 9p ... share_dir''); containers auto-mount.
   * Requires EVE-OS >= 12.7.0, all apps on the same node.   * Requires EVE-OS >= 12.7.0, all apps on the same node.
 +
 +===== Worked example: a container writer + VM readers =====
 +
 +The practical shape of "one app generates data, the others consume it" when the
 +consumers are **VMs** (which cannot share a writable volume among themselves):
 +
 +  * **Writer = a CONTAINER app.** Containers get the writable 9P overlay, so the writer mounts the shared content-tree volume at ''/data'' (writable, auto-mounted) and writes to it.
 +  * **Readers = VMs.** They mount the SAME volume over 9P (tag ''share_dir'') and read ''/data''.
 +  * **Data source = a patch envelope.** ''config.json'' is delivered via the metadata service (''http://169.254.169.254/eve/v1/patch/...''). The writer container polls ''description.json'', downloads the artifact, and writes versioned copies (''config-<ts>.json'', ''config.latest.json'') into ''/data''.
 +
 +Wiring:
 +
 +  - Shared **content-tree + block-storage** volume (as above), attached to the writer container AND the reader VMs.
 +  - The writer needs a **LOCAL network instance** — ''169.254.169.254'' is only reachable via a Local NI (a Switch NI is pure L2 and cannot reach it).
 +  - Create a **patch envelope** (''zedcloud_patch_envelope'') with the artifact inline (base64), and **bind** it to the writer instance (''zedcloud_patch_reference_update''). ''action = PATCH_ENVELOPE_ACTION_ACTIVATE'' presents it to the app.
 +  - Optionally expose a web UI from the writer with a **portmap ACL** (''actions { portmap = true; portmapto { app_port = 8080 } }'').
 +
 +Notes proven on-device: ''description.json'' returns a list of envelopes, each with
 +**''PatchID''** (capital ID) and **''BinaryBlobs[]''** entries carrying ''fileName'', ''fileSha'',
 +and a full ''url''. The content-tree's base image rootfs (e.g. busybox: ''bin/'', ''etc/'', …)
 +appears under ''/data'' as the seed — use a ''FROM scratch'' base if you want ''/data'' to
 +start empty.
 +
 +===== Deployment gotchas (learned on-device) =====
 +
 +  * **Container image tag is immutable AND the app holds it.** To bump an image tag you must recreate the image AND every app/instance that references it — otherwise you get ''Image <x> is already in use by app bundle'' (409). ''-replace'' the instance + app + image together so the app is torn down before the image.
 +  * **"Invalid version number" / "request body parsing failed" on a ''zedcloud_image''** = you changed ''image_rel_url'' on an image that already exists (it's immutable) → an update the API rejects. Recreate it (''-replace''). It is **not** the tag value or the registry image content.
 +  * **Patch envelope artifact changes = recreate, not update.** Editing the artifact triggers ''PUT /patch-envelope/id/{id}'' → 400. ''-replace'' the envelope (and its ''patch_reference_update'' binding). Bump ''user_defined_version'' per version so the metadata ''Version'' field reflects reality.
 +  * **Content-tree volume ''accessmode''** is required — omit it and the create fails with ''access mode cannot be invalid''. Use ''READONLY'' for the content-tree; ''READWRITE'' for the connected block-storage.
 +  * **Provider-computed drift** (e.g. content-tree ''size_bytes "0" -> null'') triggers rejected updates — add ''lifecycle { ignore_changes = [size_bytes] }''.
 +  * **Build container images with ''--provenance=false --sbom=false''** — clean hygiene (avoids "unknown/unknown" attestation manifests in the index). Not strictly required for ZEDEDA to accept the image, but good practice.
 +  * **9P mount tag is ''share_dir''** (a literal in EVE ''hypervisor/kvm.go''), and it's triggered by the drive's **CONTAINER format**, not by ''mountpath''.
 +
 +===== Updating the config (runbook) =====
 +
 +Push a new config version **without** redeploying the image, app, VMs, or volumes —
 +you only recreate the patch envelope. The writer auto-fetches it on its next poll and
 +drops a new versioned file into ''/data''.
 +
 +<code bash>
 +# 1. Edit the config artifact
 +$EDITOR Demo-Hummingbird/c-init/patch-config.json
 +
 +# 2. Bump the version on the envelope in 6-Instances-Deploy-hum.tf
 +#    user_defined_version = "2.0"  ->  "3.0"
 +
 +# 3. Recreate the envelope + its binding (in-place update is rejected -> -replace)
 +terraform apply \
 +  -replace='zedcloud_patch_envelope.tf_demo_config_pe' \
 +  -replace='zedcloud_patch_reference_update.tf_demo_config_pe_bind'
 +
 +# 4. Wait ~30-60s (controller -> device propagation + the writer's poll interval)
 +
 +# 5. Verify (on the writer container or any reader VM)
 +cat /data/config.latest.json      # new content
 +cat /data/config.history          # <ts>  <sha> per version
 +#    writer log line: [pcw] new config.json (v=3.0) -> /data/config-<ts>.json (sha=...)
 +</code>
 +
 +  * **''-replace'' both resources:** an in-place artifact update returns HTTP 400; and the envelope's ID changes on recreate, so the ''patch_reference_update'' binding must be recreated to re-point at it.
 +  * **Bumping ''user_defined_version''** is recommended (labels the version, shows in the metadata ''Version'' field and the writer log) but not strictly required — the writer detects change by content SHA.
 +  * **You do NOT touch** the container image, the writer app, the VMs, or the volumes. That is the whole point of the patch-envelope design: config changes with nothing redeployed.
 +
 +==== First-time deploy (for reference) ====
 +
 +<code bash>
 +# build + push the writer image (clean manifest — no attestation entries)
 +docker buildx build --platform linux/amd64,linux/arm64 --provenance=false --sbom=false \
 +  -t zedmanny/patch-config-writer:1.2.0 --push .
 +
 +# bring everything up
 +terraform apply
 +
 +# if the image was already created and you changed its tag, the image is immutable AND
 +# held by the app -> recreate the whole chain in one apply:
 +terraform apply \
 +  -replace='zedcloud_application_instance.tf_patch_config_writer_1' \
 +  -replace='zedcloud_application.tf_patch_config_writer_app' \
 +  -replace='zedcloud_image.demo_patch_config_writer'
 +</code>
  
 ===== Sources ===== ===== Sources =====
  
-  * ZEDEDA Help Center — "Attach Volume Instances to Multiple Edge Applications" +  * ZEDEDA Help Center — "Attach Volume Instances to Multiple Edge Applications", "Update Edge Application Instances with Patch Envelopes" 
-  * EVE source: ''pkg/pillar/cmd/volumemgr/handlevolumeref.go'' (the share guard), ''pkg/pillar/hypervisor/kvm.go'' (9P mount tag ''share_dir'')+  * EVE source: ''pkg/pillar/cmd/volumemgr/handlevolumeref.go'' (the share guard), ''pkg/pillar/hypervisor/kvm.go'' (9P mount tag ''share_dir''), ''pkg/pillar/cmd/domainmgr/domainmgr.go'' (CONTAINER format → 9P)
  
zededa/sharing-persist-volume-by-two-apps.1784896534.txt.gz · Last modified: by mc