新手推荐
首次部署回归终端时,建议先阅读 Docker Compose 部署。该方案可以用于生产环境,组件边界清晰,也便于理解平台如何通过 kubeconfig 接入外置 Kubernetes 集群。
本页介绍部署回归终端前需要确认的系统环境、服务器架构和 Kubernetes 基础环境。后续部署文档在没有特别说明发行版时,默认以 Debian 系 Linux 环境展开。
系统环境
回归终端推荐部署在 Linux 服务器上。平台服务本身是单二进制程序,也可以放入容器运行;PostgreSQL、Valkey、NATS、registry、VictoriaLogs 和 Kubernetes 生态在 Linux 上都有更稳定的部署路径。
推荐使用 Debian 或 Debian 系发行版,例如 Debian Stable、Ubuntu LTS。后续命令在没有特别说明时,会优先使用 Debian 系发行版的包管理器、目录布局和 systemd 行为作为默认环境。
Windows Server 和 Unix 系统也可以运行部分组件。使用这些系统时,需要自行构建平台镜像或二进制,准备 PostgreSQL、Valkey、NATS 等组件服务,并处理服务守护、日志、网络、文件权限和容器运行时差异。正式比赛建议使用 Linux,以减少部署和故障排查成本。
部署前建议准备以下基础工具:
sudo apt update
sudo apt install -y curl ca-certificates gnupg lsb-release iproute2 iptables git gh fuse-overlayfs服务器需要直接管理 Git 题目仓库、构建镜像或调试集群时,还建议准备:
sudo apt install -y git build-essential jq服务器架构
回归终端的资源压力主要来自动态题目容器,也就是 Kubernetes 中运行的 challenge pods。平台服务、数据库、缓存、队列和日志组件在大多数比赛中只占用少量资源。资源规划时应先确认所有题目的部署方式,再估算动态容器高峰。
推荐使用以下估算方式:
- 估算高峰动态容器数:
参赛人数 * 0.2。 - 统计单个题目环境的 CPU、内存和临时存储需求。
- 按高峰动态容器数估算 challenge pods 的总资源。
- 在 challenge pods 资源需求之上,为平台和基础组件额外预留约
1 vCPU与2 GiB内存。 - 为系统、镜像缓存、数据库、日志、平台持久化数据和突发调度保留额外磁盘空间。
以 2000 人规模为例,动态容器高峰可先按 2000 * 0.2 = 400 个估算。常见轻量题目环境可以先以 16 核 CPU、64 GiB 内存作为单节点办赛的基准配置。题目包含浏览器、AI、区块链、本地大模型、编译服务或高内存数据库时,应按题目配置重新计算资源,并优先提升内存与磁盘余量。
单场比赛的平台数据量通常可以控制在 20 GiB 以内。仅举办单场比赛时,100 GiB SSD 通常可以覆盖系统、k3s、平台 PVC、镜像缓存、日志和少量备份。平台作为长期练习场持续维护时,磁盘建议从 1 TiB 起步,并按题目镜像数量、附件规模、日志留存周期和备份策略继续扩容。
单服务器单节点
单服务器单节点办赛推荐使用“集群内统一部署”方式。平台服务、PostgreSQL、Valkey、NATS、registry、VictoriaLogs 和 challenge pods 都运行在同一个 Kubernetes 节点中,由 Helm 统一管理。
这种架构部署简单,适合中小规模比赛、练习赛和单台高配服务器办赛。2000 人规模可先按以下配置准备:
| 资源 | 推荐值 | 说明 |
|---|---|---|
| CPU | 16 核或以上 | 平台本身通常只需要约 1 核,主要用于 challenge pods。 |
| 内存 | 64 GiB 或以上 | 平台和基础组件通常额外预留约 2 GiB,主要内存压力来自题目容器。 |
| 磁盘 | 单场比赛 100 GiB 或以上 SSD;长期练习场 1 TiB 或以上 SSD | 放置系统、k3s、容器运行时、PostgreSQL、bucket、media、registry、VictoriaLogs、镜像缓存和备份。 |
| 网络 | 公网入口 + 稳定内网 | 公网入口用于访问平台和题目服务,内网用于 Kubernetes 与组件通信。 |
该配置只适合作为起点。题目容器的资源限制、同时开启实例数、镜像大小和日志量会直接影响服务器需求。
多服务器分离部署
多服务器办赛时,所有服务器应位于同一个低延迟内网中。推荐将平台作为统一公网入口,把平台服务和基础组件放在一台独立服务器上,用 Docker Compose 或 systemd 启动;其他服务器组成 Kubernetes 集群,专门运行题目容器。
这种架构把平台数据和题目算力分开,便于扩容题目节点。资源估算方式与单节点一致,仍然先估算 challenge pods 高峰数量,再按题目容器请求的 CPU 和内存计算总需求。平台服务器通常只需要额外承担 Web/API、数据库、缓存、队列、文件存储和日志写入压力。公网入口建议集中在平台服务器或统一网关上,由平台配置的 traffic 映射提供题目访问地址。
平台服务器和 Kubernetes 集群之间需要保证以下连通性:
| 方向 | 用途 |
|---|---|
| 平台服务器 -> Kubernetes API | 创建、查询、续期、删除题目 Pod 和 Service。 |
| Kubernetes 节点 -> registry | 拉取题目镜像。registry 可以是平台内置仓库,也可以是 Docker Hub、GHCR、Harbor 或云厂商仓库。 |
| 平台服务器 -> 数据库 / 缓存 / 队列 / 日志服务 | 平台运行时依赖。 |
| 用户 -> 平台公网入口 | 访问 Web、API、WebSocket 和可选 registry 代理。 |
| 用户 -> 题目入口 | 访问由 traffic 脚本、Ingress、NodePort 或外部网关暴露的题目服务。 |
多节点集群内统一部署
也可以把平台和基础组件部署在同一个多节点 Kubernetes 集群内。此时需要注意平台当前以单副本 StatefulSet 方式运行,建议给节点打标签,把平台固定到单独节点或稳定节点上,并把 challenge pods 调度到其他节点。
示例节点标签:
kubectl label node platform-node ret.sh.cn/workload=platform
kubectl label node worker-1 ret.sh.cn/workload=challenge
kubectl label node worker-2 ret.sh.cn/workload=challenge平台 Helm values 可以为平台服务设置 platform.nodeSelector,为题目容器设置默认的 [cluster].node_selector。平台也支持在比赛维度配置 node selector,让 challenge pods 运行在指定节点组上。
这种方式适合已经熟悉 Kubernetes 运维的团队。部署前需要规划好持久卷、节点标签、Pod 资源限制、镜像缓存、日志收集和节点故障后的恢复流程。
准备 Kubernetes 环境
动态题目环境依赖 Kubernetes。可以使用云厂商提供的托管 Kubernetes,例如 Google Cloud Platform、AWS、Azure、阿里云、腾讯云等,也可以自建集群。初次办赛且团队不熟悉 Kubernetes 时,推荐使用 k3s 作为生产环境选择。k3s 组件少,安装路径清晰,适合中小规模 CTF 平台。
k3s 启动前配置
CTF 平台会快速创建和删除大量轻量级 Pod。Kubernetes 默认每节点 110 个 Pod 的上限通常不够用。建议在首次启动 k3s 前配置 Pod CIDR、每节点 Pod CIDR 掩码和 kubelet maxPods。
这些参数应在集群创建前确定,后续部署阶段无法平滑修改。已经启动过的测试集群建议重建后再调整,避免网络规划和节点 Pod 容量不一致。
推荐使用以下配置:
sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/config.yaml >/dev/null <<'EOF'
cluster-cidr: 10.42.0.0/16
kube-controller-manager-arg:
- node-cidr-mask-size=20
kubelet-arg:
- config=/etc/rancher/k3s/kubelet.config
EOF
sudo tee /etc/rancher/k3s/kubelet.config >/dev/null <<'EOF'
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
maxPods: 3073
EOFnode-cidr-mask-size=20 会给单节点分配更大的 Pod 地址段,适合大量轻量 Pod 的快速启停场景。maxPods: 3072 用于移除 kubelet 默认 Pod 数限制。实际可运行数量仍受节点 CPU、内存、Pod CIDR、CNI、镜像拉取速度和系统参数约束。
选择平台入口方式
平台推荐使用以下两种入口方式之一:
| 方式 | 适用场景 | 说明 |
|---|---|---|
| Ingress | 平台和网关都运行在 Kubernetes 内 | 使用 Ingress Controller 统一暴露平台服务和 TLS。 |
| NodePort + 外置 Web Server | 希望由宿主机 Nginx/Caddy 或已有网关管理 80/443 | 平台服务通过 NodePort 暴露给外置 Web Server,再由外置 Web Server 处理 TLS、静态资源、WebSocket 和 registry /v2 代理。 |
选择 NodePort + 外置 Web Server 时,宿主机 Nginx/Caddy 或已有网关需要使用 80/443。k3s 内置 Traefik 默认会通过 ServiceLB 为 80/443 写入 iptables 规则。推荐在首次启动 k3s 前把 Traefik 暴露端口移到高位端口,给外置 Web Server 留出 80/443:
sudo mkdir -p /var/lib/rancher/k3s/server/manifests
sudo tee /var/lib/rancher/k3s/server/manifests/traefik-config.yaml >/dev/null <<'EOF'
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
name: traefik
namespace: kube-system
spec:
valuesContent: |-
ports:
web:
exposedPort: 10080
websecure:
exposedPort: 10443
EOF完全不使用 Traefik 的部署可以在启动前禁用内置 Traefik:
sudo tee -a /etc/rancher/k3s/config.yaml >/dev/null <<'EOF'
disable:
- traefik
EOF安装 k3s 控制节点
完成前置配置后再启动 k3s。INSTALL_K3S_EXEC="server" 会写入 k3s 的 systemd 启动参数,前面写入的 /etc/rancher/k3s/config.yaml 和 kubelet 配置会在服务启动时读取。
curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server" sh -安装完成后,检查节点状态:
sudo k3s kubectl get nodes -o wide
sudo k3s kubectl get pods -A普通用户需要使用 kubeconfig 时,可以复制配置并修正权限:
mkdir -p ~/.kube
sudo cp /etc/rancher/k3s/k3s.yaml ~/.kube/config
sudo chown "$USER:$USER" ~/.kube/config中国大陆服务器安装
中国大陆服务器建议使用 Rancher 镜像安装脚本,并在启动前配置常用镜像源代理。镜像源可用性会随网络环境变化,部署前应先确认服务器可以访问对应地址。
sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/registries.yaml >/dev/null <<'EOF'
mirrors:
'docker.io':
endpoint:
- 'https://docker.1ms.run'
'ghcr.io':
endpoint:
- 'https://ghcr.m.daocloud.io'
'gcr.io':
endpoint:
- 'https://gcr.m.daocloud.io'
'quay.io':
endpoint:
- 'https://quay.m.daocloud.io'
'registry.k8s.io':
endpoint:
- 'https://k8s.m.daocloud.io'
EOF已经安装 k3s 后再修改 /etc/rancher/k3s/registries.yaml,需要重启 k3s 才会生效:
sudo systemctl restart k3s启动控制节点:
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh \
| INSTALL_K3S_MIRROR=cn INSTALL_K3S_EXEC="server" sh -增加工作节点
多节点集群需要在控制节点上读取 join token:
sudo cat /var/lib/rancher/k3s/server/node-token在工作节点上先写入同样的 kubelet 配置:
sudo mkdir -p /etc/rancher/k3s
sudo tee /etc/rancher/k3s/config.yaml >/dev/null <<'EOF'
kubelet-arg:
- config=/etc/rancher/k3s/kubelet.config
EOF
sudo tee /etc/rancher/k3s/kubelet.config >/dev/null <<'EOF'
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
maxPods: 32768
EOF然后加入集群:
curl -sfL https://get.k3s.io \
| K3S_URL=https://<control-plane-ip>:6443 K3S_TOKEN=<node-token> sh -中国大陆工作节点可使用镜像脚本:
curl -sfL https://rancher-mirror.rancher.cn/k3s/k3s-install.sh \
| INSTALL_K3S_MIRROR=cn K3S_URL=https://<control-plane-ip>:6443 K3S_TOKEN=<node-token> sh -节点加入后,建议为题目节点打标签:
kubectl label node worker-1 ret.sh.cn/workload=challenge
kubectl label node worker-2 ret.sh.cn/workload=challenge扩展阅读
完成环境准备后,可以根据实际架构进入正式部署流程:
- 使用 ret2boot:在一台 Linux 服务器上通过交互式安装器完成系统预检、Kubernetes、Helm、网关、平台和基础组件部署。
- 集群内统一部署:平台服务、基础组件和题目容器都部署在 Kubernetes 中。
- 裸机 / systemd 部署:平台服务和基础组件在服务器上直接运行,Kubernetes 可作为外部题目集群接入。
- Docker Compose 部署:平台服务和基础组件用 Compose 管理,适合单独平台节点或小规模部署。
