起因
早上起来,先看到的是一封欠费邮件。

当时直接懵了——明明建桶时领了三个资源包(外网下行流量 5GB、标准读写请求、标准存储 50GB),怎么还扣费?想不明白,就去群里问大佬。

大佬一眼看出问题:桶勾成了「多 AZ」模式,存储单价直接翻倍,资源包也覆盖不到这块。顺带把「挂载 + 静态站 + CDN」这套新架构也一并给了。
方案
照着他说的动手:
- 把旧桶迁到一个普通的单 AZ 标准桶;
- 用 rclone 挂到轻量云服务器上,nginx 当静态站;
- 前面套一层 EdgeOne。
域名还是 cos.yuyt.cn,博客里写死的图链一个都不用改。
整个过程比预想的折腾多了,卡住的地方大多不在迁移本身,而在各种边边角角。记下来,万一以后还要再搞一遍。
架构
三个角色各司其职:
- 轻量云服务器:跑 nginx 和 rclone mount,自身带宽小,只回源少数请求
- 对象存储 COS:放图,真正的存储
- EdgeOne:CDN 边缘缓存 + 源站代理
新旧链路对比:
旧:浏览器 → EdgeOne → 旧 COS 桶
新:浏览器 → EdgeOne → 轻量 nginx → rclone 挂载 → COS 标准桶
这套架构成立的前提有两个:
- rclone 挂载到 COS 这一段走同地域内网,不产生流量费,所以「挂载」这条路才划算;
- EdgeOne 命中缓存后基本不碰源站,轻量那点带宽只用来回源偶尔的 MISS。
另外,两个桶在同一个账号下,省掉了跨账号授权那一套。旧桶是多 AZ(贵),新桶换成标准的单 AZ,对象和路径保持一致,域名照旧。
子账号和最小权限
没用主账号的密钥,建了个 cos-mount 子账号,配一个只碰这两个桶的最小权限策略。
这里踩了第一个坑。
策略 JSON 里,动作要写成 name/cos:GetObject 这种带 name/ 前缀的写法,资源要写全六段式 qcs::cos:ap-beijing:uid/<APPID>:<bucket>。一开始照网上抄的不带前缀的写法,控制台的策略编辑器一直报错。
更坑的在后面。
我给策略加了 IP 条件,只允许轻量云服务器的公网 IP,结果 rclone 一跑就是 403 AccessDenied。查了半天才发现:轻量云服务器和 COS 同地域,cos.ap-beijing.myqcloud.com 在服务器上解析到的是内网网关 169.254.0.49,请求源 IP 是内网地址 10.x,压根不是公网 IP。把内网 IP 加进条件才通。
装 rclone:最磨人的一步
服务器出口带宽不算宽,光是把 rclone 下载下来就折腾了四轮:
- 官方安装脚本从 downloads.rclone.org 下,速度只有二三十 KB/s,下到一半还容易断;
- 换 GitHub 直连,直接挂死;
- 换 ghproxy 中转站,结果证书过期,得加
-k; - 好不容易下完了,
unzip一解压报「找不到 zipfile 目录」——文件是坏的。
最后老实了:
- 用
curl -C -断点续传加自动重试; - 下完先
unzip -t校验; - 校验过了才复制到
/usr/bin。
这么一套下来才算装好。
迁移和核对
迁移本身一条命令:
rclone copy tencentcos:旧桶 tencentcos:新桶 --checksum
同地域走内网,几十秒就跑完。收尾用 rclone check 核对:
rclone check tencentcos:旧桶 tencentcos:新桶 --fast-list
# 366 matching files, 0 differences
366 个对象、231MB,一个不差。
挂载和自启
用 systemd 起个服务,开机自启、崩了自动重挂:
ExecStart=/usr/bin/rclone mount tencentcos:新桶 /mnt/cosbed \
--vfs-cache-mode full --dir-cache-time 72h \
--allow-other --log-file /var/log/cosbed-rclone.log
nginx 和端口
服务器是 1Panel 搭的,OpenResty 跑在 Docker 里,80 和 443 都被它占了。宿主机上的 nginx 只能换个端口,用了 8088。
配置是一个只服务 cos.yuyt.cn 的 server,加 30 天缓存头和 CORS。
切 EdgeOne:两个小坑
EdgeOne 里把 cos.yuyt.cn 的源站从旧桶改成轻量云服务器:IP 源站、HTTP、端口 8088。
保存后一访问,522 连接超时。
排查一圈,是轻量云服务器的防火墙没放行 8088。加一条 TCP 8088 入站规则,立刻恢复。
缓存刷新也有讲究:目录清除的 URL 要写成 http://cos.yuyt.cn/*,不带 /* 会报格式错误。
最后把博客全站资源爬了一遍:555 个内网资源跑了两遍,全部 200,冷资源第一次 MISS、第二次 HIT,缓存正常。
PicGO 上传后 404
迁移完没两小时,就撞上新坑。
用 PicGO 往新桶传了张图,cos.yuyt.cn 预览直接 404。图明明已经进桶了,rclone lsf 也能列出来,nginx 就是回 404。

查下来,是 rclone 挂载的目录缓存在作祟。
挂载那会儿写了 --dir-cache-time 72h,目录列表 72 小时才刷一次,你从外面(PicGO)传进去的新文件,挂载根本不知道。nginx 一问,摇头,404。
解法是三步:
dir-cache-time从 72h 砍到 60s;- 重启 rclone 服务;
- 清一次 EdgeOne 缓存。
新图一分钟内就能访问了。代价是目录查询变勤了,图床这点量无所谓。
最后
等稳定几天,把旧桶删掉,子账号密钥也换掉。
这套东西其实不难,难的是那些边角料:IP 条件、下载超时、端口放行,每个都能耗掉你半天。
烦。