# Gitea Actions Runner 磁盘满 → 在线扩容（growpart + resize2fs）

**日期**：2026-05-17
**触发**：PR #412 `quality-gates::build-check` 失败 2m53s（比正常 build 时间还短），本地 build 通过。诊断 runner 机磁盘 88% 撑爆 npm install/build cache。
**结论**：act_runner 在 `43.166.205.48`（独立机；非 Gitea web 同机）。云控扩容 + OS 内 `growpart` + `resize2fs` 在线生效，无需停机重启。

---

## 诊断路径

### 信号：本地 build 通过 + CI 失败比正常 build 时间短

CI 上 `quality-gates::build-check` 短时间内失败（2m53s，正常 6m+），**比 backend build 还快就 fail**。本地 `npm run build` 通过 → 不是代码问题。**资源问题**最可能（磁盘满 / OOM）。

### Step 1：找对 runner 机

项目是**双 runner 架构**（参见 `docs/ops/02-gitea-config.md`）：

- **主力 dedicated-runner-1**：`43.166.205.48` 独立机，4c16G，承担所有重型 job（build / next）
- **兜底 workspace-runner**：`43.130.59.228` 跟 Gitea 同机，`capacity=0` 常态不接活（1.9G OOM）

build-check 这种重型 job 一定跑在 dedicated-runner-1（`43.166.205.48`）。判断方式：

```bash
# 43.166.205.48（dedicated-runner-1，主力）：进程一定在跑
ssh ubuntu@43.166.205.48 'ps -ef | grep act_runner | grep -v grep'
# 输出 /usr/local/bin/act_runner daemon --config /etc/act_runner/config.yaml

# 43.130.59.228（workspace-runner，兜底）：capacity=0，几乎不接活
```

> 旧版 `docs/ops/01-server-infrastructure.md` 把"Gitea 主机 + Actions Runner"写在一起，
> 易误判 runner 只在 43.130.59.228。本 PR 已修正为双 runner 架构清单。

### Step 2：确认磁盘满 + 云端是否已扩

```bash
ssh ubuntu@43.166.205.48 'df -h /; lsblk'
```

关键模式 — 云控扩容已生效但 OS 内没 resize：

```
df -h /                lsblk
Filesystem  Size Use%   vda  91G   ← 物理盘已扩
/dev/vda2    50G  88%   └─vda2 50G ← 分区没跟上（差 41G 未用）
```

`vda` 大小 > `vda2` 大小 → 云端扩容已落地到 hypervisor，但 OS 内 partition table 还是旧的。

## 在线扩容（不停机不重启）

```bash
ssh ubuntu@43.166.205.48 << 'EOF'
sudo growpart /dev/vda 2      # 扩 GPT partition 表里的 vda2 到全盘
sudo resize2fs /dev/vda2      # 扩 ext4 文件系统（在线，mounted / 也行）
df -h /                        # 验证
EOF
```

实测输出（vda 50G → 91G）：

```
CHANGED: partition=2 start=4096 old: size=104853471 end=104857566
                                new: size=190836703 end=190840798
resize2fs 1.47.0 (5-Feb-2023)
Filesystem at /dev/vda2 is mounted on /; on-line resizing required
old_desc_blocks = 7, new_desc_blocks = 12
The filesystem on /dev/vda2 is now 23854587 (4k) blocks long.

Filesystem      Size  Used Avail Use% Mounted on
/dev/vda2        90G   42G   45G  48%  /     ← 50G→90G，使用率 88%→48%
```

整个流程 < 5 秒。

## 安全性

- `growpart`（cloud-utils 包，云镜像标配）：原子操作，**只改 GPT partition 表 end sector**，不动数据
- `resize2fs`：ext4 在线 resize **设计就支持 mounted /**，kernel 直接扩 metadata blocks
- act_runner 正在跑的 CI job **不受影响**（fs handle 一直可用）
- ⚠️ **xfs 不一样**：xfs 用 `xfs_growfs <mountpoint>`，不是 `resize2fs`

## 验证 CI 真的恢复

push 一个空 commit 触发 build：

```bash
git commit --allow-empty -m "ci: 验证 runner 扩容后 build"
git push
```

观察 `build-check` 时长：扩容前 **2m53s 失败** → 扩容后 **6m4s 成功**（这才是正常 nest+next build 时长）。

## 为什么 `echo 1 > /sys/.../rescan` 不工作

virtio_blk driver **不暴露** `device/rescan` 文件（只 SCSI/iSCSI 才有）。本机 `/sys/class/block/vda/device/` 下没有 `rescan`，写会 `Permission denied`（实际是 ENOENT 表现）。

云厂商 virtio 默认是 **hot-resize 透传**——hypervisor 端扩容后 guest kernel 立即看到新大小（`lsblk` 显示 91G），无需 rescan。OS 内只需做 partition + filesystem 两步。

## 何时再用

- CI runner build job 失败但本地通过 → 优先怀疑 runner 磁盘 / 内存
- 云控扩容后 `lsblk` 显示 vda > vda2 → 跑 growpart + resize2fs
- 同套流程适用于：app server / Gitea web / 任何 ext4 + virtio 的腾讯云/阿里云/AWS VM

## 反例

- ❌ 重启实例 —— 大锤，没必要，growpart 在线即可
- ❌ 卸载 /dev/vda2 后 resize —— root fs 卸不了，会失败
- ❌ 假设 runner 跟 Gitea 同机 —— 文档过期，实际拆开了

## 关联

- 同 PR 修正 `docs/ops/01-server-infrastructure.md` runner 真实 IP
- `docs/ops/02-ci-cd-architecture.md §9.1`「Gitea + act_runner 不要同机」拆机原因
- `.learnings/2026-05-10-gitea-1.26-upgrade-and-act-runner-compat-saga.md` 拆机时的事故记录
- PR #412 是触发本次诊断的具体 PR
