本章记录回归终端上线后的日常维护方式,覆盖集群内部署、ret2boot 部署、裸机 / systemd 部署和 Docker Compose 部署。涉及 Kubernetes 的命令主要用于平台运行在集群内、或平台需要排查动态题目环境的场景;裸机和 Docker Compose 部署需要把平台服务日志、进程管理和数据目录命令按实际路径替换。
涉及 Kubernetes / Helm 的命令默认 Helm release 名为 ret2shell,平台 namespace 为 ret2shell-platform,题目 namespace 为 ret2shell-challenge。如果你的部署使用了外部 PostgreSQL、Valkey、NATS、registry 或 VictoriaLogs,对应组件的日志、升级和备份应在外部系统中完成。
维护时应把部署配置、数据库备份、平台数据目录备份和操作记录放在一起管理。部署配置可能是
values.production.yaml、ret2boot 配置、.env、docker-compose.yml或/etc/ret2shell/config.toml。不要直接修改 Kubernetes 中由 Helm 生成的对象,也不要在数据目录中手动删除、移动、改名或改权限,除非你已经确认这些目录的用途并做好了可恢复备份。
例行巡检
日常运维可以关注以下状态:
# 仅在集群内部部署方案和 ret2boot 方案中看这些
helm status ret2shell -n ret2shell-platform
helm history ret2shell -n ret2shell-platform
kubectl -n ret2shell-platform get pods,svc,ingress,pvc -o wide
kubectl -n ret2shell-platform get statefulset,deploy -o wide
kubectl -n ret2shell-platform get events --sort-by=.lastTimestamp
# 使用裸机部署时
## 查看各个组件的情况也可以使用上述两个命令,将服务名称替换成各个组件的名称
systemctl status ret2shell.service
## 串流日志
journalctl -xeu ret2shell.service -f
# 使用 Docker Compose 部署时,在部署文件目录内
docker compose ps
docker compose logs -f ret2shell
# 如果你开启了集群功能,无论使用哪种部署方式,最好都要例行巡检一下题目容器的状况
kubectl -n ret2shell-challenge get pods,svc,networkpolicy -o wide
kubectl -n ret2shell-challenge get events --sort-by=.lastTimestamp
kubectl get nodes -o wide
kubectl top nodes
kubectl top pods -A如果
kubectl top不可用,说明集群没有安装 Metrics Server,或 Metrics Server 当前异常。它不影响平台基础功能。
ret2shell-platform 中应重点关注:
| 资源 | 正常状态 | 常见异常 |
|---|---|---|
statefulset/ret2shell-platform | 1/1 就绪 | 配置错误、数据库不可达、缓存不可达、探针失败、镜像拉取失败。 |
statefulset/ret2shell-postgresql | 内置数据库启用时 1/1 就绪 | PVC 未绑定、磁盘满、数据库启动失败、主版本升级不兼容。 |
statefulset/ret2shell-valkey | 单实例或主从实例就绪 | 密码不一致、AOF 损坏、内存不足、PVC 问题。 |
statefulset/ret2shell-nats | NATS JetStream 实例就绪 | JetStream 存储不可写、token 不一致、集群路由异常。 |
deployment/ret2shell-registry | 内置 registry 启用时 Pod 就绪 | 镜像层存储满、外部访问地址配置错误、节点无法拉取题目镜像。 |
statefulset/ret2shell-victoria-logs | 内置 VictoriaLogs 启用时 1/1 就绪 | 日志盘满、平台无法写入集中日志、查询超时。 |
pvc/* | 全部 Bound | StorageClass 不存在、Local PV 节点不匹配、磁盘空间不足。 |
ret2shell-challenge 中应重点关注题目 Pod 是否大量处于 Pending、ImagePullBackOff、CrashLoopBackOff、OOMKilled 或长期 Terminating。这些状态通常分别对应资源不足、镜像拉取失败、题目进程崩溃、内存限制过低或节点/网络插件异常。
平台日志
平台日志有三种来源:
- Web 管理后台的
/admin/logs页面。它查询 VictoriaLogs,适合按时间、等级、账号、来源 IP、trace id 和 LogSQL 条件检索。 - Kubernetes stdout。它来自容器标准输出,适合服务无法进入后台或 VictoriaLogs 不可用时排障。
- 平台本地日志文件。Helm 部署中默认位于平台 Pod 内的
/var/lib/ret2shell/log,可以从/admin/logs下载,也可以进入 Pod 只读检查。
后台日志页面常用字段:
| 字段 | 用途 |
|---|---|
LEVEL | 过滤 DEBUG、INFO、WARN、ERROR。比赛期间一般先看 WARN 和 ERROR。 |
SIZE | 限制返回条数。问题发生时间明确时可以先用 100,再放宽。 |
Trace ID | 追踪一次请求或后台任务。前端请求、后台 worker 和部分事件会携带同一个 trace。 |
Account | 按用户账号过滤请求日志。选手反馈问题时优先填写这个字段。 |
IP | 按来源 IP 过滤。需要确认反向代理正确传递真实 IP,否则这里可能只看到网关地址。 |
Log Query SQL | 直接输入 VictoriaLogs LogSQL。填写后其他结构化过滤项会让位给自定义查询。 |
Kubernetes 侧查看平台日志:
kubectl -n ret2shell-platform logs statefulset/ret2shell-platform -c platform --tail=200
kubectl -n ret2shell-platform logs statefulset/ret2shell-platform -c platform -f
kubectl -n ret2shell-platform logs -l app.kubernetes.io/component=platform --since=1h查看平台本地日志文件列表和容量:
kubectl -n ret2shell-platform exec statefulset/ret2shell-platform -c platform -- \
sh -lc 'ls -lh /var/lib/ret2shell/log && du -sh /var/lib/ret2shell/log'平台本地日志按天写入,文件名形如 ret2shell.2026-01-29.log。开启日志压缩后,旧日志会归档为 ret2shell.YYYY-MM.log.tar.gz 或 ret2shell.YYYY.log.tar.gz。不要手动删除正在写入的当天日志;需要控制保留量时,修改 platform.config.logging.filesKept 或接入外部日志保留策略。
组件日志
各组件都带有 app.kubernetes.io/component 标签。排障时先用标签找 Pod,再按组件查看日志。
kubectl -n ret2shell-platform get pods --show-labels
kubectl -n ret2shell-platform get pods -l app.kubernetes.io/component=postgresql -o wide常用日志命令:
kubectl -n ret2shell-platform logs -l app.kubernetes.io/component=platform --tail=200
kubectl -n ret2shell-platform logs -l app.kubernetes.io/component=postgresql --tail=200
kubectl -n ret2shell-platform logs -l app.kubernetes.io/component=valkey --tail=200
kubectl -n ret2shell-platform logs -l app.kubernetes.io/component=nats --tail=200
kubectl -n ret2shell-platform logs -l app.kubernetes.io/component=registry --tail=200
kubectl -n ret2shell-platform logs -l app.kubernetes.io/component=victoria-logs --tail=200组件启用 metrics sidecar 时,需要指定容器名:
kubectl -n ret2shell-platform logs <pod-name> -c metrics --tail=200题目容器日志位于 ret2shell-challenge:
kubectl -n ret2shell-challenge get pods -o wide
kubectl -n ret2shell-challenge logs <pod-name> --tail=200
kubectl -n ret2shell-challenge logs <pod-name> -c <container-name> --tail=200
kubectl -n ret2shell-challenge logs <pod-name> -c <container-name> --previous --tail=200--previous 用于查看上一次崩溃容器的日志,对 CrashLoopBackOff 和 OOMKilled 很有用。如果题目镜像没有 shell,kubectl exec 可能不可用,此时应优先依赖 describe、事件和容器日志。
基础集群组件通常在 kube-system。K3s 部署中常见组件包括 CoreDNS、local-path-provisioner、metrics-server、Traefik 和 kube-proxy 相关组件:
kubectl -n kube-system get pods,svc,deploy,daemonset,configmap -o wide
kubectl -n kube-system get events --sort-by=.lastTimestamp
kubectl -n kube-system logs -l k8s-app=kube-dns --tail=100
kubectl -n kube-system logs -l app=local-path-provisioner --tail=100如果平台入口使用独立的 Ingress Controller,例如 ingress-nginx namespace,需要到对应 namespace 查看 Ingress Controller 的 Pod、Service 和日志。
数据目录
Helm 部署中,平台服务把 platform.persistence 挂载到 /var/lib/ret2shell。这个目录保存平台文件态数据,应和 PostgreSQL 一起备份。
| 目录 | 用途 | 审计建议 |
|---|---|---|
/var/lib/ret2shell/bucket | 比赛、题目、附件、checker、环境配置、题目仓库和 Git 记录。 | 只做容量、文件数量和备份完整性检查。不要手动改题目文件,题目发布状态和数据库记录需要保持一致。 |
/var/lib/ret2shell/media | 用户上传图片、平台媒体文件和缩略图。 | 关注容量增长和异常大文件。不要绕过平台接口删除媒体,否则数据库中的引用可能悬空。 |
/var/lib/ret2shell/log | 平台本地结构化日志和归档日志。 | 可只读查看、下载和备份。删除策略应通过配置或日志系统完成。 |
/var/lib/ret2shell/captures | 题目环境交互捕获数据。开启 enableCapture 后可能增长较快。 | 关注容量和保留周期。当前后台捕获页面未完成时,不要直接把目录当作稳定 API 使用。 |
只读审计命令:
kubectl -n ret2shell-platform exec statefulset/ret2shell-platform -c platform -- \
sh -lc 'find /var/lib/ret2shell -maxdepth 2 -type d -print'
kubectl -n ret2shell-platform exec statefulset/ret2shell-platform -c platform -- \
sh -lc 'du -sh /var/lib/ret2shell/* 2>/dev/null'
kubectl -n ret2shell-platform exec statefulset/ret2shell-platform -c platform -- \
sh -lc 'find /var/lib/ret2shell/bucket -mindepth 1 -maxdepth 1 -type d | wc -l'使用本地静态 PV 时,宿主机上还会有一组 PV 目录。默认模板使用 /srv/ret2shell/backend/storage 作为根目录:
| 宿主机目录 | 对应组件 | 保存内容 |
|---|---|---|
platform-pv1 | platform.persistence | 平台 /var/lib/ret2shell 数据。 |
database-pv1 | postgresql.persistence | PostgreSQL 数据文件。 |
cache-pv1 | valkey.persistence | Valkey AOF 和运行数据。 |
queue-pv1 | nats.persistence | NATS JetStream 存储。 |
registry-pv1 | registry.persistence | 题目镜像层和 manifest。 |
logs-pv1 | victoriaLogs.persistence | VictoriaLogs 索引和日志数据。 |
这些目录由对应容器维护。不要在宿主机上手动 rm、mv、chown、编辑数据库文件或清理镜像层。需要迁移或清理时,应先停写、备份,再使用对应组件支持的工具完成。
宿主机侧只读审计可以使用:
sudo du -sh /srv/ret2shell/backend/storage/*
sudo find /srv/ret2shell/backend/storage -maxdepth 2 -type d -print如果磁盘即将耗尽,优先判断增长来源:题目镜像看 registry-pv1,平台附件和题目仓库看 platform-pv1/bucket,媒体看 platform-pv1/media,平台日志看 platform-pv1/log,集中日志看 logs-pv1。不要用删除目录的方式“腾空间”,否则后续恢复成本通常更高。
配置变更
回归终端有两类配置来源:
| 来源 | 位置 | 生效方式 |
|---|---|---|
| 部署配置 | values.production.yaml,由 Helm 渲染成 Secret、ConfigMap、StatefulSet、Service、Ingress、PVC 等资源。 | 修改 values 后执行 helm upgrade。生成的 config.toml 和 blocked.txt 会触发平台 Pod 滚动重建。 |
| 运行时配置 | Web 管理后台,例如 /admin/edit、/admin/email、/admin/traffic、/admin/lifecycle。 | 写入数据库并清理平台配置缓存,通常不需要重启平台。 |
部署配置适合管理数据库连接、缓存连接、NATS、registry、VictoriaLogs、外部域名、入口、PVC、镜像版本、资源限制、节点选择器、RBAC、日志目录等基础设施项。运行时配置适合管理平台展示信息、邮件设置、全局 traffic 脚本、全局 lifecycle 脚本和默认题目节点选择器。
查看当前 Helm values 和渲染后的平台配置:
helm get values ret2shell -n ret2shell-platform > values.installed.yaml
kubectl -n ret2shell-platform get secret ret2shell-config \
-o jsonpath='{.data.config\.toml}' | base64 -d
kubectl -n ret2shell-platform get configmap ret2shell-blocked -o yaml修改生产配置的常规流程:
cd ~/ret2shell-deploy
helm template ret2shell "./ret2shell-${R2S_VERSION}.tgz" \
-n ret2shell-platform \
-f values.production.yaml \
> rendered.yaml
helm upgrade --install ret2shell "./ret2shell-${R2S_VERSION}.tgz" \
-n ret2shell-platform \
-f values.production.yaml \
--dry-run
helm upgrade --install ret2shell "./ret2shell-${R2S_VERSION}.tgz" \
-n ret2shell-platform \
-f values.production.yaml \
--wait \
--timeout 15m发布后检查:
helm status ret2shell -n ret2shell-platform
kubectl -n ret2shell-platform rollout status statefulset/ret2shell-platform --timeout=5m
kubectl -n ret2shell-platform get pods,pvc,svc,ingress -o wide
helm test ret2shell -n ret2shell-platform --logs如果设置了 platform.config.existingSecret 或 platform.blocked.existingConfigMap,Helm 只知道对象名称,不会自动感知对象内容变化。修改外部 Secret 或 ConfigMap 后,需要显式重启平台 Pod:
kubectl -n ret2shell-platform rollout restart statefulset/ret2shell-platform
kubectl -n ret2shell-platform rollout status statefulset/ret2shell-platform --timeout=5m敏感词文件对应 /etc/ret2shell/blocked.txt,Helm values 中是 platform.blocked.content。建议把敏感词列表作为配置文件管理,随 values 一起审阅和发布,不要直接进入 Pod 修改挂载文件。
组件升级
升级流程必须先按安装方式区分。不要把 ret2boot、Helm、systemd 和 Docker Compose 的命令混用。
| 安装方式 | 升级入口 | 适用范围 |
|---|---|---|
| 手动集群内部署 | Helm Chart 和 values.production.yaml | 平台服务、内置 PostgreSQL、Valkey、NATS、registry、VictoriaLogs 和 PVC。 |
| 通过 ret2boot 部署 | ret2boot update | 由 ret2boot 记录和管理的 Kubernetes、Helm、网关、平台和内置基础组件资源。 |
| 纯裸机部署 | systemd、二进制、配置文件和系统包 | 平台服务、前端静态文件、本机数据库、本机缓存、本机队列、本机 registry。 |
| Docker Compose 部署 | .env、docker-compose.yml 和镜像 | Compose 管理的平台服务和基础组件,外置 Kubernetes 只运行题目容器。 |
无论使用哪一种方式,升级前都应完成三件事:
- 保存当前部署配置和版本记录。
- 备份 PostgreSQL 与平台数据目录。
- 确认回滚路径。数据库迁移、数据库主版本升级、组件存储格式变化和 PVC 数据变化通常不能靠“回滚程序版本”恢复。
平台数据目录备份应按你的存储系统完成。使用本地静态 PV 时,可以在停写窗口对宿主机 PV 目录做备份;使用云盘、Longhorn、Rook Ceph、NFS CSI 等存储时,应使用对应快照或备份能力。
一般来说不推荐使用本地静态 PV 之外的 PV 来存储回归终端的数据,回归终端使用 Git 进行比赛文件管理,对于网络文件系统来说,Git 操作通常压力会很大。
手动集群内部署
手动集群内部署使用 Helm 管理平台和内置基础组件。升级时只改 Chart、values 和镜像版本,不要直接编辑 Helm 生成的 StatefulSet、Secret、ConfigMap 或 PVC。
升级前保存 Helm 状态和数据库备份:
cd ~/ret2shell-deploy
helm get values ret2shell -n ret2shell-platform > "values.installed.$(date +%F).yaml"
helm history ret2shell -n ret2shell-platform > "helm-history.$(date +%F).txt"
DB_POD="$(kubectl -n ret2shell-platform get pod -l app.kubernetes.io/component=postgresql -o jsonpath='{.items[0].metadata.name}')"
kubectl -n ret2shell-platform exec "$DB_POD" -- \
sh -lc 'PGPASSWORD="$POSTGRES_PASSWORD" pg_dump -U "$POSTGRES_USER" -d "$POSTGRES_DB" -Fc' \
> "ret2shell-postgresql.$(date +%F).dump"各组件的升级入口:
| 组件 | Helm values 字段 | 说明 |
|---|---|---|
| 平台服务 | platform.image.tag 或 platform.image.digest,以及 Chart 版本。 | 平台 StatefulSet 是单副本,升级会有短暂不可用。运行中的题目 Pod 不会因为平台 Pod 重建而自动删除,但经平台代理的 WebSocket 流量会中断。 |
| PostgreSQL | postgresql.image.tag | 小版本升级前也要备份。主版本升级不要只改镜像 tag,应按 PostgreSQL 主版本升级流程处理,必要时新建实例后 pg_dump / pg_restore。 |
| Valkey | valkey.image.tag | 单实例会重启一次;复制模式按 StatefulSet 顺序滚动。确认密码和持久化配置不变。 |
| NATS | nats.image.tag | JetStream 数据在 PVC 中。多副本时注意集群路由和磁盘空间。 |
| Registry | registry.image.tag | 默认策略是 Recreate。镜像层在 registry PVC 中,升级前关注磁盘容量和存储兼容性。 |
| VictoriaLogs | victoriaLogs.image.tag | 日志查询短暂不可用不影响平台写本地日志。升级前确认存储格式兼容性和可用空间。 |
升级平台 Chart:
R2S_VERSION="<new-version>"
curl -fLO "https://github.com/ret2shell/ret2shell/releases/download/${R2S_VERSION}/ret2shell-${R2S_VERSION}.tgz"
curl -fLO "https://github.com/ret2shell/ret2shell/releases/download/${R2S_VERSION}/ret2shell-${R2S_VERSION}.tgz.sha256"
EXPECTED_SHA256="$(awk '{print $1}' "ret2shell-${R2S_VERSION}.tgz.sha256")"
ACTUAL_SHA256="$(sha256sum "ret2shell-${R2S_VERSION}.tgz" | awk '{print $1}')"
test "$EXPECTED_SHA256" = "$ACTUAL_SHA256"
helm show values "./ret2shell-${R2S_VERSION}.tgz" > "values.upstream.${R2S_VERSION}.yaml"把新默认 values 与当前 values.production.yaml 对比后,更新生产 values,再渲染和试运行:
helm template ret2shell "./ret2shell-${R2S_VERSION}.tgz" \
-n ret2shell-platform \
-f values.production.yaml \
> rendered.yaml
helm upgrade --install ret2shell "./ret2shell-${R2S_VERSION}.tgz" \
-n ret2shell-platform \
-f values.production.yaml \
--dry-run确认渲染结果和 dry-run 输出后发布:
helm upgrade --install ret2shell "./ret2shell-${R2S_VERSION}.tgz" \
-n ret2shell-platform \
-f values.production.yaml \
--wait \
--timeout 15m
helm status ret2shell -n ret2shell-platform
kubectl -n ret2shell-platform rollout status statefulset/ret2shell-platform --timeout=5m
kubectl -n ret2shell-platform get pods,pvc,svc,ingress -o wide
kubectl -n ret2shell-platform get events --sort-by=.lastTimestamp
helm test ret2shell -n ret2shell-platform --logs回滚 Helm release:
helm history ret2shell -n ret2shell-platform
helm rollback ret2shell <revision> -n ret2shell-platform --wait --timeout 15m回滚只能回滚 Kubernetes 资源和 values。已经执行过的数据库迁移、外部组件升级、PVC 数据格式变化不会自动回退。
通过 ret2boot 部署
ret2boot 部署的环境应优先使用 ret2boot 升级。这个流程不是无人值守自动升级,需要管理员在控制平面节点上执行命令并观察结果。没有保留 ret2boot 安装状态、或后来改成手工 Helm 管理的环境,应按“手动集群内部署”处理。
ret2boot 的升级命令会读取已保存的安装状态,通常包括 /etc/ret2shell/ret2boot.toml 和 /etc/ret2shell/ret2boot-platform-values.yaml。升级过程中,它会检查集群引导资源,确保 Helm CLI 可用,下载最新的 Ret2Shell Helm Chart,校验 sha256,生成 ret2boot 管理的 values、平台运行配置、敏感词文件和存储资源清单,然后执行 Helm 升级并重启已有的平台工作负载。命令只支持在 ret2boot 管理的控制平面安装上使用。
ret2boot 启动时可能会提示有新的 ret2boot 版本并下载到缓存,但当前进程仍会使用已经启动的版本继续执行。需要先升级 ret2boot 自身时,应先替换 /usr/local/bin/ret2boot,再执行平台升级:
ret2boot --version
R2B_VERSION="$(curl -fsSL https://api.github.com/repos/ret2shell/ret2boot/releases/latest | sed -n 's/.*"tag_name": "\(.*\)".*/\1/p' | head -n1)"
R2B_TARGET="x86_64-unknown-linux-musl"
curl -fLO "https://github.com/ret2shell/ret2boot/releases/download/${R2B_VERSION}/ret2boot-${R2B_VERSION}-${R2B_TARGET}.tar.gz"
curl -fLO "https://github.com/ret2shell/ret2boot/releases/download/${R2B_VERSION}/ret2boot-${R2B_VERSION}-${R2B_TARGET}.tar.gz.sha256"
EXPECTED_SHA256="$(awk '{print $1}' "ret2boot-${R2B_VERSION}-${R2B_TARGET}.tar.gz.sha256")"
ACTUAL_SHA256="$(sha256sum "ret2boot-${R2B_VERSION}-${R2B_TARGET}.tar.gz" | awk '{print $1}')"
test "$EXPECTED_SHA256" = "$ACTUAL_SHA256"
tar -xzf "ret2boot-${R2B_VERSION}-${R2B_TARGET}.tar.gz"
sudo install -m 755 "ret2boot-${R2B_VERSION}-${R2B_TARGET}/ret2boot" /usr/local/bin/ret2boot
ret2boot --version升级前先确认 GitHub 访问、GitHub CLI 登录、Helm release 状态和平台 Pod 状态。ret2boot 下载 release 资源时会读取 gh auth token --hostname github.com,如果没有可用 token,下载会失败。使用 ret2boot update 时,应确认 root 环境也能读取 GitHub CLI 登录状态。
sudo gh auth status --hostname github.com
sudo gh auth token --hostname github.com >/dev/null
helm status ret2shell -n ret2shell-platform
kubectl -n ret2shell-platform get pods,pvc -o wide
sudo cp /etc/ret2shell/ret2boot.toml "ret2boot.$(date +%F).toml"
sudo cp /etc/ret2shell/ret2boot-platform-values.yaml "ret2boot-platform-values.$(date +%F).yaml"确认数据库备份和平台数据目录备份已经完成后,执行升级:
ret2boot update执行完成后,ret2boot 会输出本次同步报告。常见变化包括 Helm release 不存在、Helm Chart 变化、平台工作负载规格变化、Helm values 变化、平台配置漂移已修正、敏感词配置漂移已修正、存储类状态变化等。如果没有需要应用的变化,报告会说明当前状态已经同步。
升级后检查:
helm status ret2shell -n ret2shell-platform
kubectl -n ret2shell-platform rollout status statefulset/ret2shell-platform --timeout=5m
kubectl -n ret2shell-platform get pods,pvc,svc,ingress -o wide
kubectl -n ret2shell-challenge get pods,svc -o wide
helm test ret2shell -n ret2shell-platform --logsret2boot 会维护这些生产路径:/etc/ret2shell/ret2boot.toml、/etc/ret2shell/ret2boot-platform-values.yaml、/srv/ret2shell/backend/config/config.toml、/srv/ret2shell/backend/config/blocked.txt、/srv/ret2shell/backend/deployments/0-init.yaml、/srv/ret2shell/backend/deployments/1-volumes.yaml、/srv/ret2shell/backend/deployments/7-platform.yaml 和 /var/cache/ret2shell/ret2boot。不要手动改这些文件来绕过 ret2boot;如需变更平台配置,应先调整 ret2boot 使用的安装配置,再通过 ret2boot 或 Helm 流程应用。
ret2boot sync 适合用于修正配置漂移、重新渲染网关配置和同步 ret2boot 记录的 Chart,不等同于升级到最新平台版本。需要拉取最新 Ret2Shell release 时,应使用 ret2boot update。
如果升级在 Helm 阶段失败,可以使用前面手动集群内部署流程中的 helm history 和 helm rollback 查看并回滚 release。如果失败发生在 Helm 升级前,先检查错误输出、GitHub 访问、gh auth 状态、Chart 缓存目录和 /etc/ret2shell/ret2boot.toml。
纯裸机部署
纯裸机部署由 systemd 管理平台服务和本机基础组件。升级时不要使用 Helm 或 ret2boot;应按系统服务边界分别处理平台二进制、前端静态文件、配置文件和基础组件。
升级前备份数据库、配置和平台数据:
sudo install -d -m 0750 -o ret2shell -g ret2shell /var/lib/ret2shell/backups
sudo -iu postgres pg_dump -Fc ret2shell > "/var/lib/ret2shell/backups/ret2shell.$(date +%F).dump"
sudo tar -C / -czf "/var/lib/ret2shell/backups/ret2shell-config.$(date +%F).tar.gz" etc/ret2shell
sudo tar -C /var/lib -czf "/var/lib/ret2shell/backups/ret2shell-data.$(date +%F).tar.gz" \
ret2shell/bucket \
ret2shell/media \
ret2shell/captures平台服务升级流程:
sudo systemctl stop ret2shell
sudo install -m 0755 r2s-server /usr/local/bin/r2s-server
sudo rsync -a --delete web/dist/ /usr/local/share/ret2shell/web/
sudo systemctl daemon-reload
sudo systemctl start ret2shell
sudo systemctl status ret2shell
journalctl -u ret2shell -f启动后检查健康状态:
curl -fsS http://127.0.0.1:8080/api/ping如果新版本需要新增配置字段,先更新 /etc/ret2shell/config.toml 和 /etc/ret2shell/sensitive_word_list.txt,再启动平台。r2s-server 启动时会执行数据库迁移;迁移完成后再开放流量。
裸机部署中的 PostgreSQL、Valkey、NATS、registry、VictoriaLogs 和 Nginx 应按各自软件的升级文档处理。小版本升级通常由系统包管理器完成,主版本升级前必须阅读对应组件的迁移说明,并准备独立回滚方案。平台二进制可以换回旧版本,但已经完成的数据库迁移不会自动回退。
需要回滚平台程序时,停止 ret2shell,恢复旧的 /usr/local/bin/r2s-server、/usr/local/share/ret2shell/web 和配置备份,再启动服务。只有确认数据库结构仍兼容旧版本时,才执行程序回滚。
Docker Compose 部署
Docker Compose 部署由 .env 和 docker-compose.yml 决定镜像版本。升级时不要使用 Helm 或 ret2boot;应先备份 Compose 配置、数据库和 volume,再拉取新镜像并重建相关服务。
升级前备份:
cd /opt/ret2shell
mkdir -p backups
docker compose exec -T database pg_dump -U ret2shell ret2shell > "backups/ret2shell.$(date +%F).sql"
tar -czf "backups/ret2shell-config.$(date +%F).tar.gz" .env docker-compose.yml config只升级平台服务时,修改 .env 中的 R2S_VERSION,然后执行:
docker compose pull platform
docker compose up -d platform gateway
docker compose ps
docker compose logs -f platform检查平台健康状态:
curl -fsS http://127.0.0.1/api/ping如果同时升级 Compose 中的 PostgreSQL、Valkey、NATS、registry 或 VictoriaLogs 镜像,先确认对应 volume 数据格式兼容,再执行:
docker compose pull
docker compose up -d
docker compose psCompose 回滚通常是把 .env 中的 R2S_VERSION 改回旧版本,再执行 docker compose pull platform && docker compose up -d platform gateway。如果升级已经执行数据库迁移,或基础组件已经写入新格式数据,必须先确认旧版本仍兼容,必要时从升级前备份恢复数据库和 volume。
滚动升级时可以先降低业务压力:暂停比赛开放、通知用户短暂维护、避免在提交高峰或大量选手启动环境时升级。平台单副本意味着它不是无感升级;需要多组件升级时,建议先升级可独立验证的可选组件,再升级平台服务,最后执行健康检查和业务检查。
Namespace 排查
排查服务器问题时,先分别查看 ret2shell-platform、ret2shell-challenge 和 kube-system。不要只看 Pod 状态,事件、PVC、Service、Ingress 和节点状态通常能更快指向根因。
平台 namespace:
kubectl -n ret2shell-platform get all -o wide
kubectl -n ret2shell-platform get ingress,pvc,configmap,secret,serviceaccount,role,rolebinding -o wide
kubectl -n ret2shell-platform describe pod <pod-name>
kubectl -n ret2shell-platform describe pvc <pvc-name>
kubectl -n ret2shell-platform get events --sort-by=.lastTimestamp题目 namespace:
kubectl -n ret2shell-challenge get pods,svc,networkpolicy -o wide --show-labels
kubectl -n ret2shell-challenge describe pod <pod-name>
kubectl -n ret2shell-challenge describe svc <service-name>
kubectl -n ret2shell-challenge get events --sort-by=.lastTimestamp系统 namespace:
kubectl -n kube-system get pods,svc,deploy,daemonset,configmap -o wide
kubectl -n kube-system describe pod <pod-name>
kubectl -n kube-system get events --sort-by=.lastTimestamp节点层面:
kubectl get nodes -o wide
kubectl describe node <node-name>
kubectl top node <node-name>
kubectl get pods -A -o wide --field-selector spec.nodeName=<node-name>常见判断:
| 现象 | 优先检查 |
|---|---|
| 平台 502 / 无法访问 | 平台 Pod、Ingress / NodePort、网关日志、/api/ping、数据库和缓存连接。 |
| 登录态异常 | ret2shell-platform 日志、Valkey 日志、auth.signingKey 是否变更、浏览器时间和域名 HTTPS 配置。 |
| 提交后长时间无结果 | NATS、平台 worker 日志、PostgreSQL、题目 checker 日志、提交相关 trace。 |
| 在线环境无法启动 | ret2shell-challenge 事件、Pod 状态、镜像拉取、节点资源、默认 node selector、registry 外部地址。 |
| 在线环境能启动但无法连接 | Service、traffic 脚本、网关映射、NodePort / Ingress、安全组、题目容器实际监听端口。 |
| 大量 Pod Pending | 节点 CPU/内存/临时存储不足、node selector 没有匹配节点、PVC 或网络插件异常。 |
| 大量 ImagePullBackOff | registry 地址、节点到 registry 网络、image pull secret、镜像 tag 是否存在。 |
选手环境问题排查
选手反馈线上环境问题时,先记录四类信息:
- 选手账号、用户 ID、队伍 ID。
- 比赛 ID、题目 ID、题目名称。
- 问题发生时间、前端报错、访问地址或 traffic token。
- 是否所有人都有问题,还是单个用户 / 单个队伍有问题。
用户 ID 可以从后台用户管理页查看。题目 ID 和比赛 ID 通常能从后台题目页面、URL、日志字段或提交记录中确认。找到 ID 后,按标签定位 Pod:
# 按用户定位
kubectl -n ret2shell-challenge get pods \
-l ret.sh.cn/user=<user_id> \
-o wide --show-labels
# 按题目定位
kubectl -n ret2shell-challenge get pods \
-l ret.sh.cn/challenge=<challenge_id> \
-o wide --show-labels
# 按题目 + 用户定位个人实例
kubectl -n ret2shell-challenge get pods \
-l ret.sh.cn/challenge=<challenge_id>,ret.sh.cn/user=<user_id> \
-o wide --show-labels
# 按题目 + 队伍定位团队实例
kubectl -n ret2shell-challenge get pods \
-l ret.sh.cn/challenge=<challenge_id>,ret.sh.cn/team=<team_id> \
-o wide --show-labels
# 如果拿到了 traffic token
kubectl -n ret2shell-challenge get pod,svc \
-l ret.sh.cn/traffic=<traffic_token> \
-o wide --show-labelsPod 名称形如 ret2shell-<challenge_id>-<user_id>-<timestamp>。Pod 和同名 Service 都带有 ret.sh.cn/* 标签;注解中保存了可读名称、端口和续期次数。
查看实例详情:
POD="<pod-name>"
kubectl -n ret2shell-challenge describe pod "$POD"
kubectl -n ret2shell-challenge get pod "$POD" -o jsonpath='{.metadata.labels}{"\n"}{.metadata.annotations}{"\n"}'
kubectl -n ret2shell-challenge get svc "$POD" -o yaml
kubectl -n ret2shell-challenge logs "$POD" --tail=200
kubectl -n ret2shell-challenge logs "$POD" --previous --tail=200多容器题目需要指定容器:
kubectl -n ret2shell-challenge get pod "$POD" -o jsonpath='{.spec.containers[*].name}{"\n"}'
kubectl -n ret2shell-challenge logs "$POD" -c <container-name> --tail=200需要进入容器时:
kubectl -n ret2shell-challenge exec -it "$POD" -c <container-name> -- sh如果镜像里没有 sh,应使用题目镜像提供的调试方式,或者重新构建带调试工具的临时镜像在测试环境复现。不要在生产题目 Pod 中安装软件或修改文件来“临时修好”,这些修改不会持久化,也会让后续判断变得不可靠。
按现象继续判断:
| 现象 | 排查方式 | 常见处理 |
|---|---|---|
| 找不到 Pod | 选手可能未启动实例、实例已过期、平台启动实例失败。 | 查 /admin/logs 中该账号和题目 ID 的日志,再让选手重新启动。 |
Pending | describe pod 看 Events。 | 补节点资源、修正 ret.sh.cn/workload 节点标签、调整题目资源限制。 |
ImagePullBackOff | 看 describe pod 中的拉取错误。 | 修正镜像 tag、registry 地址、节点访问权限或 image pull secret。 |
CrashLoopBackOff | 看 logs --previous。 | 修题目启动命令、环境变量、端口、内存限制或依赖文件。 |
Running 但连不上 | 查 Service、端口、traffic 脚本、网关和安全组。 | 确认题目进程监听 env.toml 配置端口,确认 traffic 返回地址可从公网访问。 |
| 只有外网访问失败 | 看 ret.sh.cn/internet 标签和网络策略。 | 如果题目配置为不联网,外网访问失败可能是预期行为;否则检查 NetworkPolicy 和节点出站策略。 |
| 只有某个节点上的实例失败 | kubectl describe node 和该节点上的系统 Pod。 | 临时把节点从题目调度范围移出,迁移或重启实例,再修节点网络、镜像缓存或磁盘问题。 |
平台日志中按账号或 trace 检索:
/admin/logs?account=<account>
/admin/logs?trace=<trace_id>也可以在 Kubernetes stdout 中按时间窗口查看:
kubectl -n ret2shell-platform logs statefulset/ret2shell-platform -c platform --since=30m处理选手实例时,优先使用平台页面或 API 停止、重启、续期实例。直接删除 Pod 只适合应急处理;如果手动删除,应同时确认同名 Service 是否已经清理,并在操作记录中写清楚原因、时间、Pod 名称和影响范围。
维护记录
每次生产维护建议记录以下内容:
| 项目 | 记录内容 |
|---|---|
| 时间窗口 | 开始时间、结束时间、是否影响比赛。 |
| 变更内容 | Chart 版本、镜像 tag、values diff、运行时配置变更。 |
| 备份 | 数据库备份文件、平台数据备份或存储快照编号。 |
| 验证 | helm status、rollout status、helm test、平台页面、在线环境启动测试。 |
| 回滚方案 | Helm revision、数据库恢复点、外部组件恢复方式。 |
