Reference Architectures¶
This page answers a question the reference plant and the homelab setup can't: what does this actually look like plugged into a real plant? It sketches a few physical topologies for Cloud-Native DCS, from a single bench skid up to a multi-site deployment, and names the hardware, networks, and zone boundaries that tend to show up in each.
These are illustrative patterns, not certified reference designs. A real installation still has to be engineered against site-specific safety, cybersecurity, and qualification requirements. Treat this page as a starting point for the topology conversation, not a shopping list.
How the software maps to hardware¶
Before looking at any one topology it helps to name the three roles Cloud- Native DCS expects from the infrastructure underneath it:
| Role | What runs here | Typical hardware | Arch |
|---|---|---|---|
| Control plane | Kubernetes control plane, operators, gateway, historian, MQTT broker, audit archiver | Industrial PC or rackmount server, 4–16 cores, 16–64 GB RAM, SSD | x86_64 (linux/amd64) |
| Edge / unit runtime | One unit-runtime pod per Unit, io-probe, device drivers |
Fanless DIN-rail IPC or existing x86_64 edge gateway, 2–4 cores, 2–8 GB RAM | x86_64 (linux/amd64) |
| Field I/O | Remote I/O couplers, PLCs-as-gateway, smart instruments | Wago 750, Beckhoff EK, Phoenix ILC, vendor-specific RIO | n/a (protocol-bound, with no compute role) |
Release images are published for linux/amd64 only. x86_64 is the
supported production architecture for both roles. ARM hardware (Raspberry
Pi and other SBCs, ARM cloud instances) is a community/experimental tier:
you would have to build your own images and the configurations are
untested.
Two properties matter for every topology:
- Unit runtimes must sit on the same L2 segment as the field I/O they
talk to (Modbus TCP, EtherNet/IP, OPC UA). The runtime pod uses
hostNetwork: trueand is pinned to a node withnodeSelector: dcs.io/device=<unit>. See Device Enrollment. - The control plane does not need to sit on the field network. It only needs reachability to the edge nodes for the Kubernetes API and the gateway's bidirectional streams. This is what makes cloud or server-room control planes viable.
Network zones (IEC 62443 / Purdue)¶
All three patterns below use the same zone vocabulary. If your site already speaks Purdue levels, these map cleanly:
| Zone | Purdue level | What lives here |
|---|---|---|
| Enterprise | L4–L5 | ERP, corporate IT, internet egress |
| DMZ | L3.5 | MES integration point, historian replica, reverse proxy to gateway UI |
| Operations | L3 | Cloud-Native DCS control plane (Kubernetes), HMI workstations, engineering workstations |
| Supervisory / Control | L2 | Edge nodes running unit runtimes, local HMI panels |
| Basic control / Process | L0–L1 | Remote I/O, PLCs-as-gateway, smart instruments, sensors, actuators |
Conduits between zones are enforced with firewalls at the site boundary and Kubernetes NetworkPolicies inside the cluster. See Security Hardening for the NetworkPolicy layer and Threat Model for the trust assumptions.
Pattern A — Single skid / pilot line¶
The smallest serious deployment: one process cell, a handful of units, a single-node or 3-node Kubernetes cluster (Talos, k3s) on an x86_64 industrial PC in the control cabinet. The edge nodes are the same box or a couple of fanless DIN-rail IPCs in the same enclosure. Good for pilot plants, R&D skids, or a contract manufacturer running one suite.
flowchart TB
subgraph L4["Enterprise (L4)"]
Eng[Engineering laptop]
end
subgraph L3["Operations (L3)"]
IPC["Industrial PC<br/>single-node Kubernetes<br/>control plane + gateway + historian"]
end
subgraph L2["Control (L2)"]
Edge1["Edge IPC<br/>unit-runtime: reactor-1"]
Edge2["Edge IPC<br/>unit-runtime: tank-1"]
end
subgraph L1["Process (L0-L1)"]
RIO1[Wago 750 rack]
RIO2[Wago 750 rack]
Field1[(Sensors / valves)]
Field2[(Sensors / valves)]
end
Eng -->|HTTPS, VPN| IPC
IPC <-->|k8s API + gRPC| Edge1
IPC <-->|k8s API + gRPC| Edge2
Edge1 -->|Modbus TCP| RIO1
Edge2 -->|Modbus TCP| RIO2
RIO1 --- Field1
RIO2 --- Field2
What this gives you: a fully functional DCS with audit trail, recipes, and HMI on one cabinet's worth of hardware. No HA, no DMZ. If the IPC dies the plant stops executing new batches (running batches keep going on the edge runtimes until they need the control plane again).
Where it breaks: single point of failure on the control plane, no segmentation between operations and process networks, MES integration has to terminate directly on the IPC. Fine for a pilot, and beneath what a GMP suite requires.
Pattern B — Production plant with HA¶
A single site running production batches under GMP. Three control-plane nodes in the server room, a DMZ between operations and enterprise, a dedicated edge node per Unit on the process floor, and field networks segmented per process cell.
flowchart TB
subgraph L4["Enterprise (L4)"]
MES[MES / ERP]
Cloud[Cloud observability]
end
subgraph DMZ["DMZ (L3.5)"]
Proxy[Reverse proxy<br/>HMI ingress]
MQTTBridge[MQTT bridge<br/>historian replica]
end
subgraph L3["Operations (L3)"]
subgraph CP["k8s control plane (HA)"]
N1[Node 1]
N2[Node 2]
N3[Node 3]
end
HMI1[HMI workstation]
HMI2[HMI workstation]
end
subgraph L2A["Process cell A (L2)"]
EA1[Edge IPC: reactor-1]
EA2[Edge IPC: reactor-2]
EA3[Edge IPC: centrifuge-1]
end
subgraph L2B["Process cell B (L2)"]
EB1[Edge IPC: tank-1]
EB2[Edge IPC: filter-dryer-1]
end
subgraph L1A["Field A (L0-L1)"]
IOA[Remote I/O rings]
end
subgraph L1B["Field B (L0-L1)"]
IOB[Remote I/O rings]
end
MES <-->|REST / OPC UA| Proxy
Cloud <-->|OTLP| Proxy
Proxy <--> CP
MQTTBridge <--> CP
HMI1 --> CP
HMI2 --> CP
CP <--> EA1
CP <--> EA2
CP <--> EA3
CP <--> EB1
CP <--> EB2
EA1 --> IOA
EA2 --> IOA
EA3 --> IOA
EB1 --> IOB
EB2 --> IOB
What this gives you: HA on the control plane, clean zone boundaries for a 21 CFR Part 11 + IEC 62443 posture, per-cell blast radius on the field network, and a DMZ that is the only thing the MES talks to directly.
Hardware notes:
- Control-plane nodes are typically x86_64 rackmount servers (dual PSU, redundant NICs, hardware TPM). Kubernetes distribution is a choice. Talos (what the reference deployments run) and k3s both work fine at this size, and full k8s via kubeadm or a vendor distro is common if the plant already has a platform team.
- Edge IPCs are fanless x86_64 DIN-rail boxes. Two networks are in play: the L2 supervisory network to reach the API server, and the field network to reach remote I/O. Per-unit nodes keep failure blast radius to one Unit.
- Bond each zone, active-backup — 3 ports minimum, 4 for the full posture (ADR 0026). The field interface is bonded across two ports (required: a single field link makes a pulled cable indistinguishable from a dead node, escalating a cable fault into a Unit Hold and a failover). The supervisory interface is bonded too where the port budget allows. Land the two members of a bond on different switches where the plant has them, noting that this covers a switch failure only where the far end is also redundant. Single-homed remote I/O caps the benefit for the field zone. The supervisory zone, whose far end is the multi-node control plane, is where two switches genuinely pay off. Bonding is worth doing on a single switch regardless. Do not trunk both zones over one bond to fit a 2-port box: it trades the zone separation the IEC 62443 posture depends on for the port saving. Spec 4-port IPCs.
- Every field-facing bond is on a VLAN scoped to its process cell. The edge node is the only routed path between L2 and L1 for that cell.
Edge-node redundancy (ADR 0006): a failed edge IPC no longer strands
its Unit. The product implements hold-then-resume failover: re-binding
a Unit's runtime to a deployment-designated standby node. Because the
controller↔I/O link is a network connection (remote Ethernet I/O), the
standby needs no physical adjacency, and any enrolled node with
field-network reach can take the role. Per-Unit availability.failoverTargets names the
eligible standbys, and availability.mode chooses the posture:
Autonomy(default): on a control-plane partition the edge keeps controlling. Failover is a manual, fenced operation (the operator confirms the old node is powered off / field-disconnected). Preserves today's partition-autonomy behavior exactly.Failover(opt-in): the runtime holds a control lease and self-fences on expiry. The operator auto-re-binds to a standby after a safety margin. Trades partition autonomy for automatic recovery.
Standby topology is the deployment's choice:
- Dedicated standby per primary controller (recommended) — a cold spare IPC per Unit, same field-network VLAN. Deterministic failover target, easiest to qualify, preserves the 1:1 controller:Unit blast radius. Doubles edge-hardware count for the cells that need it.
- Shared spare pool (cost option) — one or a few spares shared across several Units. Lower hardware cost. The trade-off is that after a failure Units can co-locate on one node (the failover surfaces a co-location guard, refused by default). Size the spare's CPU/RAM for the busiest Unit it may host, and its NICs for every field VLAN in the pool.
What is not provided is hot-standby state replication or bumpless
switchover (explicitly rejected in ADR 0006, since batch tolerates the
ISA-88 Hold/Restart exception path). The running phase survives a
failover: SFC execution state lives in Phase.Status in the control
plane, and the edge node holds none of it. Process-level safe-state logic
in the SFC remains the first-line mitigation. See
HA and Failure Modes.
Pattern C — Multi-site with shared control plane¶
Several plants, each with its own field-level infrastructure, reporting into a shared Kubernetes control plane hosted centrally, either in a regional server room or in cloud infrastructure (VPC, private link to each site). Each site still runs its own edge nodes locally. The control plane is remote.
flowchart TB
subgraph Cloud["Central / Cloud (L3+)"]
CP["k8s control plane<br/>operators + gateway + historian<br/>multi-tenant by namespace (site-*)"]
Obs[Observability stack]
end
subgraph DMZA["Site A DMZ"]
PA[Reverse proxy + local historian cache]
end
subgraph SiteA["Site A (L2)"]
EA1[Edge node: reactor-1]
EA2[Edge node: tank-1]
IOA[(Field I/O)]
end
subgraph DMZB["Site B DMZ"]
PB[Reverse proxy + local historian cache]
end
subgraph SiteB["Site B (L2)"]
EB1[Edge node: granulator-1]
EB2[Edge node: blender-1]
IOB[(Field I/O)]
end
CP <-->|mTLS over VPN| PA
CP <-->|mTLS over VPN| PB
PA <--> EA1
PA <--> EA2
PB <--> EB1
PB <--> EB2
EA1 --> IOA
EA2 --> IOA
EB1 --> IOB
EB2 --> IOB
CP --> Obs
What this gives you: one place to author recipes, deploy operator upgrades, and aggregate audit data. Each site's field and L2 networks stay physically isolated from the WAN. Only the per-site DMZ box reaches the central control plane, and only over an authenticated tunnel.
Hardware notes:
- The control plane is the same shape as Pattern B (HA k8s) but is infrastructure (cloud VMs, a colocated cluster, or a corporate data centre). It never touches a field network.
- Each site has a small DMZ appliance that terminates the tunnel, caches historian writes locally when the WAN is down, and republishes once the link returns. This is what keeps batch execution resilient to WAN outages.
- Site-level namespaces (
site-<name>, created automatically by the Site controller) are the primary multi-tenant boundary. Per-site RBAC and NetworkPolicies are required, because a shared control plane must never mean shared access.
Where it breaks: regulatory posture gets harder. Some jurisdictions treat any off-site storage of batch records as a data residency concern, and some GMP auditors expect the record of record to live on-site. The per-site historian cache in the DMZ lets you satisfy either requirement, but it has to be designed deliberately.
Hardware shortlist (indicative)¶
The project is vendor-neutral, and these are the categories that keep showing up in practice. None is an endorsement:
| Role | Category examples | Notes |
|---|---|---|
| Control-plane node | Rackmount x86_64 server (Dell, HPE, Supermicro), Intel NUC-class IPC | 4–16 cores, 16–64 GB RAM, NVMe, dual NIC, TPM |
| Edge node | Fanless x86_64 DIN-rail IPC (Advantech, Siemens IPC227/427, Beckhoff CX) | Quad NIC (3 minimum — bonded field interface, ADR 0026), 8–32 GB SSD, wide-temp rated |
| Edge node (ARM — community/experimental) | Raspberry Pi 5, Revolution Pi, NVIDIA Jetson, Radxa, Compulab | Not a supported production tier: release images are linux/amd64-only, so you must build your own; watch for industrial certifications |
| Remote I/O | Wago 750, Beckhoff EK, Phoenix Contact Axioline, Siemens ET200 | Pick based on protocol (Modbus TCP, EtherNet/IP, PROFINET, OPC UA) |
| Field network switch | Managed industrial switch with VLANs and per-port ACLs | Needed to enforce per-cell L1 segmentation. A second switch splits the failure domain, but surviving a field switch failure needs the I/O end to be redundant too (ring topology or dual-homed devices) — controller bonding alone does not get you there (ADR 0026) |
Choosing a pattern¶
A rough decision tree:
- One Unit, one cabinet, no GMP requirement yet → Pattern A.
- One site, GMP, more than a few Units, needs an audit trail you can defend → Pattern B.
- Multiple sites, central authoring team, wants one deployment story → Pattern C, with Pattern B as the local blueprint for each site's field infrastructure.
None of these is a cliff. It is straightforward to start on Pattern A, migrate the control plane to HA hardware to become Pattern B, and later relocate that control plane to a central site to become Pattern C.
Related Documentation¶
- Deploy Your Own Instance -- end-to-end walkthrough on a single-node cluster
- Capacity Planning -- sizing numbers per role
- HA and Failure Modes -- what fails when a node dies
- Security Hardening -- NetworkPolicy-level zone enforcement
- Threat Model -- trust boundaries and assumptions
- Device Enrollment -- how edge nodes join the cluster
- IEC 62443 Traceability -- zones and conduits requirements mapping