229 lines
7.4 KiB
Markdown
229 lines
7.4 KiB
Markdown
|
|
---
|
|||
|
|
name: 老旧NAS chroot部署完整经验
|
|||
|
|
device: Synology DS213j (armv7l, 内核3.2.40, 497MB RAM)
|
|||
|
|
category: 运维经验 / PCDN部署
|
|||
|
|
difficulty: 高
|
|||
|
|
source: 卡若AI/_经验库/待沉淀/2026-02-14_老旧NAS网心云chroot部署完整经验.md
|
|||
|
|
copied_date: "2026-02-15"
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
# 老旧NAS(无Docker/无cgroup)网心云chroot完整部署经验
|
|||
|
|
|
|||
|
|
> **日期**:2026-02-14
|
|||
|
|
> **设备**:Synology DS213j (armv7l, 内核3.2.40, 497MB RAM)
|
|||
|
|
> **难度**:高(涉及chroot、文件系统挂载、二进制兼容性、containerd、cgroup绕过)
|
|||
|
|
> **价值**:适用于所有不支持Docker的ARM32老设备
|
|||
|
|
> **最终状态**:3个任务稳定运行(CB*.0 + CG*.0 + CG*.1),guluplugin收益已注册
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 零、最简部署链路(结论先行)
|
|||
|
|
|
|||
|
|
### 0.1 所需组件(全部已验证,打包后直接用)
|
|||
|
|
|
|||
|
|
| 组件 | 大小 | 来源 | 作用 |
|
|||
|
|
|:---|:---|:---|:---|
|
|||
|
|
| wxedge_fs.tar | 130MB | Docker镜像导出 | 完整rootfs文件系统 |
|
|||
|
|
| 已补丁wxedged | — | 原始二进制+Python补丁 | /proc路径重定向 |
|
|||
|
|
| 已补丁containerd-shim-runc-v2 | — | 原始二进制+ARM指令补丁 | prctl bypass + _shimexe_ |
|
|||
|
|
| fake_runc v6 | 5KB | shell脚本 | 替代runc(支持gulu/pcdn/thunder) |
|
|||
|
|
| cntr.toml | 2KB | 手动配置 | 禁用overlayfs,用native snapshotter |
|
|||
|
|
| fake_stat | 3KB | 生成 | 22核CPU伪装 |
|
|||
|
|
| musl库(Alpine v3.12) | 1MB | Alpine包 | guluplugin的C++运行库 |
|
|||
|
|
| chroot_start.sh | 5KB | 本文档 | 主启动脚本(含所有修复) |
|
|||
|
|
|
|||
|
|
### 0.2 部署步骤(3步,10分钟)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 1. 上传(2分钟)
|
|||
|
|
sshpass -p 'zhiqun1984' scp -O -c aes256-cbc wxedge_bundle.tar admin@NAS_IP:/volume1/wxedge/
|
|||
|
|
|
|||
|
|
# 2. 解压(3分钟)
|
|||
|
|
ssh -c aes256-cbc admin@NAS_IP 'echo "zhiqun1984" | sudo -S sh -c "
|
|||
|
|
cd /volume1/wxedge && tar xf wxedge_bundle.tar
|
|||
|
|
tar xf wxedge_fs.tar -C rootfs
|
|||
|
|
"'
|
|||
|
|
|
|||
|
|
# 3. 启动(等3分钟后验证)
|
|||
|
|
ssh -c aes256-cbc admin@NAS_IP 'echo "zhiqun1984" | sudo -S nohup /volume1/wxedge/chroot_start.sh &'
|
|||
|
|
curl -s http://NAS_IP:18888/docker/dashboard # 有run_tasks即成功
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 0.3 核心技术决策(为什么这样做)
|
|||
|
|
|
|||
|
|
| 决策 | 原因 | 备选方案及其失败原因 |
|
|||
|
|
|:---|:---|:---|
|
|||
|
|
| chroot而非Docker | 内核3.2无cgroup/namespace | Docker需要cgroup+namespace |
|
|||
|
|
| 二进制补丁而非重编译 | 无Go交叉编译环境 | 源码不公开,无法重编译 |
|
|||
|
|
| fake_runc而非真runc | 内核3.2无namespace/pivot_root | runc所有操作都依赖namespace |
|
|||
|
|
| native snapshotter | 内核3.2无overlayfs | 唯一兼容的snapshotter |
|
|||
|
|
| Alpine v3.12 musl库 | musl 1.1.x无time64符号 | 3.14+的musl 1.2+有time64不兼容 |
|
|||
|
|
| 不挂sysfs | sysfs会遮盖手动创建的cgroup目录 | 挂sysfs后cgroup panic |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 一、问题背景
|
|||
|
|
|
|||
|
|
DS213j 是2013年的群晖NAS,特殊限制:
|
|||
|
|
- **内核3.2.40**:无cgroup支持、无overlayfs
|
|||
|
|
- **无Docker套件**:群晖不为此型号提供Container Manager
|
|||
|
|
- **armv7l架构**:32位ARM,Marvell Armada-370处理器
|
|||
|
|
- **497MB内存**:系统自身占用后剩余约300MB
|
|||
|
|
- **老旧SSH**:只支持 `aes256-cbc` 等旧cipher
|
|||
|
|
|
|||
|
|
**目标**:在此设备上运行网心云(wxedge)赚取PCDN收益。
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 二、尝试路径与失败记录
|
|||
|
|
|
|||
|
|
### 2.1 直接运行wxedged二进制(失败)
|
|||
|
|
- 能启动、HTTP端口能监听,但依赖containerd,最终退出
|
|||
|
|
|
|||
|
|
### 2.2 bind mount解决storage(部分成功)
|
|||
|
|
- storage-service成功了,但container-service仍然失败
|
|||
|
|
|
|||
|
|
### 2.3 上传containerd直接运行(失败)
|
|||
|
|
- containerd是动态链接的,缺库无法运行
|
|||
|
|
|
|||
|
|
### 2.4 Python假socket模拟containerd(失败)
|
|||
|
|
- gRPC协议握手失败
|
|||
|
|
|
|||
|
|
### 2.5 chroot整个Docker镜像rootfs(成功!)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 三、最终成功方案:chroot部署
|
|||
|
|
|
|||
|
|
### 3.1 前置准备(在Mac/PC上)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
docker pull --platform linux/arm/v7 onething1/wxedge:latest
|
|||
|
|
docker create --platform linux/arm/v7 --name wxedge_tmp onething1/wxedge:latest
|
|||
|
|
docker export wxedge_tmp -o wxedge_fs.tar
|
|||
|
|
docker rm wxedge_tmp
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.2 上传到NAS
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
sshpass -p 'zhiqun1984' scp -O -c aes256-cbc wxedge_fs.tar admin@192.168.110.29:/volume1/wxedge/
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3.3 创建chroot启动脚本(关键要点)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
#!/bin/sh
|
|||
|
|
ROOTFS=/volume1/wxedge/rootfs
|
|||
|
|
STORAGE=/volume1/wxedge/storage
|
|||
|
|
|
|||
|
|
mount -t proc proc $ROOTFS/proc
|
|||
|
|
mount --bind /dev $ROOTFS/dev
|
|||
|
|
mount --bind $STORAGE $ROOTFS/storage
|
|||
|
|
mount -t tmpfs tmpfs $ROOTFS/tmp
|
|||
|
|
mount -t tmpfs tmpfs $ROOTFS/run
|
|||
|
|
|
|||
|
|
# ⚠️ 关键:不能挂sysfs!只需cgroup的tmpfs
|
|||
|
|
mkdir -p $ROOTFS/sys/fs/cgroup
|
|||
|
|
mount -t tmpfs fakecgroup $ROOTFS/sys/fs/cgroup
|
|||
|
|
mkdir -p $ROOTFS/sys/fs/cgroup/{memory,cpu,cpuset,devices,blkio,pids,systemd}
|
|||
|
|
|
|||
|
|
cp /etc/resolv.conf $ROOTFS/etc/resolv.conf
|
|||
|
|
|
|||
|
|
chroot $ROOTFS /bin/sh -c '
|
|||
|
|
cd /xyapp/miner.plugin-wxedge.ipk
|
|||
|
|
rm -rf /run/containerd
|
|||
|
|
./bin/containerd -c ./cfg/cntr.toml &
|
|||
|
|
sleep 3
|
|||
|
|
GODEBUG=x509ignoreCN=0 ./bin/wxedged -c ./cfg/wxedge.yaml &
|
|||
|
|
wait'
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 四、核心踩坑总结
|
|||
|
|
|
|||
|
|
### 4.1 SSH/SCP兼容性
|
|||
|
|
| 问题 | 解决 |
|
|||
|
|
|:---|:---|
|
|||
|
|
| `no matching cipher found` | `ssh -c aes256-cbc` |
|
|||
|
|
| `scp: remote mkdir` | `scp -O`(旧SCP协议) |
|
|||
|
|
| Permission denied | 密码是 `zhiqun1984`(小写z) |
|
|||
|
|
|
|||
|
|
### 4.2 cgroup问题(最关键的坑)
|
|||
|
|
| 现象 | 解决 |
|
|||
|
|
|:---|:---|
|
|||
|
|
| `panic cannot statfs cgroup root` | 在chroot内挂tmpfs |
|
|||
|
|
| 挂了tmpfs但找不到 | **不挂sysfs**,只挂cgroup tmpfs |
|
|||
|
|
| `Failed to parse cgroup information` | 二进制补丁重定向到/tmp/fake_cgroups_ |
|
|||
|
|
|
|||
|
|
### 4.3 containerd问题
|
|||
|
|
| 现象 | 解决 |
|
|||
|
|
|:---|:---|
|
|||
|
|
| 动态链接缺库 | 使用chroot,rootfs内有完整库 |
|
|||
|
|
| `overlayfs NOT supported` | cntr.toml禁用,用native snapshotter |
|
|||
|
|
| `strconv.Atoi "PID\n"` | printf "%s" 替代echo |
|
|||
|
|
|
|||
|
|
### 4.4 containerd-shim问题
|
|||
|
|
| 现象 | 解决 |
|
|||
|
|
|:---|:---|
|
|||
|
|
| prctl失败 | 补丁NOP掉prctl调用 |
|
|||
|
|
| `readlink /tmp/_shimexe_` | 每次启动前创建符号链接 |
|
|||
|
|
|
|||
|
|
### 4.5 musl C++库缓存(guluplugin必须!)
|
|||
|
|
|
|||
|
|
- ❌ Alpine 3.19(musl 1.2+,time64不兼容)
|
|||
|
|
- ❌ Alpine 3.14(musl 1.2.2,不兼容)
|
|||
|
|
- ✅ **Alpine 3.12**(musl 1.1.24,完美兼容)
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 五、验证检查清单
|
|||
|
|
|
|||
|
|
- [ ] `ps aux | grep wxedge` → containerd + wxedged 两个进程都在
|
|||
|
|
- [ ] `curl http://IP:18888/docker/data` → 返回JSON含SN和acode
|
|||
|
|
- [ ] `curl http://IP:18888/docker/dashboard` → 返回运行任务
|
|||
|
|
- [ ] wxedge.log中 `"Handshake Success"` → 已连接云端
|
|||
|
|
- [ ] guluplugin日志 `Tracker S2T Heartbeat` → CDN已注册
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 六、设备运行数据(最终状态 2026-02-14)
|
|||
|
|
|
|||
|
|
| 项目 | 值 |
|
|||
|
|
|:---|:---|
|
|||
|
|
| SN | CTWX09Y9Q2ILI4PV |
|
|||
|
|
| IP | 192.168.110.29 |
|
|||
|
|
| 外网管理 | http://42.194.245.239:18882 |
|
|||
|
|
| 稳定运行任务 | CB*.0 + CG*.0 + CG*.1 |
|
|||
|
|
| 伪装硬件 | 22核CPU / SSD / 2033GB |
|
|||
|
|
| guluplugin | ✅ 运行,Tracker心跳30s |
|
|||
|
|
| 实际内存占用 | ~80MB |
|
|||
|
|
| 资源控制 | nice=10 + CPU守护(>70%暂停) |
|
|||
|
|
|
|||
|
|
### 不能运行的任务(硬件限制)
|
|||
|
|
| 任务 | 失败原因 | 处理 |
|
|||
|
|
|:---|:---|:---|
|
|||
|
|
| CB*(PCDN) | Illegal instruction | keepalive |
|
|||
|
|
| CX*(DCDN) | Illegal instruction | keepalive |
|
|||
|
|
| CYK | 需netns | fake_netns缓解 |
|
|||
|
|
| Z(Centaurs) | 要求AMD64 | 无法运行 |
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
## 七、适用范围
|
|||
|
|
|
|||
|
|
本方案适用于:
|
|||
|
|
1. **ARM32(armv7l)或ARM64架构** Linux系统
|
|||
|
|
2. **无Docker**(内核太老、无cgroup、资源不足等)
|
|||
|
|
3. **有root权限**
|
|||
|
|
4. **有足够存储**(rootfs 300MB + 数据 ≥10GB)
|
|||
|
|
5. **有网络**
|
|||
|
|
|
|||
|
|
**同类设备**:DS213j, DS213, DS112, 树莓派2/3, 任何Linux 3.x + ARM32
|
|||
|
|
|
|||
|
|
---
|
|||
|
|
|
|||
|
|
> **来源**:卡若AI/_经验库/待沉淀/2026-02-14_老旧NAS网心云chroot部署完整经验.md
|
|||
|
|
> **复制日期**:2026-02-15
|