4 节点 k3s(--docker)集群资源配置分配方案
分析对象:单台 Proxmox VE 服务器上 4 台 VM 组建 k3s 集群 宿主机:E5 2650(32 逻辑核心)/ 192 GB RAM / 340 GB 剩余磁盘 容器运行时: INSTALL K3S EXE…
分析对象:单台 Proxmox VE 服务器上 4 台 VM 组建 k3s 集群 宿主机:E5-2650(32 逻辑核心)/ 192 GB RAM / 340 GB 剩余磁盘 容器运行时:
INSTALL_K3S_EXEC="--docker"部署平台:GZCTF CTF 比赛平台 角色:researcher · 数据驱动分析
1. 节点角色分配决策
可行方案概览
| 方案 | 角色分布 | etcd 节点数 | 是否推荐 | 核心理由 |
|---|---|---|---|---|
| A | 1 control-plane + 3 worker | 1 | ✅ 推荐 | 标准 k8s 架构,资源集中给比赛容器 |
| B | 2 control-plane + 2 worker | 2 | ❌ | etcd 2 节点无法形成多数派,官方不推荐 |
| C | 4 hybrid(全部 control-plane + worker) | 4 | ⚠️ 可选 | 4 节点 etcd 开销大,但可用资源更多 |
为什么不选 B(2 control-plane + 2 worker)?
根据来源(etcd 官方文档 about FAQ),etcd 集群需要**多数派(quorum)**才能写入:
| etcd 节点数 | 多数派 | 容错数 |
|---|---|---|
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 2 | 1 |
| 4 | 3 | 1 |
| 5 | 3 | 2 |
2 节点 etcd 的致命缺陷:任何一个节点故障,集群剩余 1 节点 < 2(多数派),整个集群不可写入。在单物理机场景下,这个“HA 假象”没有任何实际价值,反而比 1 节点更脆弱——因为 1 节点 etcd 只要节点活着就能读写,2 节点损失 1 个就直接停摆。
为什么不选 C(4 hybrid)?
4 hybrid 意味着所有 4 个节点都运行 k3s server(含 embedded etcd)。根据 k3s 官方文档和社区实测数据:
- 4 节点 etcd 的多数派是 3,容错 1 节点——但在单物理机上,物理机挂 = 4 节点全挂,这个容错没有意义
- 每个 server 节点比 agent 节点多消耗约 300-400 MB 内存(etcd 进程 + 控制面组件),4 节点比 1 节点多浪费约 900-1200 MB
- etcd 节点之间需要额外的网络心跳和同步流量,虽然在同一宿主机上延迟低,但仍增加了 CPU 开销
- 唯一值得考虑的情况:如果以后要迁移到多物理机,4 server 节点可以直接带走,不需要重新部署 control-plane。但为此牺牲当前的内存和磁盘,不划算
为什么选 A(1 control-plane + 3 worker)?
根据数据显示,在单物理机 4 节点场景下,这是最合理的分配:
优势分解:
- 资源集中:1 个 control-plane 节点承担 GZCTF 主服务 + PostgreSQL + Redis,3 个 worker 节点全部资源用于比赛容器
- 3 个 worker 提供足够的调度弹性:GZCTF 可以将题目容器分布到 3 个 worker 上,比 2 节点方案多出 50% 的调度空间
- control-plane 节点可以做轻量 worker:k3s 默认 server 节点也运行 agent(schedulable),所以 control-plane 也能跑少量比赛容器(如 GZCTF 本身的 Pod)
- 运维简洁:只有 1 个节点需要维护 etcd 和 control-plane 配置
但——有一个更优的变体
推荐变体 A’:1 control-plane(hybrid,可调度)+ 3 worker
即 control-plane 节点不 disable agent,允许它跑 GZCTF 基础设施 Pod(GZCTF、PostgreSQL、Redis)和少量比赛容器。这样:
- control-plane 的 2-4 vCPU 和内存不被浪费
- GZCTF 和 DB 跑在 control-plane 上,离 kube-apiserver 最近,延迟最低
- 3 个纯 worker 专注跑比赛容器
2. 磁盘分配的特别考量(最紧张的资源)
2.1 340 GB 的总账
这是本方案最关键的约束。根据来源(k3s 官方文档、Docker 存储驱动文档、Ubuntu Server 安装指南),每台 VM 的基础磁盘需求如下:
每台 VM 基础磁盘需求明细
| 项目 | 最小占用 | 正常占用 | 说明 |
|---|---|---|---|
| Ubuntu Server 24.04 minimal | 3.0 GB | 5.0 GB | 含内核、基础工具、grub |
| 系统更新缓存(apt cache) | 0.5 GB | 1.5 GB | apt upgrade 后的缓存 |
| k3s 二进制 + 配置 | 0.2 GB | 0.5 GB | /usr/local/bin/k3s + config |
| Docker CE 包 | 0.3 GB | 0.5 GB | dockerd, containerd, runc |
| Docker overlay2 元数据 | 0.5 GB | 1.0 GB | /var/lib/docker/ 基础结构 |
| 系统日志(/var/log) | 1.0 GB | 3.0 GB | 含 Docker 容器日志、k3s 日志 |
| kubelet 日志 + 状态 | 0.5 GB | 1.0 GB | /var/lib/kubelet/ |
| 临时文件(/tmp) | 0.5 GB | 1.0 GB | 容器构建、镜像拉取临时文件 |
| 基础小计(无可调度容器) | ~6.5 GB | ~13.5 GB | — |
Docker 镜像存储预估
根据来源(GZCTF 常用镜像、Docker Hub 镜像大小数据):
| 镜像 | 大小(压缩) | 大小(解压/磁盘占用) | 说明 |
|---|---|---|---|
| alpine:latest | ~3 MB | ~7 MB | 最基础镜像 |
| ubuntu:22.04 | ~30 MB | ~80 MB | 常用基础镜像 |
| nginx:alpine | ~10 MB | ~25 MB | Web 题常用 |
| python:3.11-slim | ~50 MB | ~140 MB | 脚本题常用 |
| node:20-alpine | ~40 MB | ~130 MB | Node 题常用 |
| php:8.2-apache | ~120 MB | ~400 MB | PHP Web 题 |
| mysql:8.0 | ~130 MB | ~500 MB | 数据库题 |
| postgres:16 | ~100 MB | ~380 MB | 数据库题 |
| GZCTF 主镜像 | ~200 MB | ~600 MB | GZCTF 平台自身 |
| redis:7 | ~30 MB | ~110 MB | 缓存/数据题 |
| 合计(一套完整镜像) | ~700 MB | ~2.4 GB | 所有基础镜像 |
一个有趣的发现是:Docker 的 overlay2 存储驱动下,镜像的每层之间共享存储。如果多个镜像基于同一基础层(如都基于 alpine),基础层只存一份,但每个镜像的独有层仍需要额外空间。实际上,拉取 10 个不同镜像大约占 3-5 GB 的磁盘空间(取决于基础镜像复用程度)。
CTF 题目镜像额外需求
假设 30 道题,每道题一个自定义镜像:
| 题目类型 | 平均镜像大小 | 30 题总大小 | 备注 |
|---|---|---|---|
| Web | 400 MB | 12 GB | 含 PHP/Node/Python 运行时 |
| PWN | 300 MB | 9 GB | Ubuntu + socat + 二进制 |
| Crypto | 100 MB | 3 GB | 轻量脚本 |
| Misc | 200 MB | 6 GB | 各类工具组合 |
| Reverse | 150 MB | 4.5 GB | 分析环境 |
| 合计 | ~230 MB/题 | ~34.5 GB | 所有题目镜像 |
日志和运行时增长
| 项目 | 比赛期间增长 | 说明 |
|---|---|---|
| Docker 容器日志(JSON 文件) | 2-5 GB/worker | 每容器 stdout/stderr,取决于题目 |
| k3s 审计日志 | 0.5-1 GB | kube-apiserver 请求日志 |
| kubelet 日志 | 0.5-1 GB | 节点状态同步 |
| 系统日志 | 0.5-1 GB | syslog, auth.log |
| 容器 overlay 层写入 | 0.5-2 GB | 容器运行时的读写层 |
| 合计(每 worker) | ~4-10 GB | — |
2.2 磁盘分配方案
总可用磁盘 340 GB。分配给 4 台 VM,关键决策是:
- control-plane 节点需要多少额外空间存 GZCTF 数据和 Docker 镜像?
- worker 节点需要多少空间存题目镜像?
根据数据推算,最合理的分配方式是 control-plane 节点分配较大磁盘(因为要存 GZCTF + PostgreSQL 数据 + 所有基础镜像),worker 节点分配较少(但也要能存题目镜像)。
磁盘分配逻辑分层
| 方案 | 控制面 | 3 × Worker | 总分配 | 剩余 | 特点 |
|---|---|---|---|---|---|
| 紧缩 | 50 GB | 3 × 90 GB | 320 GB | 20 GB | 最紧凑,每 worker 90 GB |
| 均衡 | 60 GB | 3 × 85 GB | 315 GB | 25 GB | 控制面宽裕点 |
| 宽松 | 80 GB | 3 × 80 GB | 320 GB | 20 GB | 都够用但不大 |
等等——紧缩方案为什么是 3×90=270 + 50 = 320?实际上控制面 50 GB 可能不够(GZCTF 数据 + PostgreSQL + 所有基础镜像可能需要 20-30 GB 的镜像存储 + 数据)。让我们更精确地分配。
实际推荐分配:
| 方案 | 控制面 | 3 × Worker | 总分配 | 剩余 | 控制面可容纳 | 每个 Worker 可容纳 |
|---|---|---|---|---|---|---|
| 紧凑 | 60 GB | 3 × 85 GB | 315 GB | 25 GB | OS + Docker + GZCTF + DB + 部分镜像 | OS + Docker + ~50 GB 题镜像 |
| 推荐 | 80 GB | 3 × 80 GB | 320 GB | 20 GB | OS + GZCTF + DB + 全部基础镜像 | OS + Docker + ~55 GB 题镜像 |
| 宽松 | 100 GB | 3 × 75 GB | 325 GB | 15 GB | 更宽裕的日志和缓存空间 | 题镜像空间 → 50 GB |
推荐方案给控制面 80 GB 的原因:
- Ubuntu + Docker + k3s 基础:~10 GB
- GZCTF 主镜像 + PostgreSQL 数据 + Redis:~10 GB
- 全部基础镜像缓存(避免 worker 重复拉取?不,每个 worker 的 Docker 是独立的,还是要各自拉取):但如果用 registry mirror 可以减轻
- 日志和 DB 增长预留:~10 GB
- 实际可用:~50 GB 富余
给每个 worker 80 GB 的原因:
- Ubuntu + Docker + k3s 基础:~10 GB
- 30 题镜像(分散到 3 worker,每 worker 约 10 题):~15-25 GB
- 容器运行时读写层 + 日志:~10 GB
- 实际可用:~35-45 GB 富余
3. 每台 VM 详细配置(多方案可选)
基线参数计算
CPU 逻辑核心分配依据(来源:Intel Xeon E5-2650 v4 规格,PassMark ~15,000):
- Proxmox 自身预留:2 核心(超线程=4 线程),用于管理 Web 界面、备份、IO 调度
- 可用给 VM 的物理核心:~14 核心(= ~28 线程)
- 4 台 VM 分配 28 线程,平均 7 线程/VM
但值得注意的是,E5-2650 的单核性能较弱(PassMark 单核 ~1500,对比现代 i5 的 ~3000+),意味着一台 VM 分配过少 vCPU 会导致容器调度延迟。建议至少 4 vCPU/VM。
内存分配依据(来源:k3s 官方资源需求,社区实测):
- 控制面节点 GZCTF + PostgreSQL + Redis + k3s server + Docker + 缓冲:见下表细算
- Worker 节点 k3s agent + Docker + 容器运行 + 缓冲:见下表细算
方案一:中配均衡(推荐)
集群总览
| 节点 | 角色 | vCPU | 内存 | 磁盘 | 运行内容 |
|---|---|---|---|---|---|
| k3s-cp | control-plane(可调度) | 6 核 | 24 GB | 80 GB | k3s server+agent, GZCTF, PostgreSQL, Redis, coredns, traefik |
| k3s-w1 | worker | 6 核 | 48 GB | 80 GB | k3s agent, 题目容器 |
| k3s-w2 | worker | 6 核 | 48 GB | 80 GB | k3s agent, 题目容器 |
| k3s-w3 | worker | 6 核 | 48 GB | 80 GB | k3s agent, 题目容器 |
| 合计 | 24 核 | 168 GB | 320 GB | — |
Proxmox 预留:8 核 + 18 GB + 20 GB 磁盘 → 物理机剩余:32-24=8 核空闲用于 IO/管理,192-168-6(proxmox)=18 GB 空闲,340-320=20 GB 空闲
控制面节点(k3s-cp)24 GB 内存细账
k3s server (含 embedded etcd) -768 MB (单节点 etcd 轻量)
k3s agent -256 MB
Docker daemon -160 MB
cri-dockerd -60 MB
GZCTF (.NET 8 主服务) -512 MB
PostgreSQL 16 -384 MB
Redis 7 -128 MB
coredns + traefik + kube-system -192 MB
OS + 系统服务 -512 MB
日志缓冲区 + 运维窗口 -512 MB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
固定开销合计 ~3.5 GB
可用给比赛容器 ~20.5 GB
Worker 节点(48 GB)内存细账
k3s agent -256 MB
Docker daemon -160 MB
cri-dockerd -60 MB
OS + 系统服务 -512 MB
日志缓冲区 + 运维窗口 -512 MB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
固定开销合计 ~1.5 GB
可用给比赛容器 ~46.5 GB
集群总可用比赛内存
3 × worker 可用容器内存 46.5 × 3 = 139.5 GB
control-plane 可用容器内存 20.5 GB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
集群总可用给比赛容器 160 GB
方案二:高配(控制面更大,worker 不变)
| 节点 | 角色 | vCPU | 内存 | 磁盘 | 运行内容 |
|---|---|---|---|---|---|
| k3s-cp | control-plane(可调度) | 8 核 | 32 GB | 100 GB | k3s server+agent, GZCTF, PostgreSQL, Redis |
| k3s-w1 | worker | 6 核 | 48 GB | 75 GB | k3s agent, 题目容器 |
| k3s-w2 | worker | 6 核 | 48 GB | 75 GB | k3s agent, 题目容器 |
| k3s-w3 | worker | 6 核 | 48 GB | 75 GB | k3s agent, 题目容器 |
| 合计 | 26 核 | 176 GB | 325 GB | — |
控制面 32 GB 内可给约 28 GB 用于比赛容器。
集群总可用比赛内存:46.5×3 + 28 = 167.5 GB
方案三:紧凑型(资源有限时)
| 节点 | 角色 | vCPU | 内存 | 磁盘 | 运行内容 |
|---|---|---|---|---|---|
| k3s-cp | control-plane(可调度) | 4 核 | 16 GB | 60 GB | k3s server+agent, GZCTF, PostgreSQL, Redis |
| k3s-w1 | worker | 4 核 | 32 GB | 85 GB | k3s agent, 题目容器 |
| k3s-w2 | worker | 4 核 | 32 GB | 85 GB | k3s agent, 题目容器 |
| k3s-w3 | worker | 4 核 | 32 GB | 85 GB | k3s agent, 题目容器 |
| 合计 | 16 核 | 112 GB | 315 GB | — |
控制面 16 GB 内可给约 11 GB 用于比赛容器。
Worker 32 GB 内可给约 30.5 GB 用于比赛容器。
集群总可用比赛内存:30.5×3 + 11 = 102.5 GB
4. 最终可用资源估算
4.1 按推荐方案(方案一)估算
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
集群总可用比赛容器内存: 160 GB
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
按每容器 128 MB(轻量题): ~1,280 个容器
按每容器 256 MB(标准题): ~640 个容器
按每容器 512 MB(重型题): ~320 个容器
结合 CTF 实际场景:
- 30 道题,200 支队伍 = 6,000 个容器(不可能,大多数题目是单实例共享)
- 实际 GZCTF 的 k8s 模式下,每道题每个队伍一个独立实例
- 如果 30 题 × 100 队且题目容器 256 MB/个 = 30×100×256MB = 768 GB(远超可用)
- 实际比赛中:① 部分题目是单实例(所有人都连同一个容器)② 部分题目才按队伍隔离
- GZCTF 支持两种模式:题目级配置,可按需选择
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
根据来源(GZCTF 官方文档 - 容器策略配置),CTF 题目分为:
- 单实例模式:所有队伍共用同一个容器实例(适用于静态题目如 Crypto、Reverse)
- 多实例模式:每支队伍一个独立容器实例(适用于 Web、PWN 等需要隔离的题目)
实际能支撑的规模估算(按照典型混合模式:10 题多实例 + 20 题单实例):
| 规模等级 | 多实例题目数 | 单实例题目数 | 队伍数 | 容器数 | 内存需求 | 是否可支撑 |
|---|---|---|---|---|---|---|
| 小型 | 5 题 | 25 题 | 50 队 | 5×50 + 25 = 275 | 275×256MB ≈ 70 GB | ✅ 绰绰有余 |
| 中型 | 10 题 | 20 题 | 100 队 | 10×100 + 20 = 1,020 | 1,020×256MB ≈ 260 GB | ❌ 超出 |
| 中型(优化) | 10 题@128MB | 20 题 | 100 队 | 1,020 | 10×100×128MB + 20×256MB ≈ 133 GB | ✅ 可行 |
| 大型 | 15 题 | 15 题 | 200 队 | 15×200 + 15 = 3,015 | 3,015×256MB ≈ 770 GB | ❌ 远远超出 |
结论:以推荐方案一(160 GB 可用容器内存),可以支撑:
- ✅ 50 队 × 30 题:任意配置都绰绰有余
- ✅ 100 队 × 30 题:需要控制多实例题目的内存限制在 128 MB,或者减少多实例题数量
- ⚠️ 200 队 × 30 题:极困难。除非绝大部分题目是单实例,且多实例题目容器严格限制在 128 MB 以内
4.2 宿主机 CPU 占用估算
根据来源(Intel Xeon E5-2650 v4 SPEC 数据),单核 PassMark 约 1,500,32 线程总 PassMark 约 15,000。
比赛期间 CPU 压力来源:
- 容器启动风暴:比赛开始时的并发容器创建,kubelet 调用 Docker → runc 创建 cgroup 和网络命名空间,每个容器约消耗 0.5-1 秒的 CPU 时间
- Web 题访问:Nginx/PHP/Node 的 HTTP 请求处理
- PWN 题交互:网络连接处理
- GZCTF 本身:API 请求、判题、Flag 验证
以推荐方案一(24 vCPU 分配给 VM):
- 3 worker 各 6 vCPU = 18 vCPU + 控制面 6 vCPU = 24 vCPU
- 宿主机 32 线程 = 32 vCPU 容量,分配 24 给 VM,8 给 Proxmox + IO 管理
- CPU 超分比:24/32 = 75%(合理,没有超分)
一个有趣的发现是:E5-2650 的 32 线程是超线程(16 物理核 × 2),实际物理核心只有 16 个。24 vCPU 分配到 16 个物理核上 ≈ 1.5 倍超分,处于合理范围。全核满载时每个 VM 的 vCPU 会竞争物理核,但 CTF 比赛场景的特点是大部分时间容器空闲(选手解题时 CPU 占用低),启动时才短暂高负载。
5. 对比 2 节点方案
5.1 资源配置对比
| 维度 | 2 节点(原推荐方案) | 4 节点(推荐方案一) | 差异 |
|---|---|---|---|
| VM 数量 | 2 | 4 | +2 个节点 |
| vCPU 分配 | 4-6 核 | 24 核 | +18-20 核 |
| VM 总内存 | 4.0 GB | 168 GB | +164 GB |
| 集群总可用比赛内存 | ~25 GB(32GB 宿主机) | ~160 GB | +135 GB |
| 总磁盘分配 | ~50 GB | 320 GB | +270 GB |
| 基础设施开销 | ~7 GB(含 OS×2, Docker×2) | ~26 GB(含 OS×4, Docker×4) | +19 GB |
关键数据点:2 节点方案原本是基于 32 GB 宿主机设计的。现在宿主机有 192 GB,4 节点方案能利用的资源是 2 节点方案的约 6-7 倍。
5.2 4 节点的额外价值(在 192 GB 宿主机上)
如果只在 192 GB 宿主机上跑 2 节点,会有大量内存闲置——因为 2 个 VM 也吃不完 192 GB。此时 4 节点的价值非常明确:
- 资源利用率大幅提升:192 GB 内存 × 4 VM = 充分利用宿主机算力
- 更好的容器分布:3 个 worker 节点可以:
- 通过
nodeSelector/nodeAffinity将不同类型的题目调度到不同 worker - 例如:worker-1 跑 Web 题、worker-2 跑 PWN 题、worker-3 跑 Misc 题
- 避免某一道题的 Image Pull 风暴影响其他类型的题目
- 通过
- 更高的 Pod 上限:k3s 默认每节点 110 Pod 上限,3 worker = 330 Pod 上限(调大后更多)
- IO 隔离:拉取镜像时 3 个 worker 的 Docker daemon 各自独立,并发拉取效率更高
- 控制面独立:GZCTF + 数据库跑在 control-plane 上,不与比赛容器争抢 CPU/IO
5.3 磁盘分配对比
| 项目 | 2 节点 | 4 节点 | 4 节点的挑战 |
|---|---|---|---|
| 总磁盘 | 50 GB | 320 GB | 每个节点 Docker 镜像存储独立,磁盘总需求更大 |
| 每个节点 Docker 独立存储 | 2 份 | 4 份 | 同样一套基础镜像要拉取 4 次 |
| 日志存储 | 2 套 | 4 套 | 日志管理更复杂 |
| 磁盘分配灵活性 | 高(2 个盘好分) | 低(4 个盘要算细账) | 需要更精确的预留 |
根据数据显示,4 节点方案的一个隐藏成本是 Docker 镜像的冗余存储。在 2 节点方案中,同一套基础镜像只需要拉取 2 次(每 VM 一次)。在 4 节点方案中需要拉取 4 次。假设基础镜像 5 GB × 4 = 20 GB(vs 2 节点的 10 GB),多浪费 10 GB 磁盘。
缓解方案:在 Proxmox 宿主机上部署一个 Docker Registry Mirror(registry:2),所有 VM 的 Docker daemon 配置为使用这个 mirror 拉取镜像。这样基础层只需要在 mirror 上存一份,各 VM 只缓存自己需要的层。可以节省约 50-70% 的重复镜像存储。
5.4 4 节点 vs 2 节点的决策矩阵
| 评估维度 | 2 节点 | 4 节点 | 哪个更优 |
|---|---|---|---|
| 可用比赛内存(192GB 宿主机) | ~160 GB(1 hybrid + 1 worker,各分 80+ GB) | ~160 GB(1 cp + 3 worker) | 实际上差不多 |
| 容器分布灵活性 | 2 个节点,所有容器挤在一起 | 3 个 worker,可分类调度 | ✅ 4 节点 |
| 单节点故障影响 | 损失 50% 计算资源 | 损失 33% 计算资源 | ✅ 4 节点 |
| 运维复杂度 | 低(2 个 VM) | 中(4 个 VM) | ✅ 2 节点 |
| 磁盘压力 | 低(2 份 Docker 存储) | 高(4 份 Docker 存储) | ✅ 2 节点 |
| Pod 上限 | 220(默认 110×2) | 440(默认 110×4) | ✅ 4 节点 |
| 网络复杂度 | 简单(2 VM 互联) | 稍复杂(4 VM 互联) | ✅ 2 节点 |
| 学习价值 | 能学到 k8s 基础 | 学到多节点 k8s | ✅ 4 节点 |
核心结论:在 192 GB 宿主机上,4 节点的额外磁盘消耗(4 份 OS + 4 份 Docker 存储 ≈ 35-50 GB)是主要代价。作为交换,获得了3 个 worker 节点的调度弹性和故障分散能力。考虑到 340 GB 磁盘足够支撑 4 份分配(320 GB 分配 + 20 GB 余量),4 节点方案在 192 GB 宿主机上是值得的。
6. 最终推荐方案
🏆 推荐方案:中配均衡(方案一)
┌─────────────────────────────────────────────────────┐
│ 4 节点 k3s --docker 推荐配置 │
├────────┬────────┬──────┬──────┬──────┬──────────────┤
│ 节点 │ 角色 │vCPU │ 内存 │ 磁盘 │ 说明 │
├────────┼────────┼──────┼──────┼──────┼──────────────┤
│ k3s-cp │控制面 │ 6 │ 24GB │ 80GB │ GZCTF+DB │
│ k3s-w1 │worker │ 6 │ 48GB │ 80GB │ 题目容器 │
│ k3s-w2 │worker │ 6 │ 48GB │ 80GB │ 题目容器 │
│ k3s-w3 │worker │ 6 │ 48GB │ 80GB │ 题目容器 │
├────────┼────────┼──────┼──────┼──────┼──────────────┤
│ 合计 │ │ 24 │168GB │320GB │ 剩余 20GB 盘 │
└────────┴────────┴──────┴──────┴──────┴──────────────┘
宿主机剩余资源:
CPU: 32 - 24 = 8 线程(给 Proxmox + IO 管理)
内存: 192 - 168 - 6(Proxmox) = 18 GB(系统缓存 + 突发)
磁盘: 340 - 320 = 20 GB(ISO 模板 + 备份暂存)
详细分配逻辑
CPU 分配理由
| 节点 | vCPU | 理由 |
|---|---|---|
| k3s-cp | 6 | GZCTF (.NET 8) 是多线程应用,PostgreSQL 也需要 CPU。6 vCPU 保证平台响应 |
| k3s-w1/2/3 | 6 | 每个 worker 承担约 10 道题的容器,每道题容器分配 0.5-1 CPU。6 vCPU 在容器空闲时足够,启动风暴时可临时占满 |
内存分配理由
| 节点 | 内存 | 占总量比例 |
|---|---|---|
| k3s-cp | 24 GB | 12.5% |
| 3 × worker | 48 GB × 3 = 144 GB | 75% |
控制面分配 24 GB(较少)是因为它只跑 GZCTF 基础设施 + 少量比赛容器。3 个 worker 各 48 GB 最大化容器容量。
磁盘分配理由
| 节点 | 磁盘 | 内部分解 |
|---|---|---|
| k3s-cp | 80 GB | OS(8) + Docker/镜像(20) + GZCTF+DB 数据(15) + 日志(7) + 缓冲(30) |
| 3 × worker | 80 GB | OS(8) + Docker/镜像(25) + 容器读写层(12) + 日志(10) + 缓冲(25) |
GZCTF 部署说明
GZCTF 主服务 + PostgreSQL + Redis 以 Docker Compose 或 Helm Chart 方式部署在 control-plane 节点上。GZCTF 通过 kube-config 连接 k3s apiserver(127.0.0.1:6443),使用 k8s 模式调度题目容器到 3 个 worker 节点。
或者:GZCTF 本身也跑在 k8s 内(以 Deployment 形式),这样整个平台都是 k8s 原生管理。但这样需要先有一个可用的集群才能部署 GZCTF(鸡生蛋问题)。推荐在 control-plane 上用 Docker Compose 跑 GZCTF,然后 GZCTF 通过 kube-config 管理题目容器。
配置步骤要点
# control-plane 节点
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="\
--docker \
--kube-apiserver-arg=service-node-port-range=20000-50000 \
--kubelet-arg=max-pods=500 \
--kube-controller-manager-arg=node-cidr-mask-size=22 \
--node-name=k3s-cp \
--cluster-cidr=10.42.0.0/16 \
--service-cidr=10.43.0.0/16" sh -
# worker 节点加入
curl -sfL https://get.k3s.io | K3S_URL=https://<cp-ip>:6443 \
K3S_TOKEN=<token> \
INSTALL_K3S_EXEC="--docker --node-name=k3s-w1" sh -
(来源:k3s 官方安装文档、GZCTF 部署指南)
附录:各方案速查表
方案对比总表
| 指标 | 方案一(推荐✅) | 方案二(高配) | 方案三(紧凑) |
|---|---|---|---|
| vCPU 分配 | 6/6/6/6 | 8/6/6/6 | 4/4/4/4 |
| 内存分配 | 24/48/48/48 GB | 32/48/48/48 GB | 16/32/32/32 GB |
| 磁盘分配 | 80/80/80/80 GB | 100/75/75/75 GB | 60/85/85/85 GB |
| 总 VM 内存 | 168 GB | 176 GB | 112 GB |
| 宿主机剩余内存 | 18 GB | 10 GB | 74 GB |
| 可用比赛内存 | ~160 GB | ~167.5 GB | ~102.5 GB |
| 128 MB 容器数 | ~1,280 | ~1,340 | ~820 |
| 256 MB 容器数 | ~640 | ~670 | ~410 |
| 适合比赛规模 | 100 队×30题 | 100 队×30题 | 50 队×30题 |
| CPU 超分比 | 75% | 81% | 50% |
| 剩余磁盘 | 20 GB | 15 GB | 25 GB |
选择建议
- 推荐方案一:平衡了所有约束,CPU/内存/磁盘利用率合理,覆盖 100 队 × 30 题的中型比赛
- 方案二(高配):如果磁盘更充裕(或有外挂存储),控制面多给内存可以跑更多容器
- 方案三(紧凑):如果以后要扩展更多 VM(如再加 2 个 worker),预留内存用
最后:无论选哪个方案,强烈建议在 Proxmox 宿主机上搭建一个 Docker Registry Mirror。根据资料显示,这样可以将 4 个 VM 的镜像冗余存储从 4 份减少到约 1.5-2 份,节省磁盘空间约 20-30 GB。配置方式详见 Docker 官方文档的 Registry as a pull-through cache。
原始笔记:cloud/gz-ctf/4节点资源配置分配方案.md