Files
42_38/PVECluster_Architecture.md
Timmy bd62f397a1 docs: CT118 改 static .118 + adminer restart=always;SOP 新增 IP/Podman 復原檢查
2026-06-04 停電後 CT118(ip=dhcp)漂到 .207 導致以 .118 連 DB/Redis 的服務中斷,
改為 static 192.168.42.118;adminer 容器停在 Created(無 restart 策略)已重建為
--restart=always。SOP 新增步驟 5(IP 回 VMID pattern)與步驟 6(Podman restart 策略)。

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-04 12:34:54 +08:00

356 lines
20 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PVECluster 叢集架構文件
> 最後更新2026-06-04停電復原CT118 由 DHCP 改 static `.118`、adminer 補 `--restart=always`SOP 新增 IP 漂移與 Podman restart 策略檢查步驟)
>
> 2026-05-29新增「停電復電 SOP」全 guest 設定 onboot=1 + startup 分層;停電後修復 K3s VM 根碟 ext4 損壞)
## 一、叢集概覽
| 項目 | 值 |
|---|---|
| **叢集名稱** | PVECluster |
| **PVE 版本** | 8.4.14Kernel 6.8.12-16-pve |
| **節點數** | 3 |
| **Quorum** | 正常corosync_votequorum |
| **VM/容器總數** | 22含 1 個 template |
| **HA** | 未啟用 |
## 二、節點硬體規格
三台節點規格完全相同:
| 項目 | 規格 |
|---|---|
| **CPU** | Intel Core i3-6100 @ 3.70GHz2C/4T |
| **記憶體** | 16 GB DDR4 |
| **系統碟** | ~68 GBLVM含 local + local-lvm |
| **網卡** | Realtek RTL8111 GbE |
| **顯示** | Intel HD Graphics 530內顯 |
| **SATA** | Intel Q170 Chipset AHCI |
### 節點清單
| 節點 | IP | 用途 | 上線時間 |
|---|---|---|---|
| **pve** | 192.168.42.38 | 主節點 | ~9.2 天 |
| **pve-02** | 192.168.42.39 | 工作節點 | ~9.2 天 |
| **pve-03** | 192.168.42.40 | 工作節點 | ~9.2 天 |
### 節點資源使用(即時快照)
| 節點 | CPU 使用率 | 記憶體使用 | 系統碟使用 |
|---|---|---|---|
| pve | ~7% | 6.7 GB / 16 GB (43%) | 12.2 GB / 68 GB |
| pve-02 | ~12% | 10.9 GB / 16 GB (70%) | 12.1 GB / 68 GB |
| pve-03 | ~15% | 10.1 GB / 16 GB (64%) | 11.0 GB / 68 GB |
## 三、網路架構
```
網際網路
[192.168.42.10] GatewayOpenWRT VM 110 的 GW
├── vmbr0 (Linux Bridge)
│ ├── pve (enp1s0) — 192.168.42.38/24
│ ├── pve-02 (enp1s0) — 192.168.42.39/24
│ └── pve-03 (enp1s0) — 192.168.42.40/24
├── VM 110 OpenWRT — 進階路由/防火牆
└── 所有 VM/CT 皆掛在 vmbr0
IP 範圍192.168.42.100 ~ 192.168.42.126
```
- **Bridge**: `vmbr0`每節點各一bridge port 為 `enp1s0`
- **Gateway**: `192.168.42.10`
- **SDN Zone**: `localnetwork`(三節點皆啟用,狀態正常)
- **所有 VM/CT 靜態 IP**,格式為 `192.168.42.<VMID>`
### NetBird Subnet Router遠端存取內網
- **Router 節點**: CT100`192.168.42.100`NetBird IP `100.71.236.202`
- **廣播網段**: `192.168.42.0/24`Network Route `home-lan`metric 9999masquerade=true
- **分發群組**: `personal`Mac、iPhone 等個人裝置)
- **Access Control**: `personal``servers`
- **效果**: `personal` 群組成員路由表自動新增 `192.168.42.0/24 → CT100 NetBird IP`,可透過 CT100 存取整個 LAN 上的任何裝置OpenWrt .10、PVE 節點 .38/.39/.40、NAS .20 等,即使該裝置未安裝 NetBird
- **主機端設定**: CT100 上 `/etc/sysctl.d/99-netbird-route.conf``net.ipv4.ip_forward=1`(持久化)
- **為何不選 CT124**: CT124 的 Tailscale 是 kernel-mode`iptables-legacy ts-forward` chain 的 `100.64.0.0/10 → !tailscale0` DROP 規則會與 NetBird 的 forwarding/masquerade chain 衝突CT100 的 Tailscale 為 userspace無此問題
## 四、儲存架構
### 儲存池一覽
| 儲存名稱 | 類型 | 共享 | 容量 | 已用 | 用途 |
|---|---|---|---|---|---|
| **local** | dir | 否 | 68 GB/節點 | ~12 GB | ISO、備份、模板 |
| **local-lvm** | lvmthin | 否 | ~160 GB/節點 | 變動 | VM 磁碟、CT rootfs |
| **syno-lvm** | LVM (iSCSI) | 是 | 1 TB | ~642 GB | VM 磁碟、CT rootfs主要儲存 |
| **syno-iscsi** | iSCSI | 是 | — | — | syno-lvm 的底層 target |
| **synology-backup** | CIFS | 是 | 2.75 TB | ~2.37 TB | 備份、ISO、模板、snippets |
| **pbs** | PBS | 是 | 78 GB | ~16 GB | Proxmox Backup Server 備份 |
### 儲存拓撲
```
Synology NAS (192.168.42.20)
├── iSCSI Target ──► syno-iscsi ──► syno-lvm (LVM, 1TB, 共享)
│ └── 大部分 VM/CT 磁碟存放於此
└── CIFS Share (Backup) ──► synology-backup (2.75TB, 共享)
└── 備份、ISO、模板
Proxmox Backup Server (192.168.42.30, VM 111)
└── PBS datastore "data-store" ──► pbs (294GB, 共享)
└── VM/CT 快照備份
各節點本地
├── /var/lib/vz ──► local (68GB)
│ └── ISO、vztmpl、備份
└── LVM thin pool ──► local-lvm (~160GB)
└── 部分 VM/CT 磁碟CT112, CT113, CT123
```
## 五、VM / 容器清單
### QEMU 虛擬機
| VMID | 名稱 | 節點 | 狀態 | CPU | 記憶體 | 磁碟 | Tags | 用途 |
|---|---|---|---|---|---|---|---|---|
| **110** | OpenWRT | pve | running | 2C | 512 MB | 8 GB (syno-lvm) | openwrt | OpenWRT 24.10.4 路由器/防火牆/PPPoE/WireGuard |
| **111** | PBS | pve-02 | running | 2C | 2 GB | 32G + 80G (syno-lvm) | backup;pbs | PBS (192.168.42.30:8007) 78GB, 41 筆備份 |
| **120** | K3s Server | pve-02 | running | 2C | 8 GB | 83 GB (syno-lvm) | k3s | K3s control-planeServer |
| **121** | K3s Agent | pve | running | 2C | 8 GB | 82 GB (syno-lvm) | k3s | K3s worker node |
| **122** | K3s Agent | pve-03 | running | 2C | 8 GB | 82 GB (syno-lvm) | k3s | K3s worker node |
| **9000** | ubuntu-2404-cloud-template | pve | template | 2C | 2 GB | 3.5 GB (syno-lvm) | cloud-init;template | UEFI/q35 Cloud-init VM 模板 (user=ubuntu, DHCP) |
### LXC 容器
| VMID | 名稱 | 節點 | 狀態 | CPU | 記憶體 | 磁碟 | IP | Tags / 用途 |
|---|---|---|---|---|---|---|---|---|
| **100** | CT100 | pve-02 | running | 1C | 256 MB | 8G (syno-lvm) | .42.100 | SSH Jump Box + Bore Server (:7835) + Tailscale + NetBird (100.71.236.202, ct100.netbird.selfhosted) + NetBird Subnet Router (192.168.42.0/24, masquerade) + Watchtower |
| **101** | CT101 | pve-02 | running | 1C | 128 MB | 8G (syno-lvm) | .42.101 | RustDesk Server (21115-21119) + Headscale (備用) + NetBird (100.71.200.94, ct101.netbird.selfhosted) + Watchtower |
| **102** | CT102 | pve | running | 1C | 512 MB | 8G (syno-lvm) | .42.102 | Tailscale + Proxy Pool + Cloudflare Tunnel + Watchtower |
| **104** | CT104 | pve | running | 1C | 96 MB | 8G (syno-lvm) | .42.104 | Caddy 靜態檔案/反向代理 (:80) + Tailscale |
| **105** | CT105 | pve | running | 1C | 128 MB | 8G (syno-lvm) | .42.105 | EchoIP (mpolden/echoip:8080) + Watchtower |
| **107** | CT107 | pve-02 | running | 1C | 64 MB | 8G (syno-lvm) | .42.107 | MailPit (axllent/mailpit, Web:8025 SMTP:1025) |
| **108** | CT108 | pve-03 | running | 4C | 2 GB | 16G (syno-lvm) | .42.108 | Python 微服務環境 (12 服務, supervisord+uv) |
| **109** | CT109 | pve | running | 1C | 512 MB | 16G (local-lvm) | .42.109 | Hermes Agent v0.9.0 (NousResearch, Python 3.11 + Node.js) |
| **112** | CT112 | pve-03 | running | 1C | 2 GB | 32G (local-lvm) | .42.112 | OpenClaw Gateway v2026.3.13 (Node.js) |
| **114** | CT114 | pve-03 | running | 1C | 128 MB | 8G (syno-lvm) | .42.114 | Podman 測試 + Nginx Quadlet (:8080) |
| **115** | CT115 | pve-02 | running | 2C | 2 GB | 40G (syno-lvm) | .42.115 | Lydia Prod — Python + Caddy + MSSQL Express |
| **116** | CT116 | pve | running | 1C | 128 MB | 8G (syno-lvm) | .42.116 | Bark 推播通知 (finab/bark-server:8080) + Watchtower |
| **117** | CT117 | pve-02 | running | 2C | 2 GB | 60G (syno-lvm) | .42.117 | Lydia Test — Python (:5000) + MSSQL Express |
| **118** | CT118 | pve-03 | running | 1C | 1 GB | 8G (syno-lvm) | .42.118 | PostgreSQL 16 + Redis + Proxy Pool (10x Tor) + Adminer (:8080) + Podman |
| **124** | CT124 | pve-03 | running | 2C | 8 GB | 80G (syno-lvm) | .42.124 | Docker 服務集中台 (20+ 服務: NPM, Gitea, Karakeep, Vaultwarden, Jellyfin 等) + Tailscale (kernel-mode) + NetBird (100.71.40.35, ct124.netbird.selfhosted) |
| **126** | CT126 | pve | running | 1C | 256 MB | 8G (syno-lvm) | .42.126 | Headscale v0.28.0 控制伺服器 (17 節點) + Tailscale + Watchtower |
### 狀態統計
| 狀態 | 數量 |
|---|---|
| Running | 19 |
| Stopped | 0 |
| Template | 1VM 9000 |
### 各節點負載分佈
| 節點 | VM | LXC (running) | LXC (stopped) | 分配 CPU | 分配記憶體 |
|---|---|---|---|---|---|
| **pve** | 2 (110, 121) | 6 (102,104,105,109,116,126) | 0 | 10C | ~11.5 GB |
| **pve-02** | 2 (111, 120) | 5 (100,101,107,115,117) | 0 | 11C | ~15 GB |
| **pve-03** | 1 (122) | 5 (108,112,114,118,124) | 0 | 8C | ~22 GB |
## 六、備份策略
### Proxmox Backup Server
- **位置**: VM 111pve-02IP `192.168.42.30:8007`
- **Datastore**: `data-store`78 GB已用 ~16 GB
- **保留策略**: `keep-all=1`
### 備份排程(目前皆已停用 enabled=0
| 排程 | 目標 | 儲存 | 保留 | 壓縮 |
|---|---|---|---|---|
| 每日 03:00 | CT115, CT117Lydia prod/test | pbs | keep-daily=7 | — |
| 02:30, 22:30 | CT103, CT106, CT108, CT124 | pbs | keep-daily=7 | zstd |
| 每日 02:00 | VM 110OpenWRT | pbs | keep-daily=3 | — |
### Synology NAS 備份
- **位置**: `192.168.42.20`CIFS share `Backup`
- **容量**: 2.75 TB已用 ~2.37 TB
- CT124 有掛載 `/mnt/ds1515-backup` 指向此 share
## 七、關鍵服務架構圖
```
┌─────────────────────────────────────────────────────────────────┐
│ PVECluster │
│ 192.168.42.38/39/40 │
├──────────────┬──────────────────┬────────────────────────────────┤
│ pve (.38) │ pve-02 (.39) │ pve-03 (.40) │
├──────────────┴──────────────────┴────────────────────────────────┤
│ │
│ 【網路層】 │
│ VM110 OpenWRT 24.10.4 ── GW: 192.168.42.10 │
│ PPPoE HiNet / WireGuard VPN (10.0.0.1) │
│ DNAT: SSH Jump, Bore, NPM, RustDesk, Headscale, SQL │
│ CT104 Caddy ───── 反向代理80/443
│ CT124 ─────────── NPM + Gitea + 20 服務集中台 + Tailscale + NetBird │
│ │
│ 【認證/安全】 │
│ CT124 Vaultwarden ── 密碼管理 │
│ CT100 ─────────── SSH Jump Box + Bore Server + Tailscale + NetBird + NetBird Subnet Router (192.168.42.0/24) │
│ CT101 ─────────── RustDesk Server + Headscale 備用 + NetBird遠端存取
│ CT102 ─────────── Tailscale + Cloudflare Tunnel + Proxy Pool │
│ CT126 ─────────── Headscale 控制伺服器 (17 節點, 8080/9090/50443) │
│ │
│ 【AI / Agent】 │
│ CT109 ─────────── Hermes Agent v0.9.0 (NousResearch) │
│ │
│ 【應用服務】 │
│ CT115 Lydia ───── Prod (Python + Caddy + MSSQL, SSH:30022) │
│ CT117 Lydia ───── Test (Python:5000 + MSSQL, SSH:50022) │
│ CT108 ─────────── Python 微服務 x12 (supervisord+uv, 4C/4GB) │
│ CT112 ─────────── OpenClaw Gateway v2026.3.13 (Node.js) │
│ CT124 Karakeep ── 書籤/知識管理 + Jellyfin 媒體 │
│ │
│ 【Kubernetes (K3s v1.33.6 + Longhorn)】 │
│ VM120 K3s ─────── Server/control-plane (pve-02, 8GB) │
│ VM121 K3s ─────── Agent/worker (pve, 8GB) │
│ VM122 K3s ─────── Agent/worker (pve-03, 8GB) │
│ 服務: Traefik, CodiMD, Adminer, HTTPbin, │
│ OpenGist, PostgreSQL, Vaultwarden │
│ │
│ 【工具/通知】 │
│ CT107 ─────────── MailPit郵件測試
│ CT116 ─────────── Bark推播通知
│ CT105 ─────────── EchoIPIP 查詢port 8080
│ │
│ 【資料庫】 │
│ CT118 ─────────── PostgreSQL 16 + Redis + Proxy Pool (10x Tor) │
│ │
│ 【備份】 │
│ VM111 PBS ─────── Proxmox Backup Server (192.168.42.30) │
│ Synology NAS ──── iSCSI (syno-lvm) + CIFS (backup) │
│ 192.168.42.20 │
│ │
│ 【模板】 │
│ VM9000 ────────── Ubuntu 24.04 Cloud-init Template │
└──────────────────────────────────────────────────────────────────┘
```
## 八、已知問題與注意事項
### Tailscale kernel-mode + NetBird 共存iptables-legacy 封包丟棄
適用場景:同一台容器/主機上 **Tailscale 以 kernel mode 運行**(非 userspace又要加掛 NetBird client。目前 **CT124** 是此情境CT100/CT101 的 Tailscale 是 userspace不受影響
**症狀**NetBird tunnel `wt0` 建立成功、peer 狀態 Connected但從其他 NetBird peer ping CT124 的 `100.71.40.35` 完全不通CT124 本地也收不到任何 NetBird 流量。
**成因**Tailscale kernel mode 會在 `iptables-legacy``ts-input``ts-forward` chain預設把 `100.64.0.0/10`CGNAT範圍內、且 **不是**`tailscale0` 進來的封包全部 DROP。NetBird 的 `100.71.0.0/16` 剛好落在這個 CGNAT 區段內,於是 `wt0` 收到的 NetBird 封包會被 Tailscale 的 rule 靜默丟掉。
**修復**:在 `iptables-legacy` 裡針對 `wt0` 介面放行,並放在 chain 最前面(`-I ... 1`)以搶在 Tailscale rule 之前:
```bash
iptables-legacy -I INPUT 1 -i wt0 -j ACCEPT
iptables-legacy -I FORWARD 1 -i wt0 -j ACCEPT
iptables-legacy -I FORWARD 1 -o wt0 -j ACCEPT
```
**開機持久化**CT124 上已部署):
- `/usr/local/sbin/netbird-iptables-legacy-fix.sh` — 執行上述三條規則的腳本
- `/etc/systemd/system/netbird-iptables-fix.service` — 開機時呼叫該腳本的 oneshot unit
未來若有其他 CT 同時跑 Tailscale kernel mode + NetBird需套用相同 workaround。
### Ubuntu 25.04 LXC 容器 Console 無法登入
Ubuntu 25.04 的 systemd 新增了 `ImportCredential` 指令,在 LXC 容器中不支援,導致 `console-getty.service` 啟動失敗exit 243/CREDENTIALSWeb Console 看不到登入提示。
**修復方式**(建立容器後立即執行):
```bash
pct exec <vmid> -- bash -c 'mkdir -p /etc/systemd/system/console-getty.service.d && cat > /etc/systemd/system/console-getty.service.d/override.conf << EOF
[Service]
ExecStart=
ExecStart=-/sbin/agetty -o "-- \\\\u" --noreset --noclear --keep-baud 115200,57600,38400,9600 - \$TERM
ImportCredential=
EOF
systemctl daemon-reload && systemctl reset-failed console-getty && systemctl restart console-getty'
```
建議同時加上 `features: nesting=1``tty: 2`
```bash
pct set <vmid> -features nesting=1 -tty 2
```
### 停電 / 不正常斷電復電 SOP
整個機房為**單一電源、無 UPS**,三節點會同時斷電。已知斷電會造成 syno-lvm 上的 guest 根檔案系統 ext4 損壞(尤其有大量寫入的 K3s VM
**判斷是否為停電**:三節點 `who -b` / `last -x reboot` 顯示**幾乎同一秒**開機,且上一個 boot 的 journal 結尾無正常關機程序(無 `Stopping...` / `Reached target Shutdown`,直接中斷)。
**復電後復原步驟**
1. **確認叢集**`pvecm status`Quorate: Yes`pvesm status`syno-lvm / syno-iscsi / synology-backup / pbs 皆 activepbs 需 VM 111 開機後才會 active
2. **啟動所有 guest** — 已全數設定 `onboot=1`,正常會自動分層啟動(見下)。若需手動:`qm start <id>` / `pct start <id>`
- ⚠️ 透過 SSH 跑 `pct start` 後 session 可能被容器常駐 monitor`lxc-start -F`)卡住,導致後續 chained 指令不執行。逐台執行或加 `</dev/null >/dev/null 2>&1` 導開 fd。
3. **檢查 guest 是否真的起來** — Proxmox 顯示 `running` ≠ guest OS 正常。逐台 ping / SSH不通的用 `qm monitor <id>``screendump /tmp/x.ppm` 看 console。若看到 `EXT4-fs error ... Remounting filesystem read-only` 代表根碟損壞,需離線 fsck。
4. **離線修復損壞的根碟VM** — guest 內部無法自救(根已唯讀)。在該 VM 所在節點執行:
```bash
qm stop <id>
lvchange -ay syno_vg/vm-<id>-disk-1 # 停 VM 後 LV 會 inactive需重新啟用
LOOP=$(losetup -Pf --show /dev/syno_vg/vm-<id>-disk-1) # 用 loop 掃出分割區pve 無 kpartx
e2fsck -fy ${LOOP}p1 # p1 = cloudimg-rootfs-fy 自動修復
losetup -d $LOOP
qm start <id>
```
修復成功後 console 應顯示 `EXT4-fs (sda1): re-mounted ... r/w`(不再被踢成唯讀)。
5. **檢查 IP 是否回到 VMID pattern** — 所有 guest 應為 static IP`192.168.42.<VMID>`),不要靠 DHCP。若用 `ip=dhcp`,停電後 OpenWRT 重新分配可能漂到別的位址2026-06-04 停電後 CT118 漂到 `.207`,導致以 `.118` 連 DB/Redis 的服務全斷)。修法:`pct set <id> -net0 ...,ip=192.168.42.<VMID>/24,gw=192.168.42.10,...` 後 `pct reboot <id>`。
6. **檢查 Podman 容器 restart 策略** — Proxmox guest `onboot=1` 只保證容器 OS 開機;容器內的 Podman 服務需各自 `--restart=always`(靠 `podman-restart.service`,已 enabled開機帶起所有 always 容器)才會自動回來。沒設策略的(曾發生於 CT118 的 `adminer`)停電後停在 `Created`,需手動 `podman start` 或帶 `--restart=always` 重建。注意 Podman 4.9.3 的 `podman update` 不支援 `--restart`,改策略只能重建容器。
**開機自動啟動 / 分層策略**22 台全設 `onboot=1`,每節點獨立依 order 啟動,`up` 為啟動後延遲秒數):
| 層 | startup | 成員 |
|---|---|---|
| **T1 網路** | `order=1,up=20` | VM 110 OpenWRT、CT 100 NetBird Router |
| **T2 基礎** | `order=2,up=15` | VM 111 PBS、VM 120 K3s-server、CT 126 Headscale、CT 118 PostgreSQL/Redis |
| **T3 應用** | `order=3,up=8` | 其餘所有 VM/CTK3s agents 121/122 + 各服務 CT |
> 設定指令VM 用 `qm set <id> --onboot 1 --startup order=N,up=S`CT 用 `pct set <id> --onboot 1 --startup order=N,up=S`。
### K3s VM 登入與操作
- **登入帳號為 `ubuntu`(非 root** — 三台皆由 VM 9000 cloud-init 模板建立。`ssh ubuntu@192.168.42.12{0,1,2}`root 登入會被拒。
- **kubectl 需 `sudo`** — kubeconfig 在 root 權限下,例:`sudo kubectl get nodes`(從 VM 120 server 執行)。
- 重建/重開後 SSH host key 可能變動,必要時先 `ssh-keygen -R <ip>`。
- VM 121/122 為 stateless worker停機時工作負載會自動重調度到其他節點可安心離線維護。
## 九、Corosync 叢集通訊
```
totem:
cluster_name: PVECluster
version: 2
secauth: on
link_mode: passive
ip_version: ipv4-6
nodelist:
pve (nodeid=1, ring0=192.168.42.38, votes=1)
pve-02 (nodeid=2, ring0=192.168.42.39, votes=1)
pve-03 (nodeid=3, ring0=192.168.42.40, votes=1)
quorum:
provider: corosync_votequorum
需要 2/3 節點在線才能維持 quorum
```