digraph storage_flow {
rankdir=LR;
graph [
fontname="Helvetica Neue",
fontsize=16,
pad=1.2,
nodesep=0.45,
ranksep=1.6,
bgcolor="#f0f4f8",
label="ExpertFab – Speicherfluss & HA-Analyse",
labelloc=t,
labeljust=c,
splines=polyline,
compound=true,
newrank=true,
];
node [fontname="Helvetica Neue", fontsize=11, shape=box, style="filled,rounded", margin="0.15,0.10"];
edge [fontname="Helvetica Neue", fontsize=10, arrowsize=0.8];
/* ─────────────────────────────────────────────
SCHICHT 1 – APPLIKATIONEN
───────────────────────────────────────────── */
subgraph cluster_apps {
label=<① APPLIKATIONEN
(K3s Pods)>;
style=filled; bgcolor="#e3eef7"; color="#2980b9"; penwidth=2; fontcolor="#1a5276";
subgraph cluster_erpnext {
label="ns: erpnext"; style=filled; bgcolor="#d6eaf8"; color="#5dade2";
gui [label=<Gunicorn
+ Workers>, shape=hexagon, fillcolor="#aed6f1", color="#2980b9"];
nginx [label=<Nginx
(Frontend)>, shape=hexagon, fillcolor="#aed6f1", color="#2980b9"];
mdb [label=<MariaDB 10.6
StatefulSet>, shape=cylinder, fillcolor="#fdebd0", color="#d35400"];
}
subgraph cluster_paperless {
label="ns: paperless"; style=filled; bgcolor="#d6eaf8"; color="#5dade2";
ppl [label=<Paperless-NGX>, shape=hexagon, fillcolor="#aed6f1", color="#2980b9"];
pgp [label=<PostgreSQL>, shape=cylinder, fillcolor="#fdebd0", color="#d35400"];
}
subgraph cluster_zitadel {
label="ns: zitadel"; style=filled; bgcolor="#d6eaf8"; color="#5dade2";
pgz [label=<PostgreSQL
(Zitadel)>, shape=cylinder, fillcolor="#fdebd0", color="#d35400"];
}
subgraph cluster_rmq {
label="ns: rabbitmq"; style=filled; bgcolor="#d6eaf8"; color="#5dade2";
rmq [label=<RabbitMQ>, shape=cylinder, fillcolor="#fdebd0", color="#d35400"];
}
}
/* ─────────────────────────────────────────────
SCHICHT 2 – PVCs
───────────────────────────────────────────── */
subgraph cluster_pvcs {
label=<② KUBERNETES PVCs>;
style=filled; bgcolor="#eaf5ea"; color="#27ae60"; penwidth=2; fontcolor="#1e8449";
subgraph cluster_pvc_erpnext {
label=<longhorn-erpnext [Retain ✅]>;
style=filled; bgcolor="#d5f5e3"; color="#52be80";
pvc_mdb [label=<mariadb-sts-0
3 Gi RWO>, fillcolor="#d5f5e3", color="#1e8449"];
pvc_sites [label=<erpnext-sites
3 Gi RWX ⚠>, fillcolor="#fef9e7", color="#e67e22"];
pvc_logs [label=<erpnext-logs
1 Gi RWX ⚠>, fillcolor="#fef9e7", color="#e67e22"];
}
subgraph cluster_pvc_paperless {
label=<longhorn-paperless [Retain ✅]>;
style=filled; bgcolor="#d5f5e3"; color="#52be80";
pvc_ppl [label=<media
10 Gi RWO>, fillcolor="#d5f5e3", color="#1e8449"];
pvc_pgp [label=<postgres
5 Gi RWO>, fillcolor="#d5f5e3", color="#1e8449"];
}
subgraph cluster_pvc_del {
label=<longhorn [Delete ⚠]>;
style=filled; bgcolor="#fef9e7"; color="#e67e22";
pvc_pgz [label=<zitadel-pg
10 Gi RWO>, fillcolor="#fef9e7", color="#d35400"];
pvc_rmq [label=<rabbitmq
5 Gi RWO>, fillcolor="#fef9e7", color="#d35400"];
}
}
/* ─────────────────────────────────────────────
SCHICHT 3 – LONGHORN ENGINE
───────────────────────────────────────────── */
subgraph cluster_longhorn {
label=<③ LONGHORN STORAGE ENGINE
(driver.longhorn.io)>;
style=filled; bgcolor="#f4ecf7"; color="#8e44ad"; penwidth=2; fontcolor="#6c3483";
subgraph cluster_sm {
label=<⚠ RWX Share-Manager
läuft auf: efsckubnode02 (Proxmox n01)
→ SPOF: fällt n01, fallen RWX-Volumes (ERPNext)>;
style=filled; bgcolor="#fef9e7"; color="#e67e22"; penwidth=2;
sm_sites [label=<share-manager
erpnext-sites>, shape=ellipse, fillcolor="#fdebd0", color="#e67e22"];
sm_logs [label=<share-manager
erpnext-logs>, shape=ellipse, fillcolor="#fdebd0", color="#e67e22"];
}
subgraph cluster_replicas {
label=<✅ Block-Replikation: 2 Replicas je Volume
Daten auf verschiedenen K3s-Worker-Nodes>;
style=filled; bgcolor="#eafaf1"; color="#27ae60"; penwidth=2;
rep_a [label=<Replica A
auf: efsckubnode1
(Proxmox n02)>, shape=cylinder, fillcolor="#d5f5e3", color="#1e8449"];
rep_b [label=<Replica B
auf: efsckubnode02
(Proxmox n01)>, shape=cylinder, fillcolor="#d5f5e3", color="#1e8449"];
}
subgraph cluster_csi {
label=<⚠ CSI Controller-Pods
Nur auf efsckubnode1 (n02)
→ fällt n02: keine neuen Volumes>;
style=filled; bgcolor="#fef9e7"; color="#e67e22";
csi [label=<csi-attacher (3×)
csi-provisioner (3×)
csi-resizer (3×)>, fillcolor="#fdebd0", color="#e67e22"];
}
}
/* ─────────────────────────────────────────────
SCHICHT 4 – K3s NODES (VMs)
───────────────────────────────────────────── */
subgraph cluster_k3s {
label=<④ K3s CLUSTER>;
style=filled; bgcolor="#fdf2f8"; color="#c0392b"; penwidth=2; fontcolor="#922b21";
subgraph cluster_ctrl {
label=<🔴 Control Plane – SINGLE POINT OF FAILURE
Nur 1 Node, VM auf Proxmox n01
→ n01 fällt = kein Cluster-Management, kein Pod-Rescheduling>;
style=filled; bgcolor="#fadbd8"; color="#e74c3c"; penwidth=3;
kubadm [label=<efsckubadm
10.42.71.50
VM: efsckubctl (n01)>, shape=diamond, fillcolor="#f1948a", color="#c0392b"];
}
subgraph cluster_workers {
label=<✅ Worker Nodes auf verschiedenen Proxmox Hosts>;
style=filled; bgcolor="#eafaf1"; color="#27ae60";
node1 [label=<efsckubnode1
10.42.71.51
VM auf: Proxmox n02
→ Replica A + CSI Controllers>, fillcolor="#d5f5e3", color="#1e8449"];
node2 [label=<efsckubnode02
10.42.71.52
VM auf: Proxmox n01
→ Replica B + share-manager>, fillcolor="#fdebd0", color="#e67e22"];
}
}
/* ─────────────────────────────────────────────
SCHICHT 5 – PROXMOX HOSTS
───────────────────────────────────────────── */
subgraph cluster_proxmox {
label=<⑤ PROXMOX CLUSTER efproxcl02
⚠ Nur 2 Nodes – kein 3-Node-Quorum / kein automatisches Fencing>;
style=filled; bgcolor="#fdfefe"; color="#7f8c8d"; penwidth=2;
subgraph cluster_pn01 {
label=<efproxcl02n01 10.42.70.1
🔴 KRITISCH: Control-Plane + efsckubnode02 + share-manager
Ausfall → ERPNext vollständig down (kein Rescheduling möglich)>;
style=filled; bgcolor="#fadbd8"; color="#e74c3c"; penwidth=2;
pn01 [label=<Proxmox Host 1
64 vCPU / 128 GB RAM>, shape=box, fillcolor="#f1948a", color="#c0392b"];
disk_n01 [label=<Lokaler Speicher
Replica B
erpnext / paperless
zitadel / rabbitmq>, shape=cylinder, fillcolor="#fadbd8", color="#e74c3c"];
}
subgraph cluster_pn02 {
label=<efproxcl02n02 10.42.70.2
🟡 Ausfall → degradiert: Daten intakt (Replica B ok)
Keine neuen Volumes (CSI weg), ERPNext-Pods reschedule auf node02>;
style=filled; bgcolor="#fef9e7"; color="#e67e22"; penwidth=2;
pn02 [label=<Proxmox Host 2
64 vCPU / 128 GB RAM>, shape=box, fillcolor="#fdebd0", color="#d35400"];
disk_n02 [label=<Lokaler Speicher
Replica A
erpnext / paperless
zitadel / rabbitmq>, shape=cylinder, fillcolor="#fef9e7", color="#e67e22"];
}
}
/* ─────────────────────────────────────────────
EDGES
───────────────────────────────────────────── */
/* Apps → PVCs */
mdb -> pvc_mdb [color="#2980b9", penwidth=2];
gui -> pvc_sites [color="#2980b9", penwidth=2];
nginx -> pvc_logs [color="#2980b9", penwidth=2];
ppl -> pvc_ppl [color="#2980b9", penwidth=2];
pgp -> pvc_pgp [color="#2980b9", penwidth=2];
pgz -> pvc_pgz [color="#2980b9", penwidth=2];
rmq -> pvc_rmq [color="#2980b9", penwidth=2];
/* RWX PVCs → share-manager */
pvc_sites -> sm_sites [color="#e67e22", penwidth=2, style=dashed, label="NFS"];
pvc_logs -> sm_logs [color="#e67e22", penwidth=2, style=dashed, label="NFS"];
/* share-manager → Replica B */
sm_sites -> rep_b [color="#e67e22", penwidth=2];
sm_logs -> rep_b [color="#e67e22", penwidth=2];
/* RWO PVCs → beide Replicas (Longhorn CSI) */
pvc_mdb -> rep_a [color="#27ae60", penwidth=2, label="Longhorn CSI"];
pvc_mdb -> rep_b [color="#27ae60", penwidth=2];
pvc_ppl -> rep_a [color="#27ae60", penwidth=2];
pvc_ppl -> rep_b [color="#27ae60", penwidth=2];
pvc_pgp -> rep_a [color="#27ae60", penwidth=2];
pvc_pgp -> rep_b [color="#27ae60", penwidth=2];
pvc_pgz -> rep_a [color="#27ae60", penwidth=2];
pvc_pgz -> rep_b [color="#27ae60", penwidth=2];
pvc_rmq -> rep_a [color="#27ae60", penwidth=2];
pvc_rmq -> rep_b [color="#27ae60", penwidth=2];
/* Sync zwischen Replicas */
rep_a -> rep_b [color="#27ae60", penwidth=2.5, style=bold, label="sync\n(synchron)"];
/* CSI → Volumes */
csi -> rep_a [color="#95a5a6", style=dotted, label="provision"];
/* Replicas → K3s Worker Nodes */
rep_a -> node1 [color="#27ae60", penwidth=2, label="physisch auf"];
rep_b -> node2 [color="#27ae60", penwidth=2, label="physisch auf"];
/* Control-Plane → Workers */
kubadm -> node1 [color="#7f8c8d", style=dashed, label="API"];
kubadm -> node2 [color="#7f8c8d", style=dashed];
/* K3s Nodes → Proxmox Hosts */
kubadm -> pn01 [color="#e74c3c", penwidth=3, label="VM auf n01"];
node2 -> pn01 [color="#e67e22", penwidth=2.5, label="VM auf n01"];
node1 -> pn02 [color="#27ae60", penwidth=2, label="VM auf n02"];
/* Proxmox → Disk */
pn01 -> disk_n01 [color="#95a5a6"];
pn02 -> disk_n02 [color="#95a5a6"];
/* Backup */
disk_n01 -> disk_n02 [color="#95a5a6", style=dashed,
label="daily-backup CronJob\n(Longhorn, auf efsckubnode02)"];
/* ─────────────────────────────────────────────
RANK CONSTRAINTS – Spalten erzwingen (newrank=true erlaubt cross-cluster)
───────────────────────────────────────────── */
subgraph rank_apps { rank=same; gui; nginx; mdb; ppl; pgp; pgz; rmq; }
subgraph rank_pvcs { rank=same; pvc_mdb; pvc_sites; pvc_logs; pvc_ppl; pvc_pgp; pvc_pgz; pvc_rmq; }
subgraph rank_lh { rank=same; sm_sites; sm_logs; rep_a; rep_b; csi; }
subgraph rank_nodes { rank=same; kubadm; node1; node2; }
subgraph rank_prox { rank=same; pn01; disk_n01; pn02; disk_n02; }
}