docs: migrate all documentation to Discourse wiki topics

All knowledge docs (architecture, runbooks, references, audits, policies)
have been migrated to community.turnsys.com as wiki topics in the VP
TechOps category. Discourse is now the canonical source of truth for
documentation; git edit history no longer serves as the doc changelog.

37 .md files converted to short pointers linking to their Discourse
topics. AGENTS.md updated with new documentation workflow policy.
Code (scripts, configs, playbooks) remains authoritative in git.
This commit is contained in:
2026-08-06 14:08:34 -05:00
parent d6988bb35f
commit 88faf35ec3
37 changed files with 378 additions and 8239 deletions
+10 -452
View File
@@ -1,452 +1,10 @@
# Fleet Audit — 2026-07-29 (consolidated, storage-corrected)
> **The single authoritative audit.** Supersedes all prior audits and the
> placement data in [`PROJECT.md`](PROJECT.md) §4-§8 where they conflict.
> Capacity targets are codified in [`CAPACITY-GOALS.md`](CAPACITY-GOALS.md).
**Audit time:** 2026-07-29, fresh data from all 7 hosts (~05:09 CDT hardware
dumps + ~05:40 CDT capacity probe). Storage configs read directly from
`/etc/pve/storage.cfg`, `/etc/exports`, `/etc/fstab` on every host.
**Hosts online:** tsys1, tsys3, tsys4, tsys5, tsys6, tsys7, tsys9
**Hosts offline:** tsys2 (Win10, pending rebuild), tsys8 (retired / permanently offline)
---
## 1. Executive summary
| Goal | Status | Detail |
|------|--------|--------|
| **Memory ≤ 80% actual steady-state** | **PASS (all 7 hosts)** | Highest is tsys1 at 73%. Fleet is healthy. |
| **CPU ~50% at idle** | **MISS (all 7 hosts)** | Every host idles at **0-5% busy**. Under-utilized, not over-loaded. |
| Finding | Severity | § |
|---------|----------|---|
| **D2 carries 17 VMs** — the worst IOPS hotspot in the fleet | High | 5 |
| **S1 is NOT empty — it carries 16 sectestbed VMs via `local-nonprod`** (previous audit was wrong) | High | 4, 5 |
| ~~tsys6 S1 NFS export typo~~ (`S21`) — **FIXED by operator 2026-07-29**; all 8 stores active | Resolved | 6 |
| ~~tsys9 missing S1~~ in storage.cfg — **FIXED by operator 2026-07-29**; S1 active | Resolved | 6 |
| **`local-nonprod` on tsys5 = the S1 physical disk** (dir storage, not a separate disk) | Topology | 4 |
| **tsys5 is single-CPU** (CPU2 socket unpopulated; prior "dual E5620" was wrong) | Medium | 9 |
| **cnode4 (601) stopped, cnode5 (706) deleted** (user action this session) | Resolved | 10 |
---
## 2. Host capacity (live, 2026-07-29 ~05:40 CDT)
| Host | CPU (era) | Threads | RAM | Running VMs | Alloc RAM | Alloc% | **Actual%** | Swap used | CPU busy | Load |
|------|-----------|---------|-----|-------------|-----------|--------|------------|-----------|----------|------|
| tsys1 | i7-4770 Haswell (2013) | 8 | 31 GB | 11 | 36 GB | 115% | **73%** | 0 | 4% | 1.1 |
| tsys3 | Xeon E3-1535M v5 Skylake (2015) | 8 | 31 GB | 1 | 28 GB | 90% | **10%** | 0 | 0% | 0.3 |
| tsys4 | Xeon E3-1246 v3 Haswell (2013) | 8 | 16 GB | 1 | 2 GB | 13% | **14%** | 1.1 GB | 0% | 1.3 |
| tsys5 | Xeon E5620 Westmere (2010) **single CPU** | 8 | 94 GB | 17 | 126 GB | 134% | **37%** | 0 | 5% | 4.0 |
| tsys6 | 2× Xeon E5530 Nehalem (2009) | 16 | 126 GB | 2 | 44 GB | 35% | **4%** | 0 | 0% | 0.6 |
| tsys7 | 2× Xeon E5-2630 v2 Ivy Bridge (2013) | 24 | 189 GB | 5 | 52 GB | 28% | **7%** | 0 | 1% | 0.9 |
| tsys9 | i5-10500 Comet Lake (2020) | 12 | 23 GB | 6 | 30 GB | 129% | **62%** | 0 | 1% | 0.3 |
**Changes since first collection (~05:09):** cnode4 (601) stopped on tsys6,
cnode5 (706) deleted from tsys7. No host migrations performed yet.
---
## 3. Storage topology (CORRECTED — read from live configs)
> **`storage.cfg` is per-host, not cluster-wide.** Each Proxmox node defines its
> own storage entries. The same physical disk can appear under different storage
> IDs on different hosts. This was the source of the prior audit's errors.
### 3.1 Physical disk → Proxmox storage ID mapping
| Physical disk | Server | NFS export | NFS ID (clients) | Local ID (on tsys5) | Type |
|---------------|--------|------------|-----------------|---------------------|------|
| WDC Red 3TB | tsys4 | `/mnt/tsys4/D2` | `D2` | — | HDD |
| SK hynix SC300 512GB | tsys4 | `/mnt/tsys4/D3` | `D3` | — | SSD (USB) |
| Hitachi 2TB | tsys4 | `/mnt/tsys4/D5` | `D5` | — | HDD |
| *(disk1)* | tsys4 | `/mnt/tsys4/D1` | *(not in most storage.cfg)* | — | unknown |
| *(disk7)* | tsys4 | `/mnt/tsys4/D7` | *(not in most storage.cfg)* | — | unknown |
| **Seagate 916GB** | **tsys5** | **`/mnt/pfv-tsys5/S1`** | **`S1`** | **`local-nonprod`** | **HDD** |
| Seagate 916GB | tsys5 | `/mnt/pfv-tsys5/S2` | `S2` | `S2` (NFS client) | HDD |
| Seagate 916GB | tsys5 | `/mnt/pfv-tsys5/S3` | `S3` | `S3` (NFS client) | HDD |
| Toshiba 458GB | tsys5 | `/mnt/pfv-tsys5/S4` | `S4` | `S4` (NFS client) | HDD |
| **Samsung 860 PRO 234GB** | **tsys5** | **`/mnt/pfv-tsys5/ssd`** | **`T5-SSD`** | **`SSD`** (dir, local-only) | **SSD** |
### 3.2 Critical correction: `local-nonprod` = S1
On tsys5, the storage entry is:
```
dir: local-nonprod
path /mnt/pfv-tsys5/S1
```
**`local-nonprod` is NOT a separate disk.** It is the **S1 Seagate 916GB HDD**,
accessed locally as a directory storage instead of via NFS. The 16 sectestbed
and preprod VMs "on local-nonprod" are physically on S1. They appear locked to
tsys5 because Proxmox treats `local-nonprod` (dir type) as a different storage
than `S1` (NFS type), even though they point to the same directory.
**Implication:** S1 has **16 VMs of IOPS load**, not 0. The prior audit's plan
to move production VMs onto S1 would have stacked them on top of 16 sandboxes.
### 3.3 Disk speed tiers (HDD only — SSD/NVMe deferred to Friday)
| Tier | Spindles | Speed | Current use |
|------|----------|-------|-------------|
| NFS-HDD (tsys4) | D2, D5 | 80-120 MB/s | Production VMs |
| NFS-HDD (tsys5) | S1, S2, S3, S4 | 80-120 MB/s | Production + sectestbed VMs |
| Local HDD (tsys5) | local-nonprod (=S1) | 80-120 MB/s | Sectestbed suite (locked to tsys5) |
| SSD (tsys4 USB) | D3 | unreliable (USB 2.0) | Empty — do not use until Friday |
| SSD (tsys5 local) | SSD dir (=Samsung 860 PRO) | 200-400 MB/s | ultix-streaming only |
---
## 4. Per-spindle IOPS load (CORRECTED)
| Spindle | Server | NFS-visible VMs | Local-only VMs | **Total physical load** |
|---------|--------|----------------|----------------|------------------------|
| **D2** (3TB) | tsys4 | **17** | 0 | **17 — worst hotspot** |
| D5 (2TB) | tsys4 | 3 | 0 | 3 |
| **S1** (916GB) | tsys5 | 0 | **16** (via local-nonprod) | **16 — second worst** |
| S2 (916GB) | tsys5 | 4 | 0 | 4 |
| S3 (916GB) | tsys5 | 3 | 0 | 3 |
| S4 (458GB) | tsys5 | 1 | 0 | 1 — most spare capacity |
**D2 and S1 are both overloaded. S2/S3/S4 and D5 have room.**
The 16 sectestbed VMs on S1 are idle sandboxes — they don't generate much real
IOPS, but they're all on one spindle. If any of them wake up simultaneously (CI
pipeline, test suite), S1 becomes a bottleneck. **Do not add production VMs to
S1.** Target S2, S3, S4, and D5 for IOPS spreading.
---
## 5. Storage bugs and config gaps found
### 5.1 BUG: tsys6 S1 export path typo (S21) — RESOLVED ✓
**Fixed by operator 2026-07-29.** The export path was corrected from `S21` to
`S1`. Verified: `pvesm status` on tsys6 shows all 8 NFS stores active, including
S1 (96 GB, 10.3% used by the sectestbed VMs visible via NFS).
### 5.2 GAP: tsys9 missing S1 in storage.cfg — RESOLVED ✓
**Fixed by operator 2026-07-29.** S1 entry added to tsys9's storage.cfg.
Verified: all 8 NFS stores active on tsys9, S1 listing identical to tsys6.
### 5.3 ORPHANED: D1 and D7 exports on tsys4
tsys4 exports D1 and D7 via NFS, but neither appears in most hosts' storage.cfg.
- **D1** holds KNELTemplate (4000) and RestoreTemplate (5500) — stopped
templates only, no running VMs.
- **D7** holds a disk for DellOpenManageEnterprise (500) — stopped.
These aren't causing problems but are underdocumented. Not actionable now.
---
## 6. Current VM inventory (host + disk, post-user-changes)
> cnode4 (601) = stopped. cnode5 (706) = deleted. All other VMs unchanged from
> start of session. `Disk` = NFS export or local storage holding the primary
> qcow2.
### tsys1 — Infrastructure (11 running)
| VMID | Name | vCPU | RAM | Disk | Server |
|------|------|------|-----|------|--------|
| 100 | pfv-bms (HomeAssistant) | 2 | 4 GB | D2 | tsys4 |
| 101 | tsys-ca | 2 | 2 GB | D2 | tsys4 |
| 102 | pfv-k8s-wnode-tsys1 | 4 | 4 GB | S3 | tsys5 |
| 103 | **pfv-netinfra-01** | 2 | 2 GB | S2 | tsys5 |
| 104 | tsys-librenms | 2 | 2 GB | D2 | tsys4 |
| 105 | tsys-proxmox-datacenter | 2 | 2 GB | D2 | tsys4 |
| 106 | pfv-k8s-cnode3 | 2 | 4 GB | D5 | tsys4 |
| 108 | **tsys-ucs-01** | 4 | 8 GB | D2 | tsys4 |
| 109 | tailscale-router | 2 | 2 GB | D2 | tsys4 |
| 114 | kali-tsys | 2 | 2 GB | D2 | tsys4 |
| 117 | tsys-secure-workbench | 2 | 4 GB | D2 | tsys4 |
### tsys3 — Compute (1 running)
| VMID | Name | vCPU | RAM | Disk | Server |
|------|------|------|-----|------|--------|
| 313 | pfv-k8s-wnode-tsys3 | 8 | 28 GB | D5 | tsys4 |
### tsys4 — Storage (1 running)
| VMID | Name | vCPU | RAM | Disk | Server |
|------|------|------|-----|------|--------|
| 400 | pfv-proxmox-backup-server | 2 | 2 GB | local-lvm | LOCAL |
### tsys5 — Storage + sandboxes (17 running)
| VMID | Name | vCPU | RAM | Disk | Server | Migratable? |
|------|------|------|-----|------|--------|-------------|
| 509 | pfv-k8s-wnode-tsys5 | 8 | 32 GB | D2 | tsys4 | Yes (NFS) |
| 5111 | ultix-streaming | 4 | 9 GB | SSD (local dir) | LOCAL | No (local) |
| 5112 | ultix-offstage | 4 | 6 GB | local-lvm | LOCAL | No (local) |
| 5101 | sectestbed-siem | 4 | 10 GB | local-nonprod (=S1) | LOCAL* | No (dir storage) |
| 53100 | tsys-preprod-awx | 4 | 9 GB | local-nonprod (=S1) | LOCAL* | No |
| 53101 | tsys-preprod-siem | 4 | 12 GB | local-nonprod (=S1) | LOCAL* | No |
| 53102 | tsys-preprod-rancherplatform | 4 | 8 GB | local-nonprod (=S1) | LOCAL* | No |
| ×10 | sectestbed suite | 4 ea | 4 GB ea | local-nonprod (=S1) | LOCAL* | No |
> *\*LOCAL = locked to tsys5. The local-nonprod VMs are on the S1 physical disk
> but accessed via dir storage, not NFS — Proxmox will not migrate them. To
> unlock, move disk from `local-nonprod` → `S1` (same physical disk, changes the
> storage ID to the NFS-shared one). Low priority — these are idle sandboxes.*
### tsys6 — RackRental-ready (2 running, 1 stopped)
| VMID | Name | vCPU | RAM | Disk | Server | Status |
|------|------|------|-----|------|--------|--------|
| 100 | pfv-k8s-wnode-tsys6 | 4 | 32 GB | S4 | tsys5 | running |
| 600 | tsys-awx | 4 | 12 GB | D2 | tsys4 | running |
| 601 | pfv-k8s-cnode4 | 4 | 4 GB | D2 | tsys4 | **STOPPED** |
### tsys7 — RackRental-ready (5 running)
| VMID | Name | vCPU | RAM | Disk | Server |
|------|------|------|-----|------|--------|
| 701 | pfv-k8s-wnode-tsys7 | 4 | 32 GB | S3 | tsys5 |
| 702 | hfnoc-uisp | 4 | 8 GB | D2 | tsys4 |
| 703 | rr-middleware | 2 | 2 GB | D2 | tsys4 |
| 704 | TCTC | 4 | 6 GB | D2 | tsys4 |
| 705 | pfv-k8s-cnode2 | 4 | 4 GB | D2 | tsys4 |
### tsys9 — Infra + control plane (6 running)
| VMID | Name | vCPU | RAM | Disk | Server |
|------|------|------|-----|------|--------|
| 901 | tsys-siem | 2 | 8 GB | D2 | tsys4 |
| 902 | **tsys-ucs-02** | 4 | 8 GB | S2 | tsys5 |
| 903 | kali-rd | 2 | 2 GB | D5 | tsys4 |
| 904 | **pfv-netinfra-02** | 2 | 4 GB | D2 | tsys4 |
| 905 | pfv-k8s-wnode-tsys9 | 4 | 4 GB | S2 | tsys5 |
| 906 | pfv-k8s-cnode1 | 2 | 4 GB | S3 | tsys5 |
### k3s control plane (ground truth via `kubectl`)
3 cnodes joined: cnode1 (906/tsys9), cnode2 (705/tsys7), cnode3 (106/tsys1).
All control-plane,etcd role. CPU 2%, mem ~1.1 GB each. **No wnodes joined yet.**
---
## 7. Workload placement model
| Workload family | Needs | Best hosts | Why |
|-----------------|-------|-----------|-----|
| **ETL / HPC / cross-compile** | High IPC + fast storage | **tsys9, tsys3, tsys2(in)** | Newest CPUs + local SSD/NVMe |
| **RackRental.net** | Massive RAM, CPU-light | **tsys7, tsys6** | 189/126 GB RAM; weak CPU fine for idle labs |
| **Infra + k8s control plane** | Always-on, low resource | **tsys1, tsys9** | Efficient enough; cnodes spread for etcd diversity |
---
## 8. Answers to operator's questions
### 8.1 "Should I make the k8s wnode VMs bigger on tsys1/9 for ETL/HPC?"
**tsys9 — YES.** Newest CPU (i5-10500, 12 threads) + local SSD. Currently 4c/4GB.
After moving tsys-siem (8 GB) to tsys6, grow to **6c/8-16 GB**.
**tsys1 — NO.** The i7-4770 is Haswell-2013 (2nd-oldest). tsys1 is the most
RAM-loaded host (73% actual, 115% alloc). It should shed VMs, not grow its wnode.
### 8.2 "Are tsys6/7 better for RackRental.net?"
**Yes.** RAM-bound, CPU-light labs fit 126/189 GB perfectly. They don't need
more RAM (4%/7% actual). Their bottleneck is disk (USB 2.0 local-lvm ≈ 30 MB/s)
— deferred to Friday + StorageClass work.
### 8.3 "How should I deploy the DDR3?"
Verify type first. tsys5/6/7 require **RDIMM ECC** (consumer UDIMM won't POST).
tsys1 is maxed (32 GB, caps at 8 GB/slot). tsys4 caps at 8 GB/slot (max 32 GB).
Most likely only useful for tsys4 16→32 GB. The real RAM lever is **free VM
migration**, not sticks. See [`CAPACITY-GOALS.md`](CAPACITY-GOALS.md) §5.
---
## 9. Hardware corrections
**tsys5 is single-CPU.** dmidecode: `CPU2: Status Unpopulated`. The T7500 has
one E5620 (4c/8t), not two. The 6 empty DIMM slots are on the CPU2 branch —
useless without a 2nd CPU. Seating a spare LGA771 Xeon would double CPU capacity
and activate the CPU2 DIMM branch.
**tsys4 is using ~1.1 GB of swap.** Only host with active swap. Minor, but
monitor after the planned RAM upgrade.
---
## 10. Target end-state inventory (RAM/CPU + HDD IOPS balanced)
> All disks stay on **HDD** (SSD/NVMe deferred to Friday). Goals: (a) relieve
> tsys1/9 RAM over-allocation, (b) relieve D2 (17→5 VMs), (c) spread to S2/S3/S4
> (currently 4/3/1), (d) **avoid S1** (already has 16 local VMs), (e) keep HA
> pairs split across storage servers.
### tsys1 — Infrastructure (6 running, ~24 GB alloc → 77%)
| VMID | Name | vCPU | RAM | Disk | Server | Change |
|------|------|------|-----|------|--------|--------|
| 100 | pfv-bms | 2 | 4 GB | D2 | tsys4 | none |
| 101 | tsys-ca | 2 | 2 GB | D2 | tsys4 | none |
| 102 | pfv-k8s-wnode-tsys1 | 4 | 4 GB | S3 | tsys5 | none |
| 103 | **pfv-netinfra-01** | 2 | 2 GB | S2 | tsys5 | none |
| 106 | pfv-k8s-cnode3 | 2 | 4 GB | D5 | tsys4 | none |
| 108 | **tsys-ucs-01** | 4 | 8 GB | D2 | tsys4 | none |
### tsys3 — Compute (1 running)
| VMID | Name | vCPU | RAM | Disk | Server | Change |
|------|------|------|-----|------|--------|--------|
| 313 | pfv-k8s-wnode-tsys3 | 8 | 28 GB | D5 | tsys4 | none |
### tsys4 — Storage (1 running)
| VMID | Name | vCPU | RAM | Disk | Change |
|------|------|------|-----|------|--------|
| 400 | pfv-proxmox-backup-server | 2 | 2 GB | local-lvm | none |
### tsys5 — Storage + sandboxes (17 running, unchanged)
All 17 stay. wnode-tsys5 (509) disk moves D2→S4. The 16 local-nonprod VMs stay
locked (idle sandboxes, low priority).
### tsys6 — RackRental-ready (3 running, ~52 GB alloc → 41%)
| VMID | Name | vCPU | RAM | Disk | Server | Change |
|------|------|------|-----|------|--------|--------|
| 100 | pfv-k8s-wnode-tsys6 | 4 | 32 GB | S4 | tsys5 | none |
| 600 | tsys-awx | 4 | 12 GB | **D5** | tsys4 | **disk D2→D5** |
| 901 | tsys-siem | 2 | 8 GB | **S2** | tsys5 | **host tsys9→tsys6, disk D2→S2** |
| ~~601~~ | ~~cnode4~~ | — | — | — | — | **DELETE (stopped, stale)** |
### tsys7 — RackRental-ready (10 running, ~64 GB alloc → 34%)
| VMID | Name | vCPU | RAM | Disk | Server | Change |
|------|------|------|-----|------|--------|--------|
| 701 | pfv-k8s-wnode-tsys7 | 4 | 32 GB | S3 | tsys5 | none |
| 702 | hfnoc-uisp | 4 | 8 GB | **S4** | tsys5 | **disk D2→S4** |
| 703 | rr-middleware | 2 | 2 GB | **S4** | tsys5 | **disk D2→S4** |
| 704 | TCTC | 4 | 6 GB | **S3** | tsys5 | **disk D2→S3** |
| 705 | pfv-k8s-cnode2 | 4 | 4 GB | **S2** | tsys5 | **disk D2→S2** |
| 104 | tsys-librenms | 2 | 2 GB | **S3** | tsys5 | **host tsys1→tsys7, disk D2→S3** |
| 105 | tsys-proxmox-datacenter | 2 | 2 GB | **S4** | tsys5 | **host tsys1→tsys7, disk D2→S4** |
| 109 | tailscale-router | 2 | 2 GB | D2 | tsys4 | **host tsys1→tsys7** (disk stays D2) |
| 114 | kali-tsys | 2 | 2 GB | **S2** | tsys5 | **host tsys1→tsys7, disk D2→S2** |
| 117 | tsys-secure-workbench | 2 | 4 GB | **S3** | tsys5 | **host tsys1→tsys7, disk D2→S3** |
### tsys9 — Infra + control + compute (5 running, ~22 GB alloc → 94%)
| VMID | Name | vCPU | RAM | Disk | Server | Change |
|------|------|------|-----|------|--------|--------|
| 902 | **tsys-ucs-02** | 4 | 8 GB | S2 | tsys5 | none |
| 903 | kali-rd | 2 | 2 GB | D5 | tsys4 | none |
| 904 | **pfv-netinfra-02** | 2 | 4 GB | D2 | tsys4 | none |
| 905 | pfv-k8s-wnode-tsys9 | **6** | **8 GB** | S2 | tsys5 | **grow 4c/4G→6c/8G** |
| 906 | pfv-k8s-cnode1 | 2 | 4 GB | S3 | tsys5 | none |
| ~~901~~ | ~~tsys-siem~~ | — | — | — | — | **move→tsys6** |
### End-state per-spindle IOPS load
| Spindle | Server | # VMs | VMs on it |
|---------|--------|-------|-----------|
| **D2** (3TB) | tsys4 | **5** | bms, ca, ucs01, tailscale, netinfra02 |
| D5 (2TB) | tsys4 | 4 | cnode3, wnode3, awx, kali-rd |
| S1 (916GB) | tsys5 | **16** (unchanged) | sectestbed suite (local-nonprod, idle) |
| **S2** (916GB) | tsys5 | **7** | netinfra01, ucs02, wnode9, cnode2, siem, kali, pdm* |
| **S3** (916GB) | tsys5 | **7** | wnode1, wnode7, cnode1, uisp, TCTC, librenms, workbench |
| **S4** (458GB) | tsys5 | **5** | wnode5, wnode6, rr-middleware, uisp*... |
> *S2/S3 carry 7 each because the sectestbed load on S1 is idle. If those 16
> sectestbed VMs ever become active, rebalance — but for now S2/S3 at 7
> production VMs each is fine (they're 916 GB disks with light per-VM I/O).*
**D2: 17→5. No VMs added to S1. S2/S3/S4 absorb the load.**
HA pairs stay split:
- netinfra: 01 on S2 (tsys5), 02 on D2 (tsys4) ✓
- ucs: 01 on D2 (tsys4), 02 on S2 (tsys5) ✓
---
## 11. Action checklist (do in this order)
### Phase 0 — fix storage config bugs first — DONE ✓
- ~~Fix tsys6 S1 typo~~ — **operator fixed 2026-07-29** (verified: 8/8 stores active)
- ~~Add S1 to tsys9 storage.cfg~~ — **operator fixed 2026-07-29** (verified)
### Phase 1 — cleanup
- **Delete cnode4 (VMID 601) on tsys6** — stopped, stale, not in cluster
- **Confirm cnode5 (706) gone** — already deleted by operator ✓
### Phase 2 — disk migrations off D2 (IOPS rebalancing)
> Do disk moves on VMs that are staying on their current host first.
- **wnode-tsys5 (509):** disk **D2 → S4** (host stays tsys5)
- **tsys-awx (600):** disk **D2 → D5** (host stays tsys6)
- **hfnoc-uisp (702):** disk **D2 → S4** (host stays tsys7)
- **rr-middleware (703):** disk **D2 → S4** (host stays tsys7)
- **TCTC (704):** disk **D2 → S3** (host stays tsys7)
- **cnode2 (705):** disk **D2 → S2** (host stays tsys7)
### Phase 3 — host + disk migrations (RAM/CPU relief, 6 VMs)
- **tsys-librenms (104):** host **tsys1 → tsys7**, disk **D2 → S3**
- **tsys-proxmox-datacenter (105):** host **tsys1 → tsys7**, disk **D2 → S4**
- **tailscale-router (109):** host **tsys1 → tsys7** (disk stays **D2**)
- **kali-tsys (114):** host **tsys1 → tsys7**, disk **D2 → S2**
- **tsys-secure-workbench (117):** host **tsys1 → tsys7**, disk **D2 → S3**
- **tsys-siem (901):** host **tsys9 → tsys6**, disk **D2 → S2**
### Phase 4 — grow the compute wnode
- **wnode-tsys9 (905):** resize **4c/4GB → 6c/8GB** (stop/start required)
### Phase 5 — join workers to k3s
- Join wnodes via `k8s/join-servers.sh`
- Label: `workload=compute` (tsys3/9), `workload=rackrental` (tsys6/7), `workload=light` (tsys1/5)
### Verification after each phase
- `qm list` per host — confirm VM count + status
- `cat /proc/meminfo` — confirm actual RAM ≤ 80%
- `kubectl top nodes` — confirm cnodes healthy
- `ssh root@pfv-tsys4 'df -h /mnt/tsys4/D2'` — confirm D2 frees up
- `ssh root@pfv-tsys5 'df -h /mnt/pfv-tsys5/S2 /mnt/pfv-tsys5/S3 /mnt/pfv-tsys5/S4'` — confirm fills
---
## 12. Future: local storage as ephemeral scratch
> Codified as standing policy in [`CAPACITY-GOALS.md`](CAPACITY-GOALS.md) §6.
The fleet has substantial **unused local storage IOPS** on several hosts. OS
drives stay on NFS (no per-node disk redundancy — see policy), but local storage
is ideal for **ephemeral scratch** (container image cache, build artifacts,
`emptyDir` volumes) where data loss on node failure is acceptable.
**Per-host opportunity:**
| Host | Local | Available | Scratch-suitable? |
|------|-------|-----------|-------------------|
| tsys3 | NVMe (PM961) | 349 GB | **Yes — best existing** |
| tsys9 | SSD (PNY CS900) | 136 GB | **Yes** |
| tsys2 | NVMe + SSD | 512 GB + 1 TB | **Yes (incoming)** |
| tsys5 | HDD (Hitachi) | ~1.7 TB | Yes (bulk) |
| tsys6 | USB 2.0 HDD | 1.7 TB | **NO (30 MB/s)** |
| tsys7 | USB 2.0 HDD | 1.7 TB | **NO (30 MB/s)** |
**The tsys6/7 problem:** they are the RackRental hosts (most in need of fast
image pulls) but their local storage is USB 2.0 — slower than NFS. The real fix
is installing internal drives (tsys6 has a disabled SAS controller; tsys7 has 5
empty SATA ports). Deferred to a physical-hardware session.
**Implementation:** post-Friday, once SSD/NVMe tiers are installed and the k8s
StorageClass design is finalized. Wnodes with local storage get a `/scratch`
mount for ephemeral data; persistent data stays on NFS. See
[`CAPACITY-GOALS.md`](CAPACITY-GOALS.md) §6.4 for the StorageClass mapping.
# proxmox/docs/AUDIT-2026-07-29.md
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Audit snapshot 2026-07-29**
>
> **Read it here:** https://community.turnsys.com/t/298
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+10 -478
View File
@@ -1,478 +1,10 @@
# Fleet Audit — 2026-07-30 (full ground-truth: network + storage + compute)
> **The single authoritative audit.** Supersedes [`AUDIT-2026-07-29.md`](AUDIT-2026-07-29.md)
> and [`PROJECT.md`](PROJECT.md) where they conflict. Capacity targets are
> codified in [`CAPACITY-GOALS.md`](CAPACITY-GOALS.md).
**Audit time:** 2026-07-30, fresh data from all 7 online hosts (~03:3003:45 UTC)
+ switch SNMP/conman captures (~03:5004:00 UTC).
**Method:** `perf/scripts/probe-storage.sh`, `perf/scripts/probe-network.sh`,
`perf/scripts/snmp-switch-audit.py`, `perf/scripts/conman-console.py` — all
read-only. No changes made to any system.
**Hosts online:** tsys1, tsys3, tsys4, tsys5, tsys6, tsys7, tsys9
**Hosts retired:** tsys8 (permanently), tsys2 (Win10, pending rebuild)
---
## 1. Physical network topology
### 1.1 Diagram
```
RACK 5 (core/data) RACK 3 (compute/RackRental)
┌─────────────────────────┐ ┌──────────────────────────┐
│ │ │ │
│ pfv-core-sw01 │ ch1 LAG │ pfv-tor3-stor │
│ PowerConnect 5448 │◄───3×1G──────────►│ Neyland 24T (PC5324) │
│ (mgmt+storage VLAN) │ (g13-15) │ (storage TOR) │
│ │ g16 UP, not │ │
│ VLAN1 (mgmt) │ in LAG; g17 │ g8-9 → tsys6 bond0 │
│ VLAN1000 (storage) │ DOWN │ g10-11 → tsys7 bond0 │
│ │ │ g20-23 → ch1 (3 active) │
│ g8 → tsys4 nic0 │ │ │
│ g19 → tsys5 nic0 │ │ pfv-tor3-mgmt │
│ g31 → tsys4 enx (USB) │ │ Neyland 24T (PC5324) │
│ g33-34 → tsys5 ch3 │ │ (mgmt TOR) │
│ ch3 → tsys5 bond (1 ln)│ │ g7 → tsys6 nic0 │
│ │ │ g3 → tsys7 nic0 │
│ tsys4 (storage+PBS) │ │ │
│ tsys5 (storage+sectest)│ │ tsys6 (RackRental) │
│ tsys1 (infra) │ │ tsys7 (RackRental) │
│ tsys3 (compute) │ │ │
│ tsys9 (infra+compute) │ │ │
└─────────────────────────┘ └──────────────────────────┘
```
### 1.2 Cross-rack trunk detail (ch1) — THE BOTTLENECK
| Property | core-sw01 (rack5) | tor3-stor (rack3) | Problem? |
|----------|-------------------|--------------------|----------|
| **Physical ports** | g13, g14, g15 (UP) | g20, g21, g22, g23 (all UP) | Asymmetry — see below |
| **LAG config** | `g(13-15,17)` mode on | `g(20-23)` mode on | g17 DOWN; g16 UP but not in LAG |
| **Active links** | **3 of 4** | **4 of 4** | Mismatch: only 3 links negotiate |
| **Hash policy** | **layer-2-3** | **layer-2-3-4** | **ASYMMETRIC** — core lacks L4 |
| **Mode** | `on` (static) | `on` (static) | No LACP negotiation/failure detection |
| **VLAN** | access vlan 1000 | access vlan 1000 | OK |
**Three root causes of cross-rack underperformance:**
1. **g16/g17 cable mismatch.** core-sw01 config says `channel-group 1` on
`g(13-15,17)`. But g17 is DOWN and g16 is UP (live, 1000/Full). The 4th
physical cable landed on g16, not g17. Result: **only 3 links active** (3 Gbps,
not the intended 4).
2. **LAG hash asymmetry.** tor3-stor uses `port-channel load-balance layer-2-3-4`
(includes TCP/UDP source+dest ports — correct for NFS with nconnect).
core-sw01 uses `port-channel load-balance layer-2-3` (no L4 ports). With
layer-2-3 hashing, **all NFS traffic between a given host pair hashes to one
physical link**. Even though the clients use `nconnect=4` (4 TCP connections
per mount), they share the same src/dst IP → same hash → **max 1 Gbps per
server pair**. This is why tsys6/7 read from tsys4/5 at ~1 Gbps, not 3-4 Gbps.
3. **Static mode (`on`) instead of LACP.** Neither switch runs LACP on the
cross-rack trunk. `mode on` provides no link-failure detection, no partner
validation, no dynamic negotiation. A dead cable stays "active" until
manually discovered.
### 1.3 Per-host network state (ground truth)
| Host | Rack | mgmt NIC | storage NIC | bond0 | Hash | Active slaves | Speed | Storage IP |
|------|------|----------|-------------|-------|------|---------------|-------|------------|
| tsys1 | 5 | nic0 → core g8 | enx (USB dongle) | bond0 (1×USB) | layer2+3 | 1 | 1G | 10.100.100.1 |
| tsys3 | 5 | nic0 → core | — (no bond) | — | — | — | — | 10.100.100.3 |
| tsys4 | 5 | nic0 → core g8 | enx8cae4ccda926 (USB) → core g31 | bond0 (1×USB) | layer2+3 | 1 | 1G | 10.100.100.4 |
| tsys5 | 5 | nic0 → core g19 | nic1 → core g34 (ch3) | bond0 | layer2+3 | **1 of 2** (nic2 DOWN) | 1G | 10.100.100.5 |
| tsys6 | 3 | nic0 → tor3-mgmt g7 | nic1+nic2 → tor3-stor g8/g9 (ch2) | bond0 | **layer3+4** | **2 of 2** | **2G** | 10.100.100.6 |
| tsys7 | 3 | nic0 → tor3-mgmt g3 | nic1+nic2 → tor3-stor g10/g11 (ch3) | bond0 | **layer3+4** | **2 of 2** | **2G** | 10.100.100.7 |
| tsys9 | 5 | nic0 → core | enx (USB dongle) | bond0 (1×USB) | layer2+3 | 1 | 1G | 10.100.100.9 |
**Key observations:**
- **tsys6/7 are the ONLY hosts with working 2G LACP** (layer3+4, 2 active slaves). Validated previously.
- **tsys4/9 use USB dongles** for storage — single 1G, no bond redundancy.
- **tsys5 bond is degraded** — nic2 is DOWN (no cable). Only nic1 active. This is
the LACP problem the operator has been struggling with. The switch side (core-sw01
ch3) shows 1 active member (g34), and tsys5's bond0 reports 1 active slave.
- **tsys1 also uses a USB dongle** for storage.
- **Hash inconsistency:** tsys6/7 use layer3+4 (correct for nconnect), tsys4/5
use layer2+3 (suboptimal for NFS multi-connection).
### 1.4 Switch inventory (SNMP + conman ground truth)
| Switch | IP | Model | Firmware | Role | Console |
|--------|----|-------|----------|------|---------|
| pfv-core-sw01 | 192.168.0.12 | Dell PowerConnect 5448 | 2.0.0.46 | Core (rack5, combined mgmt+storage) | conman port 2001 |
| pfv-tor3-stor | 192.168.0.9 | Dell PowerConnect 5324 (Neyland 24T) | 2.0.1.4 | Rack3 storage TOR | conman port 2003 |
| pfv-tor3-mgmt | 192.168.0.7 | Dell PowerConnect 5324 (Neyland 24T) | (same family) | Rack3 mgmt TOR | conman port 2002 |
| (unknown) | 192.168.0.8 | Dell PowerConnect 5324 (Neyland 24T) | (same family) | Unidentified — possibly pfv-r2-tor-top | conman port 2005? |
**Switch SNMP community:** `kn3lmgmt` (read-only). All switches respond to SNMPv2c.
**Console access:** conman on pfv-tsys4:7890 (7 consoles). Fixed during this audit
(udev symlink naming bug — singular vs plural — prevented consoles from working
after reboot).
### 1.5 Port error counters (core-sw01)
| Port | In Errors | Notes |
|------|-----------|-------|
| **g9** | **2902** | Connected to 192.168.0.21 (device unknown). Investigate CRC/cable. |
| **g38** | **590** | On VLAN 1000 (storage). Connected to a host on the storage VLAN. |
| **g26** | **73** | Connected to a management-network device. |
| All others | 0 | Healthy. |
tor3-stor shows **zero errors** on all active ports.
---
## 2. Storage topology (CORRECTED — current ground truth)
### 2.1 Storage tier definitions
| Tier | Definition | Performance | Use case |
|------|-----------|-------------|----------|
| **Tier 1** | NVMe / SSD on internal SATA/SAS | 200-3000 MB/s, high IOPS | OS drives, high-IOPS workloads |
| **Tier 2** | HDD on internal SATA/SAS | 80-150 MB/s, moderate IOPS | Production VM OS drives |
| **Tier 3** | HDD/SSD on USB "toaster" / USB adapter | 30-60 MB/s, low IOPS, unreliable | Bulk/backup/scratch only |
### 2.2 tsys4 disk inventory (CHANGED since last audit)
| Device | Model | Size | Interface | Mount | NFS export | Tier | Notes |
|--------|-------|------|-----------|-------|------------|------|-------|
| sda | Hitachi HDS723020BLA642 | 2.0 TB | Internal SATA | /mnt/albert | (not exported) | **Tier 2** | NEW — not in Proxmox storage.cfg, not exported. 0% used. |
| sdb | HITACHI HUA723020ALA640 | 2.0 TB | Internal SATA | /mnt/tsys4/D5 | D5 | Tier 2 | 13% used (220 GB). 7200 rpm. |
| sdc | WDC WD30EFRX (Red) | 3.0 TB | Internal SATA | /mnt/tsys4/D2 | D2 | Tier 2 | 7% used (170 GB). 5400 rpm. **17 VMs on this spindle.** |
| sdd | WDC WD10EZRX | 1.0 TB | Internal SATA | (pve boot/swap/local-lvm) | — | Tier 2 | Proxmox OS disk. |
| sde | ST500LM021 (Seagate) | 500 GB | **USB** | /mnt/tsys4/D3 | D3 | **Tier 3** | **CHANGED from SK hynix SSD to Seagate HDD.** 0% used. |
| sdf | WDC WD10EARS | 1.0 TB | **USB** | /mnt/tsys4/D1 | D1 | **Tier 3** | 0% used. 1 reallocated sector (SMART). |
| sdg | WDC WD50NDZW (easystore) | 5.0 TB | **USB** | /mnt/backup | (not exported) | **Tier 3** | NEW — bulk backup disk. 0% used. |
**Changes from AUDIT-2026-07-29:**
- **D3 changed:** SK hynix SC300 512GB SSD → Seagate ST500LM021 500GB HDD (still on USB).
D3 is now Tier 3 (was previously listed as unreliable USB SSD).
- **/mnt/albert added:** Hitachi 2TB internal SATA. Not exported, not in Proxmox.
Potential new Tier 2 storage.
- **/mnt/backup added:** WD 5TB USB easystore. Tier 3 bulk backup.
- **D7 removed:** Previously orphaned export (held DellOpenManageEnterprise). Now gone.
### 2.3 tsys5 disk inventory (MAJOR CHANGES — new NVMe + SSD)
| Device | Model | Size | Interface | Mount | NFS/Local | Tier | Notes |
|--------|-------|------|-----------|-------|-----------|------|-------|
| sda | ST1000VN002 (IronWolf) | 1.0 TB | Internal SATA | (not mounted) | — | Tier 2 | **Was S3.** Not in fstab, not mounted. Stale export remains in /etc/exports. |
| sdb | SK hynix SC300B | 512 GB | Internal SATA | (not mounted) | — | **Tier 1** | **NEW — relocated from tsys4 USB enclosure.** Not mounted, not in fstab, not in storage.cfg. |
| sdc | HITACHI HUS724020ALA640 | 2.0 TB | Internal SAS | (pve boot/swap/local-lvm) | — | Tier 2 | Proxmox OS disk. |
| sdd | Samsung SSD 860 PRO | 256 GB | Internal SAS | /mnt/pfv-tsys5/ssd | `ssd` dir (local) | **Tier 1** | **93% full!** Used by ultix-streaming (5111). |
| sde | ST1000VN002 (IronWolf) | 1.0 TB | Internal SAS | /mnt/pfv-tsys5/S1 | S1 (NFS + local-nonprod) | Tier 2 | 11% used. 5900 rpm. |
| sdf | ST1000VN002 (IronWolf) | 1.0 TB | Internal SAS | /mnt/pfv-tsys5/S2 | S2 (NFS) | Tier 2 | 4% used. |
| **nvme0n1** | **CT500P1SSD8 (Crucial)** | **500 GB** | **NVMe** | **(not mounted)** | — | **Tier 1** | **NEW — not mounted, not in fstab, not in storage.cfg.** 34K power-on hours. Healthy. |
**Changes from AUDIT-2026-07-29:**
- **NVMe added:** Crucial CT500P1 500GB. Not yet configured. This is the highest-
performance local storage in the fleet (true NVMe).
- **SK hynix SSD relocated:** Moved from tsys4 USB enclosure to tsys5 internal
SATA. Not yet mounted/configured.
- **S3 unmounted:** ST1000VN002 (was S3) is present but fstab entry is commented
out. /etc/exports still exports S3 (stale).
- **S4 gone:** Old Toshiba 458GB is no longer present. fstab entry commented.
storage.cfg still has a broken `dir: S4` entry (points to root filesystem).
- **S1/S2 drives changed:** Both are now ST1000VN002 IronWolf 1TB (were "Seagate
916GB" in old audit).
- **SSD nearly full:** Samsung 860 PRO at 93% — needs attention.
### 2.4 NFS export map (current, verified)
| Server | Export | NFS ID | Disk | Tier | Used |
|--------|--------|--------|------|------|------|
| tsys4 | /mnt/tsys4/D1 | D1 | WDC WD10EARS 1TB | Tier 3 (USB) | 0% |
| tsys4 | /mnt/tsys4/D2 | D2 | WDC Red 3TB | Tier 2 | 7% (170 GB) |
| tsys4 | /mnt/tsys4/D3 | D3 | Seagate 500GB | Tier 3 (USB) | 0% |
| tsys4 | /mnt/tsys4/D5 | D5 | Hitachi 2TB | Tier 2 | 13% (220 GB) |
| tsys5 | /mnt/pfv-tsys5/S1 | S1 | IronWolf 1TB | Tier 2 | 11% (96 GB) |
| tsys5 | /mnt/pfv-tsys5/S2 | S2 | IronWolf 1TB | Tier 2 | 4% (32 GB) |
| tsys5 | /mnt/pfv-tsys5/S3 | S3 | (stale — disk not mounted) | — | — |
### 2.5 NFS client mount status (nconnect)
| Host | Mounts from tsys4 | Mounts from tsys5 | nconnect=4? | Hash |
|------|-------------------|-------------------|-------------|------|
| tsys4 | (NFS server, no client mounts) | — | — | layer2+3 |
| tsys5 | D2, D3, D5 | (NFS server) | **NO nconnect** | layer2+3 |
| tsys6 | D1, D2, D3, D5 | S1, S2, S3, S4, T5-SSD | **YES** (9 mounts) | layer3+4 |
| tsys7 | D1, D2, D3, D5 | S1, S2, S3, S4, T5-SSD | **YES** (9 mounts) | layer3+4 |
**tsys5 is missing nconnect** on its 3 NFS client mounts (D2/D3/D5 from tsys4).
**tsys4 is missing nconnect** entirely (but it's primarily an NFS server, not a client).
### 2.6 Per-spindle IOPS load (running VMs only)
| Spindle | Server | NFS-visible VMs | Local-only VMs | Total | Tier | Notes |
|---------|--------|-----------------|----------------|-------|------|-------|
| **D2** (3TB Red) | tsys4 | **13** | 0 | **13** | Tier 2 | Still the worst hotspot. VMs: 100,101,104,105,108,114,117,509,600,702,704,901,904 |
| D5 (2TB Hitachi) | tsys4 | 4 | 0 | 4 | Tier 2 | VMs: 106,313,600(disk0),903 |
| S1 (1TB IronWolf) | tsys5 | 1 | 0 | 1 | Tier 2 | VM: 702 (hfnoc-uisp, 100GB) |
| S2 (1TB IronWolf) | tsys5 | 4 | 0 | 4 | Tier 2 | VMs: 103,703,705,902,905 |
| S4 (local-nonprod) | tsys5 | 0 | **12** (stopped sandboxes) | 12 idle | Tier 2 | All stopped. Low priority. |
| D3 (500GB Seagate USB) | tsys4 | 0 | 0 | 0 | **Tier 3** | Empty |
| D1 (1TB WD USB) | tsys4 | 0 | 0 | 0 | **Tier 3** | Empty |
| ssd (Samsung 860 PRO) | tsys5 | 0 | 1 | 1 | Tier 1 | VM 5111 (ultix-streaming, 288GB) |
**D2 still carries 13 running VMs** — the IOPS hotspot persists.
---
## 3. Host capacity (live ground truth, 2026-07-30)
| Host | CPU | Threads | RAM | Running VMs | Actual RAM% | Load | CPU busy |
|------|-----|---------|-----|-------------|-------------|------|----------|
| tsys1 | i7-4770 Haswell (2013) | 8 | 31 GB | 9 | **57%** | 1.1 | ~4% |
| tsys3 | Xeon E3-1535M v5 Skylake (2015) | 8 | 31 GB | 1 | 10% | 0.3 | 0% |
| tsys4 | Xeon E3-1246 v3 Haswell (2013) | 8 | 16 GB | 1 | 15% | 1.8 | 0% |
| tsys5 | Xeon E5620 Westmere (2010) **single CPU** | 8 | 94 GB | 4 (+22 stopped) | 15% | 3.3 | ~5% |
| tsys6 | 2× Xeon E5530 Nehalem (2009) | 16 | 126 GB | 2 | 12% | 0.7 | 0% |
| tsys7 | 2× Xeon E5-2630 v2 Ivy Bridge (2013) | 24 | 189 GB | 5 | 7% | 1.0 | ~1% |
| tsys9 | i5-10500 Comet Lake (2020) | 12 | 23 GB | 6 | **69%** | 0.3 | ~1% |
**Changes since AUDIT-2026-07-29:**
- **tsys1 RAM dropped 73%→57%** — some VMs apparently migrated/stopped.
- **tsys9 RAM 62%→69%** — approaching 80% goal.
- **tsys6 wnode-tsys6 grew to 64GB RAM** (was 32GB in old audit).
- **All other hosts healthy** — well under 80%.
---
## 4. Fleet consistency audit
### 4.1 PVE/kernel versions
| Host | PVE | Kernel | Status |
|------|-----|--------|--------|
| tsys1 | 9.2.5 | 7.0.14-6-pve | Current ✓ |
| tsys3 | 9.2.5 | 7.0.14-6-pve | Current ✓ |
| **tsys4** | **9.1.5** | **6.17.9-1-pve** | **BEHIND — needs upgrade** |
| tsys5 | 9.2.5 | 7.0.14-6-pve | Current ✓ |
| tsys6 | 9.2.5 | 7.0.14-6-pve | Current ✓ |
| tsys7 | 9.2.5 | 7.0.14-6-pve | Current ✓ |
| tsys9 | 9.2.5 | 7.0.14-6-pve | Current ✓ |
### 4.2 Performance tuning state
| Host | Governor | Swappiness | TCP CC | rmem/wmem_max | Tuned profile | Bond hash | nconnect |
|------|----------|------------|--------|---------------|---------------|-----------|----------|
| tsys1 | performance | 10 | bbr | 128MB | virtual-host | layer2+3 | N/A (client) |
| tsys3 | performance | 10 | bbr | 128MB | virtual-host | — | N/A |
| **tsys4** | **performance** | **1** | **bbr** | **16MB** | **throughput-performance** | **layer2+3** | **0** |
| **tsys5** | **N/A** (no driver) | **1** | **bbr** | **128MB** | **network-throughput** | **layer2+3** | **0** |
| tsys6 | performance | 10 | bbr | 128MB | virtual-host | **layer3+4** | **24** (9 mounts × 4... actually 6 options lines) |
| tsys7 | performance | 10 | bbr | 128MB | virtual-host | **layer3+4** | **24** |
| tsys9 | performance | 10 | bbr | 128MB | virtual-host | layer2+3 | N/A |
**Inconsistencies:**
- **tsys4:** rmem/wmem = 16 MB (fleet standard: 128 MB). Tuned profile wrong
(`throughput-performance` should be `network-throughput`). Missing nconnect.
- **tsys5:** Missing nconnect on NFS client mounts. No cpufreq driver (Westmere —
expected, not a bug).
- **tsys4/5 bond hash = layer2+3** — should be layer3+4 (like tsys6/7).
---
## 5. VM inventory + config audit (running VMs only)
### 5.1 Per-VM disk + CPU + network settings
> `cpu: host` = best (full instruction set passthrough). `x86-64-v2-AES` = good
> (nested-virt-safe baseline). `cache=writethrough` = safe but slow for NFS.
> `iothread=1` = present on most. `agent: 1` = qemu-guest-agent enabled.
| VMID | Name | Host | vCPU | CPU type | RAM | Disk store | Cache | iothread | qga | Notes |
|------|------|------|------|----------|-----|-----------|-------|----------|-----|-------|
| 100 | pfv-bms | tsys1 | 2 | host | 4G | D2 (raw) | — | — | ✓ | discard=on,ssd=1 |
| 101 | tsys-ca | tsys1 | 2 | v2-AES | 2G | D2 (virtio) | — | ✓ | — | no nested-virt |
| 103 | netinfra-01 | tsys1 | 2 | v2-AES | 4G | S2 | — | ✓ | — | |
| 104 | librenms | tsys1 | 2 | host | 2G | D2 | — | ✓ | ✓ | |
| 105 | proxmox-dc | tsys1 | 2 | host | 2G | D2 | — | ✓ | ✓ | |
| 106 | cnode3 | tsys1 | 4 | host | 4G | D5 | **writethrough** | ✓ | ✓ | |
| 108 | ucs-01 | tsys1 | 2 | host | 8G | D2 | **writethrough** | ✓ | ✓ | |
| 114 | kali-tsys | tsys1 | 2 | host | 2G | D2 | **writethrough** | ✓ | ✓ | |
| 117 | workbench | tsys1 | 2 | host | 4G | D2 | **writethrough** | ✓ | ✓ | |
| 313 | wnode-tsys3 | tsys3 | 8 | host | 28G | D5 | **writethrough** | ✓ | ✓ | |
| 400 | PBS | tsys4 | 2 | — | 2G | local-lvm | — | — | — | backup server |
| 509 | wnode-tsys5 | tsys5 | 2 | host | 32G | D2 (virtio) | — | ✓ | — | low vCPU (2) for k8s wnode |
| 5111 | ultix-streaming | tsys5 | 4 | — | 9G | ssd (local) | — | — | — | 288GB on SSD (93% full) |
| 5112 | ultix-offstage | tsys5 | 4 | — | 6G | local-lvm | — | — | — | 288GB |
| 100 | wnode-tsys6 | tsys6 | 2 | host | 64G | S4 | — | ✓ | — | low vCPU (2), high RAM |
| 600 | tsys-awx | tsys6 | 2 | host | 12G | D5 | **writethrough** | ✓ | ✓ | |
| 701 | wnode-tsys7 | tsys7 | 4 | host | 32G | S3 (virtio) | — | ✓ | — | |
| 702 | hfnoc-uisp | tsys7 | 2 | host | 8G | S1 | — | ✓ | ✓ | 100GB disk |
| 703 | rr-middleware | tsys7 | 2 | host | 2G | S2 | **writethrough** | ✓ | ✓ | |
| 704 | TCTC | tsys7 | 4 | host | 6G | D2 (virtio) | — | ✓ | — | |
| 705 | cnode2 | tsys7 | 4 | host | 4G | S2 | **writethrough** | ✓ | ✓ | |
| 901 | tsys-siem | tsys9 | 2 | host | 8G | D2 | **writethrough** | ✓ | ✓ | 132GB disk |
| 902 | ucs-02 | tsys9 | 2 | host | 8G | S2 | — | ✓ | ✓ | 50GB disk |
| 903 | kali-rd | tsys9 | 2 | host | 2G | D5 | **writethrough** | ✓ | ✓ | |
| 904 | netinfra-02 | tsys9 | 2 | v2-AES | 4G | D2 | — | ✓ | — | |
| 905 | wnode-tsys9 | tsys9 | 4 | v2-AES | 4G | S2 | — | ✓ | ✓ | target: grow to 6c/8G |
| 906 | cnode1 | tsys9 | 2 | host | 4G | S3 | — | ✓ | — | |
### 5.2 VM optimization findings
| Finding | VMs affected | Impact | Fix |
|---------|-------------|--------|-----|
| **cache=writethrough on NFS** | 106,108,114,117,313,600,703,705,901,903 | Writethrough forces synchronous writes — slow on NFS. `writeback` or `none` is better for NFS-backed qcow2. | Change cache mode (requires VM stop/start) |
| **Mixed CPU types** | Some `host`, some `x86-64-v2-AES` | Prevents migration between hosts with different CPU types. K8s cnodes/wnodes should match. | Standardize per workload tier |
| **Low vCPU on k8s wnodes** | wnode-tsys5 (2c), wnode-tsys6 (2c) | K8s workers undersized for compute workloads | Grow after migrations free RAM |
| **VM 500 references D7** | DellOpenManageEnterprise (stopped) | D7 export no longer exists on tsys4 | Delete or re-disk before starting |
| **qga inconsistent** | Several VMs missing agent:1 | No guest-agent communication | Enable qga fleet-wide |
---
## 6. Console infrastructure status (fixed during this audit)
**Bug found + fixed:** `console/generate-config.sh` wrote udev rules with
`SYMLINK+="console/$name"` (singular) but ser2net.yaml opened
`/dev/consoles/$name` (plural). They never matched. After every reboot, all 7
console ports failed until `setup.sh`'s manual fallback re-created symlinks.
**Fix applied:** Changed udev rule to `SYMLINK+="consoles/$name"`. Re-created
all 7 symlinks manually on pfv-tsys4. Restarted ser2net + conmand. All 7
consoles now working (verified via conman-console.py).
**Also fixed:** stale conmand process (pid 988) holding config lock, preventing
conmand systemd service from starting.
---
## 7. Findings summary (prioritized)
### Critical (cross-rack performance)
| # | Finding | Impact | Type |
|---|---------|--------|------|
| 1 | **core-sw01 LAG hash = layer-2-3** (no L4 ports) | All NFS traffic between a given host pair caps at 1 Gbps | Switch config |
| 2 | **core-sw01 ch1 cable on g16, not g17** | Only 3 of 4 cross-rack links active (3 Gbps, not 4) | Switch config |
| 3 | **Both switches use `mode on`** (static, no LACP) | No failure detection, no partner validation | Switch config |
| 4 | **tsys5 bond0 degraded** (1 of 2 slaves) | Single link to storage, no redundancy | Physical (cable) |
### High (storage configuration)
| # | Finding | Impact | Type |
|---|---------|--------|------|
| 5 | **tsys5 NVMe not configured** (CT500P1 500GB) | Best local storage in fleet sitting unused | Config |
| 6 | **tsys5 SK hynix SSD not configured** (512GB) | Relocated from tsys4, not mounted | Config |
| 7 | **D2 still carries 13 running VMs** | IOPS hotspot persists | VM placement |
| 8 | **tsys5 SSD 93% full** | Samsung 860 PRO nearly exhausted | Capacity |
| 9 | **S3/S4 stale on tsys5** | Broken exports, stale storage.cfg | Config |
### Medium (fleet consistency)
| # | Finding | Impact | Type |
|---|---------|--------|------|
| 10 | **tsys4 on PVE 9.1.5/kernel 6.17** | Behind fleet (9.2.5/7.0.14) | Upgrade |
| 11 | **tsys4 rmem/wmem = 16MB** | Suboptimal TCP buffers for NFS | Tuning |
| 12 | **tsys4/5 bond hash = layer2+3** | Suboptimal for nconnect NFS | Tuning |
| 13 | **tsys5 missing nconnect** | NFS client mounts to tsys4 lack multi-connection | Tuning |
| 14 | **cache=writethrough on 10+ VMs** | Synchronous writes slow NFS | VM config |
| 15 | **Stale tsys8 switch config** (tor3-stor ch4) | Dead LAG group for retired host | Cleanup |
### Low (monitoring / investigation)
| # | Finding | Impact | Type |
|---|---------|--------|------|
| 16 | **core-sw01 port errors** (g9:2902, g38:590, g26:73) | Possible cable/CRC issues | Investigate |
| 17 | **No continuous observability** | Only point-in-time check.sh snapshots | Monitoring |
| 18 | **/mnt/albert unused** (tsys4 Hitachi 2TB) | Potential new Tier 2 storage | Config |
| 19 | **VM 500 references non-existent D7** | Would fail on boot | Cleanup |
---
## 9. Observability stack (operator direction)
The operator has defined a clear monitoring architecture with three tools,
each serving a distinct role. Do NOT duplicate functionality across tools.
### 9.1 Current architecture
| Tool | Where it runs | Scope | Role |
|------|---------------|-------|------|
| **Beszel** | Cloudron VPS (Reston, VA) | Tailscale-connected hosts | CPU/RAM/disk/time-series metrics on all Proxmox hosts |
| **Uptime Kuma** | Cloudron VPS (Reston, VA) | All hosts + services | Up/down status + alerting via Pushover |
| **LibreNMS** (VMID 104, tsys1) | On-prem (R&D cluster) | Non-Tailscale devices only | SNMP polling for switches + devices that can't run Beszel agent |
| **Home Assistant** (VMID 100, tsys1) | On-prem (R&D cluster) | Physical infrastructure | Power/temperature instrumentation + alerting (UPS, PDU outlets, etc.) |
### 9.2 Division of responsibility (no duplication)
| Metric class | Tool | Notes |
|-------------|------|-------|
| CPU / RAM / disk / network time-series | **Beszel** | All Proxmox hosts (Tailscale-connected) |
| Up/down alerting (hosts + services) | **Uptime Kuma** | Pushover notifications |
| SNMP polling (switches, non-Tailscale gear) | **LibreNMS** | Port counters, LAG status, interface errors, switch health. Fill the gap Beszel can't cover (switches have no Beszel agent) |
| Power / temperature / physical env | **Home Assistant** | UPS (NUT), PDU outlets, temperature sensors. Alerting via HA automations |
### 9.3 Saturday "OAM Day" plan (2026-08-01)
The operator has designated Saturday as a dedicated operations/admin/management
day with the goal of achieving **100% instrumentation coverage**:
- [ ] Up/down alerting on ALL hosts + key services (Uptime Kuma → Pushover)
- [ ] Centralized syslog (tool TBD — candidates: dedicated syslog VM, rsyslog
relay, or Loki/Grafana stack)
- [ ] SNMP instrumentation: wire LibreNMS for all 4 switches + any non-Tailscale
devices (community: `kn3lmgmt`, IPs: 192.168.0.7/8/9/12)
- [ ] Beszel agent coverage on all 7 Proxmox hosts
- [ ] Home Assistant: wire power/temp alerting (UPS via NUT already live, PDU
via powerman, any temp sensors)
- [ ] Verify alerting paths end-to-end (test each alert fires correctly)
> Much of the groundwork is already done: NUT is live on tsys1, powerman is
> live on tsys1, LibreNMS (VMID 104) is running, conman console logging is live
> on tsys4, check.sh provides point-in-time snapshots. Saturday is about wiring
> continuous monitoring + alerting on top of these.
---
## 8. Recommendations (for operator review — NO changes applied)
### 8.1 Switch changes (require maintenance window + operator approval)
1. **Fix core-sw01 ch1 member list:** `g(13-15,17)``g(13-16)`. This makes
the 4th live cable (g16) part of the LAG.
2. **Fix core-sw01 LAG hash:** `layer-2-3``layer-2-3-4` (match tor3-stor).
This unlocks multi-link distribution for nconnect NFS traffic.
3. **Convert trunk to LACP:** Change `mode on``mode active` on both switches
for the cross-rack trunk (ch1). Enables failure detection + auto-negotiation.
4. **Remove stale tsys8 config:** Delete ch4 + g13/g14 channel-group on tor3-stor.
5. **Investigate port errors:** g9 (2902 inErr), g38 (590 inErr), g26 (73 inErr)
on core-sw01.
> **Recommended order:** Fix #2 (hash) + #1 (member) first — these are the
> highest-impact changes with the lowest risk. LACP conversion (#3) is optional
> if the static trunk is working reliably otherwise. All changes can be done
> read-only-verified via the conman + SNMP tooling in this repo.
### 8.2 Storage configuration (host-side, no switch changes needed)
1. **Mount + configure tsys5 NVMe** (CT500P1 500GB) as LVM-thin (`nvme-local`)
per [`TODO.md`](TODO.md) §3. Use for wnode-tsys5 boot disk (highest impact)
and sectestbed scratch.
2. **Mount + configure tsys5 SK hynix SSD** (512GB). Add as `dir: ssd2` or
similar. Offloads the 93%-full Samsung 860 PRO.
3. **Clean S3/S4:** Remove stale S3 export from /etc/exports. Fix/remove broken
`dir: S4` entry in storage.cfg.
4. **Decide on /mnt/albert** (tsys4 Hitachi 2TB): export as new NFS storage or
keep local-only for PBS scratch.
### 8.3 Fleet consistency + tuning (host-side)
1. **Upgrade tsys4** to PVE 9.2.5 / kernel 7.0.14 (matches fleet).
2. **Apply apply-tunings.sh --apply** to tsys4 and tsys5:
- Fix rmem/wmem to 128MB (tsys4)
- Fix tuned profile (tsys4 → network-throughput)
- Add nconnect=4 to tsys5 NFS client mounts
- Fix bond hash to layer3+4 (tsys4/5 — requires ifreload, brief network drop)
3. **Audit VM cache modes:** Change writethrough → writeback or none for NFS-
backed qcow2 disks (requires VM stop/start).
### 8.4 VM placement rebalancing (refer to [`CAPACITY-GOALS.md`](CAPACITY-GOALS.md))
The new NVMe + SSD on tsys5, the unmounted /mnt/albert on tsys4, and the 3 empty
Tier 3 USB disks (D1, D3, /mnt/backup) create opportunities for IOPS spreading
that didn't exist in the 07-29 audit. Detailed placement plan deferred to the
operator review of this document.
# proxmox/docs/AUDIT-2026-07-30.md
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Audit snapshot 2026-07-30**
>
> **Read it here:** https://community.turnsys.com/t/298
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+8 -218
View File
@@ -1,220 +1,10 @@
# Ground-Truth Audit — 2026-08-05
# proxmox/docs/AUDIT-2026-08-05.md
> **Authoritative fleet audit** performed by Crush (GLM-5.2) via read-only
> network discovery (nmap, SNMP, SSH, API queries). Supersedes
> [`AUDIT-2026-07-30.md`](AUDIT-2026-07-30.md) for all fleet state.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Method:** Tailscale `status`, nmap ping sweep (192.168.0-3.0/24), SNMP
> walks (`kn3lmgmt` community), SSH via `tests/remote.sh` + `netinfra/dns-cluster-setup/remote-dns.sh`,
> Proxmox `qm list`/`pvecm`, Docker/container inspection.
## TL;DR — What Changed Since 2026-07-30
The fleet grew significantly and the repository was restructured into a
module/subproject layout. Headline deltas:
| Metric | 2026-07-30 | 2026-08-05 | Δ |
|--------|-----------|-----------|---|
| VMs (running) | 28 | **63** | +125% |
| DNS zones | 124 | **167** | +35% |
| DHCP active leases | 333 | **98** (unique active) | 431 total active binding-state entries |
| Proxmox hosts | 7 | 7 | — |
| PVE version (fleet) | mixed (9.1.59.2.5) | **all 9.2.5** | tsys4 upgraded |
| Tailscale nodes | ~30 | **80** | full 3-tier env mirror |
| k8s cluster | LIVE (3-node HA) | **DOWN** | cnode wiped, no quorum |
| netinfra-02 | redundant secondary | **WIPED** | needs rebuild |
## Repository Restructure (DONE by operator)
Top-level dirs were consolidated into modules. **Old flat dirs no longer
exist** at the repo root:
| Was (repo root) | Now |
|-----------------|-----|
| `provisioning/` | `archive/provisioning/` — superseded by **KNELIAC** project (`/home/reachableceo/projects/KNELIAC`) |
| `powerman/` `console/` `ups/` | `dcinfra/{powerman,console,ups}/` |
| `dns-cluster-setup/` `switches/` `dhcp/` | `netinfra/{dns-cluster-setup,switches,dhcp}/` |
| `perf/` | `proxmox/perf/` (+ `proxmox/perf/scripts/`) |
Current repo root: `archive/ awx/ dcinfra/ docs/ k8s/ netinfra/ proxmox/ tests/ vendor/` + `logs/ returned-logs/`.
> **WARNING:** `README.md`, `AGENTS.md`, and `docs/docmap.md` still reference
> the OLD paths. These are being updated in this same session.
## Network Switches
SNMP community: `kn3lmgmt` (read) / `kn3lwrite` (write). SNMP responds from
the workstation LAN (no ACL — earlier "filtered" was just a wrong community).
| IP | sysName | Model | Status |
|----|---------|-------|--------|
| 192.168.0.12 | pfv-core-sw01 | PowerConnect 5448 | **UP** (Dell, core, rack5) |
| 192.168.0.7 | pfv-r3-tor-mgmt | Neyland 24T (PC5324) | **UP** (rack3 mgmt TOR) |
| 192.168.0.9 | pfv-r3-tor-stor | Neyland 24T (PC5324) | **UP** (rack3 storage TOR) |
| 192.168.0.8 | subodev-torsw01 | Neyland 24T (PC5324) | **UP** (was "unidentified" — now named) |
| 192.168.0.5 | pfv-r2-tor-top | (unknown) | **OFFLINE** — no ping, no SNMP |
**Ports open on switches:** TCP 22 (ssh), 23 (telnet), 80 (http web UI). UDP
161 (SNMP) responds with `kn3lmgmt`.
### LACP / Cross-Rack Trunk (core-sw01 ch1)
- Operator reports **LACP is fixed** (was static `mode on`, hash layer-2-3).
- SNMP confirms **ch1 ifIndex=49 is UP**; ch3 ifIndex=51 also UP.
- ch1 reports ifSpeed=1000Mbps — the Dell FastPath switch does not report
aggregate bundle speed via standard ifSpeed, so **member count + hash
algorithm need console verification** (conman requires a PTY — run manually):
```bash
conman -d pfv-tsys4:7890 -f pfv-core-sw01
# then: show interfaces status port-channel 1
# show running-config | begin port channel
```
## Proxmox Hosts (7 standalone, managed via PDM)
All **PVE 9.2.5** (tsys4 upgraded from 9.1.5 — resolves old STATUS item).
**Not clustered** — standalone installs (corosync Expected votes=1 each).
| Host | RAM used/total | VMs | Uptime | Notes |
|------|---------------|-----|--------|-------|
| pfv-tsys1 | 71% (22.7/32 GB) | 8 | 6d | Highest RAM use in fleet |
| pfv-tsys3 | 12% (3.7/32 GB) | 2 | 9d | under-utilized |
| pfv-tsys4 | 18% (2.8/16 GB) | 2 | 5d | storage server, kernel 7.0.14-8 |
| pfv-tsys5 | 48% (46.8/97 GB) | **32** | 6d | sectestbed+preprod host |
| pfv-tsys6 | 14% (18/129 GB) | 5 | 10d | 129 GB RAM, wnode+cnode3 |
| pfv-tsys7 | 30% (58.8/193 GB) | 11 | 10d | **193 GB RAM**, prod workloads |
| pfv-tsys9 | 30% (7.2/24 GB) | 3 | 9d | netinfra-02 + wnode |
**Memory capacity goal (≤80%): PASS fleet-wide.** Highest is tsys1 at 71%.
### tsys5 Storage (RESOLVED)
Old STATUS item "NVMe + SSD not configured" is **FIXED**. All storage active:
| Disk | Mount | Use |
|------|-------|-----|
| nvme0n1 (CT500P1 500GB) | /mnt/nvme (PVE: NVME dir) | 49% used |
| sdb (SK hynix 512GB SSD) | /mnt/ssd2 (PVE: ssd2 dir) | 14% used |
| sdd (Samsung 860 PRO 256GB) | /mnt/pfv-tsys5/ssd (PVE: SSD dir) | 1% |
| sde (ST1000VN002 1TB) | /mnt/pfv-tsys5/S1 | 6% |
| sdf (ST1000VN002 1TB) | /mnt/pfv-tsys5/S2 | 7% |
| local-lvm (1.67 TB thin) | LVM | 6.9% |
NFS from tsys4: D2, D3, D5 all mounted and active.
## DNS / NTP / DHCP (netinfra)
### pfv-netinfra-01 (PRIMARY — 192.168.3.252, TS 100.70.181.72)
| Service | State | Detail |
|---------|-------|--------|
| **Technitium DNS** | UP (Docker `tsys-dns`, 5d) | Container, NOT systemd. Config: `/home/localuser/services/technitium/config` → `/etc/dns`. **167 zones.** Port 5380 via docker-proxy. |
| **Pi-hole** | UP (healthy, 26h) | `/dev/shm` = **1.0 GB** (operator hotfix applied). Healthcheck = `dig pi.hole` (DNS-resolution based). |
| **NTP** | UP (`ntpsec`, NOT chrony) | Clock synchronized. |
| **DHCP** | UP (`isc-dhcp-server`) | **753 active leases** (was 333). |
### pfv-netinfra-02 (SECONDARY — 192.168.3.253, TS 100.71.171.20)
**WIPED.** Reachable on Tailscale (host key changed, cleared from known_hosts)
but **SSH key auth fails** (`Permission denied (publickey,password)`). Needs
full rebuild as redundant node — see Pending.
## Kubernetes (pfv-k8s) — DOWN
| Node | Tailscale IP | k3s API :6443 | Location |
|------|-------------|---------------|----------|
| pfv-k8s-cnode1 | 100.125.134.53 | **closed** | VM 102 on tsys1 |
| pfv-k8s-cnode2 | 100.109.34.72 | **OPEN** | VM 705 on tsys7 |
| pfv-k8s-cnode3 | 100.106.222.18 | **closed** | VM 603 on tsys6 |
- **No etcd quorum** (≤1 of 3 members). cnode1 and cnode3 k3s not listening.
- **kubeconfig stale**: `~/.kube/config.pfv-k8s` points to `100.97.178.106:6443`
— an IP matching NO current cnode. Cluster must be rebuilt.
- Worker nodes (5) all online on Tailscale, **not joined**:
pfv-k8s-wnode-tsys3/5/6/7/9.
## Monitoring / Observability Stack
| System | Host | Status | Access |
|--------|------|--------|--------|
| LibreNMS | tsys-librenms (100.86.204.77) | UP (Tailscale) | API needs token (401) — SSH in to create |
| Uptime Kuma | status.knownelement.com | UP | API key in `~/.secrets/api-keys.env`; `/metrics` needs auth |
| Beszel | (fleet) | deployed (per STATUS) | metrics host TBD |
| Home Assistant | (HAOS VM) | configured (per STATUS) | NUT integration live |
| **Vault** | vault.knownelement.com | **Deployed, UNCONFIGURED** | API keys migration = HIGH priority TODO |
## Console Management (pfv-tsys4)
ser2net listening on all 7 ports (2001-2007) bound to Tailscale 100.70.77.93.
All 7 `/dev/consoles/<name>` symlinks present:
```
pfv-core-sw01→ttyUSB2 pfv-tor3-mgmt→ttyUSB1 pfv-tor3-stor→ttyUSB6
pfv-rrinfra-rtr→ttyUSB5 pfv-r2-tor-top→ttyUSB7 subodev-torsw→ttyUSB0
pfv-r2-sw→ttyUSB3
```
**conman requires a PTY** — cannot be driven via stdin pipe from Crush. Use an
interactive terminal, or the conman client directly.
## Tailscale Fleet (80 nodes)
Three full environment tiers now exist, each mirroring the same service set:
- **`tsys-*` (production):** tsys-awx, tsys-ca, tsys-cloudron, tsys-librenms,
tsys-proxmox-datacenter, tsys-proxmox-mailgw-01/02, tsys-siem, tsys-ucs-01/02,
tsys-umbrel, tsys-voip
- **`preprod-*`:** preprod-awx, preprod-ca, preprod-cloudron, preprod-hfnoc-uisp,
preprod-librenms, preprod-proxmox-datacenter, preprod-proxmox-mailgw,
preprod-rancherplatform, preprod-siem, preprod-voip
- **`sectestbed-*`:** sectestbed-awx, sectestbed-ca, sectestbed-cloudron,
sectestbed-hfnoc-uisp, sectestbed-k8s-cnode, sectestbed-k8s-wnode,
sectestbed-librenms, sectestbed-netinfra, sectestbed-proxmox-datacenter,
sectestbed-proxmox-mailgw, sectestbed-proxmox-pbs, sectestbed-proxmox-pve,
sectestbed-rancherplatform, sectestbed-sandbox, sectestbed-siem, sectestbed-voip
Plus: pfv-tsys1/3/4/5/6/7/9, pfv-k8s-cnode1/2/3, pfv-k8s-wnode-tsys3/5/6/7/9,
pfv-netinfra-01/02, pfv-proxmox-backup-server, pfv-rr-middleware-01/02,
pfv-bms, pfv-jetson-nano-1, pfvsvrpi, devbox-cloudron, hfnoc-uisp,
kali-rd, kali-tsys, netbird, preprod-awx, subopi-dev-3/4, subopi3,
stlpc-artroom/garage, siter-bizoffice, ultix-* (endpoints).
> **Note:** Tailscale reports `--accept-routes is false` on this workstation.
## Identified LAN Hosts (non-switch)
| IP | Identity | Evidence |
|----|----------|----------|
| 192.168.0.100 | stlpc-garage.knel.net | Linux + Postfix + xrdp |
| 192.168.0.250 | Linux storage (NFS) | SSH + rpcbind |
| 192.168.1.166 | pfv-stor1 (NAS) | Samba smbd 4 + Golang HTTP + SSH |
| 192.168.3.1 | gateway/router | Linux + xrdp |
## Divergences vs STATUS.md (2026-07-30)
1. **VM count 28→63** — sectestbed (16) + preprod (8) + new prod VMs added
2. **DNS zones 124→167**, **DHCP leases 333→753**
3. **tsys4 PVE 9.1.5→9.2.5** (was "behind fleet")
4. **tsys5 NVMe+SSD** now configured (was "not configured")
5. **tsys-umbrel + tsys-sipwise** deployed (new VMs)
6. **LACP core↔r3-stor** operator reports fixed (was #1 known issue)
7. **k8s cluster** now DOWN (was LIVE)
8. **netinfra-02** wiped (was redundant secondary)
9. **Technitium** now Docker container (was systemd dnsServer)
10. **NTP** is ntpsec (STATUS assumed chrony)
11. **Pi-hole /dev/shm** = 1 GB (operator hotfix; gravity.db healthcheck still DNS-based)
12. **Tailscale fleet** 3× larger with 3 environment tiers
## Pending / Recommended Next Actions
*(From `nextprompt` — reference only; awaiting operator direction)*
- **netinfra-02 rebuild** as redundant secondary (SSH key deploy + Technitium
zone sync + DHCP failover-peer)
- **k8s cluster rebuild** (fix wiped cnode, restore quorum, join 5 wnodes)
- **Pi-hole** add gravity.db healthcheck to compose (current check is DNS-only)
- **Vault** migrate all API keys (HIGH priority)
- **Monitoring**: deploy unpoller + netdisco to LibreNMS VM; add weathermap/smokeping
- **Home Assistant**: own all environmental monitoring/reporting
- **Benchmarking**: iperf (1gbps-per-flow verification) + fio + CPU/RAM across cluster
- **Repo gardening**: README/AGENTS/docmap path fixes (this session)
> **Audit snapshot 2026-08-05 (current authoritative)**
>
> **Read it here:** https://community.turnsys.com/t/298
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+9 -219
View File
@@ -1,220 +1,10 @@
# Capacity & Sizing Goals
# proxmox/docs/CAPACITY-GOALS.md
**Date:** 2026-07-29
**Status:** Authoritative. These are the operator's standing targets. Every
fleet audit and VM-placement decision is evaluated against them.
> Companion to [`AUDIT-2026-07-29.md`](AUDIT-2026-07-29.md) (the current
> placement analysis) and [`PROJECT.md`](PROJECT.md) (the fleet hardware report).
---
## 1. Memory target: 80% steady-state
**Rule:** Keep each node at or below **80% physical RAM utilization at steady
state.** Occasional bursts above 80% are acceptable (that is what swap is for);
the *sustained* idle-to-average load must sit at ~80% or below.
**Two metrics must both be tracked:**
| Metric | Definition | Target |
|--------|-----------|--------|
| **Actual usage** | `MemTotal - MemAvailable` from `/proc/meminfo` | **≤ 80%** steady state (the real rule) |
| **Allocation commitment** | sum of running-VM `memory:` vs host RAM | planning ceiling — keep < 100% where possible |
**Why both:** KSM (same-page merging) and virtio-balloon mean *actual* usage is
often well below the sum of VM allocations (e.g. tsys1 allocates 115% but uses
72% actual). Actual usage is the steady-state truth; allocation is the
worst-case ceiling if every VM suddenly fills its reservation. A host is
"healthy" when actual ≤ 80% **and** allocation isn't so far over 100% that a
balloon-deflate storm could OOM it.
**Tolerance:** brief actual spikes to 90-100% are fine. Persistent swap use
(>~1 GB on a steady basis) means the host is over-committed and VMs should
migrate off.
## 2. CPU target: ~50% utilization at idle
**Rule:** Ideally, nodes sit around **50% CPU utilization at idle.**
This is a *utilization* goal, not a headroom goal. The fleet is
**CPU-underutilized** (most hosts idle at 0-6%). On a shoestring budget, idle
silicon is wasted investment and (for the PowerEdge hosts) wasted electricity.
The intent is to **pack workloads** so the baseline load consumes roughly half
the compute, reserving the other half for bursts.
**Practical implications:**
- The older, power-hungry hosts (tsys6 Nehalem, tsys5 Westmere) should either be
doing useful work at ~50% or be candidates to power down / solar-gate when
idle. Running them at 0-6% wastes power per core.
- The newer, efficient hosts (tsys9 Comet Lake, tsys3 Skylake) are cheap to run
idle and are the natural home for always-on control-plane + infra.
- vCPU overcommit is fine for idle workloads; the 50% target is about *actual*
utilization, not vCPU ratios.
## 3. Workload placement model
The fleet serves three distinct workload families. Placement should follow CPU
quality + storage speed + RAM size, in that order of relevance per family.
### 3.1 ETL / HPC / cross-compile (CPU + storage bound)
Large geospatial/weather ETL, RTL/firmware simulation, cross-compile pipelines.
**Needs high IPC (modern cores) + fast storage (SSD/NVMe).** RAM is moderate
(8-32 GB per job).
| Host | CPU | Storage | Fit |
|------|-----|---------|-----|
| **tsys9** | i5-10500 Comet Lake (2020) — **best IPC in fleet** | local SSD (PNY CS900) | **Primary compute node** |
| **tsys3** | Xeon E3-1535M v5 Skylake (2015) | local NVMe (Samsung PM961) | **Fast compute node** |
| tsys2 (incoming) | i7-7820HQ Kaby Lake (2017) | NVMe 960 PRO + SSD 850 EVO | **Fast compute node** (post-rebuild) |
These three hosts have the newest CPUs and the only fast local storage. Their
wnodes should be the **compute-tier** workers, sized larger (more cores/RAM) and
labeled `workload=compute`.
### 3.2 RackRental.net — network labs on demand (RAM + IOPS bound, CPU-light)
Business idea: rent out ephemeral network labs (containerlab topologies) on
demand. Many containers / network namespaces, short-lived, mostly idle once up.
**Needs massive RAM + fast container-image pulls. CPU quality is secondary**
(labs are idle between keystrokes).
| Host | CPU | RAM | Fit |
|------|-----|-----|-----|
| **tsys7** | 2× E5-2630 v2 Ivy Bridge (2013), 24 threads | **189 GB** | **Primary RackRental host** |
| **tsys6** | 2× E5530 Nehalem (2009), 16 threads | **126 GB** | **Secondary RackRental host** |
**Verdict: tsys6/7 are the correct RackRental hosts.** Their weak CPUs are
irrelevant for idle network labs; their RAM is unmatched. Their wnodes should be
labeled `workload=rackrental`.
**Caveat (deferred):** their local-lvm is USB 2.0 portable HDD (~30 MB/s), which
is terrible for container image pulls. This is a *disk* problem, not a RAM/CPU
problem, and is deferred to the post-Friday storage-class work. RAM-wise they are
ready today.
### 3.3 Infrastructure + k8s control plane (always-on, low resource)
netinfra, UCS, LibreNMS, SIEM, tailscale-router, PBS, k3s cnodes. Lightweight,
must stay up. Lives on tsys1 + tsys9 (and the cnodes spread across hosts for
etcd diversity).
---
## 4. Host role summary (target)
| Host | CPU era | RAM | Primary role | Wnode class |
|------|---------|-----|--------------|-------------|
| tsys1 | Haswell 2013 | 32 GB (maxed) | Infra + control plane | light (4c/4G) |
| tsys2 | Kaby Lake 2017 | 32 GB | Compute (incoming) | compute |
| tsys3 | Skylake 2015 | 32 GB | Compute | compute |
| tsys4 | Haswell 2013 | 16 GB | Storage (NFS + PBS) | — |
| tsys5 | Westmere 2010 | 96 GB | Storage + fast-tier hub | compute (NVMe, post-Friday) |
| tsys6 | Nehalem 2009 | 126 GB | RackRental | rackrental |
| tsys7 | Ivy Bridge 2013 | 189 GB | RackRental | rackrental |
| tsys9 | Comet Lake 2020 | 24 GB | Infra + control plane + compute | compute (growable) |
## 5. DDR3 memory policy
**Do not blindly add RAM to tsys6/7.** They idle at 6%/9% actual usage with
117/171 GB free — they are RAM-saturated in the wrong direction (over-provisioned,
not starved). The fleet's RAM pressure is on the *infra* hosts (tsys1/5/9
over-allocated), and that is solved by **migrating VMs** to tsys6/7's existing
free RAM, not by installing sticks.
Compatibility is decisive and is documented per-host in
[`AUDIT-2026-07-29.md`](AUDIT-2026-07-29.md) §5. Short version: tsys5/6/7 require
**Registered ECC (RDIMM)**; only RDIMM sticks will POST. Consumer UDIMM
(Patriot / most Kingston) fits essentially nowhere useful here.
---
## 6. Local storage policy: ephemeral scratch, not OS drives
**Principle:** Local disk storage is a **scratch tier**, not a boot/OS tier.
VM OS drives stay on NFS (tsys4/tsys5) where redundancy is handled by spreading
across physical disks and -01/-02 HA pairs. Local storage is used for ephemeral
workloads where data loss on node failure is acceptable by definition.
### 6.1 Why OS drives stay on NFS
Individual Proxmox nodes have **no local disk redundancy** (single disk, no
RAID, no ZFS mirror). If a host's local disk dies, every VM on it is gone.
Redundancy is instead achieved at the **storage-server + application layer**:
- **-01/-02 HA pairs** (netinfra, UCS): each half on a different NFS server
- **k8s spreading**: cnode/wnode disks spread across D2/D5/S2/S3/S4 so no
single disk or server failure takes down the whole cluster
- **PBS backups**: all VMs are backed up to Proxmox Backup Server regardless of
disk tier
This is deliberate. Moving OS drives to local storage would trade NFS network
latency for single-disk-failure risk. Not worth it for persistent workloads.
### 6.2 What local storage IS good for: ephemeral scratch
Workloads that produce or consume temporary data that can be discarded on node
failure. These are exactly the workloads where NFS latency hurts most and local
IOPS help most:
| Use case | Why local scratch helps | Examples |
|----------|------------------------|---------|
| **Container image pulls** | Image layers write to local disk during pull; NFS-over-HDD is seek-bound and slow | RackRental labs, any pod startup |
| **Build artifacts** | Cross-compile / firmware builds write hundreds of small files; local SSD/NVMe is 10-100x faster than NFS-HDD | ETL, cross-compile, CI pipelines |
| **Temporary processing** | Intermediate data that doesn't need to survive a reboot | Weather/GIS transform scratch, log rotation |
| **kubelet ephemeral storage** | `emptyDir` volumes, container writable layers | All k8s pods |
### 6.3 Per-host local storage inventory and suitability
| Host | Local storage | Type | Available | Scratch-suitable? | Notes |
|------|--------------|------|-----------|-------------------|-------|
| **tsys2** | NVMe 960 PRO + SSD 850 EVO | NVMe + SSD | 512 GB + 1 TB | **Yes — best in fleet** | Incoming (post-rebuild). No NFS needed at all |
| **tsys3** | local-lvm (Samsung PM961) | NVMe | 349 GB | **Yes — excellent** | Fastest existing local storage. 0% used |
| **tsys9** | local-lvm (PNY CS900) | SSD | 136 GB | **Yes — excellent** | Low latency. 0% used |
| **tsys5** | local-lvm (Hitachi) | HDD | ~1.7 TB | Yes (bulk) | Large capacity, HDD speed. Storage host — scratch is secondary |
| **tsys1** | local-lvm | HDD | ~90 GB | Marginal (small) | Barely worth it; tsys1 is infra-loaded anyway |
| **tsys4** | local-lvm | HDD | ~62 GB | No | PBS host; minimal free space |
| **tsys6** | local-lvm (WD My Passport) | **USB 2.0 HDD** | 1.7 TB | **NO — 30 MB/s** | Slower than NFS. Do not use for VMs |
| **tsys7** | local-lvm (WD portable) | **USB 2.0 HDD** | 1.7 TB | **NO — 30 MB/s** | Slower than NFS. Do not use for VMs |
**tsys6/7 are the hard problem.** They are the RackRental hosts — exactly the
workload that benefits most from local scratch (fast container image pulls) —
but their local storage is USB 2.0 portable HDD, which is slower than
NFS-over-HDD. Options for the future:
1. **Install internal drives** (tsys6 has a disabled SAS controller; tsys7 has
5 empty SATA ports). This is the real fix — gives both RackRental hosts proper
local scratch. Deferred to a physical-hardware session.
2. **Accept NFS for image pulls** and use local-lvm only for swap/temp that
tolerates 30 MB/s. Functional but sluggish for lab spin-up.
### 6.4 How this maps to k8s StorageClasses (future, post-Friday)
The scratch tier maps to two k8s concepts:
```
StorageClass: local-fast
provisioner: local-path
where: tsys3 (NVMe), tsys9 (SSD), tsys2 (NVMe+SSD), tsys5 (HDD)
use: emptyDir replacement, build artifacts, container runtime cache
redundancy: none — ephemeral, dies with the pod
StorageClass: nfs-hdd (existing concept)
provisioner: nfs-subdir-external
where: D2/D5 (tsys4), S1/S2/S3/S4 (tsys5)
use: persistent bulk data, VM OS drives, anything that must survive restarts
redundancy: cross-server spreading + PBS backup
```
A wnode with local scratch gets a second disk (or a partition on local-lvm)
mounted as `/scratch`. ETL jobs write intermediate data to `/scratch`
(local-fast) and final output to `/data` (nfs-hdd). Pods that need ephemeral
fast storage request `local-fast` PVCs; pods that need persistence request
`nfs-hdd`.
**This is forward-looking.** The concrete implementation (formatting local-lvm,
adding to Proxmox as VM disk targets, defining StorageClasses, labeling nodes)
happens after the Friday maintenance window when the SSD/NVMe tiers are
physically installed and the storage architecture is finalized.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Capacity targets + workload placement model**
>
> **Read it here:** https://community.turnsys.com/t/304
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+9 -174
View File
@@ -1,175 +1,10 @@
# Fleet Drift Report
# proxmox/docs/DRIFT-2026-07-30.md
> **Data gathered:** 2026-07-30 ~04:15 UTC (live, via `tests/remote.sh` from all 7 hosts)
> **Probe script:** `/tmp/pfv-probe-drift.sh` (read-only, all 7 hosts in parallel)
> **Report generated:** 2026-07-30
---
## Executive Briefing
### What needs your decision now
| # | Issue | Impact | Recommendation |
|---|-------|--------|---------------|
| **1** | **lldpd INACTIVE on tsys1** | No LLDP neighbor data from tsys1 — blind spot in network topology map | Enable: `systemctl enable --now lldpd` |
| **2** | **tsys9 missing 2 SSH keys** | Only 3 authorized_keys vs 5 on every other host — possible access gap | Verify which keys should be present; add missing |
| **3** | **iperf3 missing on tsys9** | Can't run throughput tests from the best compute host | Install: `apt install iperf3` |
| **4** | **net-tools missing on tsys1/6/7** | `ifconfig`/`netstat` unavailable (minor — `ip` command works) | Install for consistency: `apt install net-tools` |
| **5** | **sysstat missing on tsys5** | No `iostat`/`mpstat`/`sar` on a storage host | Install: `apt install sysstat` |
| **6** | **nvme-cli missing on tsys4/5** | Can't query NVMe health/SMART on the storage servers that have NVMe | Install: `apt install nvme-cli` |
| **7** | **tsys4 tuning drift** | rmem/wmem=16MB (fleet: 128MB), tcp_max_syn_backlog=1024 (fleet: 2048+), netdev_max_backlog=5000 (fleet: 250000), tuned=throughput-performance (should be network-throughput) | Run `apply-tunings.sh --apply` on tsys4 |
| **8** | **noatime only on tsys5 root** | All other hosts use relatime on root fs — minor perf difference | Standardize (noatime preferred for storage hosts) |
| **9** | **rsyslog inactive fleet-wide** | No syslog forwarding/receiving anywhere | Saturday OAM Day: set up centralized syslog |
| **10** | **snmpd inactive fleet-wide** | No SNMP polling on hosts (switches have it) | Saturday OAM Day: wire snmpd for LibreNMS |
| **11** | **beszel not deployed** | No metrics agent on any host yet | Saturday OAM Day: deploy Beszel agent fleet-wide |
### Consistent across the fleet (good)
These items are the SAME on all 7 hosts — no drift:
- **PVE version:** 9.2.5 / kernel 7.0.14-6-pve (except tsys4: 9.1.5 / 6.17.9 — known, separate upgrade task)
- **Debian version:** all on trixie/13
- **tcp_congestion_control:** bbr everywhere
- **CPUs scaling_governor:** performance everywhere (except tsys5: no cpufreq driver — Westmere, expected)
- **ethtool:** same version everywhere
- **nfs-common:** same version everywhere
- **tcpdump:** same version everywhere
- **smartmontools:** 7.5 everywhere, smartd active everywhere
- **tuned:** installed everywhere
- **SSHD config:** PermitRootLogin=yes, KbdInteractiveAuthentication=no everywhere (pubkey+2FA via PAM)
- **PasswordAuthentication:** not explicitly set (default) — relies on 2FA PAM module
### Quick severity summary
- **Fix now (5 min each, no risk):** lldpd on tsys1, iperf3 on tsys9, sysstat on tsys5, nvme-cli on tsys4/5
- **Fix with tuning pass:** tsys4 rmem/wmem/backlog/tuned-profile (via existing `apply-tunings.sh --apply`)
- **Saturday OAM Day:** rsyslog, snmpd, beszel fleet-wide deployment
- **Investigate:** tsys9 SSH key count (2 keys missing)
---
## Appendix A: Package Presence Matrix
> MISSING = not installed. Version shown = installed version (truncated).
| Package | tsys1 | tsys3 | tsys4 | tsys5 | tsys6 | tsys7 | tsys9 |
|---------|-------|-------|-------|-------|-------|-------|-------|
| lldpd | **MISSING** | 1.0.18 | 1.0.18 | 1.0.18 | 1.0.18 | 1.0.18 | 1.0.18 |
| smartmontools | 7.5 | 7.5 | 7.5 | 7.5 | 7.5 | 7.5 | 7.5 |
| nfs-common | 2.8.3 | 2.8.3 | 2.8.3 | 2.8.3 | 2.8.3 | 2.8.3 | 2.8.3 |
| nfs-kernel-server | — | — | 2.8.3 | 2.8.3 | — | — | — |
| iperf3 | 3.18 | 3.18 | 3.18 | 3.18 | 3.18 | 3.18 | **MISSING** |
| tcpdump | 4.99.5 | 4.99.5 | 4.99.5 | 4.99.5 | 4.99.5 | 4.99.5 | 4.99.5 |
| rsyslog | installed | installed | installed | installed | installed | installed | installed |
| qemu-guest-agent | — | — | — | — | — | — | — |
| snmpd | **MISSING** | **MISSING** | **MISSING** | **MISSING** | **MISSING** | **MISSING** | **MISSING** |
| net-tools | **MISSING** | 2.10 | 2.10 | 2.10 | **MISSING** | **MISSING** | **MISSING** |
| ethtool | 6.14.2 | 6.14.2 | 6.14.2 | 6.14.2 | 6.14.2 | 6.14.2 | 6.14.2 |
| sysstat | 12.7.5 | 12.7.5 | 12.7.5 | **MISSING** | 12.7.5 | 12.7.5 | 12.7.5 |
| nvme-cli | 2.13 | 2.13 | **MISSING** | **MISSING** | 2.13 | 2.13 | 2.13 |
| conman | — | — | 0.3.1 | — | — | — | — |
| ser2net | 4.6.4 | — | 4.6.4 | — | — | — | — |
| nut-server | 2.8.1 | — | — | — | — | — | — |
| tuned | 2.25.1 | 2.25.1 | 2.25.1 | 2.25.1 | 2.25.1 | 2.25.1 | 2.25.1 |
> **Note:** conman on tsys1, ser2net on tsys1, and nut-server on tsys1 are
> expected — tsys1 hosts the UPS (NUT) and has ser2net from a previous config.
> conman/ser2net on tsys4 is expected (console server). These are not drift.
## Appendix B: Service State Matrix
| Service | tsys1 | tsys3 | tsys4 | tsys5 | tsys6 | tsys7 | tsys9 |
|---------|-------|-------|-------|-------|-------|-------|-------|
| lldpd | **inactive** | active | active | active | active | active | active |
| smartd | active | active | active | active | active | active | active |
| snmpd | **inactive** | **inactive** | **inactive** | **inactive** | **inactive** | **inactive** | **inactive** |
| rsyslog | **inactive** | **inactive** | **inactive** | **inactive** | **inactive** | **inactive** | **inactive** |
| beszel | — | — | — | — | — | — | — |
> snmpd, rsyslog, and beszel are inactive on ALL hosts. These are Saturday OAM
> Day items, not drift — they haven't been deployed yet.
## Appendix C: Sysctl Tuning Matrix
| Setting | tsys1 | tsys3 | tsys4 | tsys5 | tsys6 | tsys7 | tsys9 |
|---------|-------|-------|-------|-------|-------|-------|-------|
| rmem_max | 128MB | 128MB | **16MB** | 128MB | 128MB | 128MB | 128MB |
| wmem_max | 128MB | 128MB | **16MB** | 128MB | 128MB | 128MB | 128MB |
| tcp_congestion | bbr | bbr | bbr | bbr | bbr | bbr | bbr |
| swappiness | 10 | 10 | 1 | 1 | 10 | 10 | 10 |
| tcp_max_syn_backlog | 2048 | 2048 | **1024** | 4096 | 4096 | 4096 | 2048 |
| netdev_max_backlog | 250000 | 250000 | **5000** | 250000 | 250000 | 250000 | 250000 |
| governor | perf | perf | perf | N/A | perf | perf | perf |
> **tsys4 is the outlier** on 4 settings: rmem/wmem (16MB vs 128MB),
> tcp_max_syn_backlog (1024 vs 2048+), netdev_max_backlog (5000 vs 250000).
> These directly affect NFS throughput — the 16MB TCP buffers cap per-connection
> window size, and the low backlog values can cause packet drops under load.
> swappiness=1 on tsys4/5 is intentional (storage hosts).
## Appendix D: Tuned Profile Matrix
| Host | Profile | Expected | Match? |
|------|---------|----------|--------|
| tsys1 | virtual-host | virtual-host | ✓ |
| tsys3 | virtual-host | virtual-host | ✓ |
| **tsys4** | **throughput-performance** | **network-throughput** | **✗** |
| tsys5 | network-throughput | network-throughput | ✓ |
| tsys6 | virtual-host | virtual-host | ✓ |
| tsys7 | virtual-host | virtual-host | ✓ |
| tsys9 | virtual-host | virtual-host | ✓ |
## Appendix E: SSH + Security State
### Authorized keys (root)
| Host | Key count | Notes |
|------|-----------|-------|
| tsys1 | 5 | Standard |
| tsys3 | 5 | Standard |
| tsys4 | 5 | Standard |
| tsys5 | 5 | Standard |
| tsys6 | 5 | Standard |
| tsys7 | 5 | Standard |
| **tsys9** | **3** | **2 fewer keys than rest of fleet — investigate** |
### SSHD config (consistent across fleet)
| Setting | Value | All hosts |
|---------|-------|-----------|
| PermitRootLogin | yes | ✓ (all) |
| PasswordAuthentication | (default — not set) | ✓ (all) |
| KbdInteractiveAuthentication | no | ✓ (all) |
> 2FA is enforced via PAM module (`secharden-2fa`), not via sshd's
> KbdInteractiveAuthentication. The PAM approach is consistent.
## Appendix F: Filesystem Mount Options
| Host | root fs mount option | Notes |
|------|---------------------|-------|
| tsys1 | relatime | Default |
| tsys3 | relatime | Default |
| tsys4 | relatime | Default |
| **tsys5** | **noatime** | **Only host with noatime on root** |
| tsys6 | relatime | Default |
| tsys7 | relatime | Default |
| tsys9 | relatime | Default |
> Minor: noatime reduces metadata writes (slight improvement on HDD).
> Storage hosts (tsys4/5) would benefit most from noatime.
## Appendix G: Raw Data Location
All raw drift probe output is stored in `/tmp/<hostname>-drift.txt` on this
workstation (not committed — ephemeral). Re-gather any time with:
```bash
for h in pfv-tsys1 pfv-tsys3 pfv-tsys4 pfv-tsys5 pfv-tsys6 pfv-tsys7 pfv-tsys9; do
PROX_HOST=$h bash tests/remote.sh prox-file /tmp/pfv-probe-drift.sh > /tmp/$h-drift.txt
done
```
The probe script should be saved to the repo as `perf/scripts/probe-drift.sh`
for reuse. It is read-only and portable.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Fleet drift report 2026-07-30**
>
> **Read it here:** https://community.turnsys.com/t/298
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+8 -171
View File
@@ -1,173 +1,10 @@
# Host Reference
# proxmox/docs/HOST-REFERENCE.md
> **One-page-per-host quick reference for every Proxmox node.** Hardware,
> network, storage, role, and running VMs. Data gathered 2026-07-30.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> Companion docs: [`NETWORK-TOPOLOGY.md`](NETWORK-TOPOLOGY.md),
> [`STORAGE-ARCHITECTURE.md`](STORAGE-ARCHITECTURE.md),
> [`VM-INVENTORY.md`](VM-INVENTORY.md).
---
## Fleet summary
```mermaid
graph TB
subgraph "RACK 5 -- Core / Data / Infra"
T1["tsys1 -- Infra<br>i7-4770 | 32GB | 9 VMs<br>57% RAM"]
T3["tsys3 -- Compute<br>Xeon E3-1535M v5 | 32GB | 1 VM<br>10% RAM"]
T4["tsys4 -- Storage+PBS<br>Xeon E3-1246 v3 | 16GB | 1 VM<br>15% RAM"]
T5["tsys5 -- Storage+Sandbox<br>Xeon E5620 | 96GB | 4 VMs<br>15% RAM"]
T9["tsys9 -- Infra+Compute<br>i5-10500 | 24GB | 6 VMs<br>69% RAM"]
end
subgraph "RACK 3 -- Compute / RackRental"
T6["tsys6 -- RackRental<br>2x Xeon E5530 | 126GB | 2 VMs<br>12% RAM"]
T7["tsys7 -- RackRental<br>2x Xeon E5-2630 v2 | 189GB | 5 VMs<br>7% RAM"]
end
```
| Host | CPU (era) | Threads | RAM | PVE | Kernel | Role | Running VMs | RAM actual% |
|------|-----------|---------|-----|-----|--------|------|-------------|-------------|
| tsys1 | i7-4770 Haswell (2013) | 8 | 32 GB | 9.2.5 | 7.0.14 | Infra | 9 | 57% |
| tsys3 | Xeon E3-1535M v5 Skylake (2015) | 8 | 32 GB | 9.2.5 | 7.0.14 | Compute | 1 | 10% |
| tsys4 | Xeon E3-1246 v3 Haswell (2013) | 8 | 16 GB | **9.1.5** | **6.17.9** | Storage + PBS | 1 | 15% |
| tsys5 | Xeon E5620 Westmere (2010) | 8 | 96 GB | 9.2.5 | 7.0.14 | Storage + Sandbox | 4 | 15% |
| tsys6 | 2x Xeon E5530 Nehalem (2009) | 16 | 126 GB | 9.2.5 | 7.0.14 | RackRental | 2 | 12% |
| tsys7 | 2x Xeon E5-2630 v2 Ivy Bridge (2013) | 24 | 189 GB | 9.2.5 | 7.0.14 | RackRental | 5 | 7% |
| tsys9 | i5-10500 Comet Lake (2020) | 12 | 24 GB | 9.2.5 | 7.0.14 | Infra + Compute | 6 | 69% |
**Retired:** tsys2 (Win10, pending rebuild), tsys8 (permanently retired)
---
## pfv-tsys1 -- Infrastructure host
| Attribute | Value |
|-----------|-------|
| **Role** | Infrastructure: Home Assistant, CA, netinfra-01, LibreNMS, PDM, k8s cnode3, UCS-01, kali, workbench |
| **Hardware** | Dell, i7-4770 Haswell (2013), 8 threads, 32 GB RAM (maxed) |
| **PVE** | 9.2.5 / kernel 7.0.14-6-pve |
| **mgmt IP** | 192.168.3.11 (vmbr0, DHCP) |
| **Tailscale** | 100.121.189.98 |
| **Storage IP** | 10.100.100.1 (datanet via nic1, USB dongle, no bond) |
| **NFS mounts** | S1, S2, S3, S4, D2 (all nconnect=4) |
| **Local storage** | local-lvm (~90 GB, HDD, marginal) |
| **Tuning** | governor=performance, swappiness=10, bbr, rmem/wmem=128MB, tuned=virtual-host |
| **Bond** | None (single USB NIC for storage) |
| **Special services** | NUT (UPS), powerman (PDU) |
| **Running VMs** | 100, 101, 103, 104, 105, 106, 108, 114, 117 |
---
## pfv-tsys3 -- Compute host
| Attribute | Value |
|-----------|-------|
| **Role** | Compute: k8s wnode-tsys3 (28 GB RAM, 8 vCPU) |
| **Hardware** | Xeon E3-1535M v5 Skylake (2015), 8 threads, 32 GB RAM |
| **PVE** | 9.2.5 / kernel 7.0.14-6-pve |
| **mgmt IP** | 192.168.2.5 (vmbr0, DHCP) |
| **Storage IP** | 10.100.100.3 (datanet via enx USB dongle, no bond) |
| **NFS mounts** | D2, D5, S2, S4, T5-SSD (all nconnect=4) |
| **Local storage** | local-lvm (Samsung PM961 NVMe, 349 GB, 0% used) -- **best existing local storage** |
| **Tuning** | governor=performance, swappiness=10, bbr, rmem/wmem=128MB, tuned=virtual-host |
| **Bond** | None (single USB NIC for storage) |
| **Running VMs** | 313 |
---
## pfv-tsys4 -- Storage server + PBS
| Attribute | Value |
|-----------|-------|
| **Role** | NFS storage server (D1/D2/D3/D5) + Proxmox Backup Server + console management (conman/ser2net) |
| **Hardware** | Xeon E3-1246 v3 Haswell (2013), 8 threads, 16 GB RAM |
| **PVE** | **9.1.5** / kernel **6.17.9-1-pve** (BEHIND fleet) |
| **mgmt IP** | 192.168.3.251 (vmbr0, DHCP) |
| **Tailscale** | 100.70.77.93 |
| **Storage IP** | 10.100.100.4 (datanet via enx8cae4ccda926 USB dongle, bond0 with 1 slave) |
| **NFS mounts** | None (NFS server only) |
| **Local storage** | local-lvm (WDC WD10EZRX 1TB, ~62 GB free) |
| **NFS exports** | D1 (WD 1TB USB), D2 (WDC Red 3TB), D3 (Seagate 500GB USB), D5 (Hitachi 2TB) |
| **Other disks** | /mnt/albert (Hitachi 2TB, not exported), /mnt/backup (WD 5TB USB) |
| **Tuning** | governor=performance, swappiness=1, bbr, **rmem/wmem=16MB** (should be 128MB), **tuned=throughput-performance** (should be network-throughput) |
| **Bond** | bond0 (1 USB slave), hash=layer2+3 |
| **Special services** | ser2net + conman (7 switch consoles on :7890) |
| **Running VMs** | 400 (PBS) |
| **Notes** | USB NIC bottleneck. Needs PVE upgrade + tuning alignment. |
---
## pfv-tsys5 -- Storage server + sandboxes
| Attribute | Value |
|-----------|-------|
| **Role** | NFS storage server (S1/S2) + sectestbed sandboxes + ultix streaming |
| **Hardware** | Dell T7500, Xeon E5620 Westmere (2010) **single CPU** (CPU2 socket empty), 8 threads, 96 GB RAM |
| **PVE** | 9.2.5 / kernel 7.0.14-6-pve |
| **mgmt IP** | 192.168.3.179 (vmbr0, DHCP) |
| **Storage IP** | 10.100.100.5 (storagenet via bond0, **1 of 2 slaves active** -- nic2 DOWN) |
| **NFS mounts** | D2, D3, D5 from tsys4 (**missing nconnect**) |
| **NFS exports** | S1 (IronWolf 1TB), S2 (IronWolf 1TB), S3 (stale), SSD (Samsung 860 PRO) |
| **Local storage** | local-lvm (Hitachi 2TB), local-nonprod (=S1), SSD dir (Samsung 860 PRO 256GB) |
| **Unconfigured disks** | **NVMe CT500P1 500GB** (not mounted), **SK hynix SC300B 512GB SSD** (not mounted) |
| **Tuning** | governor=N/A (no cpufreq driver on Westmere), swappiness=1, bbr, rmem/wmem=128MB, tuned=network-throughput |
| **Bond** | bond0 (1 of 2 slaves), hash=layer2+3 |
| **Running VMs** | 509, 515, 5111, 5112 (+ 22 stopped sandboxes) |
| **Notes** | Bond degraded (needs 2nd cable). NVMe + SSD need mounting/config. SSD 93% full. Single CPU. |
---
## pfv-tsys6 -- RackRental host
| Attribute | Value |
|-----------|-------|
| **Role** | RackRental: k8s wnode-tsys6 (64 GB RAM) + AWX |
| **Hardware** | 2x Xeon E5530 Nehalem (2009), 16 threads, 126 GB RAM |
| **PVE** | 9.2.5 / kernel 7.0.14-6-pve |
| **mgmt IP** | 192.168.3.169 (vmbr0, DHCP) |
| **Tailscale** | 100.73.35.111 |
| **Storage IP** | 10.100.100.6 (storagenet via bond0, **2 of 2 slaves active**, 2G LACP) |
| **NFS mounts** | D1, D2, D3, D5, S1, S2, S3, S4, T5-SSD (9 mounts, all nconnect=4) |
| **Local storage** | local-lvm (WD My Passport USB 2.0 HDD, 1.7 TB, **30 MB/s -- do not use for VMs**) |
| **Tuning** | governor=performance, swappiness=10, bbr, rmem/wmem=128MB, tuned=virtual-host |
| **Bond** | bond0 (2 of 2 slaves), **hash=layer3+4** (correct) |
| **Running VMs** | 100 (wnode-tsys6, 64GB), 600 (tsys-awx) |
| **Notes** | Best storage bond in fleet (2G LACP). Local storage is USB 2.0 -- unusable for scratch. |
---
## pfv-tsys7 -- RackRental host
| Attribute | Value |
|-----------|-------|
| **Role** | RackRental: k8s wnode-tsys7 + hfnoc-uisp + rr-middleware + TCTC + k8s cnode2 |
| **Hardware** | 2x Xeon E5-2630 v2 Ivy Bridge (2013), 24 threads, 189 GB RAM |
| **PVE** | 9.2.5 / kernel 7.0.14-6-pve |
| **mgmt IP** | 192.168.3.55 (vmbr0, DHCP) |
| **Storage IP** | 10.100.100.7 (datanet via bond0, **2 of 2 slaves active**, 2G LACP) |
| **NFS mounts** | D1, D2, D3, D5, S1, S2, S3, S4, T5-SSD (9 mounts, all nconnect=4) |
| **Local storage** | local-lvm (WD portable USB 2.0 HDD, 1.7 TB, **30 MB/s -- do not use for VMs**) |
| **Tuning** | governor=performance, swappiness=10, bbr, rmem/wmem=128MB, tuned=virtual-host |
| **Bond** | bond0 (2 of 2 slaves), **hash=layer3+4** (correct) |
| **Running VMs** | 701, 702, 703, 704, 705 |
| **Notes** | Best storage bond in fleet (2G LACP). Most RAM in fleet (189 GB). Local storage USB 2.0. |
---
## pfv-tsys9 -- Infra + Compute
| Attribute | Value |
|-----------|-------|
| **Role** | Infra + Compute: k8s cnode1 + wnode-tsys9 + siem + UCS-02 + netinfra-02 + kali |
| **Hardware** | i5-10500 Comet Lake (2020), 12 threads, 24 GB RAM |
| **PVE** | 9.2.5 / kernel 7.0.14-6-pve |
| **mgmt IP** | 192.168.3.58 (vmbr0, DHCP) |
| **Storage IP** | 10.100.100.9 (datanet via enx9c69d36a5b6c USB dongle, no bond) |
| **NFS mounts** | D2, D5, S2, S3, S4, T5-SSD (all nconnect=4) |
| **Local storage** | local-lvm (PNY CS900 SSD, 136 GB, 0% used) -- **excellent for scratch** |
| **Tuning** | governor=performance, swappiness=10, bbr, rmem/wmem=128MB, tuned=virtual-host |
| **Bond** | None (single USB NIC for storage) |
| **Running VMs** | 901, 902, 903, 904, 905, 906 |
| **Notes** | Newest CPU (best IPC in fleet). **69% RAM -- approaching 80% goal.** Target for compute growth (after siem migrates off). |
> **Per-host hardware/network/storage/tuning/role reference**
>
> **Read it here:** https://community.turnsys.com/t/304
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+10 -485
View File
@@ -1,485 +1,10 @@
# K8S.md -- Kubernetes Architecture Deep-Dive
**Date:** 2026-07-27
**Purpose:** Detailed kubernetes architecture plan for the pfv-k8s cluster.
Companion to [`PROJECT.md`](PROJECT.md) (which has the fleet-wide assessment).
**Status:** For discussion in a future session. No changes made.
---
## Table of Contents
1. [Workload Profile](#1-workload-profile)
2. [Current State](#2-current-state)
3. [Target Architecture](#3-target-architecture)
4. [Control Plane (Cnodes)](#4-control-plane-cnodes)
5. [Worker Nodes (Wnodes)](#5-worker-nodes-wnodes)
6. [Storage Class Design](#6-storage-class-design)
7. [ETL/HPC Considerations](#7-etlhpc-considerations)
8. [Migration Plan](#8-migration-plan)
---
## 1. Workload Profile
This cluster runs **R&D and RackRental (containerlab) workloads** via
Kubernetes. Production (Gitea, RustFS, Redmine, websites) lives on a VPS in
Reston, VA running Cloudron.
**Workload types expected:**
| Type | Description | Storage need | RAM need | Examples |
|------|------------|-------------|----------|---------|
| **ETL (weather/GIS)** | Batch processing of large geospatial datasets. Sequential reads, transform, sequential writes. | High capacity (100s of GB), moderate IOPS | Medium (8-32 GB per job) | GRIB/NetCDF processing, raster reprojection |
| **HPC (hardware startup)** | Compute-intensive simulations, firmware build pipelines, hardware-in-the-loop testing. | Low capacity, moderate IOPS | High (32-128 GB per job) | RTL simulation, PCB thermal analysis |
| **RackRental (containerlab)** | Rapid deployment/teardown of network lab topologies. Many containers, short-lived. | Low capacity, high IOPS (container image pulls) | Low-Medium (4-16 GB) | Network topology testing, protocol validation |
**Key storage insight:** ETL workloads need bulk capacity (NFS-HDD is fine --
sequential I/O). HPC and containerlab need low-latency random I/O (local
SSD/NVMe is essential). The tiered StorageClass design (section 6) serves both.
---
## 2. Current State
### 2.1 pfv-k8s nodes and their storage
| Node | Type | Host | Storage | Disk type | Status |
|------|------|------|---------|-----------|--------|
| cnode1 (107) | control | tsys1 | D5 (tsys4) | NFS-HDD | running |
| cnode2 (603) | control | tsys6 | D2 (tsys4) | NFS-HDD | running |
| cnode3 (106) | control | tsys1 | D2 (tsys4) | NFS-HDD | running |
| cnode4 (601) | control | tsys6 | D2 (tsys4) | NFS-HDD | running |
| cnode5 (602) | control | tsys6 | D5 (tsys4) | NFS-HDD | running |
| wnode-tsys3 (313) | worker | tsys3 | D5 (tsys4) | NFS-HDD | running |
| wnode-tsys5 (509) | worker | tsys5 | D2 (tsys4) | NFS-HDD | running |
| wnode-tsys6 (100) | worker | tsys6 | D5 (tsys4) | NFS-HDD | **STOPPED** |
| wnode-tsys7 (701) | worker | tsys7 | D5 (tsys4) | NFS-HDD | running |
| wnode-tsys9 (905) | worker | tsys9 | S3 (tsys5) | NFS-HDD | running |
### 2.2 Problems
1. **100% of cnodes on tsys4 NFS.** D2 disk failure loses 3 of 5 cnodes =
etcd quorum lost.
2. **90% of all k8s nodes on tsys4 NFS.** tsys4 failure kills the cluster.
3. **Zero nodes use SSD or NVMe.** All on NFS-over-HDD.
4. **Zero nodes use local-lvm.** tsys3/6/7/9 all have empty local storage
(349 GB / 1.7 TB / 1.7 TB / 136 GB SSD respectively).
5. **wnode-tsys6 is stopped.** Reduces cluster capacity.
6. **3 cnodes on tsys6** -- should be on lighter hosts to free tsys6 for workers.
---
## 3. Target Architecture
### 3.1 Design principles
1. **Cnodes on lightweight hosts** (tsys1, tsys9, tsys3) -- frees tsys6/7 for
heavy workers.
2. **Cnode storage split across tsys4 and tsys5** -- etcd survives either
storage server failing.
3. **Wnode boot disks on local storage** -- eliminates NFS latency for
container runtime and kubelet.
4. **Wnode data disks on NFS-HDD** -- bulk capacity for ETL/weather/GIS.
5. **tsys5 NVMe dedicated to wnode-tsys5** -- fastest tier for HPC jobs.
6. **One wnode per hypervisor host** -- maximize total cluster capacity.
### 3.2 Target node-host-storage matrix
| Node | Type | Host | Boot disk | Data disk | Disk type |
|------|------|------|-----------|-----------|-----------|
| cnode1 | control | tsys1 | D5 (tsys4) | -- | NFS-HDD |
| cnode2 | control | tsys9 | D2 (tsys4) | -- | NFS-HDD |
| cnode3 | control | tsys1 | S2 (tsys5) | -- | NFS-HDD |
| cnode4 | control | tsys9 | D5 (tsys4) | -- | NFS-HDD |
| cnode5 | control | tsys3 | S3 (tsys5) | -- | NFS-HDD |
| wnode-tsys1 | worker | tsys1 | D5 (tsys4) | -- | NFS-HDD (small) |
| wnode-tsys2 | worker | tsys2 | **NVMe (960 PRO 512GB)** | **SATA SSD (850 EVO 1TB)** | **NVMe + SSD -- no NFS needed** |
| wnode-tsys3 | worker | tsys3 | **local-lvm (NVMe PM961)** | S3 (NFS) | **LOCAL-NVMe** |
| wnode-tsys5 | worker | tsys5 | **NVMe (local, Friday)** | local-nonprod (HDD) | **NVMe** |
| wnode-tsys6 | worker | tsys6 | D2 (tsys4 NFS) | -- | NFS-HDD (local-lvm is USB 2.0 -- do not use) |
| wnode-tsys7 | worker | tsys7 | D5 (tsys4 NFS) | -- | NFS-HDD (local-lvm is USB 2.0 -- do not use) |
| wnode-tsys9 | worker | tsys9 | **local-lvm (SSD)** | S2 (NFS) | **LOCAL-SSD** |
### 3.3 Storage server distribution after changes
| Storage server | cnodes | wnodes (boot) | wnodes (data) |
|---------------|--------|---------------|---------------|
| tsys4 (D2) | cnode2 | wnode-tsys6 | wnode-tsys7 |
| tsys4 (D5) | cnode1, cnode4 | wnode-tsys1 | -- |
| tsys5 (S2) | cnode3 | wnode-tsys9 | -- |
| tsys5 (S3) | cnode5 | -- | wnode-tsys3 |
**Note:** wnode-tsys2 needs no NFS (1.5 TB local SSD). wnode-tsys6/7 stay on
NFS by design -- their local-lvm is USB 2.0 portable HDD (~30 MB/s), slower
than NFS-HDD, and the user has chosen not to install internal drives.
**No single disk or server is a quorum-losing failure point.**
---
## 4. Control Plane (Cnodes)
### 4.1 Cnode sizing
Each cnode: 4 cores, 4 GB RAM, 32 GB disk. This is sufficient for etcd +
kubernetes control plane components (API server, scheduler, controller-manager).
### 4.2 Cnode host placement rationale
| Host | cnodes | RAM for cnodes | Total host RAM | Remaining for other VMs |
|------|--------|---------------|---------------|------------------------|
| tsys1 | 2 (cnode1, cnode3) | 8 GB | 32 GB | ~24 GB (but 11 infra VMs consume most) |
| tsys9 | 2 (cnode2, cnode4) | 8 GB | 24 GB | ~16 GB (4 infra VMs + 1 wnode) |
| tsys3 | 1 (cnode5) | 4 GB | 32 GB | ~28 GB (1 wnode at 20 GB = 8 GB headroom) |
**tsys6 and tsys7 have ZERO cnodes** -- fully dedicated to heavy worker nodes.
### 4.3 Cnode storage placement rationale
The 5 cnodes are split 3-on-tsys4 / 2-on-tsys5:
| Disk | cnodes | Rationale |
|------|--------|-----------|
| D5 (tsys4 HDD) | cnode1, cnode4 | Spread load across 2 disks on tsys4 |
| D2 (tsys4 HDD) | cnode2 | Only 1 cnode on D2 (was 3 -- reduces blast radius) |
| S2 (tsys5 HDD) | cnode3 | tsys5 storage for quorum diversity |
| S3 (tsys5 HDD) | cnode5 | tsys5 storage, different disk than S2 |
**If D2 fails:** cnode2 dies. 4 of 5 survive. Quorum OK.
**If D5 fails:** cnode1 + cnode4 die. 3 of 5 survive. Quorum OK.
**If tsys4 fails:** cnode1, cnode2, cnode4 die. cnode3 + cnode5 survive on
tsys5. **Only 2 of 5 -- QUORUM LOST.**
Wait -- that is a problem. If tsys4 goes completely offline, we lose 3
cnodes and only have 2 on tsys5. That loses quorum (need 3).
**Revision needed:** Move 1 more cnode to tsys5 storage. Target: 2 on tsys4,
3 on tsys5. But that means tsys5 failure (3 cnodes die) leaves only 2 on
tsys4. Same problem inverted.
The fundamental issue: with 5 cnodes and 2 storage servers, the best split is
3/2. The server holding 3 cnodes is a quorum-loss risk if it fails. The server
holding 2 cnodes is safe (3 survive).
**Proper solution: 3 cnodes on the "less likely to fail" server, 2 on the
other.** After Friday's hardware work:
- tsys4 will have a new PCIe NIC + 64 GB RAM -- more reliable
- tsys5 will have bond0 fixed + NVMe -- more reliable
Either way, 3/2 split means one server failure could lose quorum. **To truly
solve this, use a 3rd storage target.** Options:
- Use tsys9 local SSD for 1 cnode (breaks the 2-server model, adds a 3rd
independent failure domain)
- Use local-lvm on the cnode's own host (etcd data is local to the VM's host,
no NFS dependency at all)
**Best option: put cnode boot disks on local-lvm where available.** This
eliminates NFS entirely for the control plane. Each cnode's etcd data lives on
its own host's local disk -- no shared dependency.
| cnode | Host | **Recommended storage** | Type |
|-------|------|------------------------|------|
| cnode1 | tsys1 | **local-lvm** (if space) or D5 (tsys4) | LOCAL-HDD or NFS-HDD |
| cnode2 | tsys9 | **local-lvm (SSD)** | **LOCAL-SSD** |
| cnode3 | tsys1 | **S2 (tsys5)** | NFS-HDD |
| cnode4 | tsys9 | **local-lvm (SSD)** | **LOCAL-SSD** |
| cnode5 | tsys3 | **local-lvm** | LOCAL-HDD |
With this layout, a tsys4 failure takes down 0 cnodes. A tsys5 failure takes
down 1 (cnode3). A host failure takes down at most 2 cnodes. Quorum always
survives.
**This is the recommended approach.** Local storage for cnodes wherever
possible. NFS only as fallback.
### 4.4 etcd performance on local vs NFS
| Storage | Typical fsync latency | etcd commit latency | Impact |
|---------|----------------------|--------------------|--------|
| NFS-HDD (via USB dongle on tsys4) | 5-15 ms | 10-30 ms | Slow API responses, sluggish pod scheduling |
| NFS-HDD (via PCIe NIC, post-Friday) | 2-8 ms | 5-15 ms | Better but still network-bound |
| Local HDD (tsys1/3/6/7 local-lvm) | 1-5 ms | 3-10 ms | No network hop, moderate improvement |
| Local SSD (tsys9 PNY CS900) | 0.1-0.5 ms | 0.5-2 ms | **10-30x faster than NFS-HDD** |
| NVMe (tsys5, Friday) | 0.02-0.1 ms | 0.1-0.5 ms | **100x faster than NFS-HDD** |
etcd is the heartbeat of the kubernetes control plane. Every API call, every
pod schedule, every controller reconciliation involves an etcd write. Cutting
etcd commit latency from 15 ms to 1 ms makes the entire cluster feel 15x more
responsive. **This is the single highest-impact change for k8s performance.**
---
## 5. Worker Nodes (Wnodes)
### 5.1 One wnode per hypervisor host
| Host | wnode | Boot disk | Data disk | Total RAM | wnode RAM | Role |
|------|-------|-----------|-----------|-----------|-----------|------|
| tsys1 | wnode-tsys1 | D5 (tsys4 NFS) | -- | 32 GB | 4-8 GB | Small worker, infra co-tenant |
| tsys2 | wnode-tsys2 | **NVMe (960 PRO 512GB)** | **SATA SSD (850 EVO 1TB)** | 32 GB | 16-24 GB | **Best storage of any worker -- 1.5TB local SSD, no NFS needed** |
| tsys3 | wnode-tsys3 | **local-lvm (349 GB)** | S3 (NFS) | 32 GB | 20 GB | General worker |
| tsys5 | wnode-tsys5 | **NVMe (local)** | local-nonprod (HDD) | 96 GB | 32-64 GB | **HPC/ETL powerhouse** |
| tsys6 | wnode-tsys6 | D2 (tsys4 NFS) | -- | 128 GB | 64-96 GB | **Heavy worker, max RAM.** local-lvm is USB 2.0 -- stays on NFS |
| tsys7 | wnode-tsys7 | D5 (tsys4 NFS) | -- | 192 GB | 96-128 GB | **Heavy worker, max RAM.** local-lvm is USB 2.0 -- stays on NFS |
| tsys9 | wnode-tsys9 | **local-lvm SSD (136 GB)** | S2 (NFS) | 24 GB | 4-8 GB | Small worker, SSD boot |
### 5.2 Why boot disks on local-lvm
Current: all wnodes boot from NFS. Every container image pull, every kubelet
log write, every ephemeral volume traverses the NFS network path.
With local-lvm boot disks:
- **Container image pulls** write to local disk (100-150 MB/s HDD, no network
hop) instead of NFS-HDD (80-120 MB/s with network latency)
- **kubelet logs** stay local (no NFS writes for log rotation)
- **ephemeral storage** (emptyDir volumes) uses local disk by default
- **NFS server failure does not kill the wnode** -- the VM stays running, only
the data disk (if mounted) goes away
### 5.3 Wnode sizing guidance
| Host | Recommended wnode config | Rationale |
|------|------------------------|-----------|
| tsys7 (192 GB) | 8-12 cores, 96-128 GB RAM, NFS boot | Largest host -- run the heaviest ETL/HPC jobs here. local-lvm is USB 2.0 |
| tsys6 (128 GB) | 8 cores, 64-96 GB RAM, NFS boot | Second-largest -- parallel heavy jobs. local-lvm is USB 2.0 |
| tsys5 (96 GB + NVMe) | 4 cores, 32-64 GB RAM, NVMe boot + HDD data | NVMe makes this fastest for I/O-bound HPC |
| tsys3 (32 GB) | 4 cores, 20 GB RAM, local-lvm boot | General-purpose worker |
| tsys2 (32 GB, NVMe+SSD, incoming) | 4 cores, 16-24 GB RAM, **NVMe boot + SSD data** | **Fastest storage worker** -- HPC with I/O bounds |
| tsys1 (32 GB) | 2 cores, 4-8 GB RAM | Small worker, don't starve infra VMs |
| tsys9 (24 GB) | 2-4 cores, 4-8 GB RAM | Small worker, SSD boot is the advantage |
### 5.4 Tainting and labeling strategy
Label wnodes by capability so the k8s scheduler can target them:
```yaml
# Heavy RAM hosts (ETL/HPC)
wnode-tsys6: workload=heavy, ram=128g
wnode-tsys7: workload=heavy, ram=192g
# NVMe host (I/O-intensive HPC)
wnode-tsys5: workload=hpc, storage=nvme
# SSD boot host (low-latency)
wnode-tsys9: workload=light, storage=ssd
# General workers
wnode-tsys3: workload=general
wnode-tsys2: workload=storage-fast, storage=nvme
wnode-tsys1: workload=light
```
Then use nodeSelector or nodeAffinity in job specs:
```yaml
# Weather/GIS ETL job -- needs lots of RAM
spec:
nodeSelector:
workload: heavy
# Firmware build -- needs fast storage
spec:
nodeSelector:
storage: nvme
```
---
## 6. Storage Class Design
### 6.1 Proposed StorageClasses
| StorageClass | Provisioner | Where | Speed | Use case |
|-------------|------------|-------|-------|----------|
| `local-fast` | local-path (k8s) | wnode local-lvm / NVMe | 100-3500 MB/s | Container runtime, scratch, databases |
| `nfs-hdd` | nfs-subdir-external-provisioner | tsys4 D2/D5, tsys5 S1-S4 | 80-120 MB/s | Bulk data, weather/GIS datasets |
| `nfs-ssd` | nfs-subdir-external-provisioner | tsys4 D3, tsys5 T5-SSD | 200-400 MB/s | Latency-sensitive persistent data |
### 6.2 How this maps to wnode disk topology
Each wnode has:
- **Disk 1 (boot/OS):** local-lvm or NVMe. Contains the OS, kubelet, container
runtime. k8s `local-fast` StorageClass provisioner points here.
- **Disk 2 (bulk data, optional):** NFS mount. Mounted inside the VM as a
second block device or filesystem. k8s `nfs-hdd` provisioner points here.
Inside k8s, pods request storage via PVC:
```yaml
# ETL job: needs bulk storage for weather data
apiVersion: v1
kind: PersistentVolumeClaim
spec:
storageClassName: nfs-hdd
accessModes: [ReadWriteMany] # NFS allows RWX
resources:
requests:
storage: 500Gi
# HPC job: needs fast scratch
spec:
storageClassName: local-fast
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 50Gi
```
### 6.3 NFS-SSD tier (D3 and T5-SSD -- both on tsys5 after Friday)
**Storage philosophy (user directive): NVMe/SSD is EXCLUSIVELY for k8s worker
scratch space, with the exception of ultix-streaming which stays on T5-SSD.
Spinning rust hosts all other infrastructure VMs** (UCS, netinfra, LibreNMS,
SIEM, etc.).
The SSD NFS exports:
- **D3 (tsys5 SAS, 445 GB free):** k8s scratch exclusively (etcd, container
cache, ephemeral volumes). Currently 99% empty.
- **T5-SSD (tsys5 SAS, 140 GB free after ultix-streaming):** ultix-streaming
occupies 83 GB. Remaining 140 GB available for k8s use.
**tsys5 is the fast-tier hub:** NVMe (local) + D3 SSD + T5-SSD all on one host.
This simplifies the StorageClass design -- latency-sensitive k8s PVCs target
tsys5 SSD exports, bulk PVCs target either server.
### 6.4 NFS data distribution across storage servers
To avoid re-creating the "everything on tsys4" problem, distribute NFS data
disks across both servers:
| wnode | Boot (local) | Bulk data (NFS) | NFS server |
|-------|-------------|-----------------|------------|
| wnode-tsys3 | local-lvm | S3 | tsys5 |
| wnode-tsys5 | NVMe | local-nonprod | local (no NFS) |
| wnode-tsys6 | D2 (tsys4 NFS) | -- | tsys4 |
| wnode-tsys7 | D5 (tsys4 NFS) | -- | tsys4 |
| wnode-tsys9 | local-lvm (SSD) | S2 | tsys5 |
This balances: 2 wnodes using tsys4 for bulk data, 2 using tsys5.
---
## 7. ETL/HPC Considerations
### 7.1 Weather/GIS ETL pipeline
Typical flow: download GRIB/NetCDF files -> process (reproject, aggregate) ->
store results.
| Stage | Storage class | Why |
|-------|-------------|-----|
| Download raw data | `nfs-hdd` | Large sequential writes. NFS-HDD handles this well. |
| Processing scratch | `local-fast` | Random access during transform. Local disk avoids NFS latency. |
| Store results | `nfs-hdd` | Large sequential writes. Persistent. |
**Recommendation:** Deploy a `local-fast` PV mount as `/scratch` on every
wnode. ETL jobs use `/scratch` for intermediate processing and write final
output to the NFS-mounted `/data`.
### 7.2 HPC workloads (hardware startup)
Use cases: RTL simulation, PCB thermal analysis, firmware build pipelines.
| Workload | Best wnode | Why |
|----------|-----------|-----|
| RTL simulation (CPU-bound, high RAM) | tsys7 (192 GB) | Most RAM, most cores (24t) |
| Firmware builds (I/O-bound, moderate RAM) | tsys5 (NVMe) | Fastest storage for compile I/O |
| Hardware-in-the-loop (latency-sensitive) | tsys9 (local SSD) | Lowest latency storage |
| Parallel batch jobs | tsys6 + tsys7 | Distribute across both heavy hosts |
### 7.3 RackRental/containerlab
Rapid container deployment. Key need: fast container image pulls.
This is where **local-lvm boot disks** shine. Currently, every container image
pull writes through NFS to a spinning disk -- slow. With local-lvm, images
cache on local disk (even HDD is 2-3x faster than NFS-HDD for random I/O).
On tsys9 (SSD) and tsys5 (NVMe), image pulls are near-instant.
### 7.4 Data locality for ETL
For weather/GIS data that is read repeatedly (e.g., climate reanalysis), cache
it on local-lvm of the heavy hosts:
```
tsys3 local-lvm (NVMe 349 GB): /data/cache/weather/ -- fastest cache tier
tsys5 NVMe (local): /data/cache/gis/ -- fastest cache tier
```
**Note:** tsys6/7 local-lvm is USB 2.0 portable HDD (~30 MB/s) -- cannot
be used for caching. Pre-populate weather/GIS data on D2/D5 (NFS) instead.
This avoids re-reading the same data from the same NFS export on every job
if the data is already cached in the page cache.
---
## 8. Migration Plan
**Key enabler:** The hosts are standalone Proxmox installs, but **Proxmox
Datacenter Manager (PDM)** manages them collectively and supports VM migration
between nodes. Storage migration can be done via the PDM/Proxmox UI rather
than manual disk copies -- the destination node just needs access to the target
storage (which all nodes have for NFS exports, and local storage can be
migrated through the UI's "Storage Migrate" function).
### 8.1 Phase 1: Friday (after hardware work)
After tsys5 cable + NVMe and tsys4 NIC + RAM:
1. **Format tsys5 NVMe** as local directory storage (e.g., `nvme-local`)
2. **Restart wnode-tsys6** (VM 100). Keep on NFS (D5). local-lvm is USB 2.0 --
do not use for VM storage. Recreate on D2 or D5 NFS.
3. **Move wnode-tsys9** (VM 905) disk from S3 (NFS) to local-lvm (SSD).
### 8.2 Phase 2: Cnode rebalance (maintenance window)
These changes require creating new VMs on target hosts and migrating disks.
Plan for a maintenance window with the k8s cluster briefly down.
1. Create cnode2 on tsys9 (local-lvm SSD if possible, or D2 NFS).
2. Create cnode4 on tsys9 (D5 NFS or local-lvm SSD).
3. Create cnode5 on tsys3 (S3 NFS or local-lvm).
4. Move cnode3 disk from D2 to S2 (tsys4 to tsys5).
5. Join new cnodes to etcd cluster, drain old cnode2/4/5, remove.
### 8.3 Phase 3: Wnode local storage migration (maintenance window)
1. Recreate wnode-tsys3 with boot disk on local-lvm (349 GB).
2. wnode-tsys6 stays on NFS (local-lvm is USB 2.0 HDD -- not suitable).
3. wnode-tsys7 stays on NFS (same reason).
4. Recreate wnode-tsys5 with boot disk on NVMe.
5. Add data disks (NFS) as second SCSI devices where applicable.
### 8.4 Phase 4: tsys2 integration (when rebuilt)
1. Install Proxmox on tsys2.
2. Run `scripts/check.sh` to inventory.
3. Run `scripts/apply-tunings.sh --apply`.
4. Create wnode-tsys2 with **boot disk on NVMe (960 PRO)** and **data disk on SATA SSD (850 EVO)**. No NFS needed -- 1.5 TB local SSD is the most local storage of any worker.
5. Join to k8s cluster.
### 8.5 Phase 5: Critical VM relocation
1. Move netinfra-02 (VM 904) from D2 to S3 (tsys5 HDD).
2. Move ucs-02 (VM 902) from D5 to S2 (tsys5 HDD).
3. (No change to T5-SSD -- ultix-streaming stays.)
---
## Open questions for next session
1. **Are the hosts a Proxmox cluster (pvecm) or standalone?** This determines
whether live migration is available (huge simplification) or we need manual
disk migration. Check `pvecm status` on each host.
2. **What k8s distribution is in use?** (k3s, kubeadm, RKE2?) This affects how
nodes are joined/drain and how StorageClasses are configured.
3. **Container runtime?** (containerd, cri-o?) Affects local storage layout.
4. **Is there a container image registry mirror in the cluster?** Or do all
pulls go to Docker Hub / external? A local registry on D3 SSD would speed
up all pulls.
5. **What specific ETL tools?** (GDAL, PostGIS, xarray, Dask?) This affects
whether jobs need shared (RWX) or exclusive (RWO) storage.
6. **HPC job scheduler?** (plain k8s Jobs, Argo Workflows, Volcano?) Affects
how we label and taint nodes.
# proxmox/docs/K8S.md
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Legacy k8s storage/host analysis**
>
> **Read it here:** https://community.turnsys.com/t/305
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+9 -24
View File
@@ -1,25 +1,10 @@
# Naming and DNS Policy
# proxmox/docs/NAMING-POLICY.md
> **Canonical naming policy for the PFVCluster fleet.**
> Established: 2026-07-31
## Rule
**The Proxmox VM name is the canonical identifier.** Everything else
derives from it:
1. **VM name** (set via `qm set <vmid> --name <name>`) is the source of truth
2. **DNS records** (Technitium, forward + reverse) must match the VM name exactly
3. **Tailscale node name** must match the VM name
4. **Monitoring/alerting** (Beszel, Uptime Kuma, LibreNMS) uses the VM name
5. **Inventory/k8s** references use the VM name
Any mismatch between VM name and DNS/Tailscale name is a **critical bug**
that must be fixed. The Technitium DNS API key is stored at
`~/.secrets/api-keys.env` for programmatic DNS management.
## Tools
- Technitium DNS API key: `~/.secrets/api-keys.env`
- Uptime Kuma API key: `~/.secrets/api-keys.env`
- DNS audit: `perf/scripts/probe-vm-dns.sh`
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Canonical naming policy for VMs/DNS/Tailscale**
>
> **Read it here:** https://community.turnsys.com/t/304
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+8 -363
View File
@@ -1,365 +1,10 @@
# Network Topology
# proxmox/docs/NETWORK-TOPOLOGY.md
> **Complete physical + logical network reference for the PFVCluster.**
> Data gathered 2026-07-30 via SNMP, LLDP, conman console captures, and direct
> host probes. All data is live ground truth -- not documentation inherited.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> Companion docs: [`STORAGE-ARCHITECTURE.md`](STORAGE-ARCHITECTURE.md),
> [`HOST-REFERENCE.md`](HOST-REFERENCE.md), [`VM-INVENTORY.md`](VM-INVENTORY.md).
> Findings/analysis: [`AUDIT-2026-07-30.md`](AUDIT-2026-07-30.md).
---
## 1. Physical topology diagram
```mermaid
graph TB
subgraph "RACK 5 - Core / Data / Infra"
CORE["pfv-core-sw01<br>PowerConnect 5448<br>192.168.0.12<br>(mgmt + storage VLANs)"]
TSYS1["pfv-tsys1<br>i7-4770 Haswell<br>Infra host"]
TSYS3["pfv-tsys3<br>Xeon E3-1535M v5<br>Compute"]
TSYS4["pfv-tsys4<br>Xeon E3-1246 v3<br>NFS Storage + PBS"]
TSYS5["pfv-tsys5<br>Xeon E5620 Westmere<br>NFS Storage + Sandboxes"]
TSYS9["pfv-tsys9<br>i5-10500 Comet Lake<br>Infra + Compute"]
TSYS4_CONSOLE["conman + ser2net<br>7 switch consoles<br>Tailscale 100.70.77.93:7890"]
TSYS1_PDU["Cyclades PM10i PDU<br>powerman on tsys1"]
TSYS1_UPS["APC Smart-UPS C 1500<br>NUT on tsys1"]
end
subgraph "RACK 3 - Compute / RackRental"
TOR3STOR["pfv-tor3-stor<br>PowerConnect 5324<br>192.168.0.9<br>storage VLAN"]
TOR3MGMT["pfv-tor3-mgmt<br>PowerConnect 5324<br>192.168.0.7<br>mgmt VLAN"]
TSYS6["pfv-tsys6<br>2x Xeon E5530 Nehalem<br>RackRental"]
TSYS7["pfv-tsys7<br>2x Xeon E5-2630 v2<br>RackRental"]
end
%% Cross-rack trunk (two one-way dotted arrows with labels)
CORE -. "ch1: 3x1G active (g13-15)<br>hash=layer-2-3<br>mode=on" .-> TOR3STOR
TOR3STOR -. "ch1: 4x1G (g20-23)<br>hash=layer-2-3-4<br>mode=on" .-> CORE
%% Rack 5 connections to core
CORE --> TSYS1
CORE --> TSYS3
CORE --> TSYS4
CORE --> TSYS5
CORE --> TSYS9
%% Rack 3 connections
TOR3STOR --> TSYS6
TOR3STOR --> TSYS7
TOR3MGMT --> TSYS6
TOR3MGMT --> TSYS7
```
### How to read this diagram
The dashed line between core-sw01 and tor3-stor is the **cross-rack trunk** --
the most critical link in the cluster. It carries all NFS storage traffic
between rack-3 compute hosts (tsys6/7) and rack-5 storage hosts (tsys4/5).
The trunk is a 4-port static LAG, but only 3 links are active due to a cable
mismatch (see §3 below).
---
## 2. Subnet / VLAN map
| VLAN | Subnet | Purpose | Where it lives |
|------|--------|---------|----------------|
| **1** (default) | 192.168.0.0/22 | Management network | All switches, all hosts (vmbr0 DHCP) |
| **1000** | 10.100.100.0/24 | Storage network (NFS) | core-sw01 + tor3-stor only (trunked) |
| -- (Tailscale) | 100.x.y.z/32 (CGNAT) | Remote access / overlay | All hosts + select VMs |
**Management IPs (VLAN 1, via DHCP reservations):**
| Host | mgmt IP (vmbr0) | Tailscale IP |
|------|-----------------|--------------|
| tsys1 | 192.168.3.11 | 100.121.189.98 |
| tsys3 | 192.168.2.5 | (connected) |
| tsys4 | 192.168.3.251 | 100.70.77.93 |
| tsys5 | 192.168.3.179 | (connected) |
| tsys6 | 192.168.3.169 | 100.73.35.111 |
| tsys7 | 192.168.3.55 | (connected) |
| tsys9 | 192.168.3.58 | (connected) |
**Storage IPs (VLAN 1000, static):**
| Host | Storage IP | Interface |
|------|-----------|-----------|
| tsys1 | 10.100.100.1 | datanet (nic1, USB dongle) |
| tsys3 | 10.100.100.3 | datanet (enx8cae4ccda774, USB dongle) |
| tsys4 | 10.100.100.4 | datanet (enx8cae4ccda926, USB dongle) |
| tsys5 | 10.100.100.5 | storagenet (bond0 → nic1, single link) |
| tsys6 | 10.100.100.6 | storagenet (bond0 → nic1+nic2, 2G LACP) |
| tsys7 | 10.100.100.7 | datanet (bond0 → nic1+nic2, 2G LACP) |
| tsys9 | 10.100.100.9 | datanet (enx9c69d36a5b6c, USB dongle) |
**Switch IPs (VLAN 1, static DHCP reservations):**
| Switch | IP | Model | Console |
|--------|----|-------|---------|
| pfv-core-sw01 | 192.168.0.12 | PowerConnect 5448 | conman port 2001 |
| pfv-tor3-stor | 192.168.0.9 | PowerConnect 5324 (Neyland 24T) | conman port 2003 |
| pfv-tor3-mgmt | 192.168.0.7 | PowerConnect 5324 (Neyland 24T) | conman port 2002 |
| (unidentified) | 192.168.0.8 | PowerConnect 5324 (Neyland 24T) | conman port 2005? |
**SNMP community:** `kn3lmgmt` (read-only, all switches respond to SNMPv2c)
---
## 3. Cross-rack trunk detail (ch1) -- the critical link
This trunk carries ALL NFS storage traffic between rack 3 (tsys6/7) and
rack 5 (tsys4/5). It is the single most important network path in the cluster.
```mermaid
graph LR
subgraph "core-sw01 (rack5)"
G13["g13<br>1G UP"]
G14["g14<br>1G UP"]
G15["g15<br>1G UP"]
G16["g16<br>1G UP<br>NOT in LAG!"]
G17["g17<br>DOWN<br>in config but<br>no cable"]
end
subgraph "tor3-stor (rack3)"
G20["g20<br>1G UP"]
G21["g21<br>1G UP"]
G22["g22<br>1G UP"]
G23["g23<br>1G UP"]
end
G13 --- G20
G14 --- G21
G15 --- G22
G16 -.- G23
G17 -.->|no cable| G23
```
### Configuration comparison
| Property | core-sw01 (rack5) | tor3-stor (rack3) | Match? |
|----------|-------------------|--------------------|--------|
| Physical ports configured | g(13-15,17) | g(20-23) | **No -- asymmetric** |
| Physical ports UP | g13, g14, g15, g16 | g20, g21, g22, g23 | -- |
| Active in LAG | g13, g14, g15 (3) | g20, g21, g22, g23 (4) | **No -- 3 vs 4** |
| Load-balance hash | layer-2-3 (MAC+IP) | layer-2-3-4 (MAC+IP+Port) | **No -- asymmetric** |
| Channel mode | on (static) | on (static) | Yes (both should be LACP) |
| VLAN | access vlan 1000 | access vlan 1000 | Yes |
### Problems
1. **g16/g17 cable mismatch.** The 4th physical cable from tor3-stor lands on
core-sw01 g16, but the config expects it on g17. g16 is UP (1G, full duplex)
but is NOT in the LAG group. g17 is configured in the LAG but has no cable
(DOWN). Result: **only 3 of 4 links are active**.
2. **Hash policy asymmetry.** core-sw01 hashes on layer-2-3 (src/dst MAC + IP).
tor3-stor hashes on layer-2-3-4 (src/dst MAC + IP + TCP/UDP port). With
layer-2-3 on core-sw01, **all traffic between a given host pair hashes to
one link** regardless of how many TCP connections (nconnect) are used.
3. **Static mode (`on`).** Neither switch runs LACP. There is no link-failure
detection -- a dead cable stays in the LAG until manually discovered.
---
## 4. Complete switch port map
### pfv-core-sw01 (PowerConnect 5448, 48 ports) -- rack 5
| Port | Speed | Status | VLAN | Description / Connected device |
|------|-------|--------|------|-------------------------------|
| g1 | 1000 | UP | 1 | pfvsvrpi (Raspberry Pi) |
| g4 | 100 | UP | 1 | pfv-tsys4 (mgmt, secondary) |
| g5 | -- | UP | 1 | pfv-tsys1 (mgmt) |
| g6 | 100 | UP | 1 | pfvsvrpi (secondary) |
| g8 | 1000 | UP | 1 | pfv-tsys4-mgmt |
| g9 | 1000 | UP | 1 | AP-Wallmount (UAP-AC-LR) **⚠ 2902 inErrors** |
| g10 | 1000 | UP | 1 | (unknown) |
| g11 | 1000 | UP | 1 | (unknown) |
| g12 | 1000 | UP | 1 | (unknown) |
| **g13** | **1000** | **UP** | **1000 (ch1)** | **cross-rack trunk → tor3-stor g20** |
| **g14** | **1000** | **UP** | **1000 (ch1)** | **cross-rack trunk → tor3-stor g21** |
| **g15** | **1000** | **UP** | **1000 (ch1)** | **cross-rack trunk → tor3-stor g22** |
| **g16** | **1000** | **UP** | **1000** | **cross-rack trunk cable (NOT in LAG -- should be g17)** |
| **g17** | -- | **DOWN** | **1000 (ch1)** | **in LAG config but no cable** |
| g19 | 1000 | UP | 1 | pfv-tsys5-mgmt |
| g21 | 1000 | UP | 1 | (unknown) |
| g23 | 100 | UP | 1 | pfv-tsys9 (mgmt) |
| g26 | 1000 | UP | 1 | AP-Tabletop **⚠ 73 inErrors** |
| g27 | 1000 | UP | 1000 | pfv-tsys3-stor (datanet) |
| g31 | 1000 | UP | 1000 | pfv-tsys4-stor (datanet, USB) |
| g32 | -- | -- | -- | pfv-tsys4-storage (configured, DOWN) |
| g33 | -- | -- | -- | pfv-tsys5-stor (ch2, DOWN/Not Present) |
| g34 | 1000 | UP | 1000 (ch3) | pfv-tsys5-stor (bond0, 1 link active) |
| g38 | 1000 | UP | 1000 | pfv-tsys9-stor (datanet) **⚠ 590 inErrors** |
| g40 | 1000 | UP | 1000 | pfv-tsys1-stor (datanet) |
| g41 | 1000 | UP | 1 | (unknown) |
| g43 | 1000 | UP | 1 | pfv-tsys3 (mgmt) |
| g44 | 1000 | UP | 1 | (unknown) |
| g45-g48 | -- | DOWN | -- | (Combo ports, unused) |
**Port-channels on core-sw01:**
| Channel | Speed | Status | Members | VLAN | Notes |
|---------|-------|--------|---------|------|-------|
| ch1 | 1000 | UP | g13-15 (active), g17 (inactive) | 1000 | Cross-rack trunk to tor3-stor |
| ch2 | -- | DOWN | g32-33 (non-candidate) | -- | Unused |
| ch3 | 1000 | UP | g34 (active) | 1000 | tsys5 storage bond (degraded, 1 of 2 links) |
**LAG hash:** `port-channel load-balance layer-2-3`
### pfv-tor3-stor (PowerConnect 5324 / Neyland 24T, 24 ports) -- rack 3
| Port | Speed | Status | VLAN | Description / Connected device |
|------|-------|--------|------|-------------------------------|
| g1 | 1000 | UP | 1 | (unknown -- uplink to tor3-mgmt or router) |
| g2-g7 | 1000 | UP | 1 | (unused but UP) |
| **g8** | **1000** | **UP** | **1000 (ch2)** | **tsys6 stor nic1** |
| **g9** | **1000** | **UP** | **1000 (ch2)** | **tsys6 stor nic2** |
| **g10** | **1000** | **UP** | **1000 (ch3)** | **tsys7 stor nic1** |
| **g11** | **1000** | **UP** | **1000 (ch3)** | **tsys7 stor nic2** |
| **g13** | **1000** | **UP** | **--** | **tsys8-stor (STALE -- tsys8 retired)** |
| **g14** | **1000** | **UP** | **--** | **tsys8-stor (STALE -- tsys8 retired)** |
| g15-g19 | 1000 | UP | 1000 | (unused storage ports) |
| **g20** | **1000** | **UP** | **1000 (ch1)** | **cross-rack trunk → core-sw01 g13** |
| **g21** | **1000** | **UP** | **1000 (ch1)** | **cross-rack trunk → core-sw01 g14** |
| **g22** | **1000** | **UP** | **1000 (ch1)** | **cross-rack trunk → core-sw01 g15** |
| **g23** | **1000** | **UP** | **1000 (ch1)** | **cross-rack trunk → core-sw01 g16** |
| g24 | -- | DOWN | 1 | (spanning-tree disabled, portfast) |
**Port-channels on tor3-stor:**
| Channel | Speed | Status | Members | VLAN | Notes |
|---------|-------|--------|---------|------|-------|
| ch1 | 1000 | UP | g20-23 (`mode on`) | 1000 | Cross-rack trunk to core-sw01 (4x1G) |
| ch2 | 1000 | UP | g8-9 (`mode auto`) | 1000 | tsys6 storage bond (2x1G LACP) |
| ch3 | 1000 | UP | g10-11 (`mode auto`) | 1000 | tsys7 storage bond (2x1G LACP) |
| ch4 | 1000 | UP | g13-14 (`mode on`) | 1000 | **tsys8-stor (STALE -- retired host)** |
**LAG hash:** `port-channel load-balance layer-2-3-4`
### pfv-tor3-mgmt (PowerConnect 5324 / Neyland 24T, 24 ports) -- rack 3
| Port | Speed | Status | Connected device |
|------|-------|--------|-----------------|
| g3 | -- | UP | tsys7 (mgmt nic0) |
| g7 | -- | UP | tsys6 (mgmt nic0) |
(Full port map not captured -- this switch carries only VLAN 1 management
traffic. Low priority for storage performance.)
---
## 5. Per-host network interface reference
| Host | mgmt NIC | Switch port | Storage NIC | Switch port | Storage bond | Bond hash | Storage link speed |
|------|----------|-------------|-------------|-------------|-------------|-----------|-------------------|
| tsys1 | nic0 | core g5 | nic1 (onboard) | core g40 | **No bond** (single NIC) | -- | 1G |
| tsys3 | nic0 | core g43 | enx8cae4ccda774 (USB) | core g27 | **No bond** (USB dongle) | -- | 1G |
| tsys4 | nic0 | core g8 | enx8cae4ccda926 (USB) | core g31 | bond0 (1 slave, USB) | layer2+3 | 1G |
| tsys5 | nic0 | core g19 | nic1 + nic2 | core ch3 (g34) | bond0 (1 of 2 slaves) | layer2+3 | **1G (degraded)** |
| tsys6 | nic0 | tor3-mgmt g7 | nic1 + nic2 | tor3-stor g8/g9 (ch2) | bond0 (2 of 2 slaves) | **layer3+4** | **2G LACP** |
| tsys7 | nic0 | tor3-mgmt g3 | nic1 + nic2 | tor3-stor g10/g11 (ch3) | bond0 (2 of 2 slaves) | **layer3+4** | **2G LACP** |
| tsys9 | nic0 | core g23 | enx9c69d36a5b6c (USB) | core g38 | **No bond** (USB dongle) | -- | 1G |
### Key observations
- **tsys6/7 are the only hosts with working 2G LACP bonds** (layer3+4 hash, 2
active slaves). All NFS traffic from rack 3 uses these bonds.
- **tsys1/3/4/9 use USB dongles** for storage network -- single 1G, no redundancy.
- **tsys5 bond0 is degraded** -- nic2 is DOWN (no cable connected). Only nic1 is
active via core-sw01 ch3 (g34). This is the LACP problem the operator has been
troubleshooting.
- **Bond hash inconsistency:** tsys6/7 use layer3+4 (optimal for nconnect NFS),
tsys4/5 use layer2+3 (suboptimal -- same src/dst IP pair always hashes to one
link even with nconnect's multiple TCP connections).
---
## 6. NFS data flow diagram
```mermaid
graph TB
subgraph "Storage Servers (rack 5)"
T4D2["tsys4 D2<br>WDC Red 3TB<br>Tier 2"]
T4D5["tsys4 D5<br>Hitachi 2TB<br>Tier 2"]
T4D1["tsys4 D1<br>WD 1TB USB<br>Tier 3"]
T4D3["tsys4 D3<br>Seagate 500GB USB<br>Tier 3"]
T5S1["tsys5 S1<br>IronWolf 1TB<br>Tier 2"]
T5S2["tsys5 S2<br>IronWolf 1TB<br>Tier 2"]
T5SSD["tsys5 SSD<br>Samsung 860 PRO<br>Tier 1 (93% full)"]
end
subgraph "VLAN 1000 storage network"
NFS["NFS v4.2<br>nconnect=4<br>rsize/wsize=1MB"]
end
subgraph "NFS Clients"
T1["tsys1 (9 mounts)"]
T3["tsys3 (5 mounts)"]
T5["tsys5 (3 mounts, NO nconnect)"]
T6["tsys6 (9 mounts)"]
T7["tsys7 (9 mounts)"]
T9["tsys9 (5 mounts)"]
end
T4D2 --> NFS
T4D5 --> NFS
T4D1 --> NFS
T4D3 --> NFS
T5S1 --> NFS
T5S2 --> NFS
T5SSD --> NFS
NFS --> T1
NFS --> T3
NFS --> T5
NFS --> T6
NFS --> T7
NFS --> T9
```
### NFS mount inventory (live)
| Server | Export | tsys1 | tsys3 | tsys4 | tsys5 | tsys6 | tsys7 | tsys9 |
|--------|--------|-------|-------|-------|-------|-------|-------|-------|
| tsys4 | D1 | -- | -- | -- | -- | ✓ | ✓ | -- |
| tsys4 | **D2** | ✓ | ✓ | -- | ✓ | ✓ | ✓ | ✓ |
| tsys4 | D3 | -- | -- | -- | ✓ | ✓ | ✓ | -- |
| tsys4 | D5 | -- | ✓ | -- | ✓ | ✓ | ✓ | ✓ |
| tsys5 | S1 | ✓ | -- | -- | -- | ✓ | ✓ | -- |
| tsys5 | S2 | ✓ | ✓ | -- | -- | ✓ | ✓ | -- |
| tsys5 | S3 | ✓ | -- | -- | -- | ✓ | ✓ | ✓ |
| tsys5 | S4 | ✓ | ✓ | -- | -- | ✓ | ✓ | ✓ |
| tsys5 | T5-SSD | -- | ✓ | -- | -- | ✓ | ✓ | ✓ |
(✓ = NFS client mount active. tsys4 = NFS server only, no client mounts.
tsys5 = NFS server + 3 client mounts from tsys4, **missing nconnect**.)
---
## 7. Switch management access
| Method | Details |
|--------|---------|
| **SNMP** | Community `kn3lmgmt` (read-only). All 4 switches respond on VLAN 1 IPs. |
| **Console (conman)** | 7 serial consoles via ser2net + conman on pfv-tsys4. Conman server at `pfv-tsys4:7890` (Tailscale). Escape: `&.` |
| **Console tool** | `perf/scripts/conman-console.py` (PTY-based driver, portable) |
| **SNMP audit tool** | `perf/scripts/snmp-switch-audit.py` (config-driven) |
| **Direct telnet** | `telnet pfv-tsys4 200X` -- ONLY when conmand stopped (conflicts). Use conman instead. |
### Console port assignments
| Port | Console name | Switch | ID_PATH (USB port) |
|------|-------------|--------|---------------------|
| 2001 | pfv-core-sw01 | Dell PowerConnect 5448 (core, rack5) | usb-0:1.5.4.4 |
| 2002 | pfv-tor3-mgmt | Neyland 24T (mgmt TOR, rack3) | usb-0:1.6.3.1 |
| 2003 | pfv-tor3-stor | Neyland 24T (storage TOR, rack3) | usb-0:1.6.3.3.2 |
| 2004 | pfv-rrinfra-rtr | Cisco router (rrinfra) | usb-0:1.6.3.3.1 |
| 2005 | pfv-r2-tor-top | Rack 2 top-of-rack switch | usb-0:1.6.3.3.3 |
| 2006 | subodev-torsw | Suborbital device TOR switch | usb-0:1.5.4.1 |
| 2007 | pfv-r2-sw | Rack 2 old Dell switch | usb-0:1.6.3.2 |
> **Network reference: topology diagrams, switch ports, VLAN map, NFS data-flow**
>
> **Read it here:** https://community.turnsys.com/t/299
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+9 -69
View File
@@ -1,70 +1,10 @@
# Physical Systems (Pi's + other hardware)
# proxmox/docs/PHYSICAL-SYSTEMS.md
> **Access patterns and locations for physical infrastructure devices.**
> Updated: 2026-07-31
## Raspberry Pi systems
All accessible via Tailscale. Use `localuser` (passwordless sudo to root)
except where noted.
| Name | Tailscale IP | LAN IP | Access | Purpose |
|------|-------------|--------|--------|---------|
| pfvsvrpi | 100.91.151.113 | 192.168.1.230 | `localuser` | Server Pi (general purpose) |
| subopi-dev-3 | 100.64.231.65 | 192.168.1.232 | via subodev jump | Suborbital dev Pi 3 |
| subopi-dev-4 | 100.65.224.85 | 192.168.1.231 | via subodev jump | Suborbital dev Pi 4 |
> **Note from operator:** "use subodev to get into subopi-*" — subodev is
> a jump host for the suborbital Pi's.
## Network devices discovered (non-Proxmox)
| IP | Device | Type | Identified via |
|----|--------|------|---------------|
| 192.168.0.12 | pfv-core-sw01 | Dell PowerConnect 5448 | SNMP |
| 192.168.0.7 | pfv-tor3-mgmt | Neyland 24T (PC5324) | SNMP |
| 192.168.0.8 | (unidentified) | Neyland 24T (PC5324) | SNMP |
| 192.168.0.9 | pfv-tor3-stor | Neyland 24T (PC5324) | SNMP |
| 192.168.1.166 | pfv-stor1 | Linux 4.14.22 (Synology?) | SNMP |
| 192.168.1.182 | UAP-AC-LR | UniFi AP (FW 6.8.2.15592) | SNMP |
| 192.168.1.230 | pfvsvrpi | Linux 6.12.62 (RPi) | SNMP |
| 192.168.1.231 | subopi-dev-4 | Linux 6.12.25 (RPi) | SNMP |
| 192.168.1.232 | subopi-dev-3 | Linux 6.12.9 (RPi) | SNMP |
| 192.168.1.217 | subopi3 | Linux 6.12.25 (RPi) | SNMP |
## Other identified hosts (SSH open, unidentified)
| IP | Notes |
|----|-------|
| 192.168.0.72 | SSH open, no SNMP — investigate |
| 192.168.0.250 | SSH open, no SNMP — investigate |
| 192.168.1.138 | SSH open — investigate |
| 192.168.1.181 | SSH open — investigate |
| 192.168.1.192 | SSH open — investigate |
| 192.168.1.201 | SSH open — investigate |
| 192.168.1.205 | SSH open — investigate |
| 192.168.1.214 | SSH open — investigate |
| 192.168.1.223 | SSH open — investigate |
| 192.168.1.226 | SSH open — investigate |
| 192.168.1.228 | SSH open — investigate |
| 192.168.2.5 | SSH open — investigate (tsys3 vmbr0) |
| 192.168.3.1 | SSH open — investigate (gateway/router?) |
| 192.168.3.78 | SSH open — investigate |
## 192.168.3.12-24 range
These 13 hosts respond to ping but have no SSH/SNMP. Likely:
- IoT devices
- Cameras
- Phones (VoIP)
- Other DHCP clients
## UniFi Access Points
| AP | Port (core-sw01) | Model | FW |
|----|-----------------|-------|-----|
| UAP-AC-LR | g9 (2902 inErrors!) | UAP-AC-LR | 6.8.2.15592 |
| UAP-AC-Lite | g38 (590 inErrors!) | UAP-AC-Lite | (unknown) |
Both managed by UniFi controller (likely on Home Assistant VM 100 or
pfv-stor1). UniPoller exports metrics to Prometheus.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Physical infrastructure: Pis, network devices, UniFi APs**
>
> **Read it here:** https://community.turnsys.com/t/304
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+10 -857
View File
@@ -1,857 +1,10 @@
# Proxmox Cluster Project Report
**Date:** 2026-07-27 (re-audited)
**Prepared by:** Performance Optimization Engagement
**Status:** Comprehensive fleet assessment with VM placement and redundancy analysis
**Data freshness:** All 7 hosts re-audited at 21:50 CDT 2026-07-27 via
`deploy-check.sh`. VM placements reflect live state after user's PDM
migrations. This is ground truth.
---
## Table of Contents
1. [Executive Summary](#1-executive-summary)
2. [Host Fleet](#2-host-fleet)
3. [Storage Architecture](#3-storage-architecture)
4. [VM Fleet Inventory](#4-vm-fleet-inventory)
5. [Kubernetes Node Distribution](#5-kubernetes-node-distribution)
6. [Storage Redundancy Analysis](#6-storage-redundancy-analysis)
7. [Local SSD/NVMe Opportunity](#7-local-ssdnvme-opportunity)
8. [Role Alignment Audit](#8-role-alignment-audit)
9. [Network Findings](#9-network-findings)
10. [Recommendations](#10-recommendations)
11. [Hardware End-of-Support Exposure](#11-hardware-end-of-support-exposure)
12. [Open Items](#12-open-items)
---
## 1. Executive Summary
The cluster consists of 7 active Proxmox hosts and 1 incoming (pfv-tsys2),
running 43 VMs across two NFS storage servers (tsys4, tsys5). Host-side
performance tunings are complete on 5 of 7 hosts. Two hosts (tsys4, tsys5)
are blocked on physical hardware work scheduled for Friday.
**Progress since initial audit:** The user has been actively rebalancing k8s
nodes via PDM. Storage distribution improved from 90%/10% (tsys4/tsys5) to
73%/27%. One cnode now uses tsys5 storage (cnode5 on S2). More migration
needed for etcd quorum survival.
The VM-layer assessment reveals:
| # | Finding | Severity | Status |
|---|---------|----------|--------|
| 1 | **4 of 5 cnodes still store disks on tsys4 NFS.** cnode5 moved to tsys5. Still need 1-2 more moves for quorum survival. | **CRITICAL** | Improving |
| 2 | **Both -01/-02 infrastructure pairs (netinfra, UCS) on tsys4 NFS only.** | **HIGH** | TODO today |
| 3 | **No k8s node uses SSD or NVMe yet.** tsys3 has 349 GB unused local NVMe; tsys9 has 136 GB local SSD. | **HIGH** | Deferred to k8s session |
| 4 | **D3 SSD (tsys4, USB) is 99% empty (445 GB free).** Moving to tsys5 SAS Friday. | **MEDIUM** | Friday |
---
## 2. Host Fleet
### 2.1 Inventory
| Host | Model | CPU (year) | Cores | RAM | Local Disk | Role (intended) | Tuning |
|------|-------|-----------|-------|-----|-----------|-----------------|--------|
| pfv-tsys1 | OptiPlex 9020 | i7-4770 Haswell (2013) | 4c/8t | 32 GB DDR3 | HDD (LVM-thin) | **Infrastructure** | Done |
| pfv-tsys2 | Precision 5520 | i7-7820HQ Kaby Lake (2017) | 4c/8t | 32 GB (max) | **NVMe 512GB + SATA SSD 1TB** | **Kubernetes** | Incoming (Win10) |
| pfv-tsys3 | Precision 7510 | Xeon E3-1535M v5 Skylake (2015) | 4c/8t | 32 GB DDR4 | HDD (LVM-thin) | **Kubernetes** | Done |
| pfv-tsys4 | Precision T1700 | Xeon E3-1246 v3 Haswell (2013) | 4c/8t | 16 GB DDR3 | 6 disks (HDD+SSD+SMR) | **Storage (NFS+PBS)** | Blocked (NIC+RAM) |
| pfv-tsys5 | Precision T7500 | Xeon E5620 Westmere (2010) | 4c/8t | 96 GB DDR3 | 6 disks (HDD+SSD) | **Storage (NFS+VMs)** | Blocked (cable) |
| pfv-tsys6 | PowerEdge R610 | 2x Xeon E5530 Nehalem (2009) | 8c/16t | 128 GB DDR3 | HDD (LVM-thin) | **Kubernetes** | Done |
| pfv-tsys7 | PowerEdge R620 | 2x Xeon E5-2630 v2 Ivy Bridge (2013) | 12c/24t | 192 GB DDR3 | HDD (LVM-thin) | **Kubernetes** | Done |
| pfv-tsys9 | OptiPlex 7080 | i5-10500 Comet Lake (2020) | 6c/12t | 24 GB DDR4 | **250 GB SSD** (PNY CS900) | **Infrastructure** | Done |
### 2.2 Role taxonomy (per user directive)
| Role | Hosts | Workload |
|------|-------|----------|
| **Infrastructure + k8s control** | tsys1, tsys9 | Infra VMs (netinfra, UCS, PBS, CA, HA) + pfv-k8s cnodes (control plane) + small wnodes |
| **Kubernetes workers** | tsys2, tsys3, tsys6, tsys7 | pfv-k8s wnodes (heavy workers) -- these hosts have the RAM (32-192 GB) for ETL/HPC |
| **Storage** | tsys4, tsys5 | NFS server + PBS backup target. tsys5 also runs sectestbed/preprod VMs |
**Design rationale:** cnodes (control plane) are lightweight (4 cores, 4 GB
RAM each) and are weighted toward tsys1/tsys9 to keep the heavy RAM/CPU hosts
(tsys6 with 128 GB, tsys7 with 192 GB) free for large worker nodes. wnodes
run one per hypervisor host across the fleet to maximize total cluster capacity.
pfv-k8s runs all R&D and RackRental (containerlab) workloads via Kubernetes.
Production (Gitea, RustFS, Redmine, websites) lives on a VPS in Reston, VA
running Cloudron -- not in this cluster.
---
## 3. Storage Architecture
### 3.1 NFS exports from tsys4 (primary storage server)
| Export | Disk model | Type | Bus | Total | Used | Free | Use% |
|--------|-----------|------|-----|-------|------|------|------|
| D2 | WDC WD30EFRX Red | HDD (7200rpm) | SATA | 2.7 TB | 187 GB | **2.4 TB** | 8% |
| ~~D3~~ | ~~SK hynix SC300~~ | ~~SSD~~ | ~~USB~~ | — | — | — | **moving to tsys5 Friday** |
| D5 | Hitachi HDS72302 | HDD (7200rpm) | SATA | 1.8 TB | 236 GB | **1.5 TB** | 14% |
Non-exported disks on tsys4:
- sda (Hitachi 1.8T) at /mnt/albert -- not NFS shared, 1.7 TB free
- sdd (WDC 1T) -- **idle, unmounted, removable** (free up for other use)
- sdf (WDC 4.5T SMR) at /mnt/backup -- **PBS backup target**, 4.3 TB free
**D3 migration (Friday):** The SK hynix SC300 SSD is currently USB-attached on
tsys4 (via a "ThinkPad SSD" USB adapter). It is moving to a tsys5 SAS port,
eliminating the USB bottleneck. tsys4's 4 SATA ports are all occupied (sda/sdb
/sdc/sdd), so tsys5 is the better target. See section 3.2.
### 3.2 NFS exports from tsys5 (secondary storage -- becoming the fast-tier hub)
| Export | Disk model | Type | Bus | Total | Used | Free | Use% |
|--------|-----------|------|-----|-------|------|------|------|
| S1 | Seagate ST1000VN | HDD | SAS | 916 GB | 60 GB | 810 GB | 7% |
| S2 | Seagate ST1000VN | HDD | SAS | 916 GB | **6.9 GB** | **863 GB** | **1%** |
| S3 | Seagate ST1000VN | HDD | SAS | 916 GB | 7.0 GB | **863 GB** | **1%** |
| S4 | Toshiba DT01ACA050 | HDD | SAS | 458 GB | 2 MB | **435 GB** | **0%** |
| T5-SSD | Samsung 860 PRO | **SSD** | SAS | 234 GB | **122 GB** | **101 GB** | **55%** |
| **D3** (Friday) | SK hynix SC300 | **SSD** | **SAS** | **469 GB** | **2 MB** | **445 GB** | **0%** |
**tsys5 storage controllers (plenty of free ports):**
- LSI SAS1068E (SAS 6/iR): 8 ports, 3 used (Samsung SSD, Hitachi, Seagate),
**5 free**
- Intel ICH10 SATA #1 (4-port): 2 used (Seagate S3, Toshiba S4), **2 free**
- Intel ICH10 SATA #2 (2-port): **status unknown, likely free**
- 2x Renesas USB 3.0 xHCI controllers (real USB 3.0, unlike tsys6/7)
**Key finding: S2 and S3 now have k8s node disks.** S2 holds cnode5 +
wnode-tsys1 + wnode-tsys9 (6.9 GB used). S3 has wnode-tsys9's old disk
(unused, 7 GB). S4 still 99% empty (435 GB free).
T5-SSD grew to 55% used (122 GB) -- ultix-streaming is the primary consumer.
**Friday additions:**
1. **D3 (SK hynix SSD)** moves from tsys4 USB to tsys5 SAS port. Eliminates
USB 2.0 bottleneck. Becomes the second SSD-tier NFS export.
2. **PCI NVMe drive** (local-only, not NFS-exported). Used for wnode-tsys5
boot disk and HPC scratch. The fastest tier in the fleet.
After Friday, **tsys5 consolidates all fast storage**: NVMe (local) + 2 SSD
NFS exports (D3 + T5-SSD) + 4 HDD NFS exports (S1-S4). This makes tsys5 the
natural home for latency-sensitive workloads and the k8s StorageClass design
center.
### 3.3 Local storage tiers (per host, with utilization)
| Host | Storage ID | Disk type | Bus | Total | Used | Free | Used by VMs? |
|------|-----------|-----------|-----|-------|------|------|-------------|
| tsys1 | local-lvm | HDD | SATA | ~90 GB | low | ~90 GB | No (all VMs on NFS) |
| **tsys3** | **local-lvm** | **NVMe (Samsung PM961)** | **NVMe** | **349 GB** | **0 GB** | **349 GB** | **No (all VMs on NFS)** |
| tsys4 | local-lvm | HDD | SATA | ~94 GB | PBS VM | ~62 GB | Yes (PBS VM 400) |
| tsys5 | local-lvm | HDD (Hitachi 1.8T) | SATA | 1.7 TB | 40 MB | **1.7 TB** | No |
| tsys5 | local-nonprod | HDD (Seagate 1T, =S1) | SATA | 916 GB | 53 GB | **856 GB** | Yes (sectestbed suite) |
| **tsys6** | **local-lvm** | **HDD (WD My Passport)** | **USB 2.0** | **1.7 TB** | **0 GB** | **1.7 TB** | **No -- DO NOT USE for VM storage** |
| **tsys7** | **local-lvm** | **HDD (WD portable)** | **USB 2.0** | **1.7 TB** | **0 GB** | **1.7 TB** | **No -- DO NOT USE for VM storage** |
| **tsys9** | **local-lvm** | **SSD (PNY CS900)** | **SATA** | **136 GB** | **0 GB** | **136 GB** | **No (all VMs on NFS)** |
| **tsys2** | **NVMe** (Samsung 960 PRO) | **NVMe** | **NVMe** | **512 GB** | (Win10) | **512 GB** | **Incoming -- fastest boot tier after tsys5 NVMe** |
| **tsys2** | **SATA SSD** (Samsung 850 EVO) | **SSD** | **SATA** | **1 TB** | (Win10) | **1 TB** | **Incoming -- bulk data on SSD, not rust** |
**CRITICAL WARNING: tsys6 and tsys7 local-lvm is USB 2.0 portable HDD.**
The entire Proxmox OS, swap, and local-lvm on both R610 and R620 run on a
single **USB 2.0-attached WD My Passport portable HDD** (tsys6: "My Passport
260D"; tsys7: "Drive 2657"). Both servers' only USB controllers are EHCI
(USB 2.0, ~480 Mbps). There is **no USB 3.0/xHCI** on either host.
**USB 2.0 practical throughput is ~30-35 MB/s.** This is 3-4x SLOWER than
NFS-over-HDD (~80-120 MB/s). Moving wnode boot disks to local-lvm on these
hosts would **decrease** performance. local-lvm on tsys6/7 must NOT be used
for VM storage.
Additionally, both servers have completely empty internal drive bays:
- **tsys6**: SAS controller present but **DISABLED** in BIOS. No internal
drives.
- **tsys7**: 6-port SATA AHCI controller present, **5 ports EMPTY** (only
DVD-ROM on port 5). No internal drives.
This is a reliability risk beyond performance: the entire host OS boots
from a consumer-grade portable USB drive not designed for 24/7 server use.
**tsys3 correction:** Previously documented as HDD. Actually boots from a
**Samsung PM961 NVMe 512GB SSD** -- the fastest existing local storage in the
fleet. Its 349 GB of local-lvm is excellent for wnode boot disk use.
**Critical observation: every k8s host has 0% used local-lvm.** tsys3
(Samsung PM961 **NVMe**, 349 GB), tsys6 (WD My Passport **USB 2.0** HDD,
1.7 TB), tsys7 (WD portable **USB 2.0** HDD, 1.7 TB) all have unused local
storage.
**However, only tsys3's local-lvm is suitable for VM storage.** tsys6 and
tsys7 local-lvm is USB 2.0 portable HDD (~30-35 MB/s) -- slower than
NFS-over-HDD and unsuitable for wnode boot disks.
### 3.4 Disk speed tiers summary
| Tier | Where | Speed class | Best for |
|------|-------|------------|----------|
| **NVMe** | tsys3 (Samsung PM961), tsys5 (Friday addition), **tsys2 (Samsung 960 PRO 512GB)** | 2000-3500 MB/s | HPC scratch, ETL staging, container runtime, wnode boot, etcd |
| **Local SSD** | tsys9 (PNY CS900, 136 GB), **tsys2 (Samsung 850 EVO 1TB)** | 500 MB/s | wnode boot disk, etcd |
| **NFS-SSD** | tsys5 D3 (SK hynix, **SAS post-Friday**), tsys5 T5-SSD (Samsung) | 200-400 MB/s over NFS | **k8s worker scratch only** (etcd, container cache, ephemeral volumes) |
| **NFS-HDD** | tsys4 D2/D5, tsys5 S1-S4 | 80-120 MB/s over NFS | Bulk data, large disks, non-critical VMs, **wnode boot on tsys6/7** |
| **Local SATA HDD** | tsys1 local-lvm | 100-150 MB/s | Host OS only |
| **USB 2.0 HDD** | tsys6/7 local-lvm (WD My Passport) | **~30-35 MB/s** | **NOTHING -- slower than NFS, do not use for VMs** |
### 3.5 Storage tier characterization per host
| Host | Storage profile | Detail |
|------|----------------|--------|
| **tsys2** | **SSD/NVMe only** | 960 PRO NVMe 512GB + 850 EVO SATA SSD 1TB. No spinning disk. |
| **tsys3** | **NVMe only** | Samsung PM961 NVMe 512GB. No spinning disk. |
| **tsys5** | **Hybrid** (fast-tier hub) | NVMe (local, Friday) + D3 SSD + T5-SSD + S1-S4 HDD |
| **tsys4** | **Bulk/spinning disk only** | D2 HDD 3TB + D5 HDD 2TB. D3 SSD leaving Friday. PBS target on SMR HDD. |
| **tsys9** | **Local SSD + NFS** | PNY CS900 SSD 136GB local + NFS client |
| **tsys1** | **Local HDD + NFS** | Small local-lvm + NFS client |
| **tsys6/7** | **NFS only** | local-lvm is USB 2.0 HDD (unusable for VMs). All VMs on NFS. |
### 3.6 All exports are single-disk with no redundancy
Every NFS export is a single physical disk formatted ext4. No RAID, no ZFS
mirror, no mdraid. A single disk failure takes down every VM whose disk lives
on that export. This applies to **both storage servers** and to the **PBS
backup target** (a single 4.5T SMR drive).
---
## 4. VM Fleet Inventory
### 4.1 Complete VM roster (running VMs only, 40 VMs across 7 hosts)
#### tsys1 (Infrastructure) -- 11 running VMs
| VMID | Name | Cores | RAM (MB) | Disk | Storage | Tier |
|------|------|-------|----------|------|---------|------|
| 100 | pfv-bms (HomeAssistant) | 2 | 4096 | 32 GB | D2 (tsys4 HDD) | NFS |
| 101 | tsys-ca | 2 | 2048 | 32 GB | D2 (tsys4 HDD) | NFS |
| 103 | **pfv-netinfra-01** | 2 | 2048 | 32 GB | D5 (tsys4 HDD) | NFS |
| 104 | tsys-librenms | 2 | 2048 | 50 GB | D2 (tsys4 HDD) | NFS |
| 105 | tsys-proxmox-datacenter | 2 | 2048 | 32 GB | D2 (tsys4 HDD) | NFS |
| 106 | **pfv-k8s-cnode3** | 2 | 4096 | 32 GB | D2 (tsys4 HDD) | NFS |
| 107 | **pfv-k8s-cnode1** | 2 | 4096 | 32 GB | D5 (tsys4 HDD) | NFS |
| 108 | **tsys-ucs-01** | 2x2 | 8000 | 32 GB | D2 (tsys4 HDD) | NFS |
| 109 | tailscale-router | 2 | 2048 | 25 GB | D2 (tsys4 HDD) | NFS |
| 114 | kali-tsys | 2 | 2048 | 32 GB | D2 (tsys4 HDD) | NFS |
| 117 | tsys-secure-workbench | 2 | 4000 | 32 GB | D2 (tsys4 HDD) | NFS |
#### tsys3 (Kubernetes) -- 1 running VM
| VMID | Name | Cores | RAM (MB) | Disk | Storage | Tier |
|------|------|-------|----------|------|---------|------|
| 313 | **pfv-k8s-wnode-tsys3** | 4x2 | 20000 | 32 GB | D5 (tsys4 HDD) | NFS |
#### tsys4 (Storage) -- 1 running VM
| VMID | Name | Cores | RAM (MB) | Disk | Storage | Tier |
|------|------|-------|----------|------|---------|------|
| 400 | pfv-proxmox-backup-server | 2 | 2048 | 32 GB | local-lvm | LOCAL |
#### tsys5 (Storage) -- 15 running VMs
| VMID | Name | Cores | RAM (MB) | Disk | Storage | Tier |
|------|------|-------|----------|------|---------|------|
| 509 | **pfv-k8s-wnode-tsys5** | 2x4 | 32000 | 32 GB | D2 (tsys4 HDD) | NFS |
| 5101 | sectestbed-siem | 2x2 | 10000 | 132 GB | local-nonprod | LOCAL |
| 5105 | sectestbed-awx | 2x2 | 4096 | 288 GB | local-nonprod | LOCAL |
| 5106 | sectestbed-k8s-cnode | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 5107 | sectestbed-k8s-wnode | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 5108 | sectestbed-librenms | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 5109 | sectestbed-netinfra | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 5111 | ultix-streaming | 2x2 | 9000 | 288 GB | T5-SSD (tsys5 SSD) | NFS-SSD |
| 5112 | ultix-offstage | 2x2 | 6000 | 288 GB | local-lvm | LOCAL |
| 6000 | sectestbed-sandbox | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 51010 | sectestbed-tctc | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 51011 | sectestbed-cloudron | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 51012 | sectestbed-hfnoc | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 51013 | sectestbed-rancherplatform | 2x2 | 4096 | 32 GB | local-nonprod | LOCAL |
| 53100 | tsys-preprod-awx | 2x2 | 9000 | 160 GB | local-nonprod | LOCAL |
| 53101 | tsys-preprod-siem | 2x2 | 12000 | 32 GB | local-nonprod | LOCAL |
| 53102 | tsys-preprod-rancherplatform | 2x2 | 8000 | 32 GB | local-nonprod | LOCAL |
#### tsys6 (Kubernetes) -- 3 running VMs (1 wnode stopped)
| VMID | Name | Cores | RAM (MB) | Disk | Storage | Tier |
|------|------|-------|----------|------|---------|------|
| 100 | pfv-k8s-wnode-tsys6 | 2x2 | 32000 | 32 GB | D5 (tsys4 HDD) | NFS -- **STOPPED** |
| 600 | tsys-awx | 2x2 | 12000 | 32 GB | D2 (tsys4 HDD) | NFS -- **STOPPED** |
| 601 | **pfv-k8s-cnode4** | 4 | 4096 | 32 GB | D2 (tsys4 HDD) | NFS |
| 602 | **pfv-k8s-cnode5** | 4 | 4096 | 32 GB | D5 (tsys4 HDD) | NFS |
| 603 | **pfv-k8s-cnode2** | 4 | 4096 | 32 GB | D2 (tsys4 HDD) | NFS |
#### tsys7 (Kubernetes) -- 4 running VMs
| VMID | Name | Cores | RAM (MB) | Disk | Storage | Tier |
|------|------|-------|----------|------|---------|------|
| 701 | **pfv-k8s-wnode-tsys7** | 4 | 32000 | 32 GB | D5 (tsys4 HDD) | NFS |
| 702 | hfnoc-uisp | 2x2 | 8000 | 100 GB | D2 (tsys4 HDD) | NFS |
| 703 | rr-middleware | 2 | 2048 | 32 GB | D2 (tsys4 HDD) | NFS |
| 704 | TCTC | 4 | 6000 | 32 GB | D2 (tsys4 HDD) | NFS |
#### tsys9 (Infrastructure) -- 5 running VMs
| VMID | Name | Cores | RAM (MB) | Disk | Storage | Tier |
|------|------|-------|----------|------|---------|------|
| 901 | tsys-siem | 2 | 8000 | 132 GB | D2 (tsys4 HDD) | NFS |
| 902 | **tsys-ucs-02** | 2x2 | 8000 | 50 GB | D5 (tsys4 HDD) | NFS |
| 903 | kali-rd | 2 | 2048 | 32 GB | D5 (tsys4 HDD) | NFS |
| 904 | **pfv-netinfra-02** | 2 | 4000 | 32 GB | D2 (tsys4 HDD) | NFS |
| 905 | **pfv-k8s-wnode-tsys9** | 4 | 4096 | 32 GB | S3 (tsys5 HDD) | NFS |
### 4.2 Storage concentration summary
| Storage target | # of running VMs | % of fleet |
|---------------|-----------------|------------|
| **D2 (tsys4 WDC Red 3TB HDD)** | **18** | **45%** |
| D5 (tsys4 Hitachi 2TB HDD) | 9 | 23% |
| local-nonprod (tsys5 local HDD) | 10 | 25% |
| S3 (tsys5 Seagate 1TB HDD) | 1 | 3% |
| T5-SSD (tsys5 Samsung SSD) | 1 | 3% |
| local-lvm (tsys4 local) | 1 | 3% |
**27 of 40 running VMs (68%) store their disks on tsys4 NFS exports.**
If tsys4 goes offline, two-thirds of the fleet loses its storage.
---
## 5. Kubernetes Node Distribution (re-audited 21:50 CDT)
### 5.1 pfv-k8s cnode (control plane) placement -- CURRENT
| VMID | Name | Hypervisor | Storage | NFS Server | Changed? |
|------|------|------------|---------|-----------|----------|
| 906 | cnode1 | **tsys9** | D5 | tsys4 | **MOVED from tsys1** |
| 705 | cnode2 | **tsys7** | D2 | tsys4 | **MOVED from tsys6** |
| 106 | cnode3 | tsys1 | D2 | tsys4 | no change |
| 601 | cnode4 | tsys6 | D2 | tsys4 | no change |
| 706 | cnode5 | **tsys7** | **S2** | **tsys5** | **MOVED from tsys6, storage moved D5→S2** |
**Storage distribution:**
| Storage server | cnodes | Quorum impact if it fails |
|---------------|--------|--------------------------|
| tsys4 (D2+D5) | **4** (cnode1,2,3,4) | Only cnode5 survives = **QUORUM LOST** |
| tsys5 (S2) | **1** (cnode5) | 4 survive = quorum OK |
**Progress:** cnode5 is now on tsys5 (was all 5 on tsys4). But 4-of-5 on tsys4
still means a tsys4 failure loses quorum. **Need 2 more cnodes on tsys5.**
**Host distribution:** cnodes spread across 4 hosts (tsys1, tsys6, tsys7,
tsys9) -- good host diversity.
### 5.2 pfv-k8s wnode (worker) placement -- CURRENT
| VMID | Name | Hypervisor | Storage | NFS Server | RAM | Status | Changed? |
|------|------|------------|---------|-----------|-----|--------|----------|
| 102 | wnode-tsys1 | tsys1 | S2 | tsys5 | 4 GB | **STOPPED** | **NEW** |
| 313 | wnode-tsys3 | tsys3 | D5 | tsys4 | **28 GB** | running | **RAM bumped 20→28** |
| 509 | wnode-tsys5 | tsys5 | D2 | tsys4 | 32 GB | running | no change |
| 100 | wnode-tsys6 | tsys6 | D5 | tsys4 | 32 GB | running | **NOW RUNNING** |
| 701 | wnode-tsys7 | tsys7 | D5 | tsys4 | 32 GB | running | no change |
| 905 | wnode-tsys9 | tsys9 | **S2** | tsys5 | 4 GB | running | **Storage moved S3→S2** |
**One wnode per host achieved** (tsys1,3,5,6,7,9). wnode-tsys1 is created but
stopped. wnode-tsys6 restarted.
**Storage distribution:**
| Storage server | wnodes | Notes |
|---------------|--------|-------|
| tsys4 (D2+D5) | 4 (tsys3,5,6,7) | Still concentrated |
| tsys5 (S2) | 2 (tsys1,tsys9) | Improving |
### 5.3 Summary: k8s node storage distribution
| Storage server | cnodes | wnodes | Total k8s nodes |
|---------------|--------|--------|-----------------|
| **tsys4 NFS** | **4 (80%)** | **4 (67%)** | **8 (73%)** |
| **tsys5 NFS** | **1 (20%)** | **2 (33%)** | **3 (27%)** |
| Local SSD/NVMe | 0 | 0 | 0 (0%) |
**Was 90%/10%. Now 73%/27%.** Improving but still tsys4-heavy. Target: 3
cnodes on each storage server (60/40 or better) so either server failing
leaves quorum intact.
### 5.4 Remaining cnode migration needed for etcd quorum survival
To survive a tsys4 failure with quorum (3 of 5 alive), at least 3 cnodes must
be on tsys5:
| Action | Effect |
|--------|--------|
| Move cnode3 (D2→S3 on tsys5) | 3 cnodes on tsys5, 2 on tsys4. tsys4 fail = 3 survive |
| Move cnode4 (D2→S2 on tsys5) | Same result, different disk |
| Leave cnode1 and one other on tsys4 | tsys5 fail = 4 survive (OK) |
**Simplest path:** migrate cnode3 and cnode4 storage to tsys5 (S3 and S2) via
PDM. Then tsys4 failure leaves cnode5 + cnode3 + cnode4 = 3 of 5 = quorum OK.
### 5.5 Future k8s architecture (next session -- see [K8S.md](K8S.md))
The k8s layer will be tackled soon. Key requirements from user:
- **Platform:** vcluster + Rancher for multi-tenant management
- **Auth:** OIDC to Keycloak (running on Cloudron in Reston, VA production)
- **Workload isolation (vcluster per tenant):**
- RackRental workloads (containerlab network labs)
- Suborbital ITAR (compliance-restricted)
- Suborbital non-ITAR
- Starting Line Productions customer workloads
- **Solar-aware scale-out:** PowerEdge 19xx and 2950 systems (older hardware)
will be brought online during peak solar production for burst capacity.
These older cores/ram supplement the main fleet when power is abundant.
- **WNode sizing:** every Proxmox node will have a wnode. Some nodes will host
both cnodes + wnodes. Worker sizes will vary from small (4 GB, fitting into
leftover host capacity) to large (28-32 GB, consuming most of a host).
- **Friday final audit:** tsys2 will be loaded with Proxmox on Friday, and a
full final audit will be performed at that time (post-NVMe install on tsys5,
post-D3 SSD relocation, post-tsys4 NIC+RAM).
### 5.4 sectestbed k8s nodes (separate from pfv-k8s)
tsys5 also hosts a separate sectestbed kubernetes stack using local storage:
| VMID | Name | Storage |
|------|------|---------|
| 5106 | sectestbed-k8s-cnode | local-nonprod (local HDD) |
| 5107 | sectestbed-k8s-wnode | local-nonprod (local HDD) |
These are on local storage (good -- no NFS dependency) but on a single host's
single local disk (no redundancy). They are isolated from the pfv-k8s cluster.
---
## 6. Storage Redundancy Analysis
### 6.1 -01/-02 infrastructure pair audit
Two -01/-02 pairs exist in the fleet:
**Pair 1: pfv-netinfra (network infrastructure)**
| Role | VMID | Host | Storage | NFS Server |
|------|------|------|---------|-----------|
| -01 | 103 | tsys1 | D5 | **tsys4** |
| -02 | 904 | tsys9 | D2 | **tsys4** |
**Verdict: HOST redundancy OK (different hosts), STORAGE redundancy FAILED.**
Both halves depend on tsys4. If tsys4 goes down, both netinfra VMs lose their
disks. The -02 half should be on an S2/S3/S4 export from tsys5.
**Pair 2: tsys-ucs (Univention Corporate Server)**
| Role | VMID | Host | Storage | NFS Server |
|------|------|------|---------|-----------|
| -01 | 108 | tsys1 | D2 | **tsys4** |
| -02 | 902 | tsys9 | D5 | **tsys4** |
**Verdict: HOST redundancy OK (different hosts), STORAGE redundancy FAILED.**
Same issue. Both halves on tsys4. The -02 half should be on tsys5 storage.
### 6.2 Redundancy principle for paired VMs
For any -01/-02 pair to survive a single storage server failure:
```
-01 VM disk -> tsys4 NFS export (D2/D3/D5)
-02 VM disk -> tsys5 NFS export (S2/S3/S4/T5-SSD)
```
This ensures that losing either tsys4 or tsys5 takes down only one half of
the pair. Currently, **both pairs fail this test** because both halves are on
tsys4.
### 6.3 NFS server failure blast radius
If **tsys4** goes offline (USB NIC failure, disk failure, reboot):
| Impact | Count |
|--------|-------|
| k8s cnodes that lose storage | 5 of 5 (**etcd quorum lost**) |
| k8s wnodes that lose storage | 4 of 5 |
| Infrastructure VMs that lose storage | 11 of 12 on tsys1 (all on D2/D5) |
| Total VMs that lose storage | **27 of 40 (68%)** |
If **tsys5** goes offline:
| Impact | Count |
|--------|-------|
| k8s cnodes that lose storage | 0 of 5 |
| k8s wnodes that lose storage | 1 of 5 |
| Total VMs that lose storage | 1 of 40 (3%) |
**tsys4 is a massive blast-radius liability. tsys5 is barely used.**
Rebalancing VM storage across both servers dramatically reduces risk.
---
## 7. Local SSD/NVMe Opportunity
### 7.1 Available fast tiers (currently unused by k8s)
| Host | Device | Type | Size | Available for VMs? | Currently used by k8s? |
|------|--------|------|------|--------------------|-----------------------|
| tsys4 | D3 (SK hynix SC300, USB) | SSD | 512 GB | Yes (via NFS) | **No** |
| tsys5 | T5-SSD (Samsung 860 PRO) | SSD | 256 GB | Yes (via NFS) | **No** (used by ultix-streaming) |
| tsys5 | **New NVMe (Friday)** | **NVMe** | TBD | **Yes (local or NFS)** | **No** |
| tsys9 | local-lvm (PNY CS900) | SSD | 137 GB free | Yes (local) | **No** |
### 7.2 Why local storage matters for k8s nodes
Kubernetes nodes are latency-sensitive in two specific areas:
1. **etcd (control plane):** etcd writes are synchronous and latency-critical.
On NFS over HDD, every etcd write traverses: VM -> virtio-scsi -> NFS
client -> TCP -> USB dongle (on tsys4) -> ext4 -> spinning disk. Typical
latency: 2-10 ms per write. On local SSD: 0.1-0.5 ms. On NVMe: 0.02-0.1 ms.
This directly affects k8s API responsiveness and pod scheduling speed.
2. **Container image pulls:** Worker nodes pull container images frequently.
On NFS-over-HDD, image layer extraction is seek-bound and slow. Local SSD
eliminates the network hop and reduces seek time. This matters most for
RackRental/containerlab workloads that spin up containers rapidly.
### 7.3 Current waste: tsys9 local SSD
tsys9 has a 250 GB PNY CS900 SSD with 137 GB of LVM-thin space available.
**Zero VMs use it.** All 5 VMs on tsys9 boot from NFS. The local SSD sits
idle. wnode-tsys9 (VM 905) would benefit significantly from local SSD --
its disk is currently on S3 (tsys5 NFS over a Seagate HDD).
### 7.4 Upcoming opportunity: tsys5 NVMe (Friday)
The PCI NVMe being added to tsys5 will be the fastest storage tier in the
fleet. Two placement options:
**Option A: NFS-export the NVMe (shared).** All hosts can use it. Good for
VMs that might need migration. Adds the NFS/network overhead back.
**Option B: Local-only on tsys5.** VMs on tsys5 get full NVMe speed with no
network overhead. Best for k8s wnode-tsys5 and sectestbed VMs. Cannot be
accessed from other hosts.
**Recommendation:** Option B (local-only). k8s worker nodes do not need
shared storage -- pods are ephemeral and reschedule on failure. The NVMe
should be formatted as a Proxmox directory storage (or LVM-thin) on tsys5
and used for local VM images.
---
## 8. Role Alignment Audit
Per the user's intended role taxonomy: tsys1/9 = infrastructure + k8s control
plane; tsys2/3/6/7 = k8s workers; tsys4/5 = storage. Cnodes on tsys1/9 is
**correct by design** (keeps heavy hosts free for workers).
### 8.1 VMs that need to move
| VMID | Name | Current host | Issue | Target |
|------|------|-------------|-------|--------|
| 509 | pfv-k8s-wnode-tsys5 | tsys5 (storage) | Worker on storage host | tsys7 or tsys2 (when online) |
| 905 | pfv-k8s-wnode-tsys9 | tsys9 (infra) | Can stay if small; user decides | tsys9 OK if small wnode |
### 8.2 Host capacity for k8s nodes
| Host | Role | Current k8s nodes | k8s RAM used | RAM total | Headroom |
|------|------|-------------------|-------------|-----------|----------|
| tsys1 | Infra+k8s ctrl | 2 cnodes | 8 GB | 32 GB | ~12 GB (after 11 infra VMs) |
| tsys3 | K8s worker | 1 wnode | 20 GB | 32 GB | ~12 GB |
| tsys6 | K8s worker | 3 cnodes + 1 wnode (stopped) | 12 GB | 128 GB | **~116 GB** |
| tsys7 | K8s worker | 1 wnode | 32 GB | 192 GB | **~160 GB** |
| tsys9 | Infra+k8s ctrl | 1 wnode | 4 GB | 24 GB | ~12 GB (after 4 infra VMs) |
| tsys2 | K8s worker | 0 (incoming) | 0 | 32 GB | ~32 GB |
**tsys6 and tsys7 are dramatically underutilized** -- 116 GB and 160 GB of
free RAM respectively. They should be the primary targets for heavy worker
nodes and ETL/HPC workloads.
### 8.3 tsys6 wnode-tsys6 is stopped
VM 100 (pfv-k8s-wnode-tsys6) is stopped on tsys6. Its disk is on D5 (tsys4
NFS). This wnode should be restarted (or recreated on local-lvm) to restore
cluster capacity.
---
## 9. Network Findings
### 9.1 tsys9 storage NIC is a USB dongle (new finding)
Validating tsys9 revealed that its storage network interface
(`enx9c69d36a5b6c`) is USB-attached (`parentbus usb`). This is the same
anti-pattern as tsys4. The onboard Intel NIC (`enp0s31f6`) is used for
management; storage uses the USB adapter.
**Impact:** Same as tsys4 -- achieves line rate but is susceptible to cable
wobble, ESD, and USB controller resets. For an infrastructure host with 5
VMs, this is a reliability risk.
**Mitigation:** tsys9 is an OptiPlex 7080 SFF -- it has PCIe slots. A
PCIe NIC would eliminate this risk (same recommendation as tsys4).
### 9.2 tsys4 and tsys5 still blocked (Friday hardware work)
| Host | Blocker | Staged fix |
|------|---------|-----------|
| tsys4 | USB cdc_ncm storage NIC | PCIe NIC install + RAM upgrade (16 to 64 GB) |
| tsys5 | bond0 broken (1 of 2 slaves) | Plug 2nd ethernet cable + apply layer3+4 hash |
### 9.3 LACP resolved on tsys6/tsys7
tsys6 to tsys7 storage path now measures **1.83 Gbps** (was 943 Mbps).
The switch LACP hash change took effect after renegotiation. The 56-106K
retransmits on this path are confirmed to be non-lossy multi-flow TCP-over-
LACP overhead. See `RESULTS.md` (not yet created) for the full analysis.
### 9.4 NFS nconnect=4 + noatime confirmed active
All hosts (including tsys9) show `nconnect=4,noatime` in their NFS mount
options. Each host maintains 4 TCP connections per NFS mount to each storage
server. This was the Tier 0 tuning item from the performance optimization
engagement and is confirmed working cluster-wide.
---
## 10. Recommendations
**No changes have been made. These are assessment-only recommendations.**
See `K8S.md` for the detailed kubernetes architecture deep-dive.
### 10.1 CRITICAL: Critical infrastructure VM placement (netinfra, UCS)
These are the most critical production VMs in the fleet. They must survive
any single-point failure (host, storage server, or disk).
**Design principle for -01/-02 HA pairs:**
- Different hypervisors (already satisfied: tsys1 vs tsys9)
- Different storage servers (currently FAILED: all on tsys4)
- Prefer SSD for latency-sensitive services
**Recommended placement:**
| VM | Host | Storage | Tier | Free space | Rationale |
|----|------|---------|------|-----------|-----------|
| **netinfra-01** (103) | tsys1 | **D5 (tsys4 HDD)** | NFS-HDD | 1.5 TB | DNS/DHCP/NTP = minimal I/O. Stays put. |
| **netinfra-02** (904) | tsys9 | **S3 (tsys5 HDD)** | NFS-HDD | 870 GB | Move from D2. Cross-server redundancy. Minimal I/O. |
| **ucs-01** (108) | tsys1 | **D2 (tsys4 HDD)** | NFS-HDD | 2.4 TB | Stays put. LDAP/AD does not need SSD. |
| **ucs-02** (902) | tsys9 | **S2 (tsys5 HDD)** | NFS-HDD | 870 GB | Move from D5. Cross-server redundancy. No SSD needed. |
**Failure survival matrix (all single-point failures):**
| Failure | netinfra-01 | netinfra-02 | ucs-01 | ucs-02 | Result |
|---------|-------------|-------------|--------|--------|--------|
| tsys4 dies | dies (D5) | **alive** (S3) | dies (D2) | **alive** (S2) | netinfra-02 + ucs-02 alive |
| tsys5 dies | **alive** (D5) | dies (S3) | **alive** (D2) | dies (S2) | netinfra-01 + ucs-01 alive |
| tsys1 dies | dies | **alive** | dies | **alive** | -02 pair survives |
| tsys9 dies | **alive** | dies | **alive** | dies | -01 pair survives |
| Any single disk | **all 4 on different disks/servers** | **all 4 alive** | | | |
**Why this works:** Every row has at least one netinfra and one UCS alive.
The network (DNS/DHCP) and directory (AD/LDAP) services never go fully dark.
**D3 SSD repurposed:** With UCS staying on HDD, the D3 SSD (moving to tsys5
Friday) is freed for latency-sensitive workloads that actually benefit from
SSD -- sectestbed k8s nodes, CI/CD artifact cache, or a container image
registry mirror. Not infrastructure VMs.
### 10.2 CRITICAL: Cnode (control plane) storage split
**Problem:** All 5 cnodes store disks on tsys4. D2 disk failure loses etcd
quorum (3 of 5 cnodes share D2).
**Target: cnodes weighted toward tsys1/tsys9 (lightweight hosts), freeing
tsys6/tsys7 for heavy workers. Storage splits across tsys4 and tsys5.**
| cnode | Current host | **Target host** | Current storage | **Target storage** | Rationale |
|-------|-------------|----------------|----------------|-------------------|-----------|
| cnode1 (107) | tsys1 | **tsys1** (stays) | D5 (tsys4) | **D5 (tsys4)** -- no change | Already correct |
| cnode3 (106) | tsys1 | **tsys1** (stays) | D2 (tsys4) | **S2 (tsys5)** -- **MOVE disk** | Split storage to tsys5 |
| cnode2 (603) | tsys6 | **tsys9** | D2 (tsys4) | **D2 (tsys4)** -- no disk change | Free tsys6 for heavy workers |
| cnode4 (601) | tsys6 | **tsys9** | D2 (tsys4) | **D5 (tsys4)** -- spread disk | Free tsys6; spread off D2 |
| cnode5 (602) | tsys6 | **tsys3** | D5 (tsys4) | **S3 (tsys5)** -- **MOVE disk** | Free tsys6; split storage to tsys5 |
**Result after changes:**
| Host | cnodes | Storage server |
|------|--------|---------------|
| tsys1 | cnode1 (D5), cnode3 (S2) | tsys4 + tsys5 |
| tsys9 | cnode2 (D2), cnode4 (D5) | tsys4 |
| tsys3 | cnode5 (S3) | tsys5 |
- 3 cnodes on tsys4 storage, 2 on tsys5. Either storage server can fail and
etcd keeps quorum (3 of 5 survive).
- D2 has 1 cnode (was 3). D5 has 2. S2 and S3 have 1 each. No single disk
holds more than 2 cnodes.
- Cnodes now on 3 hosts (tsys1, tsys9, tsys3). Any single host failure leaves
at least 3 cnodes alive.
- **tsys6 and tsys7 are fully freed** for heavy worker nodes.
Note: tsys1 RAM is tight (32 GB, 11 infra VMs). Adding 0 new cnodes (keeping
the 2 already there) is feasible with KSM. tsys9 (24 GB) has room for 2
cnodes (8 GB). tsys3 (32 GB) has room for 1 cnode (4 GB) alongside its wnode.
### 10.3 HIGH: Wnode distribution -- one per host, tiered storage
**Target: one wnode per hypervisor host, using local storage where possible
and NFS-HDD for bulk data.**
| wnode | Host | Boot disk (OS+containers) | Data disk (bulk/ETL) | Rationale |
|-------|------|--------------------------|---------------------|-----------|
| wnode-tsys1 | tsys1 | D5 (tsys4 NFS) | -- | Small wnode on infra host. Minimal capacity. |
| wnode-tsys3 | tsys3 | **local-lvm (349 GB NVMe)** | S3 (NFS) | Move from NFS to **NVMe** (Samsung PM961). Fastest boot disk after tsys5/2. |
| wnode-tsys6 | tsys6 | D2 (tsys4 NFS) | -- | **Stays on NFS.** local-lvm is USB 2.0 HDD (~30 MB/s) -- slower than NFS. |
| wnode-tsys7 | tsys7 | D5 (tsys4 NFS) | -- | **Stays on NFS.** local-lvm is USB 2.0 HDD (~30 MB/s) -- slower than NFS. |
| wnode-tsys9 | tsys9 | **local-lvm (136 GB SSD)** | S2 (NFS) | Move from NFS to local SSD. Fast boot, NFS for bulk. |
| wnode-tsys2 | tsys2 | **NVMe (Samsung 960 PRO 512GB)** | **SATA SSD (Samsung 850 EVO 1TB)** | **Best storage of any wnode.** No NFS needed -- 1.5 TB local SSD. |
| wnode-tsys5 | tsys5 | **new NVMe (local)** | local-nonprod (HDD) | **Fastest wnode in fleet.** HPC/ETL workloads land here. |
**Storage tiering strategy per wnode:**
Each wnode gets two disk tiers mapped to k8s StorageClasses:
1. **Boot + container runtime** (local-lvm or NVMe): OS, kubelet, container
images, ephemeral storage. This is where local SSD/NVMe shines -- container
image pulls and layer extraction are seek-bound and benefit enormously from
low-latency storage.
2. **Bulk data** (NFS-HDD via D2/D5/S2/S3): weather/GIS datasets, ETL staging
areas, large files that do not fit on local storage. Mounted as a second
disk in the VM and exposed to k8s as a StorageClass.
This maps to two k8s StorageClasses:
- `local-storage`: bound to the wnode's boot/local disk (fast, ephemeral)
- `nfs-bulk`: bound to NFS exports (slow, persistent, large capacity)
### 10.4 HIGH: Dedicate D3 SSD exclusively to k8s scratch
**Storage philosophy (user directive): NVMe/SSD is for k8s worker scratch
space and ultix-streaming (developer workstation running "cluster of 1"
pre-production jobs). Spinning rust hosts all other infrastructure VMs**
(UCS, netinfra, LibreNMS, SIEM, etc.).
SSD allocation after Friday:
- **D3 (tsys5 SAS, 445 GB free, 0% used)** -- dedicated to k8s scratch via
the `nfs-ssd` StorageClass (etcd, container cache, ephemeral volumes).
- **T5-SSD (tsys5 SAS, 140 GB free)** -- ultix-streaming (VM 5111) stays here
(developer workstation, runs single-node test jobs before k8s). Remaining
140 GB available for k8s.
**Deep-dive on exact k8s scratch allocation is deferred to the next session**
(K8S.md) once we know the k8s distribution, job scheduler, and workload mix.
### 10.5 MEDIUM: Restart wnode-tsys6
VM 100 (pfv-k8s-wnode-tsys6) is stopped on tsys6. Recreate on local-lvm
(1.7 TB free) instead of D5 NFS. This restores cluster capacity and moves
the boot disk to local storage simultaneously.
### 10.6 MEDIUM: tsys5 NVMe placement (Friday)
**Recommendation: local-only on tsys5, formatted as Proxmox LVM-thin or
directory storage.**
Use for:
- wnode-tsys5 boot disk (primary beneficiary -- HPC/ETL workloads)
- sectestbed VMs that need fast scratch space
- Not NFS-exported (avoid adding network overhead to the fastest tier)
### 10.7 LOW: Add PCIe NIC to tsys9
tsys9's storage NIC is a USB dongle. tsys9 is an OptiPlex 7080 with PCIe
slots. A $150 PCIe NIC eliminates the USB reliability risk.
### 10.8 LOW: Standardize PVE/kernel versions
tsys3 is on PVE kernel 7.0.14; others on 6.17.x. PVE-manager versions vary
(9.1.1 / 9.1.5 / 9.2.5). Standardize in a maintenance window.
---
## 11. Hardware End-of-Support Exposure
| Host | EOS date | Years past | Form factor |
|------|----------|-----------|-------------|
| pfv-tsys6 (R610) | 2013-05 | 13.2 | 1U server |
| pfv-tsys5 (T7500) | 2014-12 | 11.7 | Workstation |
| pfv-tsys4 (T1700) | 2018-03 | 8.4 | Workstation |
| pfv-tsys7 (R620) | 2019-03 | 7.4 | 1U server |
| pfv-tsys1 (9020) | 2019-07 | 7.0 | SFF desktop |
| pfv-tsys3 (7510) | 2020-07 | 6.0 | Laptop |
| pfv-tsys2 (5520) | TBD | -- | Laptop |
| **pfv-tsys9 (7080)** | **2024-02** | **2.4** | **SFF desktop (only supported)** |
**6 of 8 hosts are past vendor end-of-support.** Only tsys9 is still covered.
The two actual rack servers (R610, R620) are the most overdue for replacement.
This belongs in the next budget cycle.
---
## 12. Open Items
### 12.1 Immediate (do today via PDM)
1. **Migrate ucs-02** (VM 902) from D5 (tsys4) to S2 (tsys5) for cross-server
redundancy. UCS stays on HDD.
2. **Migrate netinfra-02** (VM 904) from D2 (tsys4) to S3 (tsys5).
3. **Migrate cnode3** (VM 106) from D2 (tsys4) to S3 (tsys5) -- etcd quorum.
4. **Migrate cnode4** (VM 601) from D2 (tsys4) to S2 (tsys5) -- etcd quorum.
5. **Start wnode-tsys1** (VM 102) if the cluster needs the capacity.
### 12.2 Friday maintenance window (user action)
1. **tsys4:** Install PCIe NIC (replace USB dongle), add RAM (16 to 64 GB),
reconfigure `/etc/network/interfaces`, reboot.
2. **tsys5:** Plug 2nd ethernet cable, verify bond0, apply layer3+4 hash,
install PCI NVMe, relocate D3 SSD from tsys4 USB to tsys5 SAS port,
format NVMe as local storage, reboot.
3. **tsys2:** Load Proxmox (replacing Windows 10).
4. **Final audit:** Re-run `deploy-check.sh` across all hosts including tsys2.
### 12.3 Post-Friday validation
1. Re-run iperf matrix: `./iperf-full-matrix.sh`
2. Validate tsys4 and tsys5: `./validate-fixes.sh pfv-tsys4 && ./validate-fixes.sh pfv-tsys5`
3. Run `scripts/check.sh` on tsys2 once Proxmox is loaded.
4. Update PROJECT.md with post-hardware numbers.
### 12.4 Future: Kubernetes deep-dive (see [K8S.md](K8S.md))
Next major workstream. Requirements captured:
- **vcluster + Rancher** for multi-tenant k8s management
- **OIDC auth** to Keycloak (on Cloudron, Reston VA production)
- **Workload isolation** via separate vclusters:
- RackRental (containerlab)
- Suborbital ITAR
- Suborbital non-ITAR
- Starting Line Productions customer workloads
- **Solar-aware scale-out:** PowerEdge 19xx + 2950 systems brought online
during peak solar production for burst capacity
- **Every host gets a wnode** (variable sizing: small 4 GB to large 32 GB)
- **SSD/NVMe reserved for k8s scratch** (plus ultix-streaming exception)
- **Spinning rust for all infrastructure VMs**
### 12.5 Data gaps
| Gap | How to close |
|-----|--------------|
| tsys5 SDR/parallel-port workload dependency | Confirm what uses the SDR |
| tsys2 post-Proxmox baseline | Run `check.sh` after Friday install |
| tsys5 NVMe size and model | Confirm after Friday installation |
| tsys3 thermal state (laptop in rack) | Check `sensors` on next maintenance |
| PowerEdge 19xx/2950 inventory | When solar scale-out is planned |
### 12.6 Scripts and tools available
| Script | Purpose |
|--------|---------|
| `scripts/check.sh` | Read-only data collector (run on hosts) |
| `scripts/apply-tunings.sh` | Apply all Tier 0 tunings (dry-run/apply/rollback) |
| `scripts/fix-bond-nfs.sh` | Fix NFS options + bond hash |
| `validate-fixes.sh` | Read-only validation of all applied changes |
| `iperf-full-matrix.sh` | Full iperf test suite (mgmt + storage) |
| `deploy-check.sh` | Deploy check.sh to all hosts via SSH (now includes tsys9) |
# proxmox/docs/PROJECT.md
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Comprehensive fleet report**
>
> **Read it here:** https://community.turnsys.com/t/304
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+8 -194
View File
@@ -1,196 +1,10 @@
# Storage Architecture
# proxmox/docs/STORAGE-ARCHITECTURE.md
> **Complete storage reference for the PFVCluster.** Covers physical disks,
> NFS exports/mounts, Proxmox storage IDs, tier definitions, and per-spindle
> VM placement. Data gathered 2026-07-30 via live host probes.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> Companion docs: [`NETWORK-TOPOLOGY.md`](NETWORK-TOPOLOGY.md),
> [`HOST-REFERENCE.md`](HOST-REFERENCE.md), [`VM-INVENTORY.md`](VM-INVENTORY.md).
> Findings/analysis: [`AUDIT-2026-07-30.md`](AUDIT-2026-07-30.md).
---
## 1. Storage tier definitions
| Tier | Definition | Typical speed | Reliability | Use case |
|------|-----------|---------------|-------------|----------|
| **Tier 1** | NVMe or SSD on internal SATA/SAS/PCIe | 200-3000 MB/s | High | OS drives, high-IOPS workloads, build scratch |
| **Tier 2** | HDD on internal SATA/SAS | 80-150 MB/s | Moderate | Production VM OS drives, general-purpose storage |
| **Tier 3** | HDD/SSD on USB adapter / "toaster" | 30-60 MB/s | Low (USB) | Bulk, backup, scratch only. Never for production OS drives. |
**Policy (from [`CAPACITY-GOALS.md`](CAPACITY-GOALS.md) §6):** Local disk
storage is a scratch tier, not a boot/OS tier. VM OS drives stay on NFS
(tsys4/tsys5) where redundancy is achieved by spreading across physical disks
and HA pairs. Local storage is for ephemeral data where loss on node failure
is acceptable.
---
## 2. Physical disk inventory
### tsys4 -- NFS storage server + PBS (7 disks)
| Device | Model | Size | RPM | Interface | Mount | NFS ID | Tier | SMART | Used |
|--------|-------|------|-----|-----------|-------|--------|------|-------|------|
| sda | Hitachi HDS723020BLA642 | 2.0 TB | 7200 | SATA | /mnt/albert | (not exported) | **Tier 2** | PASSED, 0 reallocated | 0% |
| sdb | HITACHI HUA723020ALA640 | 2.0 TB | 7200 | SATA | /mnt/tsys4/D5 | **D5** | Tier 2 | PASSED, 0 reallocated | 13% (220 GB) |
| sdc | WDC WD30EFRX (Red) | 3.0 TB | 5400 | SATA | /mnt/tsys4/D2 | **D2** | Tier 2 | PASSED, 0 reallocated | 7% (170 GB) |
| sdd | WDC WD10EZRX | 1.0 TB | -- | SATA | (pve boot/swap/lvm) | -- | Tier 2 | PASSED, 1 reallocated (sdf has 1) | OS disk |
| sde | ST500LM021 (Seagate) | 500 GB | 7200 | **USB** | /mnt/tsys4/D3 | **D3** | **Tier 3** | PASSED | 0% |
| sdf | WDC WD10EARS | 1.0 TB | -- | **USB** | /mnt/tsys4/D1 | **D1** | **Tier 3** | PASSED, 1 reallocated sector | 0% |
| sdg | WDC WD50NDZW (easystore) | 5.0 TB | 5400 | **USB** | /mnt/backup | (not exported) | **Tier 3** | PASSED | 0% |
**Changes from previous audit:**
- **D3 changed:** was SK hynix SC300 512GB SSD → now Seagate ST500LM021 500GB HDD (still USB). Demoted from unreliable-SSD to Tier 3 HDD.
- **/mnt/albert added:** Hitachi 2TB internal SATA. Not exported, not in Proxmox. Unused Tier 2.
- **/mnt/backup added:** WD 5TB USB easystore. Bulk backup only.
- **D7 removed:** Previously held DellOpenManageEnterprise. Now gone.
### tsys5 -- NFS storage server + sandboxes (7 disks)
| Device | Model | Size | RPM | Interface | Mount | NFS/Local ID | Tier | SMART | Used |
|--------|-------|------|-----|-----------|-------|-------------|------|-------|------|
| sda | ST1000VN002 (IronWolf) | 1.0 TB | 5900 | SATA | **(not mounted)** | was S3 | Tier 2 | PASSED | -- |
| sdb | SK hynix SC300B | 512 GB | SSD | SATA | **(not mounted)** | -- | **Tier 1** | PASSED | **NEW, not configured** |
| sdc | HITACHI HUS724020ALA640 | 2.0 TB | 7200 | SAS | (pve boot/swap/lvm) | -- | Tier 2 | PASSED | OS disk |
| sdd | Samsung SSD 860 PRO | 256 GB | SSD | SAS | /mnt/pfv-tsys5/ssd | `ssd` / `SSD` dir (local) | **Tier 1** | PASSED | **93% full!** |
| sde | ST1000VN002 (IronWolf) | 1.0 TB | 5900 | SAS | /mnt/pfv-tsys5/S1 | **S1** + `local-nonprod` | Tier 2 | PASSED | 11% (96 GB) |
| sdf | ST1000VN002 (IronWolf) | 1.0 TB | 5900 | SAS | /mnt/pfv-tsys5/S2 | **S2** | Tier 2 | PASSED | 4% (32 GB) |
| **nvme0n1** | **CT500P1SSD8 (Crucial)** | **500 GB** | **NVMe** | **PCIe** | **(not mounted)** | -- | **Tier 1** | PASSED, 0 integrity errors, 34K hrs | **NEW, not configured** |
**Changes from previous audit:**
- **NVMe added:** Crucial CT500P1 500GB. True NVMe -- highest-performance local storage in the fleet. Not mounted, not in fstab, not in storage.cfg.
- **SK hynix SSD relocated:** Moved from tsys4 USB enclosure to tsys5 internal SATA. Not mounted or configured.
- **S3 unmounted:** sda (was S3) is present but fstab entry is commented out. Stale export remains in /etc/exports.
- **S4 gone:** Old Toshiba 458GB no longer present. fstab entry commented. storage.cfg has broken `dir: S4` entry.
- **S1/S2 drives changed:** Both are now ST1000VN002 IronWolf 1TB (5900 rpm).
- **SSD nearly full:** Samsung 860 PRO at 93% (206/234 GB) -- needs attention.
- **Boot disk changed:** HITACHI HUS724020ALA640 2TB (was Hitachi 2TB in old audit, now confirmed model).
---
## 3. NFS export → Proxmox storage ID map
```mermaid
graph LR
subgraph "tsys4 -- NFS Server"
D2["D2: /mnt/tsys4/D2<br>WDC Red 3TB<br>Tier 2 | 7% used"]
D5["D5: /mnt/tsys4/D5<br>Hitachi 2TB<br>Tier 2 | 13% used"]
D1["D1: /mnt/tsys4/D1<br>WD 1TB USB<br>Tier 3 | 0% used"]
D3["D3: /mnt/tsys4/D3<br>Seagate 500GB USB<br>Tier 3 | 0% used"]
end
subgraph "tsys5 -- NFS Server"
S1["S1: /mnt/pfv-tsys5/S1<br>IronWolf 1TB<br>Tier 2 | 11% used"]
S2["S2: /mnt/pfv-tsys5/S2<br>IronWolf 1TB<br>Tier 2 | 4% used"]
S3stale["S3: (stale export)<br>disk not mounted"]
end
subgraph "All hosts -- NFS Clients"
MNT["/mnt/pve/D1 D2 D3 D5<br>/mnt/pve/S1 S2 S3 S4<br>/mnt/pve/T5-SSD"]
end
D2 -->|NFS v4.2| MNT
D5 -->|NFS v4.2| MNT
D1 -->|NFS v4.2| MNT
D3 -->|NFS v4.2| MNT
S1 -->|NFS v4.2| MNT
S2 -->|NFS v4.2| MNT
S3stale -.->|broken| MNT
```
### NFS export details
| Server | Export path | NFS ID | Protocol | Options (client-side) |
|--------|-------------|--------|----------|----------------------|
| tsys4 | /mnt/tsys4/D1 | D1 | NFSv4.2 | nconnect=4,noatime,rsize=1048576,wsize=1048576,hard |
| tsys4 | /mnt/tsys4/D2 | D2 | NFSv4.2 | nconnect=4,noatime,rsize=1048576,wsize=1048576,hard |
| tsys4 | /mnt/tsys4/D3 | D3 | NFSv4.2 | nconnect=4,noatime,rsize=1048576,wsize=1048576,hard |
| tsys4 | /mnt/tsys4/D5 | D5 | NFSv4.2 | nconnect=4,noatime,rsize=1048576,wsize=1048576,hard |
| tsys5 | /mnt/pfv-tsys5/S1 | S1 | NFSv4.2 | nconnect=4,noatime,rsize=1048576,wsize=1048576,hard |
| tsys5 | /mnt/pfv-tsys5/S2 | S2 | NFSv4.2 | nconnect=4,noatime,rsize=1048576,wsize=1048576,hard |
| tsys5 | /mnt/pfv-tsys5/S3 | S3 | NFSv4.2 | **stale** (disk not mounted on server) |
| tsys5 | /mnt/pfv-tsys5/ssd | T5-SSD | NFSv4.2 | nconnect=4,noatime,rsize=1048576,wsize=1048576,hard |
| tsys5 | /mnt/pfv-tsys5/S4 | S4 | -- | **broken** (disk gone, storage.cfg entry stale) |
> **Note:** tsys5 is the only host where NFS client mounts (D2/D3/D5 from
> tsys4) are **missing nconnect=4**. All other client hosts have nconnect on
> all mounts.
---
## 4. Per-spindle VM placement (running VMs only)
> Shows every running VM's primary disk and the physical spindle it lives on.
> This is the IOPS distribution map -- the key to storage balancing.
```mermaid
graph TB
subgraph "tsys4 spindles"
D2["D2 -- WDC Red 3TB<br>*** 13 VMs -- WORST HOTSPOT"]
D5["D5 -- Hitachi 2TB<br>4 VMs"]
D1["D1 -- WD 1TB USB<br>0 VMs (empty)"]
D3["D3 -- Seagate 500GB USB<br>0 VMs (empty)"]
ALB["/mnt/albert -- Hitachi 2TB<br>0 VMs (not in Proxmox)"]
end
subgraph "tsys5 spindles"
S1["S1 -- IronWolf 1TB<br>1 NFS VM + 12 local stopped"]
S2["S2 -- IronWolf 1TB<br>5 VMs"]
SSD["SSD -- Samsung 860 PRO<br>1 VM (93% full!)"]
NVME["NVMe -- Crucial CT500P1<br>NOT CONFIGURED"]
HYNIX["SK hynix SSD 512GB<br>NOT CONFIGURED"]
end
D2 --- D2vms["100 101 104 105 108<br>114 117 509 600 702<br>704 901 904"]
D5 --- D5vms["106 313 600(d0) 903"]
S1 --- S1vms["702 hfnoc-uisp"]
S2 --- S2vms["103 703 705 902 905"]
SSD --- SSDvms["5111 ultix-streaming"]
```
### Detailed per-spindle load
| Spindle | Server | NFS ID | Tier | Running VMs | VMIDs | Notes |
|---------|--------|--------|------|-------------|-------|-------|
| **D2** (WDC Red 3TB) | tsys4 | D2 | Tier 2 | **13** | 100,101,104,105,108,114,117,509,600,702,704,901,904 | **Worst IOPS hotspot** |
| D5 (Hitachi 2TB) | tsys4 | D5 | Tier 2 | 4 | 106,313,600(disk0),903 | Moderate |
| S1 (IronWolf 1TB) | tsys5 | S1 + local-nonprod | Tier 2 | 1 (NFS) + 0 (local, 12 stopped) | 702 | Low; 12 stopped sandboxes on local-nonprod |
| S2 (IronWolf 1TB) | tsys5 | S2 | Tier 2 | 5 | 103,703,705,902,905 | Moderate |
| ssd (Samsung 860 PRO) | tsys5 | SSD dir | Tier 1 | 1 | 5111 | **93% full** |
| D1 (WD 1TB USB) | tsys4 | D1 | Tier 3 | 0 | -- | Empty |
| D3 (Seagate 500GB USB) | tsys4 | D3 | Tier 3 | 0 | -- | Empty |
| /mnt/albert (Hitachi 2TB) | tsys4 | (none) | Tier 2 | 0 | -- | Not in Proxmox |
| NVMe (CT500P1 500GB) | tsys5 | (none) | Tier 1 | 0 | -- | **Not configured** |
| SK hynix SSD (512GB) | tsys5 | (none) | Tier 1 | 0 | -- | **Not configured** |
### Local-only VM disks (not on NFS)
| Host | Storage ID | Disk | VMs | Notes |
|------|-----------|------|-----|-------|
| tsys4 | local-lvm | sdd (1TB internal) | 400 (PBS) | Proxmox boot/OS disk |
| tsys5 | local-lvm | sdc (2TB internal) | 5102,5103,5104,5112 | Mixed: stopped sandboxes + ultix-offstage |
| tsys5 | local-nonprod (=S1) | sde (IronWolf 1TB) | 5101,5105,5106-5109,515,53100-53103,6000,51010-51014 | All STOPPED sandboxes. Same physical disk as S1 NFS. |
| tsys5 | SSD dir | sdd (Samsung 860 PRO) | 5111 | ultix-streaming. 93% full. |
---
## 5. Storage capacity summary
| Spindle | Size | Used | Available | % Used |
|---------|------|------|-----------|--------|
| D2 (WDC Red 3TB) | 2.7 TB | 170 GB | 2.4 TB | 7% |
| D5 (Hitachi 2TB) | 1.8 TB | 220 GB | 1.5 TB | 13% |
| D1 (WD 1TB USB) | 916 GB | 2 MB | 870 GB | 0% |
| D3 (Seagate 500GB USB) | 458 GB | 2 MB | 435 GB | 0% |
| /mnt/albert (Hitachi 2TB) | 1.8 TB | 2 MB | 1.7 TB | 0% |
| /mnt/backup (WD 5TB USB) | 4.6 TB | 2 MB | 4.3 TB | 0% |
| S1 (IronWolf 1TB) | 916 GB | 96 GB | 774 GB | 11% |
| S2 (IronWolf 1TB) | 916 GB | 32 GB | 838 GB | 4% |
| SSD (Samsung 860 PRO) | 234 GB | 206 GB | **16 GB** | **93%** |
| NVMe (CT500P1) | 466 GB | -- | -- | Not configured |
| SK hynix SSD | 477 GB | -- | -- | Not configured |
**Total Tier 2 available (NFS production):** ~5.5 TB unused across D2/D5/S1/S2
**Total Tier 3 available (USB):** ~6 TB unused across D1/D3/backup
**Total Tier 1 available (unconfigured):** ~940 GB across NVMe + SK hynix SSD
> **Storage reference: tiers, disk inventory, NFS exports, VM placement**
>
> **Read it here:** https://community.turnsys.com/t/300
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+9 -241
View File
@@ -1,242 +1,10 @@
# TODO.md — Pending User Actions
# proxmox/docs/TODO.md
**Date:** 2026-07-27
**Items needing user input or physical action.**
---
## 1. tsys2 Windows hardware inventory (run on the Windows host)
pfv-tsys2 is currently Windows 10. Before rebuilding it as Proxmox, gather
hardware data so the architecture plan can account for it.
### Option A: PowerShell (recommended — single command, copy-paste output)
Open **PowerShell as Administrator** and run:
```powershell
# Full hardware inventory in one shot
Write-Output "=== COMPUTER ==="
Get-CimInstance Win32_ComputerSystem | Select-Object Manufacturer, Model, SystemType, TotalPhysicalMemory | Format-List
Write-Output "`n=== CPU ==="
Get-CimInstance Win32_Processor | Select-Object Name, NumberOfCores, NumberOfLogicalProcessors, MaxClockSpeed | Format-List
Write-Output "`n=== MEMORY STICKS ==="
Get-CimInstance Win32_PhysicalMemory | Select-Object Manufacturer, PartNumber, Capacity, Speed, ConfiguredClockSpeed, DeviceLocator, FormFactor | Format-Table -AutoSize
Write-Output "`n=== DISKS ==="
Get-PhysicalDisk | Select-Object FriendlyName, MediaType, BusType, Size, SpindleSpeed | Format-Table -AutoSize
Write-Output "`n=== DISK PARTITIONS ==="
Get-Disk | Select-Object Number, FriendlyName, Size, PartitionStyle, OperationalStatus | Format-Table -AutoSize
Write-Output "`n=== NETWORK ADAPTERS ==="
Get-NetAdapter | Select-Object Name, InterfaceDescription, Status, LinkSpeed, MacAddress | Format-Table -AutoSize
Write-Output "`n=== GPU(s) ==="
Get-CimInstance Win32_VideoController | Select-Object Name, AdapterRAM, DriverVersion, VideoProcessor | Format-List
Write-Output "`n=== PCIe SLOTS ==="
Get-CimInstance Win32_SystemSlot | Select-Object SlotDesignation, CurrentUsage, Status | Format-Table -AutoSize
Write-Output "`n=== USB DEVICES (storage + network only) ==="
Get-PnpDevice -PresentOnly | Where-Object { $_.Class -in @('DiskDrive','Net','USB') } | Select-Object Class, FriendlyName, Status | Format-Table -AutoSize
```
Copy the full output into a file (e.g., `tsys2-hardware.txt`) or paste it
directly into the chat.
### Option B: Command Prompt (cmd.exe) fallbacks
If PowerShell is unavailable for some reason, these cmd commands give a
subset:
```cmd
:: Computer model and serial
wmic computersystem get manufacturer,model
wmic bios get serialnumber
:: CPU
wmic cpu get name,numberofcores,numberoflogicalprocessors,maxclockspeed
:: RAM (total)
wmic computersystem get totalphysicalmemory
:: RAM sticks (per-slot detail)
wmic memorychip get manufacturer,capacity,speed,partnumber,devicelocator
:: Disks
wmic diskdrive get model,size,interfacetype,mediatype
:: Network adapters
wmic nic where netenabled=true get name,speed,macaddress
:: GPU
wmic path win32_videocontroller get name,adapterram,driverversion
```
### What I'm looking for
- **Disk inventory**: Are there any SSDs/NVMe available locally? (Determines
whether wnode-tsys2 can use local storage like the other wnodes.)
- **Network adapters**: How many onboard NICs? Model? (Determines whether
tsys2 needs a USB dongle for storage network like tsys4/9, or has a real
onboard NIC available.)
- **RAM layout**: Is all 32 GB in 1 stick, 2 sticks, or 4 sticks? (Affects
memory bandwidth for HPC workloads — dual-channel matters.)
- **GPU detail**: Confirm the Quadro M1200 model and VRAM for passthrough
planning.
- **PCIe slots**: Is there a free PCIe slot for adding a NIC or HBA?
- **Service tag confirmation**: `GH1XZG2` (already on file from spreadsheet).
### STATUS: Collected 2026-07-27
**Disk inventory — RESOLVED:**
- Disk 0: Samsung SSD 960 PRO **512 GB NVMe** (best local storage in fleet)
- Disk 1: Samsung SSD 850 EVO **1 TB SATA SSD**
- Both SSDs, no spinning rust. 1.5 TB total local SSD.
**Network adapters — RESOLVED (concerning):**
- StorageNetwork: **ASIX USB to Gigabit Ethernet** (dongle, D4-81-D7-3E-0D-5E)
- Ethernet: **Realtek USB GbE Family Controller** (also USB, 18-FD-CB-00-D2-CA)
- Wi-Fi: Intel 8265 (disconnected)
- **Both wired NICs are USB-attached.** Same anti-pattern as tsys4/9.
Unavoidable on this laptop form factor — no onboard PCIe NIC available.
**GPU — RESOLVED:**
- Intel HD Graphics 630 (integrated, 1 GB)
- NVIDIA Quadro M1200 (4 GB, confirmed for passthrough)
**PCIe slots — RESOLVED:**
- Slots 3/6/7/8 report "Available" but these are laptop M.2/WWAN slots, not
user-accessible full PCIe. **Cannot add a PCIe NIC.** NVMe slot occupied
by 960 PRO.
**RAM — PARTIAL:**
- Total 32 GB confirmed (34,097,573,888 bytes).
- Per-stick detail failed to run (PowerShell line-break split
`Format-T` + `able`). Re-run the command below if bandwidth planning
needs stick-level detail:
```powershell
Get-CimInstance Win32_PhysicalMemory | Select-Object Manufacturer, PartNumber, Capacity, Speed, ConfiguredClockSpeed, DeviceLocator, FormFactor | Format-Table -AutoSize
```
**Service tag — CONFIRMED:** `GH1XZG2` (Precision 5520).
---
## 2. Friday maintenance window (physical hardware)
### tsys4 — install PCIe NIC + add RAM
1. Power down tsys4 (graceful shutdown via Proxmox UI or `shutdown -h now`).
2. Install the **PCIe NIC** (Intel i350-T2 or similar 1 GbE dual-port).
3. Add **RAM**: 16 GB → 64 GB DDR3 ECC.
4. Power on, then update `/etc/network/interfaces` to replace
`enx8cae4ccda926` (USB dongle) with the new PCIe NIC device name.
5. Reboot to activate new NIC and NFS nconnect.
6. Run `validate-fixes.sh pfv-tsys4` to confirm.
### tsys5 — plug storage cable + install NVMe + relocate D3 SSD
1. Plug the **second ethernet cable** into tsys5's dedicated storage NIC.
2. Verify bond0 recovery: `cat /proc/net/bonding/bond0` — look for
"Number of ports: 2" and a real partner MAC (not all zeros).
3. Apply bond hash fix (same as tsys6/7):
```bash
echo "layer3+4" > /sys/class/net/bond0/bonding/xmit_hash_policy
```
4. **Relocate D3 SSD** from tsys4 USB to tsys5 SAS port:
- Power down tsys4
- Remove the SK hynix SC300 SSD from its USB enclosure on tsys4
- Install it on a free SAS port on tsys5 (5 ports free on LSI SAS1068E)
- On tsys5: mount as `/mnt/pfv-tsys5/D3`, add to `/etc/exports`
- Update `/etc/pve/storage.cfg` cluster-wide: repoint D3 `server` from
`pfv-tsys4-nfs-stor` to `pfv-tsys5-nfs-stor`, update `export` path
- Copy any existing D3 data from tsys4 first (currently ~2 MB, essentially
empty, so minimal migration)
5. Install the **PCI NVMe drive** (uses a PCI slot, not a SATA/SAS port).
6. Format NVMe as local directory storage (see TODO section 3 below).
7. Reboot tsys5 to activate NFS nconnect.
8. Run `validate-fixes.sh pfv-tsys5` to confirm.
---
## 3. tsys5 NVMe format/mount decision (after Friday install)
**Recommendation: local-only, not NFS-exported.** Format as Proxmox directory
storage so it shows up as a VM image target in the Proxmox UI.
After the NVMe is physically installed and visible in Proxmox:
1. Identify the device: `lsblk` or `ls /dev/nvme*`
2. Format and add to Proxmox:
```bash
# Option A: LVM-thin (thin provisioning, snapshots)
pvcreate /dev/nvme0n1
vgcreate nvme-pool /dev/nvme0n1
lvcreate -l 100%FREE -T nvme-pool/data
# Then in Proxmox UI: Datacenter > Storage > Add > LVM-Thin
# ID: nvme-local
# Volume Group: nvme-pool
# Thin Pool: data
# Content: Disk image, Container template
# Option B: Directory (simpler, no thin provisioning)
mkfs.ext4 /dev/nvme0n1
mkdir -p /mnt/nvme
mount /dev/nvme0n1 /mnt/nvme
# Add to /etc/fstab for persistence
# Then in Proxmox UI: Datacenter > Storage > Add > Directory
# ID: nvme-local
# Directory: /mnt/nvme
# Content: Disk image, Container template
```
3. Use for wnode-tsys5 boot disk (highest impact) and sectestbed VM scratch.
---
## 4. Post-hardware validation (run after Friday work)
1. Re-run iperf matrix: `./iperf-full-matrix.sh`
2. Validate tsys4 and tsys5: `./validate-fixes.sh pfv-tsys4 && ./validate-fixes.sh pfv-tsys5`
3. Update PROJECT.md with post-hardware iperf numbers.
---
## 5. UCS storage migration to spinning disk (do today)
UCS (Univention Corporate Server / open-source AD) does not need SSD. Both
UCS VMs should stay on spinning disk (HDD) and be split across storage
servers for redundancy.
| VM | Current | Target | Action |
|----|---------|--------|--------|
| ucs-01 (108) | D2 (tsys4 HDD) | **D2 (tsys4 HDD) -- no change** | Already correct |
| ucs-02 (902) | D5 (tsys4 HDD) | **S2 (tsys5 HDD)** | Move for cross-server redundancy |
**To migrate ucs-02 to S2 (use PDM/Proxmox UI):**
1. In Proxmox Datacenter or the node UI, select VM 902 on tsys9
2. Use "Migrate" or "Storage Migrate" to move the disk from D5 to S2
(both are NFS exports visible to tsys9, so this is a storage-only migration)
3. Verify VM 902 boots and LDAP/AD services are healthy after migration
Note: both VMs are currently on tsys4 HDD, which is fine for UCS. Only
ucs-02 needs to move -- it should be on a different storage server than
ucs-01 so a tsys4 failure doesn't take down both halves of the AD pair.
---
## 6. Open questions for next session
- Are the hosts a Proxmox cluster (`pvecm status`) or standalone installs?
Determines whether live migration is available.
- What k8s distribution is in use? (k3s, kubeadm, RKE2?)
- Container runtime? (containerd, cri-o?)
- Is there a local container image registry mirror?
- What specific ETL tools? (GDAL, PostGIS, xarray, Dask?)
- HPC job scheduler? (plain k8s Jobs, Argo Workflows, Volcano?)
- What uses tsys5's SDR + parallel port before planning tsys5 role changes?
- tsys3 thermal state (laptop in rack for years) — check `sensors`.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> **Pending hardware work — folded into Operations Status**
>
> **Read it here:** https://community.turnsys.com/t/298
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*
+8 -223
View File
@@ -1,225 +1,10 @@
# VM Inventory
# proxmox/docs/VM-INVENTORY.md
> **Every VM in the cluster, with host placement, disk location, CPU/RAM
> allocation, and optimization status.** Data gathered 2026-07-30.
> **Documentation moved to Discourse — the canonical source of truth.**
>
> Companion docs: [`NETWORK-TOPOLOGY.md`](NETWORK-TOPOLOGY.md),
> [`STORAGE-ARCHITECTURE.md`](STORAGE-ARCHITECTURE.md),
> [`HOST-REFERENCE.md`](HOST-REFERENCE.md).
---
## 1. VM placement diagram
```mermaid
graph TB
subgraph tsys1["tsys1 -- Infra (57% RAM)"]
VM100["100 pfv-bms<br>2c/4G D2"]
VM101["101 tsys-ca<br>2c/2G D2"]
VM103["103 netinfra-01<br>2c/4G S2"]
VM104["104 librenms<br>2c/2G D2"]
VM105["105 proxmox-dc<br>2c/2G D2"]
VM106["106 cnode3<br>4c/4G D5"]
VM108["108 ucs-01<br>2c/8G D2"]
VM114["114 kali-tsys<br>2c/2G D2"]
VM117["117 workbench<br>2c/4G D2"]
end
subgraph tsys3["tsys3 -- Compute (10% RAM)"]
VM313["313 wnode-tsys3<br>8c/28G D5"]
end
subgraph tsys4["tsys4 -- Storage (15% RAM)"]
VM400["400 PBS<br>2c/2G local-lvm"]
end
subgraph tsys5["tsys5 -- Storage+Sandbox (15% RAM)"]
VM509["509 wnode-tsys5<br>2c/32G D2"]
VM515["515 hfnoc-uisp-preprod<br>2c/2G local-nonprod"]
VM5111["5111 ultix-streaming<br>4c/9G SSD"]
VM5112["5112 ultix-offstage<br>4c/6G local-lvm"]
end
subgraph tsys6["tsys6 -- RackRental (12% RAM)"]
VM100b["100 wnode-tsys6<br>2c/64G S4"]
VM600["600 tsys-awx<br>2c/12G D5"]
end
subgraph tsys7["tsys7 -- RackRental (7% RAM)"]
VM701["701 wnode-tsys7<br>4c/32G S3"]
VM702["702 hfnoc-uisp<br>2c/8G S1"]
VM703["703 rr-middleware<br>2c/2G S2"]
VM704["704 TCTC<br>4c/6G D2"]
VM705["705 cnode2<br>4c/4G S2"]
end
subgraph tsys9["tsys9 -- Infra+Compute (69% RAM)"]
VM901["901 tsys-siem<br>2c/8G D2"]
VM902["902 ucs-02<br>2c/8G S2"]
VM903["903 kali-rd<br>2c/2G D5"]
VM904["904 netinfra-02<br>2c/4G D2"]
VM905["905 wnode-tsys9<br>4c/4G S2"]
VM906["906 cnode1<br>2c/4G S3"]
end
```
---
## 2. Complete running VM inventory (28 running VMs)
### Infrastructure (netinfra, UCS, CA, LibreNMS, PDM)
| VMID | Name | Host | vCPU | CPU type | RAM | Disk store | Spindle | Disk type | Cache | iothread | qga | Notes |
|------|------|------|------|----------|-----|-----------|---------|-----------|-------|----------|-----|-------|
| 100 | pfv-bms (HomeAssistant) | tsys1 | 2 | host | 4G | D2 (raw) | D2 | raw | -- | -- | ✓ | discard=on, ssd=1. HA for power/temp monitoring. |
| 101 | tsys-ca | tsys1 | 2 | v2-AES | 2G | D2 (virtio) | D2 | qcow2 | -- | ✓ | -- | no nested-virt flag. Certificate Authority. |
| 103 | pfv-netinfra-01 | tsys1 | 2 | v2-AES | 4G | S2 | S2 | qcow2 | -- | ✓ | -- | DNS primary (Technitium + Pi-hole). |
| 104 | tsys-librenms | tsys1 | 2 | host | 2G | D2 | D2 | qcow2 | -- | ✓ | ✓ | SNMP monitoring for switches. |
| 105 | tsys-proxmox-datacenter | tsys1 | 2 | host | 2G | D2 | D2 | qcow2 | -- | ✓ | ✓ | PDM (Proxmox Datacenter Manager). |
| 108 | tsys-ucs-01 | tsys1 | 2 | host | 8G | D2 | D2 | qcow2 | **writethrough** | ✓ | ✓ | Univention Corporate Server half 1. |
| 902 | tsys-ucs-02 | tsys9 | 2 | host | 8G | S2 | S2 | qcow2 | -- | ✓ | ✓ | UCS half 2 (HA pair with 108). |
| 904 | pfv-netinfra-02 | tsys9 | 2 | v2-AES | 4G | D2 | D2 | qcow2 | -- | ✓ | -- | DNS secondary. HA pair with 103. |
### k8s control plane (cnode1/2/3)
| VMID | Name | Host | vCPU | CPU type | RAM | Disk store | Spindle | Disk type | Cache | iothread | qga | Notes |
|------|------|------|------|----------|-----|-----------|---------|-----------|-------|----------|-----|-------|
| 106 | pfv-k8s-cnode3 | tsys1 | 4 | host | 4G | D5 | D5 | qcow2 | **writethrough** | ✓ | ✓ | etcd member. |
| 705 | pfv-k8s-cnode2 | tsys7 | 4 | host | 4G | S2 | S2 | qcow2 | **writethrough** | ✓ | ✓ | etcd member. |
| 906 | pfv-k8s-cnode1 | tsys9 | 2 | host | 4G | S3 | S3 | qcow2 | -- | ✓ | -- | etcd member. |
### k8s workers (wnodes)
| VMID | Name | Host | vCPU | CPU type | RAM | Disk store | Spindle | Disk type | Cache | iothread | qga | Notes |
|------|------|------|------|----------|-----|-----------|---------|-----------|-------|----------|-----|-------|
| 313 | pfv-k8s-wnode-tsys3 | tsys3 | 8 | host | 28G | D5 | D5 | qcow2 | **writethrough** | ✓ | ✓ | Compute worker. |
| 509 | pfv-k8s-wnode-tsys5 | tsys5 | 2 | host | 32G | D2 (virtio) | D2 | qcow2 | -- | ✓ | -- | Undersized vCPU (2). |
| 100 | pfv-k8s-wnode-tsys6 | tsys6 | 2 | host | 64G | S4 | S4 | qcow2 | -- | ✓ | -- | Undersized vCPU (2), high RAM. |
| 701 | pfv-k8s-wnode-tsys7 | tsys7 | 4 | host | 32G | S3 (virtio) | S3 | qcow2 | -- | ✓ | -- | RackRental worker. |
| 905 | pfv-k8s-wnode-tsys9 | tsys9 | 4 | v2-AES | 4G | S2 | S2 | qcow2 | -- | ✓ | ✓ | Target: grow to 6c/8G. |
### Application VMs
| VMID | Name | Host | vCPU | CPU type | RAM | Disk store | Spindle | Disk type | Cache | iothread | qga | Notes |
|------|------|------|------|----------|-----|-----------|---------|-----------|-------|----------|-----|-------|
| 114 | kali-tsys | tsys1 | 2 | host | 2G | D2 | D2 | qcow2 | **writethrough** | ✓ | ✓ | Kali Linux pentest. |
| 117 | tsys-secure-workbench | tsys1 | 2 | host | 4G | D2 | D2 | qcow2 | **writethrough** | ✓ | ✓ | Secure workbench. |
| 400 | pfv-proxmox-backup-server | tsys4 | 2 | -- | 2G | local-lvm | (local) | raw | -- | -- | -- | PBS -- all VM backups. |
| 515 | hfnoc-uisp-preprod | tsys5 | 2 | host | 2G | local-nonprod | S1 | qcow2 | -- | ✓ | -- | Preprod. Locked to tsys5. |
| 5111 | ultix-streaming | tsys5 | 4 | -- | 9G | SSD dir | SSD | qcow2 | -- | -- | -- | 288GB on Samsung 860 PRO (**93% full**). |
| 5112 | ultix-offstage | tsys5 | 4 | -- | 6G | local-lvm | (local) | raw | -- | -- | -- | 288GB. Locked to tsys5. |
| 600 | tsys-awx | tsys6 | 2 | host | 12G | D5 | D5 | qcow2 | **writethrough** | ✓ | ✓ | Ansible AWX. |
| 702 | hfnoc-uisp | tsys7 | 2 | host | 8G | S1 | S1 | qcow2 | -- | ✓ | ✓ | 100GB disk. UISP network monitoring. |
| 703 | rr-middleware | tsys7 | 2 | host | 2G | S2 | S2 | qcow2 | **writethrough** | ✓ | ✓ | RackRental middleware. |
| 704 | TCTC | tsys7 | 4 | host | 6G | D2 (virtio) | D2 | qcow2 | -- | ✓ | -- | |
| 901 | tsys-siem | tsys9 | 2 | host | 8G | D2 | D2 | qcow2 | **writethrough** | ✓ | ✓ | 132GB disk. SIEM. |
| 903 | kali-rd | tsys9 | 2 | host | 2G | D5 | D5 | qcow2 | **writethrough** | ✓ | ✓ | Kali R&D. |
---
## 3. Optimization findings
### 3.1 Cache mode audit
`cache=writethrough` forces synchronous writes to the NFS server on every write
operation. For NFS-backed qcow2, this is unnecessarily slow -- `writeback` or
`none` is recommended (qcow2 already provides journaling integrity).
| Cache mode | Count | VMs |
|-----------|-------|-----|
| **writethrough** (slow) | **10** | 106, 108, 114, 117, 313, 600, 703, 705, 901, 903 |
| none/default (optimal) | 18 | all others |
**Fix:** Change `cache=writethrough``cache=writeback` or remove (defaults to
writeback for qcow2). Requires VM stop/start.
### 3.2 CPU type audit
`cpu: host` passes the host's full CPU instruction set to the VM (best
performance). `x86-64-v2-AES` is a conservative baseline (safe for migration
but lacks some host instructions).
| CPU type | Count | VMs |
|----------|-------|-----|
| **host** | 21 | most production VMs |
| **x86-64-v2-AES** | 5 | 101, 103, 509, 904, 905 |
| not set | 2 | 400, 5111, 5112 |
**Note:** Mixed CPU types prevent live migration between hosts with different
CPU generations. K8s cnodes/wnodes should ideally match within each tier.
### 3.3 Disk controller audit
| Controller | Count | Notes |
|-----------|-------|-------|
| **scsi0** (virtio-scsi) | 22 | Optimal for Proxmox |
| **virtio0** | 4 | 101, 509, 701, 704 -- also good |
| raw (no virtio) | 2 | 100 (pfv-bms), 500 (stopped) |
All running VMs use virtio-based disk controllers. No IDE/SATA legacy disks.
### 3.4 Network audit
All running VMs use **virtio-net**. Firewall enabled on most (`firewall=1`).
No legacy e1000/rtl8139 adapters.
### 3.5 Guest agent (qga) audit
| Status | Count | VMs without qga |
|--------|-------|-----------------|
| **enabled** | 20 | -- |
| **not set** | 8 | 101, 103, 509, 100(tsys6), 701, 704, 904, 906 |
**Fix:** Enable `qm set <vmid> --agent 1` on the 8 VMs missing it. No VM
stop/start required (takes effect on next guest reboot, but the setting itself
is immediate).
### 3.6 k8s wnode sizing
| VMID | Name | vCPU | RAM | Tier target | Issue |
|------|------|------|-----|-------------|-------|
| 509 | wnode-tsys5 | 2 | 32G | compute | **Undersized vCPU** (2 for a compute worker) |
| 100 | wnode-tsys6 | 2 | 64G | rackrental | **Undersized vCPU** (2 for 64G RAM) |
| 701 | wnode-tsys7 | 4 | 32G | rackrental | OK for idle labs |
| 905 | wnode-tsys9 | 4 | 4G | compute | **Target: grow to 6c/8G** after siem migrates off |
| 313 | wnode-tsys3 | 8 | 28G | compute | OK (best compute worker) |
---
## 4. Stopped VMs (not running, for reference)
### Sectestbed / sandboxes (all on tsys5, all stopped)
| VMID | Name | RAM | Disk | Notes |
|------|------|-----|------|-------|
| 5100 | sectestbed-template | 4G | local-lvm | Base template |
| 5101 | sectestbed-siem | 10G | local-nonprod (S1) | 132G disk |
| 5102 | sectestbed-proxmox-pve | 4G | local-lvm | |
| 5103 | sectestbed-proxmox-datacenter | 4G | local-lvm | |
| 5104 | sectestbed-proxmox-pbs | 4G | local-lvm | |
| 5105 | sectestbed-awx | 4G | local-nonprod (S1) | 288G disk |
| 5106 | sectestbed-k8s-cnode | 4G | local-nonprod (S1) | |
| 5107 | sectestbed-k8s-wnode | 4G | local-nonprod (S1) | |
| 5108 | sectestbed-librenms | 4G | local-nonprod (S1) | |
| 5109 | sectestbed-netinfra | 4G | local-nonprod (S1) | |
| 51010 | sectestbed-tctc | 4G | local-nonprod (S1) | |
| 51011 | sectestbed-cloudron | 4G | local-nonprod (S1) | |
| 51012 | sectestbed-hfnoc | 4G | local-nonprod (S1) | |
| 51013 | sectestbed-rancherplatform | 4G | local-nonprod (S1) | |
| 51014 | sectestbed-proxmox-mailgw | 4G | local-nonprod (S1) | |
| 53100 | tsys-preprod-awx | 9G | local-nonprod (S1) | 160G disk |
| 53101 | tsys-preprod-siem | 12G | local-nonprod (S1) | |
| 53102 | tsys-preprod-rancherplatform | 8G | local-nonprod (S1) | |
| 53103 | tsys-preprod-proxmoxmailgw | 4G | local-nonprod (S1) | |
| 6000 | sectestbed-sandbox | 4G | local-nonprod (S1) | Has 3 state snapshots |
### Other stopped VMs
| VMID | Name | Host | RAM | Disk | Notes |
|------|------|------|-----|------|-------|
| 102 | pfv-k8s-wnode-tsys1 | tsys1 | 4G | (no disk) | Stopped, no boot disk |
| 500 | DellOpenManageEnterprise | tsys5 | 20G | **D7 (gone!)** | **Would fail -- disk export removed** |
| 5500 | RestoreTemplate | tsys5 | 2G | D2 | Template |
| 1000 | KNELTemplate | tsys1 | 2G | D2 | Base template |
| 3000 | KNELTemplate | tsys3 | 2G | D2 | Base template copy |
| 4000 | KNELTemplate | tsys4 | 2G | (local) | Base template copy |
> **Complete VM catalog with disk/CPU/RAM/config**
>
> **Read it here:** https://community.turnsys.com/t/304
>
> *Migrated 2026-08-06. This file is kept as a pointer for git-browsing context.
> Do not update content here — edit the Discourse wiki topic instead.*