What EdgeOps is
Link to section “What EdgeOps is”In 30 seconds
Link to section “In 30 seconds”EdgeOps, as this Atlas uses the word, is the work of operating compute at many remote sites (stores, plants, depots, cell sites, ships) rather than in a few data centres: bringing nodes into service without an expert, changing software across thousands of sites in staged waves, keeping each site working when its link fails, and recovering sites without a visit.
Two facts separate it from running a data centre: sites lose connectivity as a matter of course, and nobody technical is there. A Cloud Native Computing Foundation (CNCF) working group says edge applications “must adapt to network connectivity that is unreliable or even unavailable (air gapped)”, and that management needs “zero touch provisioning of hardware and software” because on-site staff may be untrained, untrusted, minimal or absent.[1] The page is for edge architects, platform teams, retail and industrial IT, and leaders deciding whether to put compute in the field.
At a glance
Link to section “At a glance”| Question | Short answer |
|---|---|
| Goal | Sites that keep serving through outages and can be changed safely, at fleet scale, without technician visits |
| Users | Platform and infrastructure teams, field operations, application teams that ship to sites, security |
| Scope | Linux-capable servers and gateways that host workloads at sites, site clusters, onboarding, staged rollouts, partition tolerance, remote recovery, physical security |
| Out of scope | Microcontroller and single-purpose embedded devices (IoTOps), robots (RoboOps), vehicles (FleetOps), CDN edge and web performance (WebOps), the WAN itself (NetworkOps) |
| Prerequisites | KubernetesOps and CloudOps; Linux; basic networking |
| Key outputs | Site profiles, golden image, onboarding flow, wave plan, partition-tolerance worksheet, recovery ladder, fleet dashboard |
| Term status | Ambiguous label; the practice behind it is real but documented under other names |
The problem it solves
Link to section “The problem it solves”Without deliberate edge operations, four things go wrong.
- A central dependency fails and every site stops. Sign-in, configuration or images fetched from the cloud at start-up turn a WAN outage into a store outage. The target is static stability: “the overall system keeps working even when a dependency becomes impaired”.[2]
- A bad change reaches everything at once, and recovery needs hands, as the 2024 CrowdStrike outage showed for endpoints (EndpointOps; see the judgement call).
- Sites drift. A site closed for a month returns three releases behind, with an expired certificate and a full disk.
- Hardware sits in a back office. LF Edge calls such nodes “physically-accessible to hackers” and “often deployed on untrusted networks”.[3]
What EdgeOps is not: the naming problem and the boundaries
Link to section “What EdgeOps is not: the naming problem and the boundaries”“EdgeOps” is not a recognised discipline. We found no standards body, foundation, certification or book that defines it, and the label has competing meanings:
- A product toolset: in Altair IoT Studio, “a set of tools for building, maintaining and continuously improving code in resource constrained devices”.[4]
- Vendor methodologies and platforms: ZPE Systems’ “infrastructure management methodology”;[5] XenonStack’s lifecycle “tool”, “platform” and DevOps “strategy”, in one article;[6] Dell’s NativeEdge, “an edge operations software platform”.[7] A Dell-sponsored article calls edge operations a “new discipline” without defining it,[8] and a third-party article says Dell promotes “DevEdgeOps”.[9]
- A company name: EdgeOps.AI sells machine-learning pipelines for edge hardware.[10]
- Consultancy definitions, such as “a comprehensive discipline that applies operational principles to distributed computing”.[11]
Even “edge” is unsettled: NIST notes no consensus on how fog, mist, cloudlets and edge computing differ.[12] The better-anchored vocabularies map onto Atlas pages:
| Term (source) | Where the compute runs | Atlas page |
|---|---|---|
| Cloud | Central regions and data centres | CloudOps |
| Service provider edge (LF Edge); Multi-access Edge Computing, MEC (ETSI)[13] | Telco access and regional sites, “almost always on a WAN”[3] | This page; links: NetworkOps |
| User edge (LF Edge); fog (NIST; IEEE 1934)[14] | On-premises servers and gateways, “typically on a LAN”;[3] NIST’s fog nodes sit “between smart end-devices and centralized (cloud) services”[12] | This page |
| Edge and mist (NIST); constrained device edge (LF Edge) | NIST’s edge is the layer “encompassing the end-devices and their users”[12] | IoTOps |
EdgeOps here is not content-delivery edge (WebOps) and not “Kubernetes on small boxes”: a cluster is one possible site runtime. These boundaries are editorial distinctions, not industry rules.
Where it comes from and where it sits
Link to section “Where it comes from and where it sits”Origins and evolution
Link to section “Origins and evolution”- 2009: cloudlets, nearby “trusted, resource-rich” computers for mobile devices.[15]
- 2014: a proposed ETSI group for Mobile-edge Computing, “IT and cloud-computing capabilities within the Radio Access Network”.[16]
- 2018: NIST’s fog model[12] and IEEE 1934-2018 (OpenFog architecture);[14] a US restaurant chain and a US retailer described a Kubernetes cluster in every location (use case 1).[17][18]
- 2023: CNCF edge-native principles;[1] Dell NativeEdge.[7]
- 2024–2026: KubeEdge graduates in the CNCF;[19] ETSI GS MEC 003 V4.1.1;[13] FIDO Device Onboard (FDO) 2.0 becomes a Proposed Standard.[20]
Glossary and mental model
Link to section “Glossary and mental model”Mental model: an edge fleet is many small data centres, each sometimes alone. Ask of every site: does it keep working alone, can I change it safely in batches, and can I get it back without going there?
| Term | Meaning | Why it matters |
|---|---|---|
| Site / edge node | A location with local compute / a Linux-capable server or gateway there | The unit of failure, rollout and recovery |
| Partition | The site cannot reach central services, or the reverse | Normal, not exceptional |
| Kubelet; static pod | The agent that runs pods on each node; a pod it starts from a local file, without the API server | Decides what restarts offline |
| etcd | The cluster’s key-value store; needs a majority of its servers and fast disks | Drives one node or three |
| PCR | A TPM register recording what booted; keys can be sealed to its value | Ties disk keys to the boot chain |
| Control plane / data plane | “The machinery involved in making changes” versus “the daily business”[2] | Decide which must work offline |
| Zero-touch provisioning (ZTP) | A node configures itself on first power-up | No expert on the site visit |
| Wave and bake time | A group of sites that gets a change together; the wait before the next group[21] | Limits blast radius; catches slow failures |
| A/B update | New OS image staged beside the running one, previous kept for rollback[22] | Reversible remotely |
| Out-of-band (OOB) path | Management access independent of the production network and OS | The last rung before a visit |
| Break-glass access | A local credential that works when central identity is unreachable | Otherwise nobody can log in |
How EdgeOps relates to other Ops
Link to section “How EdgeOps relates to other Ops”The Atlas splits sites by device class and layer, an editorial distinction: one platform team often does several of these jobs.
Diagram source (Mermaid)
flowchart BT D["`Devices: IoTOps Robots, vehicles: RoboOps, FleetOps`"]:::neutral S["`Sites: EdgeOps servers, gateways, site clusters (KubernetesOps mechanics)`"]:::core W["`Links: NetworkOps WAN, cellular, OOB`"]:::neutral C["`Centre: CloudOps GitOps, ReleaseOps`"]:::neutral O["`ObservabilityOps backends`"]:::neutral D -.->|gateways, shared patterns| S S -->|sites open every connection| W W -->|pull state, images| C W -.->|send telemetry| O classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
Text equivalent: From the bottom: devices (IoTOps) reach sites through gateways; robots and vehicles (RoboOps, FleetOps) share site patterns. Sites (servers, gateways, site clusters) are EdgeOps, using KubernetesOps mechanics. They open every connection over NetworkOps links to pull state and images from the centre (CloudOps, GitOps, ReleaseOps) and send telemetry to ObservabilityOps. Dotted lines: supporting relationships.
| Neighbour | This page owns | The neighbour owns |
|---|---|---|
| IoTOps | General-purpose servers and gateways that host workloads | Microcontroller and single-purpose embedded devices |
| KubernetesOps | Topology per site, partitions, fleet upgrade waves | Mechanics inside one cluster |
| CloudOps | What the centre may do to sites | Accounts, regions, guardrails |
| NetworkOps, NetOps | Link requirements | WAN, site LAN, OOB circuits |
| GitOps, ReleaseOps | Waves and offline-aware gates | Reconciliation; release strategy |
| ObservabilityOps | Buffering at sites; freshness | Pipelines and backends |
| RetailOps, PatchOps, SysOps | The in-store platform; delivering patches in waves | Stores as a business; patch policy; host baselines |
Principles and operating model
Link to section “Principles and operating model”Charter and principles
Link to section “Charter and principles”No body publishes an EdgeOps charter; this is the Atlas’s proposal. Mission: every site keeps serving through the failures it will meet, and every change reaches the fleet in batches that can be stopped and undone without a visit.
- Sites are alone by default: nothing the core job needs is fetched centrally at run time.
- Pull, never push: sites open outbound connections and fetch desired state (“Pulled Automatically” in OpenGitOps);[23] the centre needs no route into a store. The out-of-band path calls home too.
- Every change travels in waves, including OS, cluster and configuration changes.
- Silence after a change is a signal: a site offline before a wave is unknown; one silent for T minutes after receiving the change is a suspected failure.
- Images, not snowflakes: versioned, immutable images with a known previous version.
- Zero-touch in, zero-touch back: onboarding and re-imaging need no expert; an out-of-band path exists for when both fail.
- Assume the box will be stolen: secrets scoped to one site and revocable; know what a stolen box unlocks by itself.
- Manage the fleet as a distribution: convergence, freshness and version spread, not anecdotes.
Non-goals: device firmware, WAN design, application logic. Example goals: 98% of sites healthy on a release within seven days; 90% of incidents resolved remotely; at most two OS versions; every site class drilled yearly.
Building blocks
Link to section “Building blocks”| Building block | Operating concern |
|---|---|
| Hardware profile: one to three server or gateway models with a Trusted Platform Module (TPM) | Fewer models, fewer surprises; SD cards and eMMC “cannot handle the IO load” of etcd[24] |
| Edge OS image, for example built with bootc from container images[25] | A/B updates and rollback[22] |
| Site runtime: K3s,[26] MicroShift,[27] a KubeEdge edge node[28] or virtual machines on EVE-OS[29] | Footprint, version lag, partition behaviour |
| Fleet manager holding desired state per group of sites | Pull model, scale, wave control |
| Onboarding service (FDO owner and rendezvous, or vendor ZTP) | Voucher logistics[20] |
| Central registry plus a cache at each site | Pull storms; air gaps[30] |
| Multi-platform images: an OCI image index lists one manifest per platform[31] | Mixed x86_64 and Arm fleets (K3s runs on both);[24] canary every architecture |
| Telemetry collector with a disk buffer | Data loss after outages[32] |
| Out-of-band path: console server, cellular modem or baseboard management controller | The last remote rung |
| Site profile: wave, hardware, maintenance window, owner roles | Drives targeting for everything above |
Roles, ownership and RACI
Link to section “Roles, ownership and RACI”The RACI below is this Atlas’s proposal. Site staff are hands, not operators: give them tasks as simple as “plug in, power on”.
| Activity | Edge platform team | Application team | Field / site operations | Security | Network team |
|---|---|---|---|---|---|
| Hardware standard and OS image | A/R | C | C | C | I |
| Onboarding flow | A/R | I | R (plug in, power on) | C | C |
| Wave plan and gates | A | R (health signals) | I | C | I |
| Application releases to sites | C | A/R | I | I | I |
| Disconnection drills | A/R | R | C | I | R |
| Remote recovery and visit decision | A/R | C | R (hands on site) | I | C |
| Disk encryption, physical controls | R | I | R | A | I |
| WAN and OOB links | C | I | I | C | A/R |
A = accountable, R = responsible, C = consulted, I = informed.
Lifecycle of a site: Day 0, Day 1, Day 2
Link to section “Lifecycle of a site: Day 0, Day 1, Day 2”- Day 0 (design): site classes, hardware, control-plane placement, written connectivity assumptions, golden image, wave rules.
- Day 1 (onboarding): imaged, TPM-enrolled and given onboarding credentials at a factory or depot, the node onboards itself on site and passes an acceptance check before carrying traffic.
- Day 2 (operate): waves; certificate and credential renewal; drills; hardware swaps; remote re-imaging.
- Retirement: crypto-erase, revoke the site’s credentials, remove it from waves, route hardware to reuse (GreenOps).
Operating model and governance
Link to section “Operating model and governance”- One change path: every site change, and every promotion to the next wave, is a reviewed commit to the fleet repository. Write access to that repository or to the fleet manager reaches every site as root: protect the branch and require a second approver to promote a wave.
- Maintenance windows are data in each site profile, enforced by the upgrade tooling.
- Halt rules are written before the release: application owners name health signals; the platform team owns the gate.
- Cadence: weekly fleet review (stragglers, version spread); quarterly drill per site class; reviews of fleet-level incidents (IncidentOps).
- Exceptions expire: a site pinned out of the waves has an owner, a reason and an end date.
Architecture and workflow
Link to section “Architecture and workflow”Reference architecture
Link to section “Reference architecture”Diagram source (Mermaid)
%%{init: {"flowchart": {"nodeSpacing": 14, "rankSpacing": 20, "padding": 8}}}%%
flowchart LR
subgraph SITE["Untrusted site ×1,000s"]
subgraph NODE["Node: A/B OS, TPM"]
AG["`Fleet agent,
runtime`"]:::core
MIR["`Image
cache`"]:::neutral
COL["`Telemetry
disk queue`"]:::neutral
end
OOB["`Out-of-band
console`"]:::risk
end
subgraph CEN["Centre, via WAN"]
FM["`Fleet
manager`"]:::core
REG["Registry"]:::neutral
TEL["`Telemetry
backend`"]:::neutral
ONB["`Onboarding
service`"]:::neutral
ACC["`OOB access
service`"]:::neutral
end
AG -->|desired state| FM
MIR -->|layers| REG
COL -->|when up| TEL
NODE -->|once| ONB
OOB -.->|calls home| ACC
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
Text equivalent: Left, an untrusted site (one of thousands); right, the centre, across the WAN. On the site, a node with an A/B OS and TPM runs the fleet agent and runtime, an image cache and a telemetry disk queue; the out-of-band console sits beside it. Every arrow starts at the site: the agent pulls desired state from the fleet manager, the cache pulls layers from the registry, the node onboards once, the queue sends telemetry when the link is up, and the console calls home (dotted).
Trust boundaries. Credentials are per site, and the centre never connects in. Fleet’s agent-initiated registration shows the pull pattern: “the Manager will never make an outbound API request to the downstream clusters”.[33]
Where the control plane lives
Link to section “Where the control plane lives”The central decision, often made by default.
| Pattern | Keeps serving during a WAN outage | Can change state during the outage | Main cost |
|---|---|---|---|
| Cluster per site (K3s or MicroShift, one or three nodes) | Yes | Yes: restarts, rescheduling, local recovery | One more cluster per site to upgrade; high availability with embedded etcd needs three servers[34] |
| Stretched cluster (central control plane, nodes at sites, such as EKS Hybrid Nodes)[35] | Running pods keep running[36] | No mutating operations; a node that restarts does not start its pods until it reconnects[36] | The WAN becomes part of every recovery |
| Stretched with edge autonomy (KubeEdge, OpenYurt) | Yes | Local restarts from cached state, by the projects’ design[28][37] | Extra components; version lag |
| Provider-owned hardware (AWS Outposts; AWS owns and replaces it)[38] | Local EKS clusters keep running through “temporary, unplanned network disconnects”[39] | Not operations that need Regional APIs; Outposts “remains a fully connected offering”[39] | A service link of at least 500 Mbps[40] |
| Cloud-managed stack on your hardware (Azure Local) | Connected or disconnected deployments[41] | Depends on the mode; test it | You keep spares and hardware lifecycle, through the OEM |
What a stretched cluster does in a partition. After a grace period (50 seconds upstream, 40 on EKS) the node controller marks a
silent node Unknown.[42][36] When the pods’ unreachable toleration expires, 300 seconds by default, it evicts them,
but pods marked for deletion “may continue to run on the partitioned node”.[43] For a pod pinned to its site, eviction moves
nothing: it shows Terminating, keeps running and is replaced when the link returns. tolerationSeconds therefore only decides
whether reconnection restarts it; omit it to wait indefinitely.[43]
Zone rules rarely help a site. Upstream stops evictions only in a zone of at most 50 nodes with more than two, and at least
55%, unhealthy. A cut-off site labelled as its own topology.kubernetes.io/zone is entirely unreachable, so it is evicted at the
normal rate unless every zone is down.[44][45] One AWS page says otherwise;[46] AWS’s failover
guide agrees with upstream.[36]
The trap is a reboot during the partition. The kubelet cannot ask the API server what to run, so after a power cut the site’s
pods stay down until the link returns, and crictl cannot start them; only static pods restart.[36] AWS observed all this
with one configuration; test your own.
Example status: YAML syntax-checked; fragments, not applied. Pattern from the EKS Best Practices Guide.
# Stretched cluster: pin a site workload and decide when an outage may restart it
# kubelet flag at node registration: --node-labels=topology.kubernetes.io/zone=store-0413
# (a zone per site helps topology spread and per-site reports; it does not stop evictions)
apiVersion: apps/v1
kind: Deployment
metadata:
name: pos-sync
spec:
replicas: 1
selector:
matchLabels: {app: pos-sync}
template:
metadata:
labels: {app: pos-sync}
spec:
nodeSelector:
topology.kubernetes.io/zone: store-0413 # never "fail over" to the cloud
tolerations:
- key: node.kubernetes.io/unreachable
operator: Exists
effect: NoExecute
# outages under 30 min: no restart (default 300)
tolerationSeconds: 1800
containers:
- name: app
image: registry.example.com/store/pos-sync@sha256:<digest>
imagePullPolicy: IfNotPresent
Default for user-edge sites: a cluster or host runtime per site, managed centrally; a stretched cluster only when sites may freeze during outages (decision framework).
End-to-end workflow: from release to the last straggler
Link to section “End-to-end workflow: from release to the last straggler”Happy path. A release (application, OS image or cluster version) is signed, tested in a lab, then goes to a canary covering every model and site class, bakes, passes its gate and widens in waves. Amazon’s description of a typical pipeline is a useful model: “waves” of increasing size, baking at least one hour after each one-box stage and 12 hours after the first regional wave.[21]
Exception path. A gate fails: stop promotion, revert the wave’s desired state and recover sites down the recovery
ladder. Sites offline during the halt pull whatever desired
state is current when they return, so a halt must change it, not only pause the tool. Gates fail in two ways. Fleet treats an
offline cluster as NotReady “until it comes back online and successfully deploys the BundleDeployment”,[47] so a
NotReady gate halts healthy rollouts. Counting only reported failures is worse: bricked or boot-looping nodes never report.
Exclude sites offline before the wave; count sites that received the change but have not checked in healthy by a deadline as
suspected failures, judged against the class’s normal offline rate (Lab 1).
Diagram source (Mermaid)
flowchart TB
L["`Lab: every hardware model,
disconnection test`"]:::neutral
C["`Canary: a few sites,
every model and class`"]:::core
G1{"`Any canary failed,
or silent after
updating?`"}:::decision
W1["`Wave 1: about 5%
of sites, then bake`"]:::core
G2{"`Failed + silent
after update
below limit?`"}:::decision
W2["`Wave 2: about 25%,
then bake`"]:::core
G3{"`Still below
the limit?`"}:::decision
W3["`Wave 3: the rest,
in batches`"]:::core
S["`Sites offline earlier
converge on return`"]:::neutral
H["`Halt: revert state,
recover sites`"]:::risk
L --> C --> G1
G1 -->|none after bake| W1 --> G2
G1 -->|any| H
G2 -->|yes| W2 --> G3
G2 -->|no| H
G3 -->|yes| W3 --> S
G3 -->|no| H
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
Text equivalent: A release passes a lab (every hardware model, a disconnection test), then a canary covering every model and site class; a canary that fails, or goes silent after updating, halts it. Otherwise wave 1 (about 5%) and wave 2 (about 25%) follow, each baking, then passing only while failures plus post-update silences stay below the limit; wave 3, the rest, follows in batches. Sites offline earlier converge when they return. A failed gate halts the release: desired state reverted, affected sites recovered.
Practices, standards and tools
Link to section “Practices, standards and tools”Core practices and playbooks
Link to section “Core practices and playbooks”| Practice | Owner | Verification |
|---|---|---|
| Zero-touch onboarding | Edge platform team | Time from power-on to acceptance; share of installs needing a call |
| Image-based OS with health-checked rollback | Edge platform team | Rollback drill on each hardware model |
| Stratified waves | Platform and application teams | Canary membership report per release |
| Partition-tolerant workloads | Application teams | Disconnection drill with a power cycle |
| Telemetry buffering | Edge platform team | Outage data delivered after a drill |
| Recovery ladder and secure retirement | Platform, field operations, security | Remote resolution rate; revocation record per node |
Playbook 1: zero-touch onboarding with FDO. FIDO Device Onboard “permits late binding of device credentials”, so one device can onboard to whichever owner bought it; version 2.0 extends it to “an arbitrary device”.[20] Its ownership voucher is “extended with each owner while the device is offline”. The device opens every connection, and FDO then hands over to the management agent.[20] Related standards are SZTP (RFC 8572) for network equipment, in NetworkOps,[48] and BRSKI (RFC 8995), in IoTOps.[49]
Diagram source (Mermaid)
flowchart TB
F["`1 Factory inserts
credentials (DI);
voucher created`"]:::neutral
V["`2 Voucher reaches the
owner; node still boxed`"]:::neutral
R["`3 Owner service registers
with rendezvous (TO0)`"]:::neutral
P["`4 Staff plug it in; node
asks rendezvous for
its owner (TO1)`"]:::core
T["`5 Trust established;
secrets, config (TO2)`"]:::core
A["`6 Fleet agent registers
outbound; baseline applied`"]:::core
Q{"`7 Acceptance
check passes?`"}:::decision
OK["`In service;
added to its wave`"]:::core
NO["`Quarantine: re-image
remotely, else swap`"]:::risk
F --> V --> R --> P --> T --> A --> Q
Q -->|yes| OK
Q -->|no| NO
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
Text equivalent: The factory inserts credentials (DI) and creates a voucher, which reaches the owner while the node is boxed; the owner registers with a rendezvous server (TO0). Plugged in on site, the node finds its owner there (TO1), establishes trust and receives secrets and configuration (TO2); the fleet agent registers outbound and applies the baseline. A node that passes the acceptance check enters service and its wave; one that fails is re-imaged remotely or swapped.
Playbook 2: updates that undo themselves. bootc upgrade “does not affect the running system; updates operate in an ‘A/B’
style by default”; bootc rollback queues the previous deployment, without /etc changes.[22] With greenboot, a failing
required.d check fails the boot, and after GREENBOOT_MAX_BOOT_ATTEMPTS the node returns to the previous deployment.[50]
Caution: the optional greenboot-default-health-checks package adds a required DNS check of repository URLs,[50] which a
WAN outage during the first boot after an update can fail; leave it out where the WAN may be down.
Playbook 3: partition-tolerant workloads. Give every remote dependency of the core job (identity, licences, configuration, images, payment endpoints, time, DNS) an offline behaviour: cached, queued, degraded or refused, so that losing them “does not compromise the static stability of your applications”.[46] Queue data written offline with idempotency keys so a replay cannot apply it twice, reconcile conflicts after reconnecting, and keep a local time source: a drifting clock breaks certificate checks and ordering (money movement: FinTechOps). Prove it with a drill that includes a power cycle.
Playbook 4: telemetry that survives outages. The OpenTelemetry Collector’s exporter gives up on a batch after
max_elapsed_time (300 seconds by default) and drops data when its queue is full; a persistent queue on disk survives
restarts.[32] Size it for your longest outage (reference implementation).
Playbook 5: decide what data leaves the site. LF Edge expects work such as “stripping PII” or “extracting information from streaming video” to run close to where the data originates.[3] Per data stream, write down what the site filters or aggregates (events, not raw frames), how long raw data stays on local disk, and what never leaves (video of people, payment data: PrivacyOps). Size local storage for the longest outage; the backlog then drains only at the link’s spare capacity, so a day at 50 kB/s (4.32 GB) needs about two hours of a spare 5 Mbit/s.
Methods, standards and frameworks
Link to section “Methods, standards and frameworks”None is mandatory for edge computing as such; contracts, sector rules or customers may make some binding.
| Source | Type | Take from it |
|---|---|---|
| ETSI GS MEC 003 V4.1.1[13] | Telecom specification | MEC host, platform, management |
| FDO 2.0 (2026)[20] | Proposed Standard | Zero-touch onboarding |
| RFC 9334 (RATS)[51] | IETF architecture | Remote attestation |
| The Update Framework[52] | Update-security specification | Rollback and freeze defences |
| NIST SP 800-193[53] | Guideline | Firmware protection and recovery |
| ISA/IEC 62443[54] | Standards series | Industrial control system security |
Tooling landscape
Link to section “Tooling landscape”As of October 2026.
| Category | Verified examples | Watch-outs |
|---|---|---|
| Lightweight site Kubernetes | K3s, “a fully compliant Kubernetes distribution”;[26] MicroShift, built to “tolerate severe networking constraints”[27] | One more cluster per site to upgrade; certificates[55] |
| Stretched, cloud-to-edge Kubernetes | KubeEdge (CNCF graduated),[19] OpenYurt,[37] EKS Hybrid Nodes[35] | Partition behaviour; KubeEdge 1.23 vendors Kubernetes 1.32.10[56] while upstream maintains 1.35–1.37[57] |
| Fleet GitOps | Fleet 0.16;[47][33] other agents in GitOps | Defaults do not gate |
| Node upgrades | system-upgrade-controller Plan[58] |
Privileged jobs; channel upgrades every follower |
| Edge OS | bootc,[25] greenboot,[50] EVE-OS[29] | /etc on rollback[22] |
| Onboarding | FDO implementations;[20] vendor ZTP such as NativeEdge[7] | Voucher logistics |
| Cloud provider stacks at sites | AWS Outposts (AWS’s hardware);[38] Azure Local (yours)[41] | Connectivity and hardware duties differ: see the control-plane table |
| Site telemetry | OpenTelemetry Collector, persistent queue[32] | Defaults drop data |
Selection criteria, in order: behaviour during partitions (test it), footprint, upgrade path and version lag, onboarding support, dependence on one vendor’s control plane, and who answers the phone at 03:00.
Automation and AI
Link to section “Automation and AI”Pulls, waves, health checks and rollbacks run without people; keep humans for promoting high-risk changes past the canary and for fleet-wide emergencies. AI anomaly detection can rank failing sites, but offline sites look anomalous, and no model should widen a wave without the gates a person faces. Inference at sites belongs to MLOps.
EdgeOps in practice
Link to section “EdgeOps in practice”Reference implementation
Link to section “Reference implementation”Illustrative design: 1,200 stores, each with one server running an image-based OS, single-node K3s and an OpenTelemetry Collector; a central Fleet manager and registry. One node means a hardware fault stops local compute until a swap; three servers triple the hardware for etcd quorum.[34]
1. Site profile, one file per site; its labels drive waves, windows and reports.
Example status: YAML syntax-checked; an illustrative schema for your own tooling.
site: store-0413
region: eu-west
timezone: Europe/Dublin
hardware: {model: gen3-1u, nodes: 1, tpm: "2.0"}
connectivity:
primary: broadband
backup: lte
out_of_band: cellular-console
labels: # copied onto the Fleet cluster object
wave: wave2
hw: gen3
site-class: standard-store
maintenance_window: {days: [mon, tue, wed, thu], start: "02:00", end: "05:00"}
owners: {site_contact_role: store-manager, field_service: regional-it}
2. Application waves in Fleet. Each wave gets its own image tag (immutable in the registry, or use digests); promotion is a
reviewed one-line commit. Fleet “does not add artificial delays during rollout” and its default maxUnavailable of 100% gates
nothing,[47] so the gate lives in the pipeline that writes this file; rolloutStrategy limits batch size and
paused: true stops updates.[59]
Example status: YAML syntax-checked; keys checked against the Fleet 0.16 fleet.yaml reference; not applied. Each customization
repeats the full image map: deep-merging of per-target Helm values was not confirmed.
# fleet.yaml — in-store app bundle.
# Wave 3 has no customization and runs the root (baseline) values.
defaultNamespace: store-apps
helm:
chart: ./chart
values:
image: {repository: registry.example.com/store/pos-sync, tag: "2026.09.4"}
targetCustomizations:
- name: canary
clusterSelector: {matchLabels: {wave: canary}}
helm:
values:
image: {repository: registry.example.com/store/pos-sync, tag: "2026.10.2"}
- name: wave1
clusterSelector: {matchLabels: {wave: wave1}}
helm:
values:
image: {repository: registry.example.com/store/pos-sync, tag: "2026.10.2"}
- name: wave2 # promoted after wave 1 baked
clusterSelector: {matchLabels: {wave: wave2}}
helm:
values:
image: {repository: registry.example.com/store/pos-sync, tag: "2026.10.2"}
rolloutStrategy:
maxUnavailable: 10% # offline sites count as NotReady: leave headroom
maxUnavailablePartitions: 0
autoPartitionSize: 10% # partitions of about 120 sites
maxNew: 50 # default: at most 50 sites staged at once (pull storms)
3. Cluster upgrades inside each site, delivered by Fleet and versioned per wave the same way. Pin version: a channel upgrades
“any time it resolves to a new release”,[58] on a fleet every site at once. On 2026-10-18 the K3s stable channel resolved
to v1.36.5+k3s1.[60]
Example status: YAML syntax-checked; fields from the K3s automated-upgrade guide and the Plan reference;[61] not applied.
apiVersion: upgrade.cattle.io/v1
kind: Plan
metadata:
name: k3s-server
namespace: system-upgrade
spec:
concurrency: 1
cordon: true # single node: no drain target, so only cordon
nodeSelector:
matchExpressions:
- {key: node-role.kubernetes.io/control-plane, operator: In, values: ["true"]}
serviceAccountName: system-upgrade
upgrade:
image: rancher/k3s-upgrade
version: v1.36.5+k3s1 # one minor at a time; never skip
window:
days: [monday, tuesday, wednesday, thursday]
startTime: "02:00"
endTime: "05:00"
timeZone: Europe/Dublin
4. A boot health check that looks only inside the site. If the local API or store service does not answer, the boot fails and greenboot eventually returns to the previous OS deployment.[50]
Example status: bash -n syntax-checked; not executed (needs a bootc host with greenboot and K3s). Port and path are placeholders.
#!/usr/bin/env bash
# /etc/greenboot/check/required.d/50-site-ready.sh
# Local checks only: a WAN outage must never roll back a good image.
set -euo pipefail
for _ in $(seq 1 30); do
k3s kubectl get --raw='/readyz' >/dev/null 2>&1 && break
sleep 10
done
k3s kubectl get --raw='/readyz' >/dev/null
curl --fail --silent --max-time 5 http://127.0.0.1:30080/healthz >/dev/null
5. Telemetry buffer. Size it by calculation: at an illustrative 50 kB/s per signal, a day of outage is 50 kB/s × 86,400 s = 4.32 GB, so a 2 GiB cap covers about 11.9 hours. The cap is per queue file, with one file per exporter and signal,[62][63] so metrics plus logs can use 4 GiB. Decide in advance what the site drops first, such as debug logs.
Example status: YAML syntax-checked; keys from the collector’s exporterhelper and file storage READMEs; not run. otlp is the
deprecated alias of otlp_grpc, kept here for older collectors.[64] max_size may not exist in older versions.[62]
extensions:
file_storage/wan:
directory: /var/lib/otelcol/file_storage
create_directory: true
max_size: 2147483648 # 2 GiB
receivers:
otlp:
protocols:
grpc: {endpoint: 127.0.0.1:4317}
exporters:
otlp:
endpoint: telemetry.example.com:4317
sending_queue:
storage: file_storage/wan
queue_size: 20000 # batches on disk
retry_on_failure:
max_elapsed_time: 0 # default 300s: data dropped after five minutes of outage
service:
extensions: [file_storage/wan]
pipelines:
metrics: {receivers: [otlp], exporters: [otlp]}
logs: {receivers: [otlp], exporters: [otlp]}
6. Fleet report. Reporting convergence (healthy ÷ recently checked-in sites) flatters a fleet with many silent sites; true
convergence does not. The wave gate counts only sites that pulled the change (pulled_at).
Example status: JSON syntax-checked; this exact file was used for the executed run below.
{
"target_version": "2026.10.2",
"generated_at": "2026-10-18T06:00:00Z",
"sites": [
{"site": "store-0001", "wave": "canary", "version": "2026.10.2", "health": "ok",
"last_checkin": "2026-10-18T05:58:10Z", "pulled_at": "2026-10-14T02:00:05Z"},
{"site": "store-0002", "wave": "canary", "version": "2026.10.2", "health": "ok",
"last_checkin": "2026-10-18T05:59:02Z", "pulled_at": "2026-10-14T02:00:40Z"},
{"site": "store-0107", "wave": "wave1", "version": "2026.10.2", "health": "ok",
"last_checkin": "2026-10-18T05:57:44Z", "pulled_at": "2026-10-16T02:01:10Z"},
{"site": "store-0108", "wave": "wave1", "version": "2026.10.2", "health": "degraded",
"last_checkin": "2026-10-18T05:56:30Z", "pulled_at": "2026-10-16T02:03:20Z"},
{"site": "store-0109", "wave": "wave1", "version": "2026.09.4", "health": "ok",
"last_checkin": "2026-10-15T21:12:00Z", "pulled_at": null},
{"site": "store-0412", "wave": "wave2", "version": "2026.09.4", "health": "updating",
"last_checkin": "2026-10-18T04:06:00Z", "pulled_at": "2026-10-18T04:05:30Z"},
{"site": "store-0413", "wave": "wave2", "version": "2026.08.1", "health": "ok",
"last_checkin": "2026-09-30T10:00:00Z", "pulled_at": null},
{"site": "store-0414", "wave": "wave2", "version": "2026.10.2", "health": "failed",
"last_checkin": "2026-10-18T05:50:00Z", "pulled_at": "2026-10-18T04:02:00Z"},
{"site": "store-0415", "wave": "wave2", "version": "2026.10.2", "health": "ok",
"last_checkin": "2026-10-18T05:59:40Z", "pulled_at": "2026-10-18T04:04:10Z"}
]
}
Example status: executed on 2026-10-18 with Python 3.8.10 against the JSON above; output below is verbatim.
"""Summarise edge-fleet check-ins: convergence, wave gates, stragglers.
Usage: python3 fleet_report.py fleet-status.json [stale_hours] [silent_minutes]
Standard library only (Python 3.8+).
"""
import json
import sys
from collections import Counter, defaultdict
from datetime import datetime, timedelta
def parse(ts):
return datetime.strptime(ts, "%Y-%m-%dT%H:%M:%SZ")
def age(delta):
return "%dd %dh %02dm" % (delta.days, delta.seconds // 3600,
delta.seconds % 3600 // 60)
def main(path, stale_hours=24, silent_minutes=60):
with open(path) as f:
data = json.load(f)
now = parse(data["generated_at"])
target = data["target_version"]
sites = data["sites"]
fresh = [s for s in sites
if now - parse(s["last_checkin"]) <= timedelta(hours=stale_hours)]
healthy = [s for s in sites if s["version"] == target and s["health"] == "ok"]
print("sites in scope: %d" % len(sites))
print("reporting (<= %dh): %d" % (stale_hours, len(fresh)))
print("true convergence: %.1f%% (healthy on %s / in scope)"
% (100.0 * len(healthy) / len(sites), target))
print("reporting convergence: %.1f%% (healthy on target / reporting)"
% (100.0 * len([s for s in healthy if s in fresh]) / len(fresh)))
print("version spread: %s" % dict(Counter(s["version"] for s in sites)))
# Wave gate. Sites that never pulled the change are unknown and excluded.
# A site that pulled it, then stayed silent past the deadline, is suspect.
rows, suspects = defaultdict(Counter), []
for s in sites:
if s["pulled_at"] is None:
continue
silence = now - parse(s["last_checkin"])
if s["version"] == target and s["health"] == "ok":
state = "healthy"
elif s["health"] in ("failed", "degraded"):
state = s["health"]
elif silence > timedelta(minutes=silent_minutes):
state = "silent"
else:
state = "updating"
rows[s["wave"]]["received"] += 1
rows[s["wave"]][state] += 1
if state in ("failed", "silent"):
suspects.append((s, state, silence))
print("wave received healthy degraded updating failed silent suspect")
for wave, r in sorted(rows.items()):
print("%-7s %8d %7d %8d %8d %6d %6d %d/%d"
% (wave, r["received"], r["healthy"], r["degraded"], r["updating"],
r["failed"], r["silent"], r["failed"] + r["silent"], r["received"]))
print("suspected failures (pulled the change, then failed or went silent):")
for s, state, silence in suspects:
print(" %s %-6s last check-in %s ago" % (s["site"], state, age(silence)))
print("offline before their wave (unknown, not counted), oldest first:")
for s in sorted((s for s in sites if s["pulled_at"] is None and s not in fresh),
key=lambda s: s["last_checkin"]):
print(" %s %s silent for %s"
% (s["site"], s["version"], age(now - parse(s["last_checkin"]))))
if __name__ == "__main__":
args = [int(a) for a in sys.argv[2:4]]
main(sys.argv[1], *args)
sites in scope: 9
reporting (<= 24h): 7
true convergence: 44.4% (healthy on 2026.10.2 / in scope)
reporting convergence: 57.1% (healthy on target / reporting)
version spread: {'2026.10.2': 6, '2026.09.4': 2, '2026.08.1': 1}
wave received healthy degraded updating failed silent suspect
canary 2 2 0 0 0 0 0/2
wave1 2 1 1 0 0 0 0/2
wave2 3 1 0 0 1 1 2/3
suspected failures (pulled the change, then failed or went silent):
store-0412 silent last check-in 0d 1h 54m ago
store-0414 failed last check-in 0d 0h 10m ago
offline before their wave (unknown, not counted), oldest first:
store-0413 2026.08.1 silent for 17d 20h 00m
store-0109 2026.09.4 silent for 2d 8h 48m
Read it like an operator: in wave 2 one site reported a failure and one has been silent for almost two hours since it started updating, which is how a boot loop looks from the centre. Revert wave 2’s tag; do not promote wave 3. The 24-hour freshness view still counts store-0412 as reporting; only the post-update deadline catches it.
Hands-on labs
Link to section “Hands-on labs”Lab 1 was executed. Labs 2 and 3 need disposable virtual machines and were not executed; their expected output comes from the documentation cited inline.
Lab 1 (beginner): gate waves for a fleet that is never fully online
Link to section “Lab 1 (beginner): gate waves for a fleet that is never fully online”- Objective: compare three wave gates on a fleet that is never fully online, and see why canaries must be stratified (IoTOps Lab 3 goes further).
- Prerequisites: Python 3.8+; no network, cost or risk. About 20 minutes.
- Save the script as
waves.pyand runpython3 waves.py. Its “bad C” release bricks every model C node it reaches; those nodes never report. - Change
DAILY_OFFLINEto0.01and0.08, and the canary size from 12 to 30; rerun each time.
Example status: executed on 2026-10-18 with Python 3.8.10; output below is verbatim.
"""Simulate a staged rollout to an edge fleet where some sites are offline.
Standard library only. Deterministic: change SEED to see other runs.
"""
import random
SEED = 7
SITES = 1200
MODELS = {"A": 0.70, "B": 0.20, "C": 0.10} # hardware mix
DAILY_OFFLINE = 0.03 # chance a site is offline on a given day
CLOSED_SHARE = 0.01 # sites closed for the whole period (seasonal)
DROP_AFTER_UPDATE = DAILY_OFFLINE / 24 # unrelated drop-off within the hour
WAVES = [("canary", 12, 2), ("wave1", 60, 2), ("wave2", 300, 1), ("wave3", None, 0)]
# (name, size or None for "the rest", bake days before the next wave opens)
RULES = {"notready": "NotReady <= 2 % of the wave",
"reported": "failures reported by sites",
"two-part": "reported + silent after update"}
def build_fleet(rng):
fleet = []
for i in range(SITES):
r, acc, model = rng.random(), 0.0, "A"
for name, share in MODELS.items():
acc += share
if r < acc:
model = name
break
fleet.append({"id": i, "model": model,
"closed": rng.random() < CLOSED_SHARE,
"updated_day": None})
return fleet
def assign_waves(fleet, rng, stratified):
order = fleet[:]
rng.shuffle(order)
if stratified: # put one site of every model first, then the rest
firsts = []
for m in MODELS:
site = next(s for s in order if s["model"] == m and not s["closed"])
firsts.append(site)
order = firsts + [s for s in order if s not in firsts]
waves, start = {}, 0
for name, size, _ in WAVES:
end = len(order) if size is None else start + size
waves[name] = order[start:end]
start = end
return waves
def rollout(fleet, waves, rng, days=21):
opened, day_open, history = [], 0, []
schedule = {}
for name, _, bake in WAVES:
schedule[name] = day_open
day_open += bake
for day in range(days):
for name, sites in waves.items():
if schedule[name] == day:
opened.extend(sites)
for s in opened:
online = not s["closed"] and rng.random() >= DAILY_OFFLINE
if s["updated_day"] is None and online:
s["updated_day"] = day
done = sum(1 for s in fleet if s["updated_day"] is not None)
history.append((day, done))
return history
def canary_catches_model_c(rng, stratified, trials=2000):
hits = 0
for _ in range(trials):
fleet = build_fleet(rng)
waves = assign_waves(fleet, rng, stratified)
if any(s["model"] == "C" for s in waves["canary"]):
hits += 1
return hits / trials
def halts(rule, wave, size, received, silent):
"""Gate for one wave. A node that is bricked or boot-looping never reports."""
reported_failures = 0
if rule == "notready": # counts every site that is not Ready, for any reason
return (size - received) + silent > int(0.02 * size)
if rule == "reported": # failures among reporting sites only
return reported_failures > 0
# two-part rule: ignore sites offline before the wave, count silence after it
limit = 0 if wave == "canary" else max(1, int(0.01 * received))
return reported_failures + silent > limit
def release(waves, opening, rule, bad_model, rng):
"""Open waves in order until a gate halts; return (where, sites broken)."""
broken_total = 0
for name, sites in waves.items():
received = [s for s in sites if s["updated_day"] == opening[name]]
broken = [s for s in received if s["model"] == bad_model]
dropped = sum(1 for s in received
if s["model"] != bad_model and rng.random() < DROP_AFTER_UPDATE)
broken_total += len(broken)
if halts(rule, name, len(sites), len(received), len(broken) + dropped):
return name, broken_total
return "none", broken_total
def main():
rng = random.Random(SEED)
fleet = build_fleet(rng)
waves = assign_waves(fleet, rng, stratified=True)
history = rollout(fleet, waves, rng)
print("day sites_updated convergence")
for day, done in history:
if day in (0, 2, 4, 5, 6, 7, 10, 14, 20):
print("%3d %13d %10.1f%%" % (day, done, 100.0 * done / SITES))
opening = {}
day_open = 0
for name, _, bake in WAVES:
opening[name] = day_open
day_open += bake
print("wave sites offline on opening day")
for name, sites in waves.items():
late = sum(1 for s in sites if s["updated_day"] != opening[name])
print("%-6s %6d %22d" % (name, len(sites), late))
stragglers = [s for s in fleet if s["updated_day"] is None]
print("never updated after 21 days: %d sites (all closed: %s)"
% (len(stragglers), all(s["closed"] for s in stragglers)))
print("release gate rule halts at model C sites broken")
for label, bad in (("good", None), ("bad C", "C")):
for rule, text in RULES.items():
where, broken = release(waves, opening, rule, bad, random.Random(SEED + 2))
print("%-8s %-31s %-9s %d" % (label, text, where, broken))
for strat in (False, True):
p = canary_catches_model_c(random.Random(SEED + 1), strat)
label = "stratified" if strat else "random "
print("canary of 12, %s: contains a model C site in %.1f%% of runs"
% (label, 100 * p))
if __name__ == "__main__":
main()
- Expected output (Python 3.8.10, unchanged parameters):
day sites_updated convergence
0 12 1.0%
2 71 5.9%
4 360 30.0%
5 1169 97.4%
6 1193 99.4%
7 1193 99.4%
10 1193 99.4%
14 1193 99.4%
20 1193 99.4%
wave sites offline on opening day
canary 12 0
wave1 60 1
wave2 300 12
wave3 828 29
never updated after 21 days: 7 sites (all closed: True)
release gate rule halts at model C sites broken
good NotReady <= 2 % of the wave wave2 0
good failures reported by sites none 0
good reported + silent after update none 0
bad C NotReady <= 2 % of the wave canary 1
bad C failures reported by sites none 103
bad C reported + silent after update canary 1
canary of 12, random : contains a model C site in 71.4% of runs
canary of 12, stratified: contains a model C site in 100.0% of runs
- Validation: nothing fails in the good release, yet a 2%
NotReadygate halts it at wave 2 (12 sites offline, limit 6). Counting only reported failures lets the bad release through every wave, breaking 103 sites; the two-part rule passes the good release and stops the bad one at the canary. The random canary sits near 1 − 0.9¹² = 71.8%; the seven never-updated sites are the closed ones. - Troubleshooting:
StopIterationmeans a model has no open site (tiny fleets only); lowerCLOSED_SHARE. - Teardown: delete
waves.py.
Lab 2 (intermediate): pin, window and wave a K3s upgrade
Link to section “Lab 2 (intermediate): pin, window and wave a K3s upgrade”- Objective: upgrade a site cluster declaratively, one minor version, only inside its maintenance window.
- Prerequisites: a disposable Ubuntu VM with 2 vCPU and 2 GB RAM (the K3s server minimum),[24] outbound internet, sudo; about 45 minutes; no cost beyond the VM. Do not run on a machine you care about.
Example status: bash -n syntax-checked; not executed. Versions are the K3s releases of 2026-09-30.[60]
# 1. Install a pinned, older K3s (as a site would be after a year in the field)
curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=v1.35.9+k3s1 sh -
sudo k3s kubectl get nodes # expect one Ready node, VERSION v1.35.9+k3s1
# 2. Install the system-upgrade-controller at a pinned release
SUC=https://github.com/rancher/system-upgrade-controller/releases/download/v0.20.2
sudo k3s kubectl apply -f "$SUC/crd.yaml" -f "$SUC/system-upgrade-controller.yaml"
# 3. Label the node like a canary site
sudo k3s kubectl label node "$(hostname)" wave=canary
- Save the reference implementation’s Plan as
plan.yaml, addwave: canaryunder a newmatchLabelskey of itsnodeSelector, set yourtimeZoneand awindowthat already ended today, and apply it. - Run
sudo k3s kubectl -n system-upgrade get plans,jobs. Expected: the plan resolves its version but no job appears, because jobs “will not be created outside the time window”.[58] - Move the window to include the current time and apply again. Expected: a job runs, the node is cordoned, K3s restarts, and
sudo k3s kubectl get nodesshowsv1.36.5+k3s1.
- Validation:
sudo k3s kubectl -n system-upgrade get plan k3s-server -o jsonpath='{.status.latestVersion}'prints the pinned version, and the node is schedulable again. - Troubleshooting: a failed job with the node left cordoned (unschedulable) usually means a downgrade, which the upgrade image
refuses.[58] Skipping a minor is not blocked and may break the cluster, so check the version first; then fix it, or
delete the plan and
uncordonthe node. - Teardown:
/usr/local/bin/k3s-uninstall.sh,[65] then delete the VM.
Lab 3 (advanced): a partition drill, with a power cut
Link to section “Lab 3 (advanced): a partition drill, with a power cut”- Objective: observe a stretched cluster when a site loses the WAN, and when the site also reboots.
- Prerequisites: two disposable VMs on one network,
central(K3s server) andsite(K3s agent, joined withK3S_URLand the token in/var/lib/rancher/k3s/server/node-token; agents connect outbound to the server);[66] about 90 minutes. Lab only: the firewall rules below cut traffic.
Example status: YAML and bash -n syntax-checked; not executed. Expected behaviour is documented for upstream Kubernetes and EKS,
not verified on K3s for this page.
# site-app.yaml — pinned to the site node, as a store service would be
apiVersion: apps/v1
kind: Deployment
metadata:
name: site-app
spec:
replicas: 1
selector:
matchLabels: {app: site-app}
template:
metadata:
labels: {app: site-app}
spec:
nodeSelector: {kubernetes.io/hostname: site}
containers:
- name: web
image: nginx:1.27
ports: [{containerPort: 80, hostPort: 8080}]
# On central: deploy, then cut the site off
# (the rules live on central, so they survive a site reboot)
sudo k3s kubectl apply -f site-app.yaml
SITE_IP=192.0.2.20 # replace with the site VM's address
sudo iptables -I INPUT -s "$SITE_IP" -j DROP
sudo iptables -I OUTPUT -d "$SITE_IP" -j DROP
watch -n 10 sudo k3s kubectl get nodes,pods -o wide
# On site: the container keeps serving locally
curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8080/
sudo k3s crictl ps --name web
# Later, on site: simulate the power cut, then check again after boot
sudo systemctl reboot
# Finally, on central: heal the partition
sudo iptables -D INPUT -s "$SITE_IP" -j DROP
sudo iptables -D OUTPUT -d "$SITE_IP" -j DROP
- Expected output: within about a minute
siteshowsNotReady;[42] the localcurlstill returns200. About five minutes later central shows the podTerminatingand aPendingreplacement while the container keeps running on the site.[43] After the reboot, expect no running container until the partition heals.[36] - Validation: after healing,
sitereturns toReadyand exactly onesite-apppod runs. - Variation: make
sitea single-node K3s server with its own control plane and repeat the cut: the app keeps running and restarts after the reboot. That difference is the control-plane decision. - Troubleshooting: if nothing changes, check the rules were inserted on
central(sudo iptables -L INPUT -n | head). - Teardown: remove the rules, run
/usr/local/bin/k3s-agent-uninstall.shonsiteand/usr/local/bin/k3s-uninstall.shoncentral,[65] then delete both VMs.
Use cases and scenarios
Link to section “Use cases and scenarios”1. Restaurant and store fleets (documented, 2018 snapshots). Chick-fil-A ran “tens of containers over thousands of physically distributed clusters”;[17] its slides ask for nodes “Simple enough for a non-technologist to install” that can be re-imaged remotely; its in-house deployment system, also called Fleet, is unrelated to Rancher’s.[67] Target made each store cluster “its own standalone mini-cloud” and let teams choose groups of stores to deploy to first.[18] Lesson: cluster per site, central desired state and staged groups of sites emerged early, independently. Pitfall: this scale “breaks” some of the native tooling, says Chick-fil-A’s abstract;[17] both firms built their own deployment systems. Success metric: releases reach every store without visits.
2. Line-side inference in a plant (illustrative). Cameras feed a defect-detection model on a gateway in the plant’s operational technology (OT) network. Method: a three-node site cluster, because the line cannot stop for a hardware fault; waves timed to shift changes; a one-way data flow agreed with OT security under ISA/IEC 62443.[54] Pitfall: the OT firewall may block the agent’s outbound pull; agree that path before the first wave, and keep raw video on site (Playbook 5). Success metric: no line stops caused by site compute.
3. Ships, mines and remote depots (illustrative). Links are metered and sometimes absent for days. Method: pre-stage images in idle periods; use site caches and K3s’s peer-to-peer mirror;[68] make waves long; size telemetry buffers for the longest outage. Pitfall: a site back after three weeks may need intermediate versions. Success metric: days from reconnection to the current release, within the link budget.
Measure, secure and pay
Link to section “Measure, secure and pay”Metrics and KPIs
Link to section “Metrics and KPIs”| KPI | Definition or formula | Pitfall | Review |
|---|---|---|---|
| True convergence | Sites healthy on the target ÷ sites in scope | Dividing by reporting sites flatters | Each release |
| Check-in freshness | Sites checked in within T hours ÷ sites in scope | One T for sites that close at night | Daily |
| Wave failure rate | (Reported failures + sites silent T minutes after receiving the change) ÷ sites that received it | Counting sites offline before the wave, or ignoring silence after it | Each wave |
| Version spread | Versions in production; share two or more releases behind | Ignoring OS and cluster layers | Weekly |
| Exposure window | Fix released → 95% true convergence | Averages hide the tail | Each security fix |
| Remote resolution rate | Incidents resolved without a visit ÷ all site incidents | Staff talked through hardware fixes | Monthly |
| Drill pass rate | Site classes passing a drill with a power cycle ÷ classes | Drills without the power cycle | Quarterly |
Worked example 1: canary size. If a defect hits only hardware model C (10% of sites), a random canary of n sites includes a model C site with probability 1 − 0.9ⁿ: 71.8% for n = 12, as Lab 1 reproduced. Reaching 95% needs n ≥ ln 0.05 ÷ ln 0.9 ≈ 28.4, so 29 sites; a stratified canary with one site per model reaches 100% with three.
Worked example 2: latency. ITU-T planning values give 5 µs per km of optical fibre.[69] A data centre 1,000 km away costs 10 ms per round trip before routing, queueing or processing: too far for a 10 ms control loop, fine for a dashboard.
Security, physical security and compliance
Link to section “Security, physical security and compliance”- Physical access is the threat model. A disk key sealed in the TPM to “some combination of PCRs 7, 11, and 14 (if shim/MOK is used)”[70] protects a disk taken out of the box, but a box stolen whole boots the same signed chain and unlocks itself (a PIN is off by default),[70] leaving the running system to attack. Network-bound unlock (Clevis and Tang) opens the disk only on the site network,[71] but its Tang server must stay reachable during WAN outages, so it usually sits on site and can be stolen too; TPM plus PIN needs staff at every boot. Always lock the console and boot order, keep site credentials remotely revocable, and plan firmware protection and recovery (NIST SP 800-193).[53]
- Treat the out-of-band path as a master key: per-site credentials, multi-factor sign-in, recorded sessions and a central switch that disables it.
- Prove a node’s state before trusting it with remote attestation.[51]
- Secure the update path. The Update Framework defends against rollback, indefinite-freeze and mix-and-match attacks,[52] all plausible against sites offline for long periods.
- Plan identity for the outage. On EKS local clusters, IAM “isn’t available during network disconnects”, so AWS documents “an alternative authentication mechanism using x.509 certificates”.[39] Treat such credentials as break-glass: per site, rotated after each use.
- Mind privileged machinery. The K3s upgrade job runs with host namespaces,
CAP_SYS_BOOTand the host root mounted read-write;[58] whoever can write aPlancontrols the node. Peer-to-peer image sharing assumes equal trust between nodes.[68] - Compliance. Keeping data on site may simplify data-transfer questions, but rules depend on jurisdiction (PrivacyOps, ComplianceOps). OT security has no Atlas page; start from SecOps.
Cost, capacity and sustainability
Link to section “Cost, capacity and sustainability”Costs multiply by sites, so price one site class per year with the worksheet below. Pricing models differ: Azure
Local is “priced per physical core”,[41] while EC2 instances are “included in the price of AWS
Outposts”.[39] Bandwidth (illustrative): 300 MB of new image layers to 1,200 sites
is 360 GB per release; site caches pull once, and Fleet’s partitions and maxNew cap simultaneous pulls.[47] Capacity:
choose one node or N+1 per site class from the cost of a site outage, not habit. Hardware lifetime and embodied carbon belong to
GreenOps.
Template status: illustrative; use your own figures.
PER-SITE COST WORKSHEET (one site class, per year)
Hardware price per node ____ x nodes ____ / service life in years ____ = ____
Spares spare units ____ x unit price ____ / sites covered ____ / life ____ = ____
Visits visits per site per year ____ x cost per visit ____ = ____
Links primary ____ + backup ____ + out-of-band ____ = ____
Licences per node or per core ____ x count ____ = ____
Energy average watts ____ x 8.76 = kWh ____ x price per kWh ____ = ____
Releases MB per release ____ x releases ____ x price per GB, if metered = ____
Total per site per year = ____
Payback visits avoided by remote recovery ____ x cost per visit ____ = ____
Assurance of the operating model
Link to section “Assurance of the operating model”Check automatically the leading indicators (freshness, version spread, expired exceptions, certificate renewals) and the lagging ones (fleet-level incidents, visits, halted waves); test the design with scheduled drills.
When things go wrong
Link to section “When things go wrong”Common failures and troubleshooting
Link to section “Common failures and troubleshooting”| Symptom | Likely cause | Diagnosis | Fix and prevention |
|---|---|---|---|
| A healthy rollout halts at a large wave | Offline sites count as NotReady[47] |
Compare NotReady with check-in freshness |
Exclude sites offline before the wave; count silence after it |
| Nodes that never restart lose API access after about a year | K3s renews certificates only when it starts, from 120 days before expiry[55] | k3s certificate check --output table; CertificateExpirationWarning events |
Restart or upgrade inside the window; alert at 120 days |
| Store apps stay down after a power cut during a WAN outage | Stretched cluster: the kubelet cannot learn its pods[36] | crictl pods empty on the node |
Control plane or autonomy agent on site; drills with a power cycle |
| A telemetry gap after every outage | Retries stop after 300 s; the queue fills[32] | otelcol_exporter_enqueue_failed_* metrics[72] |
Persistent queue, max_elapsed_time: 0, sized disk |
| A good OS update rolls back where the WAN is down | A required boot check depends on DNS or the WAN[50] | greenboot journal entries | Required checks local to the site only |
| Every site jumps to an untested release | The upgrade Plan follows a channel[58] |
status.latestVersion changed with no commit |
Pin version; promote by commit |
Worked runbook: a wave-1 update leaves sites in a boot loop
Link to section “Worked runbook: a wave-1 update leaves sites in a boot loop”Illustrative scenario. An OS image reaches wave 1 (60 sites). Within an hour 9 sites stop checking in, and a store reports “the till screen keeps restarting”.
- Stop the spread (minutes 0–10). Revert wave 1’s image version in the fleet repository so reconnecting sites pull the old desired state; declare an incident (IncidentOps).
- Treat the 9 as failed until proven otherwise: they received the image, then went silent. Compare them with sites routinely offline at this hour, and look for a shared model, image or class.
- Climb the recovery ladder (figure below), recording which rung worked where.
- Verify check-in, the previous image and application health at each site.
- Prevent: add the missing model to the canary and the failing check to the lab; write the post-incident review.
Diagram source (Mermaid)
flowchart TB A["1 Automatic: failed health checks boot the previous image"]:::core B["2 Remote: management agent rolls back or re-images"]:::core C["3 Out-of-band: console or cellular path, boot menu"]:::neutral D["4 Guided hands: staff swap in a pre-imaged spare"]:::neutral E["5 Visit: technician repairs or replaces"]:::risk A -->|still failing| B B -->|agent unreachable| C C -->|not recoverable remotely| D D -.->|spare fails or none on site| E classDef core fill:#e8f3f2,stroke:#16756f,color:#122029 classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029 classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
Text equivalent: Rung 1, automatic: failed health checks boot the previous image. If the site still fails, rung 2: the agent rolls back or re-images. If the agent is unreachable, rung 3: the out-of-band path. If that fails, rung 4: staff swap in a pre-imaged spare. Rung 5, a visit, only if the spare fails or none is on site.
Anti-patterns and myths
Link to section “Anti-patterns and myths”| Anti-pattern or myth | Why it fails | Do instead |
|---|---|---|
| “The edge is a small cloud region” | Regions are staffed, secured, connected; sites are not | Design for partition, theft, no staff |
| Push from the centre into every site | Needs inbound routes and a live link | Agents pull outbound |
| A random canary | Misses the minority hardware that breaks | Stratify by model, image, class and link |
| Ship all raw data to the centre | The link and its outages decide what arrives | Filter and aggregate at the site (Playbook 5) |
| Fixing sites by SSH | Creates snowflakes the next image wipes out | Change the image or the desired state |
Deciding and adopting
Link to section “Deciding and adopting”When to use and when not to use
Link to section “When to use and when not to use”Put compute at sites when work must continue through WAN outages, needs answers faster than distance allows, produces more data than the link carries, or must stay on site for legal reasons. Do not when a thin client to a central service would do, outages are tolerable, or nobody will fund the hidden duties: spares, onboarding logistics, waves, drills, physical security and refresh.
Decision framework
Link to section “Decision framework”Diagram source (Mermaid)
%%{init: {"flowchart": {"nodeSpacing": 14, "rankSpacing": 30, "padding": 8}}}%%
flowchart TB
Q1{"`Must it keep working
through WAN outages,
or need low latency
or local data?`"}:::decision
N1["`Run it centrally:
CloudOps`"]:::neutral
Q2{"`Is it a single-purpose
or microcontroller
device?`"}:::decision
Q3{"`Must the site
restart or change
workloads while
disconnected?`"}:::decision
N2["`Device patterns:
IoTOps`"]:::neutral
S1["`Cluster or runtime
per site, managed
centrally`"]:::core
S2["`Stretched cluster
acceptable; drill
power cuts in outages`"]:::core
Q4{"`Can you staff
hardware lifecycle
and spares?`"}:::decision
O1["`Own the hardware:
stock spares, agree
swap times`"]:::core
M1["`Provider-owned
hardware, such as
Outposts: needs a
reliable link`"]:::risk
Q1 -->|no| N1
Q1 -->|yes| Q2
Q2 -->|yes| N2
Q2 -->|no| Q3
Q3 -->|yes| S1
Q3 -->|no| S2
S1 --> Q4
S2 --> Q4
Q4 -->|yes| O1
Q4 -->|no| M1
classDef core fill:#e8f3f2,stroke:#16756f,color:#122029
classDef risk fill:#fbeceb,stroke:#b4332b,color:#122029
classDef decision fill:#fdf3e3,stroke:#c9800f,color:#122029
classDef neutral fill:#f1f4f6,stroke:#5b7a87,color:#122029
Text equivalent: Without an outage, latency or data-locality need, run it centrally. With one, single-purpose and microcontroller devices follow IoTOps patterns. Otherwise, if the site must restart or change workloads while disconnected, run a cluster or runtime per site; if not, a stretched cluster is acceptable after a power-cut drill. Then, if you can staff hardware lifecycle and spares, own the hardware; if not, consider provider-owned hardware such as AWS Outposts, which needs a reliable link.
To compare options, score each 1–5 on autonomy during outages (35%), effort per site (25%), node security (20%) and cost per site (20%), this Atlas’s weights, and record the result in the decision record.
Maturity model
Link to section “Maturity model”This Atlas’s model, not an industry standard.
| Level | Observable behaviour | Exit criterion |
|---|---|---|
| 1 Hand-built | Sites set up by technicians; changes by script or SSH | Every site has a profile in version control |
| 2 Imaged | Golden image, inventory, manual waves | Two releases shipped in waves with recorded gates |
| 3 Declarative | Sites pull desired state; zero-touch onboarding; pinned upgrades | 95% true convergence within seven days |
| 4 Partition-proven | Drills with power cycles; telemetry buffered; offline-aware gates | Every site class passed a drill this year |
| 5 Self-recovering | A/B rollback, OOB paths and spares make visits rare | Remote resolution above 90% for two quarters |
Adoption roadmap: 30/60/90 days
Link to section “Adoption roadmap: 30/60/90 days”- Days 1–30: see the fleet. Inventory sites, hardware, versions, links and owners; write site profiles; measure freshness and true convergence. Quick win: an expiry report for certificates and credentials.
- Days 31–60: make change safe. Pin versions; define waves and a stratified canary; move one application to pull-based delivery; write the dependency inventory for one site class. Milestone: one release shipped in waves with recorded gates.
- Days 61–90: prove autonomy. Drill with a power cycle on a lab site, then a real one in a quiet window; buffer telemetry; draft the recovery ladder; stock spares. Milestone: the first site class passes its drill.
Toolkit
Link to section “Toolkit”Checklists
Link to section “Checklists”Before a node ships
- Image recorded; TPM enrolled; disk unlock policy chosen (TPM only, network-bound or PIN); console and boot order locked
- FDO voucher (or vendor equivalent) delivered to the owner service
- Site profile committed with wave, hardware and maintenance window
Before each release wave
- Canary covers every hardware model and architecture, image, site class and link type
- Halt rule written: failures plus silence after the change; sites offline before it excluded
- Previous version still available; rollback tested on each model
- Batch size limits registry load
Disconnection drill (per site class)
- Core job works with the WAN cut (or has a documented fallback)
- Power cycle during the outage: services return without the WAN
- Break-glass login works locally
- Telemetry from the outage arrives after reconnection
Monthly review
- Stragglers older than seven days have a plan
- Every node restarted inside its certificate renewal window; no certificate under 30 days
- Exceptions reviewed; expired ones closed
Templates
Link to section “Templates”Template status: illustrative; adapt names and numbers.
WAVE PLAN
Release: Change type: app | OS image | cluster | config
Canary sites (one per model/class/link):
Wave sizes and bake times: canary __ (bake __h) wave1 __% (__h) wave2 __% (__h) rest
Halt rule: failed + silent __ min after receiving > __ per wave (offline before: excluded)
Rollback: previous version ____ method ____ tested on models ____
Owner on call: Communication channel:
PARTITION-TOLERANCE WORKSHEET (one row per remote dependency)
Offline behaviour: cache | queue | degrade | refuse
Dependency Core job? Offline behaviour Max outage covered Tested on (date)
Identity ____ ____ ____ h ____
Licences ____ ____ ____ h ____
Images ____ ____ ____ h ____
Time, DNS ____ ____ ____ h ____
ARCHITECTURE DECISION RECORD: CONTROL-PLANE PLACEMENT
Context: site classes, link quality, outage history, staff on site
Options: cluster per site | stretched | stretched with autonomy | provider-owned hardware
Scores (autonomy 35%, effort 25%, security 20%, cost 20%):
Drill result (WAN cut plus power cycle):
Decision, consequences, review date:
Deep comparisons
Link to section “Deep comparisons”Comparisons sit where they are used: neighbours, edge, fog and cloud, control-plane patterns.
Is EdgeOps a job title or a certification? Not a standard one; the label is used mostly by vendors.
Do we need Kubernetes at the edge? No. A container runtime with a pull agent, or virtual machines on an edge OS, can be enough; Kubernetes pays off when sites run several services and the team already operates it (KubernetesOps).
How is EdgeOps different from IoTOps? By device class, an editorial line both pages share: general-purpose nodes that host workloads here; microcontroller and single-purpose embedded devices in IoTOps.
Can a site skip versions after a long outage? Not Kubernetes minors,[58] so keep intermediate images for returning sites.
Are spares worth stocking? Usually: a pre-imaged spare that staff can swap is the cheapest rung below remote recovery.
Going further
Link to section “Going further”Advanced topics and emerging direction
Link to section “Advanced topics and emerging direction”- Upstream partition behaviour is unchanged (October 2026): the pull request and issue that AWS cites were “closed without changes being merged”,[36] in September 2025.[73] Design for today’s behaviour.
- Attestation-gated onboarding: FDO’s late binding[20] plus remote attestation,[51] so secrets reach only nodes in a known state; the pieces are standard, the integration product-specific.
Learning path
Link to section “Learning path”- Prerequisites: Linux, networking, containers; KubernetesOps for cluster mechanics.
- One day: the LF Edge taxonomy and CNCF edge-native principles;[3][1] Lab 1.
- One week: Lab 2; the K3s certificate and upgrade guides; Fleet’s rollout page.[47]
- Thirty days: Lab 3; an image-based OS with a health check; a partition-tolerance worksheet for a real workload.
- Specialise and show: onboarding and attestation, fleet delivery, OT or telecom MEC; a wave simulator tuned to your fleet, a drill report, a recovery ladder with measured times per rung.
Wrap-up
Link to section “Wrap-up”Executive recap and cheat sheet
Link to section “Executive recap and cheat sheet”| Decide | Do | Measure | Watch out for |
|---|---|---|---|
| Control-plane placement per site class | Drill: WAN cut plus power cycle | Drill pass rate | Pods that cannot restart offline |
| Waves and gates | Stratified canary, bake, offline-aware gates | Wave failure rate, true convergence | Defaults that gate nothing |
| Image and update path | A/B images, local health checks, pinned versions | Version spread, exposure window | channel upgrades |
| Recovery ladder | OOB path, spares, guided swaps | Remote resolution, visits | Fixes by SSH |
Example status: commands from the K3s and Kubernetes documentation; not executed here.
k3s certificate check --output table # expiry of node certificates
kubectl -n system-upgrade get plans,jobs # upgrade progress per node
kubectl get nodes -L wave,topology.kubernetes.io/zone # waves and site zones
kubectl get events -A --field-selector reason=CertificateExpirationWarning
crictl ps # on the node; API unreachable
bootc status # booted, staged, rollback images
A judgement call: patch every site today, or keep the waves?
Link to section “A judgement call: patch every site today, or keep the waves?”Situation (illustrative). A remotely exploitable flaw in the store gateway’s web component is published, with reports of active exploitation. The fixed image is ready; normal waves take about five days (Lab 1).
| Option | For | Against |
|---|---|---|
| A. Every site today | Shortest exposure | Untested everywhere; if it breaks boot, every site needs hands |
| B. Compressed waves: stratified canary, two-hour bake, batches every few hours | Exposure in hours; stop button kept | Short bakes miss slow failures |
| C. Mitigate first (block the exposed port at the site firewall), then waves | Fast, reversible | The mitigation is a change too; canary it |
Reasoning. A looks responsible and is the trap: it turns a security risk at some sites into an availability risk at all of them. The 2024 CrowdStrike outage (a content update, not a patch) was a fleet-wide change whose recovery needed someone to “insert the USB key into an affected device”,[74] and CrowdStrike’s remedy was “an updated deployment ring process”.[75] Default: C when a reversible mitigation exists, then B; A only if exploitation is under way at your sites and the change cannot affect boot. Uncertainty: whether attackers can reach your sites, and whether the fix touches boot; settle both in the first hour.
Learning objectives and mastery check
Link to section “Learning objectives and mastery check”You can now explain the label’s ambiguity, place a site’s control plane, design waves and gates for a partly offline fleet, size a canary, plan onboarding and recovery without visits, and measure a fleet honestly.
- A rollout halts at wave 2 with 3.5% of sites
NotReadyand no failures reported. What happened, and what do you change?
Answer
Offline sites count as NotReady in Fleet,[47] and maxUnavailable is below the normal offline rate (Lab 1). Track
sites offline before the wave as stragglers; keep counting sites silent after receiving the update, which may be boot-looping.
- A team proposes one stretched cluster for 400 stores because “there is only one control plane to upgrade”. What test settles it?
Answer
A disconnection drill with a power cycle: after a reboot during the outage, pods stay down until the link returns.[36] If stores must recover locally, put a control plane or an autonomy agent on site.
- Model C is 5% of sites. How large must a random canary be to include one with 90% probability, and what is the better design?
Answer
1 − 0.95ⁿ ≥ 0.9 gives n ≥ ln 0.1 ÷ ln 0.95 ≈ 44.9, so 45 sites. A stratified canary, one site per model, is certain with far fewer.
- A K3s node ran 13 months without a restart and now fails to authenticate. Why, and what prevents it fleet-wide?
Answer
K3s certificates last 365 days and are renewed only when K3s starts, from 120 days before expiry.[55] Alert on
CertificateExpirationWarning events and restart or upgrade every node inside that window.
- Your company calls its store-platform team “EdgeOps”. What should a new joiner know about the term?
Answer
Conclusion
Link to section “Conclusion”Under a vendor-flavoured label sits a demanding practice: running many small data centres that are often alone and never staffed. Three habits carry most of it. Design each site to keep working when the link is gone, and test that with a power cut, not a slide. Move every change in stratified waves whose gates know which silences mean failure. Build the recovery ladder so a visit is the last rung. Tools change; these habits keep technicians at home.
Sources and further reading
Link to section “Sources and further reading”Re-check before reuse: the K3s channel and system-upgrade-controller release (Lab 2); Fleet’s minor version (rollout
defaults); KubeEdge’s vendored Kubernetes; the two AWS pages that disagree on zone evictions; the Collector’s otlp alias. Code
links are pinned to the tag or commit read.
Changelog: 2026-10-18 — first version (research, ledger, draft, diagrams, labs). 2026-10-18 — r1 revision after the independent review: offline-aware gates (labs re-run), eviction mechanics, provider- versus customer-owned edge, theft model, IoTOps boundary. 2026-10-18 — r2 revision after the final score: local data, edge/fog/cloud terms, multi-architecture images, cost worksheet, phone-width figures, a wave-2 gate, pinned code links, fewer restatements. 2026-10-18, post-score polish: figures 2, 5 and 6; origins before 2018; a metric source; code wrapped.
Edge Native Application Principles Whitepaper — CNCF IoT Edge Working Group, 2023. Checked 2026-10-18. ↩︎ ↩︎ ↩︎
Static stability using Availability Zones — Amazon Builders’ Library, 2019-12-05. Checked 2026-10-18. ↩︎ ↩︎
Sharpening the Edge II: Diving Deeper into the LF Edge Taxonomy and Projects — LF Edge, June 2022. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Edge Ops — Altair IoT Studio documentation, version 2025.4. Checked 2026-10-18. ↩︎ ↩︎
EdgeOps Automation Solutions — ZPE Systems, undated. Checked 2026-10-18. ↩︎ ↩︎
EdgeOps Platform Working and Its Deployment — XenonStack, 2024-08-23. Checked 2026-10-18. ↩︎
Dell NativeEdge Software Transforms Edge Operations — Dell Technologies press release, 2023-05-23. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎
The Age of Edge Ops Is Upon Us — The Next Platform, sponsored by Dell, 2024-01-24. Checked 2026-10-18. ↩︎
You Didn’t Know You Needed This – DevEdgeOps — HIPER Global, 2024-06-21. Checked 2026-10-18. ↩︎
EdgeOps.AI — company website. Checked 2026-10-18. ↩︎
What Is EdgeOps in IT Infrastructure — Opsio, updated 2025-10-24. Checked 2026-10-18. ↩︎
NIST SP 500-325: Fog Computing Conceptual Model — NIST, March 2018. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎
ETSI GS MEC 003 V4.1.1: Framework and Reference Architecture — ETSI, 2025-05. Checked 2026-10-18. ↩︎ ↩︎ ↩︎
IEEE 1934-2018: Adoption of OpenFog Reference Architecture for Fog Computing — IEEE SA, approved 2018-06-14. Checked 2026-10-18. ↩︎ ↩︎
The Case for VM-based Cloudlets in Mobile Computing — Satyanarayanan et al., IEEE Pervasive Computing, 2009. Checked 2026-10-18. ↩︎
Mobile-Edge Computing – Introductory Technical White Paper — MEC initiative founders, ETSI, September 2014. Checked 2026-10-18. ↩︎
Chick-Fil-A: Milking the Most out of 1000’s of K8s Clusters — Brian Chambers and Caleb Hurd, QCon New York, InfoQ, 2018-07-18; abstract on the QCon archive (expired TLS certificate; browsers warn). Checked 2026-10-18. ↩︎ ↩︎ ↩︎
Meet Target’s Stores Deployment Interface that Realizes Distributed Edge Computing at Retail Scale — Target Tech, 2018-06-20. Checked 2026-10-18. ↩︎ ↩︎
CNCF Announces KubeEdge Graduation — CNCF, 2024-10-15. Checked 2026-10-18. ↩︎ ↩︎
FIDO Device Onboard Specification 2.0, Proposed Standard — FIDO Alliance, 2026-04-02. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
Automating safe, hands-off deployments — Clare Liguori, Amazon Builders’ Library, 2020-06-18. Checked 2026-10-18. ↩︎ ↩︎
bootc-upgrade(8) and bootc-rollback(8) — bootc project, GitHub. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎
OpenGitOps principles v1.0.0 — OpenGitOps. Checked 2026-10-18. ↩︎
K3s requirements — K3s project. Checked 2026-10-18. ↩︎ ↩︎ ↩︎
K3s documentation — K3s project. Checked 2026-10-18. ↩︎ ↩︎
MicroShift — Red Hat / OpenShift, GitHub. Checked 2026-10-18. ↩︎ ↩︎
KubeEdge — KubeEdge project, GitHub README. Checked 2026-10-18. ↩︎ ↩︎
EVE: Edge Virtualization Engine — LF Edge, GitHub. Checked 2026-10-18. ↩︎ ↩︎
Air-Gap Install — K3s project. Checked 2026-10-18. ↩︎
OCI Image Index Specification — Open Container Initiative, image-spec v1.1.1. Checked 2026-10-18. ↩︎
Exporter Helper — OpenTelemetry Collector, GitHub. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎
Register Downstream Clusters — Fleet 0.16 documentation. Checked 2026-10-18. ↩︎ ↩︎
High Availability Embedded etcd — K3s project. Checked 2026-10-18. ↩︎ ↩︎
EKS Hybrid Nodes and network disconnections — AWS, EKS Best Practices Guide. Checked 2026-10-18. ↩︎ ↩︎
Kubernetes pod failover through network disconnections — AWS, EKS Best Practices Guide. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
OpenYurt documentation — OpenYurt project. Checked 2026-10-18. ↩︎ ↩︎
What is AWS Outposts? — AWS Outposts User Guide. Checked 2026-10-18. ↩︎ ↩︎
Prepare local Amazon EKS clusters on AWS Outposts for network disconnects — AWS, Amazon EKS User Guide. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎
Connectivity through service link — AWS Outposts User Guide. Checked 2026-10-18. ↩︎
What is Azure Local? — Microsoft Learn, updated 2026-04-22. Checked 2026-10-18. ↩︎ ↩︎ ↩︎
kube-controller-manager — Kubernetes (
--node-monitor-grace-period). Checked 2026-10-18. ↩︎ ↩︎Taints and Tolerations — Kubernetes. Checked 2026-10-18. ↩︎ ↩︎ ↩︎
node_lifecycle_controller.go — Kubernetes source (
ComputeZoneState). Checked 2026-10-18. ↩︎Best practices for stability through network disconnections — AWS, EKS Best Practices Guide. Checked 2026-10-18. ↩︎ ↩︎
Rollout Strategy — Fleet 0.16 documentation, SUSE Rancher. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
RFC 8572: Secure Zero Touch Provisioning (SZTP) — IETF, April 2019. Checked 2026-10-18. ↩︎
RFC 8995: Bootstrapping Remote Secure Key Infrastructure (BRSKI) — IETF, May 2021. Checked 2026-10-18. ↩︎
greenboot-rs README — Fedora IoT, GitHub. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
RFC 9334: Remote ATtestation procedureS (RATS) Architecture — IETF, January 2023. Checked 2026-10-18. ↩︎ ↩︎ ↩︎
TUF security — The Update Framework. Checked 2026-10-18. ↩︎ ↩︎
NIST SP 800-193: Platform Firmware Resiliency Guidelines — NIST, May 2018. Checked 2026-10-18. ↩︎ ↩︎
ISA/IEC 62443 Series of Standards — ISA. Checked 2026-10-18. ↩︎ ↩︎
k3s certificate — K3s project. Checked 2026-10-18. ↩︎ ↩︎ ↩︎
KubeEdge v1.23 changelog and go.mod at v1.23.1 — KubeEdge, GitHub, 2026. Checked 2026-10-18. ↩︎
Kubernetes Releases — Kubernetes. Checked 2026-10-18. ↩︎
Automated Upgrades — K3s project. Checked 2026-10-18. ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎ ↩︎
fleet.yaml reference — Fleet 0.16 documentation. Checked 2026-10-18. ↩︎
K3s release channels — K3s project (JSON; stable = v1.36.5+k3s1 on 2026-10-18). Checked 2026-10-18. ↩︎ ↩︎
Plan reference — rancher/system-upgrade-controller, GitHub. Checked 2026-10-18. ↩︎
File Storage Extension — OpenTelemetry Collector Contrib, GitHub. Checked 2026-10-18. ↩︎ ↩︎
persistent_queue.go — OpenTelemetry Collector source. Checked 2026-10-18. ↩︎
OTLP gRPC Exporter and its metadata.yaml (
deprecated_type: otlp) — OpenTelemetry Collector, GitHub. Checked 2026-10-18. ↩︎Environment variables and Uninstalling K3s — K3s project. Checked 2026-10-18. ↩︎ ↩︎
Quick-Start Guide and networking requirements — K3s project. Checked 2026-10-18. ↩︎
Talk slides (PDF) — Chick-fil-A, QCon New York 2018 (same archive). Checked 2026-10-18. ↩︎
Embedded Registry Mirror — K3s project. Checked 2026-10-18. ↩︎ ↩︎
ITU-T G.114: One-way transmission time — ITU-T, 2003-05 (in force), Table A.1. Checked 2026-10-18. ↩︎
systemd-cryptenroll — systemd manual. Checked 2026-10-18. ↩︎ ↩︎
Configuring automated unlocking of encrypted volumes by using policy-based decryption — Red Hat, RHEL 9 Security hardening. Checked 2026-10-18. ↩︎
Internal telemetry — OpenTelemetry, updated 2026-10-02. Checked 2026-10-18. ↩︎
Pull request #131294 and issue #131481 — Kubernetes, GitHub; both closed in September 2025. Checked 2026-10-18. ↩︎
KB5042429: New recovery tool to help with CrowdStrike issue impacting Windows devices — Microsoft Support, 2024. Checked 2026-10-18. ↩︎
Executive Summary: Root Cause Analysis — Channel File 291 — CrowdStrike, 2024-08-06. Checked 2026-10-18. ↩︎