我把OBS静态站点做挂了两次

举报
yd_272744321 发表于 2026/11/08 10:30:27 2026/11/08
【摘要】 我把团队文档站从Nginx迁到华为云OBS静态托管,三周内连踩权限、生命周期、跨区复制三个坑。这里是我的故障记录:真实报错、命令、配置片段、恢复耗时和费用变化,以及我后来改过的发布脚本。

迁移和两次故障

6 月 11 日我把组内文档站从 ECS 挪到 OBS 静态网站托管。原机器是 c7.large.2,2 vCPU、4 GiB 内存、40 GiB 系统盘,Ubuntu 22.04.4 + Nginx 1.24.0。Nginx 里我当时写了两条缓存规则,/assets/ 走 Cache-Control: public,max-age=31536000,immutable,/index.html 走 no-cache。月账单稳定在 126.4 元。迁移前一周我导了 access.log,日均 PV 2.7 万,峰值 39 req/s,静态资源占比 96.3%。构建还在 CodeArts 跑,Runner 2 核 4G,Node v18.19.1、pnpm 8.15.5,单次构建 74 秒,产物 312 MB,文件 11342 个。

我一开始把事情想简单了。

迁移当天我只做了开桶、开静态网站、绑 CNAME、全量上传四件事,obsutil 版本 5.5.12,命令和我终端历史一致。

obsutil mb obs://team-doc-prod -location=cn-north-4 -storageClass=STANDARD
obsutil setbucketwebsite obs://team-doc-prod -indexDocument index.html -errorDocument 404.html
obsutil cp ./dist obs://team-doc-prod/ -r -f -u -j=8
nslookup docs.example.com 223.5.5.5

DNS 这块我把 TTL 设成 60 秒,09:17 改记录,09:21 公网递归 DNS 已经返回网站端点。上线后第 2 天,6 月 13 日 09:42,我在控制台把桶 ACL 从 public-read 改成 private,想把权限统一收敛到策略层。09:45 值班群开始报白屏,Chrome Network 全是 403,首个报错资源是 app.5c9e2d7.js,状态码 403,耗时 37ms。

<Code>AccessDenied</Code> <Message>Access denied.</Message> <RequestId>00000190c43c6f7f40a8de4a1c9f1b2a</RequestId> <HostId>K4b3...q9==</HostId>

这个锅就是我自己背的。

我当时先做了个错误操作,我以为上传断了,09:49 重新跑全量上传,命令还是 obsutil cp ./dist ... -r -f -u。传输日志里写着 Succeed:11342 Fail:0 TotalSize:327489120B,耗时 8 分 31 秒。结果页面依旧 403。现在回头看,这一步属于脑子短路,因为返回 403 明显是授权链路,不是对象缺失。

09:58 我才老实去看桶策略 JSON,问题在 Resource 只写了桶 ARN,漏了对象通配。错的版本是 arn:aws:s3:::team-doc-prod,对的网站端点只能访问桶级别动作,拿不到对象。我改成 arn:aws:s3:::team-doc-prod/* 并保存,10:02 生效。10:04 我本地执行 curl -I https://docs.example.com/assets/app.5c9e2d7.js,响应从 403 变成 200,Content-Length: 412873。这次故障窗口是 19 分钟。

第二次故障是 7 月初我自己挖的坑。我加了生命周期,目标是清理旧资源省存储费,规则写成 assets/ 前缀对象 30 天删除。这里我漏看了一个前提,当时桶没开版本控制。7 月 10 日 10:12,线上引用的一批 hash 文件刚好到期被删,首页能开,点任意菜单就挂,Sentry 在 4 分钟里收了 713 条 404。

GET https://docs.example.com/assets/app.7f3d1a4.js 404 (Not Found)

10:16 我做了第一次回滚,切到前一天 commit 9d2c1a7 重新构建并上传,10:24 上传完成,页面还是 404。这个尝试完全失败,因为被删的是历史 hash 文件,回滚产物里没有那批对象。10:28 我又把生命周期规则改成 Disabled,以为停规则后会“恢复”,这也不成立,删除动作已经落盘,不可逆。

{
  "Rules": [{
    "ID": "clean-assets",
    "Prefix": "assets/",
    "Status": "Enabled",
    "Expiration": {"Days": 30}
  }]
}

10:33 我从 CodeArts 拉最近 15 天构建产物,API 分页 6 次,下载了 15 个 dist 包共 4.6 GB。然后写了个临时脚本按 release-manifest.json 补传缺失对象,脚本先比对 md5,再对不存在对象调用 obsutil cp。缺失 286 个文件,主要是 js.map 和字体,补传耗时 21 分钟。10:59 页面恢复,总耗时 47 分钟。返工时我把版本控制打开,生命周期改成“只清理非当前版本,保留 15 天”,当前版本不删,存储费多一点我能接受。

跨区复制、发布脚本和还没收口的问题

灾备桶在 cn-east-3,我配了 CRR。刚开的时候我按小流量经验估 1 到 2 分钟可追平,真实数据差很多。11k 文件发布后,复制完成时间在 6 到 18 分钟波动,最大一次 23 分钟。2026-08-14 15:00 到 17:10 我做切换演练,15:36 切 CNAME 到灾备网站端点,拿到的是上一个版本 index.html。现场统计是主桶 11409 对象,灾备 11276,少 133;release-manifest 对比 md5 不一致 41 项。

这个坑我连踩两次。

我那天还做过一次失败尝试,15:41 直接把 DNS 再切回主站,想先止血,结果部分运营同事本地缓存还指向灾备,反馈页面一会儿新一会儿旧。15:48 我临时跑 obsutil sync obs://team-doc-prod obs://team-doc-dr -u -f -j=20,并发开太高触发了两次 503 SlowDown,日志里有 ErrorCode: ServiceUnavailable,我改成 -j=8 才稳定,16:02 才追平。

发布脚本后来我重写了,不再全量覆盖,也不再先传根目录。现在顺序是先上传 releases/${RELEASE}/,校验 manifest,再单独切根目录 index.html 和 release-manifest.json,任何一步非 0 就退出,避免半发布。

set -euo pipefail
RELEASE=$(git rev-parse --short HEAD)
pnpm build
python3 ./scripts/make_manifest.py --dir ./dist --out ./dist/release-manifest.json
obsutil cp ./dist obs://team-doc-prod/releases/${RELEASE}/ -r -u
python3 ./scripts/check_manifest.py --src ./dist/release-manifest.json --dst obs://team-doc-prod/releases/${RELEASE}/release-manifest.json
obsutil cp ./dist/index.html obs://team-doc-prod/index.html -f
obsutil cp ./dist/release-manifest.json obs://team-doc-prod/release-manifest.json -f

改完后发布窗口从 9 分钟降到 3 分 40 秒。7 月我因为频繁全量上传,PUT/COPY 186 万次,费用 14.88 元;8 月改增量后 42 万次,3.36 元。8 月整站 OBS 账单 19.7 元,存储 1.6 元、GET 6.9 元、跨区复制流量 6.8 元,其它请求项 4.4 元。省的钱很直观,但我在规则校验、切换演练、回滚演练上投入了 11.5 小时。

现在还没收口的是缓存混搭,浏览器偶尔把旧 index.html 留 5 到 10 分钟,用户会拿到新旧资源拼在一起的页面。下周我准备先把 index.html 强制成 Cache-Control: no-store,assets 保持 immutable,max-age=31536000,连续跑 7 天观察 404 比例、白屏率和回滚成功率,再决定要不要把切流窗口固定到 23:00 以后。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。