ci: harden production quality gates
ci / verify (pull_request) Failing after 4m18s
ci / verify (pull_request) Failing after 4m18s
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# ADR-001: 使用仓库级 Runner 和不可变镜像发布生产环境
|
||||
# ADR-001: 隔离质量 CI 与 root-owned 生产发布
|
||||
|
||||
## 状态
|
||||
|
||||
@@ -10,42 +10,59 @@ Accepted
|
||||
|
||||
## 背景
|
||||
|
||||
AI Gateway 已通过独立部署仓库和 Docker Compose 手工运行在 `110.42.51.33`,公共入口是 `https://ai.51easyai.com`。同一服务器还运行认证中心、K3s 和其他 EasyAI 服务,磁盘空间有限。Gitea 1.22 的 host Runner 已知不能可靠启动第二个依赖 Job,也不完整支持 GitHub Actions 的 `environment`、`permissions` 和 `concurrency` 语义。
|
||||
AI Gateway 已通过独立部署仓库和 Docker Compose 运行在 `110.42.51.33`,公共入口是 `https://ai.51easyai.com`。同一服务器还运行认证中心、K3s 和其他 EasyAI 服务,磁盘与信任边界都很紧张。Gitea 1.22 对依赖 Job、`environment`、`permissions` 和 `concurrency` 的支持也不能作为生产发布的安全边界。
|
||||
|
||||
生产发布必须满足:源码可追溯、数据库迁移前有备份、失败可恢复上一应用版本、Secret 不进入仓库或流水线日志,并且不能让普通分支自动修改生产环境。
|
||||
源码仓需要为 Pull Request、`main` 和版本 Tag 提供真实质量门禁;生产发布还必须满足源码可追溯、镜像不可变、数据库迁移前有备份、失败可恢复上一应用版本,以及 Tag 控制的脚本不能直接取得宿主 root 权限。
|
||||
|
||||
## 决策
|
||||
|
||||
- 为 `BCAI/easyai-ai-gateway` 注册独立、仓库级 host Runner。它不与认证中心 Runner 共享身份、状态目录或任务标签。
|
||||
- Pull Request 和 `main` Push 执行相同质量门禁与镜像构建;只有符合 `vMAJOR.MINOR.PATCH` 形式、且目标提交属于 `main` 历史的 Tag 才发布生产。
|
||||
- API/Web 镜像使用完整 Git SHA 作为运行时 Tag。语义版本 Tag 只是发布授权信号,不作为可变镜像标识。
|
||||
- 验证和发布处于同一个 Runner Job。这样部署只使用已通过全部门禁的同一 checkout,并规避当前 Gitea 版本的依赖 Job 领取问题。
|
||||
- Runner 使用专属 Buildx builder,缓存上限为 2 GB。服务器 root 现有的阿里云 Registry 凭据只由固定发布助手使用,不复制到 Gitea Secret。
|
||||
- 发布助手在迁移前生成 PostgreSQL custom-format 备份并验证目录;保留最近 5 份。应用健康检查失败时恢复上一组 API/Web 镜像。
|
||||
- 数据库迁移必须保持向后兼容。自动回滚只覆盖应用镜像;数据库恢复需要人工确认,避免覆盖失败发布后产生的有效写入。
|
||||
- Gitea Runner 的 Docker 权限等价于宿主机 root 权限。因此只允许受信任的仓库维护者触发该 Runner,来自 Fork 的 Pull Request 必须先经维护者批准。
|
||||
### 质量 CI
|
||||
|
||||
- `BCAI/easyai-ai-gateway` 使用仓库级 Runner 标签 `easyai-gateway-ci-unprivileged-v2`。PR 与 `main` 由 `ci.yml` 执行,context 分别为 `ci / verify (pull_request)`、`ci / verify (push)`;`v*` Tag 必须由独立 `release-ci.yml` 执行,context 为 `release-ci / verify-tag (push)`。两份 workflow 执行相同质量门禁,但 Tag 不复用 `main` 的旧 context。
|
||||
- Runner 外层固定为 `gitea/runner:2.0.0-dind-rootless` 的指定 digest;Job 固定为 `node:24.16.0-bookworm` 的指定 digest。外层按官方 rootless DinD 要求使用 `--privileged`,但内层 Docker daemon 和 Runner 以 UID 1000 运行。
|
||||
- 不把宿主或内层 Docker socket 挂入 Job。Runner 配置使用 `docker_host: "-"`、`privileged: false`,工作流唯一允许的 bind source 是只读 `/opt/easyai-gateway-ci`,其中提供固定 Go、Node、pnpm、ShellCheck、Compose、Trivy 和 govulncheck 工具链。ShellCheck 与 Compose 使用官方静态发行物和固定 SHA-256,不复制宿主的可变插件或在 Job 中临时安装。RootlessKit 强制 `--pidns`,即使 PR 传入 `--pid=host`,Job 也不能进入外层 Runner 的 PID namespace;provision 会实测 namespace inode。
|
||||
- CI 只执行格式、静态检查、单元测试、依赖审计、Compose 校验、仓库扫描和 CI 自测;不构建发布镜像,不调用 `sudo`,不执行生产发布助手。
|
||||
- 版本 Tag 必须是完整 SemVer,且目标提交必须属于 `main` 历史。该检查是发布前置证据,但本身不授予生产权限。
|
||||
- Runner 注册状态保存在专用 Docker named volume,首次注册 Token 只传给短命注册容器;长期 systemd 服务不保存 Token,也不加入宿主 `docker`/`sudo` 用户组。
|
||||
|
||||
### 生产 CD
|
||||
|
||||
- 生产发布由部署仓的 root-owned dispatcher 负责,和源码 CI Runner 分离。dispatcher 只接受受保护的 `main` 历史版本 Tag,并在对应源码 SHA 上同时等待 `ci / verify (push)` 与本次 Tag 新产生的 `release-ci / verify-tag (push)` 成功。
|
||||
- root 服务不执行 Tag 控制的 `pnpm`、测试脚本、源码仓 shell 脚本或应用程序。它只调用部署仓中由 root 固定和审核的命令,通过 BuildKit 构建目标镜像、用 Trivy 扫描镜像、发布 Registry digest,再进行备份、迁移、健康检查和回滚。
|
||||
- API/Web 镜像以完整 Git SHA 作为可追溯 Tag,但生产 Compose 使用 Registry digest。服务器为每个 Git SHA 保存 root-only digest 清单,并拒绝把未知的既有 SHA Tag 当作可信发布物。
|
||||
- 发布助手在迁移前生成并验证 PostgreSQL custom-format 备份,保留最近 5 份。应用健康检查失败时恢复上一组 digest-pinned 镜像;数据库恢复仍需人工确认。
|
||||
|
||||
### 残余风险与触发策略
|
||||
|
||||
rootless DinD 显著缩小了 Job 到宿主 Docker/root 的直接通路,但不是虚拟机级隔离。外层容器仍需 `--privileged`;Runner、rootless Docker、内核或容器运行时漏洞,以及 Gitea 对 `jobs.<job>.container.options` 的透传,都可能造成容器边界突破。Job 还保留依赖安装所需的出站网络,并可能消耗共享主机的 CPU、内存和磁盘。因此:
|
||||
|
||||
- 来自同仓受信任分支的 PR 可自动运行;来自 Fork 的 PR 必须先由维护者检查工作流变更并在 Gitea 中批准,不能自动调度。
|
||||
- CI Job 不接收生产 Secret、宿主 Docker socket、部署目录或 Runner 状态目录。
|
||||
- Runner 容量固定为 1,外层容器设 4096 PID 上限;磁盘在安装前后硬门禁,但共享主机仍不具备完整的 CPU、内存和长期磁盘配额隔离。
|
||||
- 中长期应把不受信任 PR CI 迁移到独立主机或虚拟机;当前 rootless Runner 不能被描述为强多租户沙箱。
|
||||
- Ubuntu 22.04 没有受限 user namespace,生产主机缺少 `rootlesskit` AppArmor profile 时不硬编码该 profile。provision 会先探测;在启用了 `kernel.apparmor_restrict_unprivileged_userns=1` 的新系统上,如果 profile 缺失则失败,不会降级为 `apparmor=unconfined` 或关闭内核限制。
|
||||
|
||||
## 备选方案
|
||||
|
||||
### 复用认证中心 Runner
|
||||
### 让源码 Runner 直接挂载宿主 Docker socket
|
||||
|
||||
拒绝。现有 Runner 是认证中心仓库级身份,扩大为组织级 Runner 会让更多仓库获得同一 Docker/root 信任边界。
|
||||
拒绝。Docker socket 等价于宿主 root,任何 PR 工作流都可能取得生产服务器控制权,Fork 审批也不能把它变成可靠的技术隔离。
|
||||
|
||||
### 由 Runner 保存 SSH 或 Registry Secret
|
||||
### 使用 host executor 但移除 Docker 组
|
||||
|
||||
拒绝。Runner 已位于目标服务器,绕回 SSH 会增加长期凭据;复制 Registry Secret 也会扩大暴露面。固定 root helper 可以复用服务器现有登录状态。
|
||||
拒绝。host Job 仍可读取宿主可见文件、消耗宿主资源并攻击同一用户进程;Gitea 对容器选项的处理也无法为 host executor 提供隔离。
|
||||
|
||||
### `main` 通过后直接发布生产
|
||||
### 让 Tag 工作流通过 `sudo` 调用发布脚本
|
||||
|
||||
拒绝。`ai.51easyai.com` 是生产入口。语义版本 Tag 提供明确的发布授权点,同时仍保留自动化与可审计性。
|
||||
拒绝。Tag 可以控制 checkout 中的脚本和应用代码;root 服务不得执行这些内容。固定部署仓 dispatcher 是独立的受保护信任根。
|
||||
|
||||
### 只依赖 `latest`
|
||||
### `main` 通过后立即发布或只依赖 `latest`
|
||||
|
||||
拒绝。`latest` 无法证明运行中的容器对应哪个源码提交,也不能可靠选择回滚版本。
|
||||
拒绝。语义版本 Tag 是明确的发布授权点;digest 才能证明运行中的容器对应不可变产物并可靠选择回滚版本。
|
||||
|
||||
## 影响
|
||||
|
||||
- 日常合并不会自动改变生产;创建并推送版本 Tag 才会部署。
|
||||
- 首次启用 CD 时需要在服务器捕获当前运行镜像作为 bootstrap 回滚基线。
|
||||
- 发布前必须确保数据库迁移对上一应用版本保持兼容。
|
||||
- 如果未来增加不受信任的贡献者,应把 CI 构建迁移到隔离的 rootless Runner,并保留独立的受保护部署 Runner。
|
||||
- PR、`main` 和版本 Tag 都有自动质量证据,但源码仓 CI 成功不会单独获得生产权限。
|
||||
- 创建受保护版本 Tag 后,部署仓 dispatcher 必须同时取得同 SHA 的 `main` context 和独立 Tag context,不能把旧 `main` 成功状态误当作本次 Tag 验证。
|
||||
- 首次安装会清理本项目专属 Buildx 缓存并执行 8 GiB 前置、4 GiB 后置磁盘门禁,不会全局 prune 共享 Docker 状态。
|
||||
- 首次启用 CD 仍需捕获当前运行镜像作为 bootstrap 回滚基线,并保证数据库迁移对上一应用版本向后兼容。
|
||||
|
||||
@@ -1,42 +1,102 @@
|
||||
# 生产 CI/CD 运行手册
|
||||
|
||||
## 流水线约定
|
||||
## 信任边界与固定资源
|
||||
|
||||
- Runner:`easyai-gateway-act-runner.service`
|
||||
- Runner 标签:`easyai-gateway-linux:host`
|
||||
- Runner 状态:`/var/lib/easyai-gateway-runner`
|
||||
- 工具链:`/opt/easyai-gateway-ci`
|
||||
- Gitea:`https://git.51easyai.com/BCAI/easyai-ai-gateway`
|
||||
- 源码仓:`https://git.51easyai.com/BCAI/easyai-ai-gateway`
|
||||
- CI Runner:`easyai-gateway-ci-v2-runner.service`
|
||||
- CI 标签:`easyai-gateway-ci-unprivileged-v2`
|
||||
- Runner 状态:Docker named volume `easyai-gateway-ci-v2-data` 内的 `/data/.runner`
|
||||
- 只读工具链:`/opt/easyai-gateway-ci`
|
||||
- Runner 配置:`/etc/easyai-gateway-ci-v2/config.yaml`
|
||||
- Runner 运行参数:`/etc/easyai-gateway-ci-v2/runner.env`
|
||||
- 生产入口:`https://ai.51easyai.com`
|
||||
- 部署目录:`/root/easyai-ai-gateway-deploy`
|
||||
|
||||
PR、`main` Push 和版本 Tag 都会执行格式、Go vet/test、govulncheck、前端 lint/test/build、依赖审计、Compose 校验、Trivy 扫描与 API/Web 镜像构建。只有版本 Tag 会执行最后的生产发布步骤。
|
||||
源码仓只执行质量 CI:PR context 是 `ci / verify (pull_request)`,`main` context 是 `ci / verify (push)`,版本 Tag 使用独立 workflow/context `release-ci / verify-tag (push)`。三者都执行 Go 格式/vet/test/govulncheck、前端 lint/test/build、依赖审计、Compose 校验、Trivy 仓库扫描和 CI 脚本自测。Job 没有 Docker socket、`sudo` 或部署目录权限,也不构建发布镜像。
|
||||
|
||||
## 首次安装或修复 Runner
|
||||
生产 CD 由部署仓的 root-owned dispatcher 执行。它在相同源码 SHA 上同时等待 `ci / verify (push)` 与本次新产生的 `release-ci / verify-tag (push)` 成功,然后只运行部署仓中固定的 BuildKit 构建、Trivy 镜像扫描、digest 发布、备份、迁移、健康检查和回滚命令;不得执行 Tag checkout 中的 `pnpm`、测试、shell 脚本或应用程序。
|
||||
|
||||
从 Gitea 仓库设置的 Actions Runner 页面取得一次性仓库注册 Token,在服务器可信 checkout 中执行:
|
||||
provision 安装 checksum-pinned 的官方静态 ShellCheck `0.11.0` 和 Docker Compose `5.3.1`,不会依赖宿主是否预装这些命令。所有下载都在使用前校验固定 SHA-256,并在精确 Node Job 镜像内实际执行版本检查。
|
||||
|
||||
## 首次安装或修复 CI Runner
|
||||
|
||||
前置条件:Linux x86_64、可用 Docker Engine、root 权限,以及 Docker 文件系统至少 8 GiB 可用空间。脚本只压缩本项目专属 `easyai-gateway-ci` Buildx 缓存,不运行全局 `docker system prune`,因为该服务器与其他服务共享 Docker 状态。
|
||||
|
||||
从 Gitea 仓库设置的 Actions Runner 页面取得一次性仓库注册 Token,在服务器可信的源码 checkout 中执行:
|
||||
|
||||
```bash
|
||||
RUNNER_REGISTRATION_TOKEN='<一次性 Token>' ./scripts/provision-ci-runner.sh
|
||||
```
|
||||
|
||||
Token 只通过进程环境传入。生成的 `/var/lib/easyai-gateway-runner/.runner` 必须保持 `0600`,不得复制到仓库、报告或聊天记录。
|
||||
|
||||
验证:
|
||||
已有有效 named volume 时可直接重跑,不再需要 Token:
|
||||
|
||||
```bash
|
||||
systemctl is-active easyai-gateway-act-runner.service
|
||||
systemctl is-enabled easyai-gateway-act-runner.service
|
||||
journalctl -u easyai-gateway-act-runner.service --since '15 minutes ago'
|
||||
./scripts/provision-ci-runner.sh
|
||||
```
|
||||
|
||||
Runner 使用 `daemon --once`。每个 Job 结束后进程自然退出,再由 systemd 启动新的长轮询进程。
|
||||
注册 Token 通过交互 stdin 送给短命注册容器,不出现在宿主或容器的命令行参数中;provision 随后立即从环境中清除它,长期 systemd unit 也不包含 Token。不要输出或复制 `/data/.runner` 内容。脚本会停用旧 host Runner,并确保旧 Runner 用户和 v2 遗留用户不属于 `docker`/`sudo` 组。
|
||||
|
||||
默认磁盘门禁可用环境变量提高,但生产环境不应降低:
|
||||
|
||||
```bash
|
||||
CI_RUNNER_MIN_FREE_GIB=8 \
|
||||
CI_RUNNER_MIN_POST_INSTALL_FREE_GIB=4 \
|
||||
RUNNER_REGISTRATION_TOKEN='<一次性 Token>' \
|
||||
./scripts/provision-ci-runner.sh
|
||||
```
|
||||
|
||||
## AppArmor 分支
|
||||
|
||||
Ubuntu 22.04 默认没有 `kernel.apparmor_restrict_unprivileged_userns` 限制,当前服务器没有 `rootlesskit` profile 是受支持路径。provision 会实测 Docker 是否接受该 profile;不存在时写入:
|
||||
|
||||
```text
|
||||
RUNNER_SECURITY_OPTIONS=""
|
||||
```
|
||||
|
||||
如果新系统的 `/proc/sys/kernel/apparmor_restrict_unprivileged_userns` 为 `1`,则必须先由宿主发行版或 Docker 安装包提供并加载 `rootlesskit` profile;provision 只探测和使用,不会自行复制一份 profile。缺失时 provision 会停止;不得手工关闭该 sysctl,也不得使用 `apparmor=unconfined` 绕过。
|
||||
|
||||
参考:[Docker Rootless Docker-in-Docker](https://docs.docker.com/engine/security/rootless/tips/#rootless-docker-in-docker)、[Ubuntu 安全特性版本矩阵](https://documentation.ubuntu.com/security/security-features/security-features-overview/)。
|
||||
|
||||
## Runner 真实验证
|
||||
|
||||
安装脚本会先启动一个无 Token、无持久 Runner 状态挂载、无宿主 bind mount 的短命 rootless DinD probe;随后启动长期服务,确认 Runner 已向 Gitea declare、通过内层 `docker info` 验证 `name=rootless`,再从内层 daemon 拉取固定 digest 的 Job 镜像,并在该镜像中实际运行全部工具。人工复核:
|
||||
|
||||
```bash
|
||||
systemctl is-active easyai-gateway-ci-v2-runner.service
|
||||
systemctl is-enabled easyai-gateway-ci-v2-runner.service
|
||||
systemctl cat easyai-gateway-ci-v2-runner.service
|
||||
journalctl -u easyai-gateway-ci-v2-runner.service --since '15 minutes ago' --no-pager
|
||||
|
||||
docker inspect -f 'user={{.Config.User}} privileged={{.HostConfig.Privileged}} apparmor={{.AppArmorProfile}}' \
|
||||
easyai-gateway-ci-v2-runner
|
||||
docker inspect -f '{{range .Mounts}}{{println .Source " -> " .Destination .Mode}}{{end}}' \
|
||||
easyai-gateway-ci-v2-runner
|
||||
docker exec easyai-gateway-ci-v2-runner docker info \
|
||||
--format '{{range .SecurityOptions}}{{println .}}{{end}}'
|
||||
docker exec easyai-gateway-ci-v2-runner docker image inspect \
|
||||
'docker.io/library/node:24.16.0-bookworm@sha256:40ad9f3064e67d6860b4bc3fe1880b2953934fd6320ada990e45fe0efa6badd7' \
|
||||
--format '{{.Id}}'
|
||||
```
|
||||
|
||||
预期:外层 image user 为 `rootless`、外层因 DinD 为 `privileged=true`、内层安全选项含 `name=rootless`;RootlessKit 使用独立 PID namespace,内层 `--pid=host` 也不能看到外层 Runner;挂载仅包含专用 `/data`、只读配置和只读工具链,不能出现 `/var/run/docker.sock` 或 `/run/docker.sock`。
|
||||
|
||||
在 Gitea 中分别验证:
|
||||
|
||||
1. 同仓 PR 的 `ci / verify (pull_request)` 成功。
|
||||
2. `main` Push 的 `ci / verify (push)` 成功。
|
||||
3. 合法 SemVer Tag 新产生独立 `release-ci / verify-tag (push)`;非法或不属于 `main` 历史的 Tag 失败,且 Tag context 不能被旧 `main` context 替代。
|
||||
4. Fork PR 默认不自动调度,维护者先检查 `.gitea/workflows/**` 和容器选项后再批准。
|
||||
|
||||
## Fork PR 残余风险
|
||||
|
||||
rootless DinD 不是 VM 沙箱。外层仍按官方要求使用 `--privileged`,Gitea runner 也会解析 PR 控制的 `jobs.<job>.container.options`。配置已禁止 Job privileged、宿主/内层 Docker socket 和任意 bind source,但 Runner、rootless Docker、容器运行时或内核漏洞仍可能突破边界;Job 的出站网络和资源消耗也不是强租户隔离。因此 Fork PR 必须维护者批准,CI 不得注入生产 Secret;未来应迁移到独立 CI 主机或虚拟机。
|
||||
|
||||
## 发布生产版本
|
||||
|
||||
1. 合并到 `main`,等待 `ci / verify (push)` 成功。
|
||||
2. 在已验证的 `main` 提交上创建语义版本 Tag。
|
||||
3. 推送 Tag,等待同一 CI Job 完成镜像扫描、发布、数据库备份、迁移和公共健康检查。
|
||||
1. 合并到受保护 `main`,确认源码 CI 成功。
|
||||
2. 在已验证提交上创建完整 SemVer Tag 并推送。
|
||||
3. 确认同一 SHA 的 `ci / verify (push)` 和本次 `release-ci / verify-tag (push)` 都成功。
|
||||
4. 由部署仓 root-owned dispatcher 构建、扫描并发布 digest;源码仓工作流不会直接调用生产 helper。
|
||||
|
||||
```bash
|
||||
git switch main
|
||||
@@ -45,7 +105,7 @@ git tag -a v0.1.1 -m 'release: v0.1.1'
|
||||
git push origin v0.1.1
|
||||
```
|
||||
|
||||
流水线会部署 Tag 指向提交的完整 Git SHA,而不是 `latest` 或版本号镜像。
|
||||
dispatcher 以完整 Git SHA 发布 Registry Tag,并把 Registry 返回的 digest 写入服务器 root-only 发布清单。生产 Compose 使用 `repository@sha256:...`,不是 `latest`、版本号或可变 SHA Tag。
|
||||
|
||||
## 发布后验证
|
||||
|
||||
@@ -57,34 +117,32 @@ ssh root@110.42.51.33 'cd /root/easyai-ai-gateway-deploy && ./gateway-ops.sh ps'
|
||||
|
||||
同时检查服务器磁盘、API 日志和数据库容器健康状态。发布后的首小时如出现错误率翻倍、P95 延迟增加 50%、数据完整性或安全问题,应立即回滚。
|
||||
|
||||
## 应用回滚
|
||||
## 应用与数据库回滚
|
||||
|
||||
发布失败时脚本会自动恢复 `.release.env` 中的上一组 API/Web 镜像并重复健康检查。人工回滚到一个仍存在于本机或 Registry 的历史 Git SHA:
|
||||
发布失败时固定部署脚本会恢复上一组 API/Web digest 并重复健康检查。人工回滚只选择服务器已有 root-only 发布清单的历史 Git SHA:
|
||||
|
||||
```bash
|
||||
sudo /usr/local/sbin/easyai-ai-gateway-release <40 位历史 Git SHA>
|
||||
```
|
||||
|
||||
该操作也会先创建数据库备份。不要把 `latest`、分支名或版本号传给发布助手。
|
||||
|
||||
## 数据库恢复
|
||||
|
||||
备份位于 `/var/backups/easyai-ai-gateway`,默认只保留最近 5 份。应用回滚不会自动恢复数据库。只有确认需要回退数据且已经停止写入后,才能由操作员选择备份执行 `pg_restore`;恢复前必须再保留当前数据库副本。
|
||||
没有 `/root/easyai-ai-gateway-deploy/.releases/<SHA>.env` 的远端 SHA Tag 不应被盲目信任。数据库备份位于 `/var/backups/easyai-ai-gateway`,只保留最近 5 份。应用回滚不会自动恢复数据库;只有停止写入并再次保留当前副本后,操作员才能选择备份执行 `pg_restore`。
|
||||
|
||||
## Runner 故障恢复
|
||||
|
||||
重启前先确认没有构建、扫描或部署子进程:
|
||||
先在 Gitea 确认没有运行中的 Job,再检查服务与两个 daemon:
|
||||
|
||||
```bash
|
||||
ps -u easyai-gateway-runner -o pid,ppid,etime,cmd --forest
|
||||
systemctl status easyai-gateway-act-runner.service --no-pager
|
||||
systemctl status easyai-gateway-ci-v2-runner.service --no-pager
|
||||
docker logs --tail 100 easyai-gateway-ci-v2-runner
|
||||
docker exec easyai-gateway-ci-v2-runner docker info
|
||||
df -h /var/lib/docker
|
||||
```
|
||||
|
||||
确认空闲后才执行:
|
||||
|
||||
```bash
|
||||
systemctl restart easyai-gateway-act-runner.service
|
||||
journalctl -u easyai-gateway-act-runner.service -n 50 --no-pager
|
||||
systemctl restart easyai-gateway-ci-v2-runner.service
|
||||
journalctl -u easyai-gateway-ci-v2-runner.service -n 100 --no-pager
|
||||
```
|
||||
|
||||
不要因为日志暂时没有新增就用定时器重启 Runner;镜像构建和扫描可长时间无输出。
|
||||
不要删除 `easyai-gateway-ci-v2-data` volume;它包含 Runner 注册状态和内层 daemon 缓存。不得用全局 prune 处理磁盘压力。
|
||||
|
||||
Reference in New Issue
Block a user