Structure Charts — the systematic way
Every ```mermaid flowchart / graph block now gets a shared set of
status styles injected automatically. You never write classDef for these
again — just tag a node with :::ok, :::warn, :::err, :::crit, :::off,
or :::info and it gets the right color, consistently, everywhere.
This applies only to
graph/flowchartdiagrams. Sequence, pie, etc. are left untouched. If you define aclassDefof the same name by hand, yours wins.
1. The status palette
| Tag | Meaning | Looks like |
|---|---|---|
:::ok |
healthy / running / reachable | green |
:::warn |
degraded / misconfigured / needs attention | yellow |
:::err |
not running / missing / failed | pink |
:::crit |
hard failure / down | red |
:::off |
intentionally inert (no IP, DPDK, disabled) | gray |
:::info |
neutral annotation | blue |
graph LR
OK["✅ Running"]:::ok
WARN["⚠ Degraded"]:::warn
ERR["❌ Missing"]:::err
CRIT["❌ Down"]:::crit
OFF["no IP"]:::off
INFO["note"]:::info
%% -- dashboard status styles --
classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16;
classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006;
classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724;
classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A;
classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827;
classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
How to tag a node
graph LR
CUCP["✅ CU-CP Running"]:::ok
DU["❌ DU Not running"]:::err
CUCP --> DU
Grouping boxes (the yellow rounded containers) come for free from the theme —
just use subgraph:
subgraph CU["cu01 10.0.108.150"]
CUCP["CU-CP pod"]
CUUP["CU-UP pod"]
end
2. Ready-made templates
Copy any block below into a note and edit it. The source files also live in
~/.md-dashboard/templates/ so they work from any folder the engine serves.
Site topology
graph LR
subgraph CU["cu01 10.0.108.150"]
CUCP["CU-CP pod"]
CUUP["CU-UP pod"]
end
subgraph DU["du01 172.30.3.160"]
DUPOD["DU pod
E810-C DPDK"] end FALCON["Falcon Switch
10.0.108.129"] CORE["campus-core01
N2/N3 10.0.108.170"] MASTER["master01
K8s control-plane"] RU0["RU 0"] RU1["RU 1"] FALCON --> CORE CORE -- "N2 SCTP 38412" --> CUCP CORE -- "N3 GTP-U 2152" --> CUUP MASTER -. "K8s API" .-> CUCP CUUP -- "E1 SCTP 38462
(K8s ClusterIP — internal)" --> CUCP CUCP -- "F1-C SCTP 38472" --> DUPOD CUUP -- "F1-U UDP 2152" --> DUPOD FALCON -- "xHaul" --> DUPOD MASTER -. "K8s API" .-> DUPOD DUPOD -- "eCPRI RU0
O-RAN 7.2" --> RU0 DUPOD -- "eCPRI RU1
O-RAN 7.2" --> RU1 %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
E810-C DPDK"] end FALCON["Falcon Switch
10.0.108.129"] CORE["campus-core01
N2/N3 10.0.108.170"] MASTER["master01
K8s control-plane"] RU0["RU 0"] RU1["RU 1"] FALCON --> CORE CORE -- "N2 SCTP 38412" --> CUCP CORE -- "N3 GTP-U 2152" --> CUUP MASTER -. "K8s API" .-> CUCP CUUP -- "E1 SCTP 38462
(K8s ClusterIP — internal)" --> CUCP CUCP -- "F1-C SCTP 38472" --> DUPOD CUUP -- "F1-U UDP 2152" --> DUPOD FALCON -- "xHaul" --> DUPOD MASTER -. "K8s API" .-> DUPOD DUPOD -- "eCPRI RU0
O-RAN 7.2" --> RU0 DUPOD -- "eCPRI RU1
O-RAN 7.2" --> RU1 %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
Fault state
graph LR
subgraph CM["Control & Management"]
CORE["campus-core01
10.0.108.170
⚠ No indoor N2
⚠ 10.0.109.0/24 missing
⚠ 172.30 not persisted"]:::warn NMS["ACP NMS
NoComms ❌"]:::crit end subgraph K8S["Indoor K8s — master01 ⚠ Images not imported ⚠ NAD duplicate"] subgraph CU["cu01 10.0.108.150"] CUCP["❌ CU-CP
Not running"]:::err CUUP["❌ CU-UP
Not running"]:::err end subgraph DU["du01"] DUPOD["❌ DU
Not running"]:::err end end subgraph RADIO["Radio"] RU0["RU 0
No eCPRI"]:::err RU1["RU 1
No eCPRI"]:::err end CORE -. "N2 missing" .-> CUCP CORE -. "N3 missing" .-> CUUP NMS -. "O1 :32200 NoComms" .-> CUCP NMS -. "O1 :32300 NoComms" .-> CUUP NMS -. "O1 :32104 NoComms" .-> DUPOD CUCP -. "F1-C missing" .-> DUPOD CUUP -. "F1-U missing" .-> DUPOD DUPOD -. "eCPRI missing" .-> RU0 DUPOD -. "eCPRI missing" .-> RU1 %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
10.0.108.170
⚠ No indoor N2
⚠ 10.0.109.0/24 missing
⚠ 172.30 not persisted"]:::warn NMS["ACP NMS
NoComms ❌"]:::crit end subgraph K8S["Indoor K8s — master01 ⚠ Images not imported ⚠ NAD duplicate"] subgraph CU["cu01 10.0.108.150"] CUCP["❌ CU-CP
Not running"]:::err CUUP["❌ CU-UP
Not running"]:::err end subgraph DU["du01"] DUPOD["❌ DU
Not running"]:::err end end subgraph RADIO["Radio"] RU0["RU 0
No eCPRI"]:::err RU1["RU 1
No eCPRI"]:::err end CORE -. "N2 missing" .-> CUCP CORE -. "N3 missing" .-> CUUP NMS -. "O1 :32200 NoComms" .-> CUCP NMS -. "O1 :32300 NoComms" .-> CUUP NMS -. "O1 :32104 NoComms" .-> DUPOD CUCP -. "F1-C missing" .-> DUPOD CUUP -. "F1-U missing" .-> DUPOD DUPOD -. "eCPRI missing" .-> RU0 DUPOD -. "eCPRI missing" .-> RU1 %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
Healthy state
graph LR
subgraph CM["Control & Management"]
CORE["campus-core01
10.0.108.170
✅ N2 ESTAB
✅ N3 active
✅ Routes persisted"]:::ok NMS["ACP NMS
Comms UP ✅"]:::ok FALCON["Falcon Switch
10.0.108.129"] end subgraph K8S["Indoor K8s — master01"] subgraph CU["cu01 10.0.108.150"] CUCP["✅ CU-CP
Running"]:::ok CUUP["✅ CU-UP
Running"]:::ok end subgraph DU["du01 E810-C DPDK"] DUPOD["✅ DU
Running"]:::ok end end subgraph RADIO["Radio"] RU0["RU 0
eCPRI ✅"]:::ok RU1["RU 1
eCPRI ✅"]:::ok CELL["Indoor NR Cell
PLMN 99970 PCI 1
Cell ID 321 TAC 1"]:::ok end CORE -- "N2 SCTP 38412" --> CUCP CORE -- "N3 GTP-U 2152" --> CUUP NMS -- "O1 :32200" --> CUCP NMS -- "O1 :32300" --> CUUP NMS -- "O1 :32104" --> DUPOD CUUP -- "E1 SCTP 38462" --> CUCP CUCP -- "F1-C SCTP 38472" --> DUPOD CUUP -- "F1-U UDP 2152" --> DUPOD FALCON -- "xHaul" --> DUPOD DUPOD -- "eCPRI RU0" --> RU0 DUPOD -- "eCPRI RU1" --> RU1 RU0 -- "radio" --> CELL RU1 -- "radio" --> CELL %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
10.0.108.170
✅ N2 ESTAB
✅ N3 active
✅ Routes persisted"]:::ok NMS["ACP NMS
Comms UP ✅"]:::ok FALCON["Falcon Switch
10.0.108.129"] end subgraph K8S["Indoor K8s — master01"] subgraph CU["cu01 10.0.108.150"] CUCP["✅ CU-CP
Running"]:::ok CUUP["✅ CU-UP
Running"]:::ok end subgraph DU["du01 E810-C DPDK"] DUPOD["✅ DU
Running"]:::ok end end subgraph RADIO["Radio"] RU0["RU 0
eCPRI ✅"]:::ok RU1["RU 1
eCPRI ✅"]:::ok CELL["Indoor NR Cell
PLMN 99970 PCI 1
Cell ID 321 TAC 1"]:::ok end CORE -- "N2 SCTP 38412" --> CUCP CORE -- "N3 GTP-U 2152" --> CUUP NMS -- "O1 :32200" --> CUCP NMS -- "O1 :32300" --> CUUP NMS -- "O1 :32104" --> DUPOD CUUP -- "E1 SCTP 38462" --> CUCP CUCP -- "F1-C SCTP 38472" --> DUPOD CUUP -- "F1-U UDP 2152" --> DUPOD FALCON -- "xHaul" --> DUPOD DUPOD -- "eCPRI RU0" --> RU0 DUPOD -- "eCPRI RU1" --> RU1 RU0 -- "radio" --> CELL RU1 -- "radio" --> CELL %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
Decision / branch flow
flowchart TD
START["helm install cuup"] --> SCHED["Pod scheduled on cu01"]
subgraph PB["Path B — Multus fails to attach"]
B1["Pod created
Multus tries to attach ens7
via host-device NAD"] B2["Duplicate NAD rendering
or host-device attachment fails"] B3["Pod status: Error / CrashLoopBackOff
Starts, then immediately terminates"]:::err B1 --> B2 --> B3 end subgraph PA["Path A — Image not loaded"] A1["imagePullPolicy: Never
Image not in containerd"] A2["Pod status: ErrImageNeverPull
Appears briefly, never starts"]:::err A1 --> A2 end SCHED --> B1 SCHED --> A1 %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
Multus tries to attach ens7
via host-device NAD"] B2["Duplicate NAD rendering
or host-device attachment fails"] B3["Pod status: Error / CrashLoopBackOff
Starts, then immediately terminates"]:::err B1 --> B2 --> B3 end subgraph PA["Path A — Image not loaded"] A1["imagePullPolicy: Never
Image not in containerd"] A2["Pod status: ErrImageNeverPull
Appears briefly, never starts"]:::err A1 --> A2 end SCHED --> B1 SCHED --> A1 %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
Interface / reachability map
graph LR
CORE["campus-core01"]
subgraph DU["du01 interfaces"]
DU_A["ens1f1 10.0.107.160
✅ reachable"]:::ok DU_B["E810-C DPDK
no IP — no ICMP"]:::off DU_C["eno12429 10.0.109.2
❌ no route from Core"]:::err end subgraph CU["cu01 interfaces"] CU_A["ens3 10.0.107.150
✅ reachable"]:::ok CU_B["ens7 10.0.108.150
✅ reachable"]:::ok CU_C["172.30.0.0/16
❌ goes via ens3 wrong GW
should be ens7 → Falcon"]:::warn end CORE -- "✅ reachable via ens3" --> DU_A CORE -. "❌ no route
10.0.109.0/24 missing" .-> DU_C CORE -- "✅ reachable via ens3" --> CU_A CORE -- "✅ reachable via ens7" --> CU_B CU_B -. "❌ 172.30 traffic
wrong gateway" .-> CU_C %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
✅ reachable"]:::ok DU_B["E810-C DPDK
no IP — no ICMP"]:::off DU_C["eno12429 10.0.109.2
❌ no route from Core"]:::err end subgraph CU["cu01 interfaces"] CU_A["ens3 10.0.107.150
✅ reachable"]:::ok CU_B["ens7 10.0.108.150
✅ reachable"]:::ok CU_C["172.30.0.0/16
❌ goes via ens3 wrong GW
should be ens7 → Falcon"]:::warn end CORE -- "✅ reachable via ens3" --> DU_A CORE -. "❌ no route
10.0.109.0/24 missing" .-> DU_C CORE -- "✅ reachable via ens3" --> CU_A CORE -- "✅ reachable via ens7" --> CU_B CU_B -. "❌ 172.30 traffic
wrong gateway" .-> CU_C %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
Pod inventory per node
graph TB
subgraph DU["du01 — apptype=du-01"]
direction LR
D1["kube-proxy"]
D2["kube-flannel"]
D3["DU pod MISSING"]:::err
end
subgraph CU["cu01 — apptype=cu-01"]
direction LR
C1["kube-proxy"]
C2["kube-flannel"]
C3["CU-CP pod MISSING"]:::err
C4["CU-UP pod MISSING"]:::err
end
subgraph M["master01"]
direction LR
M1["etcd"]
M2["kube-apiserver"]
M3["kube-scheduler"]
M4["coredns"]
M5["kube-flannel"]
M6["kube-multus"]
end
%% -- dashboard status styles --
classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16;
classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006;
classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724;
classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A;
classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827;
classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
Troubleshooting decision tree
flowchart LR
START["Pod not Running
kubectl get pods -A"] --> Q{"Status?"} Q -- "Pending" --> PEND["node selector mismatch
or resource shortage
→ check kubectl describe pod"]:::warn Q -- "ErrImageNeverPull" --> IMG["Image missing in containerd
→ ctr -n k8s.io images import
on the correct node"]:::warn Q -- "CrashLoopBackOff" --> DESC{"kubectl describe pod
Events section"} DESC -- "Multus event" --> MULTUS["Multus error in Events
→ NAD conflict
or host-device attach fail
→ Step 4 fix"]:::err DESC -- "no Multus event" --> LOGS{"kubectl logs --previous"} LOGS --> APP["App error in logs
→ wrong 192.168 IP
or DPDK device missing
→ Step 2 or DPDK check"]:::err %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;
kubectl get pods -A"] --> Q{"Status?"} Q -- "Pending" --> PEND["node selector mismatch
or resource shortage
→ check kubectl describe pod"]:::warn Q -- "ErrImageNeverPull" --> IMG["Image missing in containerd
→ ctr -n k8s.io images import
on the correct node"]:::warn Q -- "CrashLoopBackOff" --> DESC{"kubectl describe pod
Events section"} DESC -- "Multus event" --> MULTUS["Multus error in Events
→ NAD conflict
or host-device attach fail
→ Step 4 fix"]:::err DESC -- "no Multus event" --> LOGS{"kubectl logs --previous"} LOGS --> APP["App error in logs
→ wrong 192.168 IP
or DPDK device missing
→ Step 2 or DPDK check"]:::err %% -- dashboard status styles -- classDef ok fill:#DCFCE7,stroke:#16A34A,stroke-width:1.5px,color:#052E16; classDef warn fill:#FEF9C3,stroke:#CA8A04,stroke-width:1.5px,color:#422006; classDef err fill:#FCE7EF,stroke:#DB2777,stroke-width:1.5px,color:#500724; classDef crit fill:#FEE2E2,stroke:#DC2626,stroke-width:1.5px,color:#450A0A; classDef off fill:#F1F5F9,stroke:#94A3B8,stroke-width:1.5px,color:#111827; classDef info fill:#EFF6FF,stroke:#3B82F6,stroke-width:1.5px,color:#0C1E3E;