Skip to content

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: true and is pinned to a node with nodeSelector: 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.