【工具治理】Nginx换机丢16子域事故复盘

这是一篇基于你提供的文档内容整理而成的技术博客文章。文章采用了"事故复盘 + 解决方案 + 实战脚本"的结构,适合发布在技术社区、团队内部知识库或个人博客上。


Nginx 换机丢了 16 个子域:掉线 16.5 小时换来的配置迁移清单

摘要 :一次看似平稳的 Nginx 服务器切换,结果丢了 16 个子域的 vhost 配置,业务掉线 16.5 小时才被发现。复盘发现两个环节同时失守:切换前没有做 server_name 全量比对,切换后的探活只 ping 了 IP、只看了状态码,没有看内容。本文给出一份可直接落地的配置迁移清单和两个脚本,希望能帮你避开同样的坑。

一、事故回顾:切换当天全绿,掉线隔天才冒头

起因很普通:老服务器要下线,新服务器装好 Nginx、迁配置、测主站、切 DNS。验收时主站正常、探活正常,所有人都认为切换完成。

问题出在那些"被遗忘的角落":

老机器上除了主站,还躺着 16 个子域的 vhost 。这些是多年间陆续加上的内部系统、测试环境或旧项目入口。这批配置散落在老的 server 块里,迁移时大家只搬了「主配置文件」,没人做过一次「新旧 Nginx 一共有哪些 server_name」的比对。

更糟的是探活设计的缺陷:

监控目标仅指向主站 URL,返回 200 即判成功;ICMP ping 新机器也通。于是,掉线的 16 个子域在监控大屏上完全隐形 。直到有用户反馈「某个系统打不开了」,距离切换已经过去 16.5 小时。

二、根因分析:两个致命的隐含假设

事后复盘,这次事故由两个隐含假设叠加造成:

  1. 假设一:「配置 = 那几个 conf 文件」
    • 真相 :Nginx 的生效配置是主配置加所有 include 文件的并集,往往散落各处。只凭「文件都拷了」来判断迁移完整,等于凭记忆验收。
  2. 假设二:「探活 200 = 业务正常」
    • 真相 :ping 通只说明机器活着,HTTP 200 只说明被监控的那个特定 URL 活着。第 17 个及以后的子域死了,主站探活一无所知。

一句话总结:切换前的「完整性」靠记忆,切换后的「健康度」看单点------两个环节各漏一步,叠出了 16.5 小时的故障。

三、避坑指南:Nginx 配置迁移六步清单

为了避免此类事故再次发生,我们梳理了以下六个动作,缺一不可:

1. 导出生效配置全量

不要比对「你以为的配置文件」,要比对生效配置。

  • 操作 :切换前在旧机器跑 nginx -T(输出当前生效的完整配置),存档为基线;新机器装完后同样跑一次,两份做 diff。

2. Server_name 清单比对

  • 操作 :从两份基线里提取全部 server_name,做集合 diff。
  • 标准:新旧清单不一致(尤其旧有新无)必须逐条归因:是「确认不迁移」还是「漏迁」?必须写进记录,严禁模糊处理。

3. 证书清点

  • 操作:对照 server_name 清单,核对每条 vhost 的证书文件是否存在、路径是否正确以及有效期是否充足。
  • 注意:证书路径漏拷是仅次于漏配的高频坑。

4. 探活按域名清单走,校内容不只校状态码

  • 操作 :对清单里每一个域名发请求。
  • 断言三点 :
    1. 状态码正确;
    2. 响应体指纹(如 md5)与切换前采集的基准一致;
    3. 证书校验通过。
  • 警示:只 curl 主页等于没测。

5. DNS 灰度与观察期

  • 操作:切 DNS 先降 TTL,分批切流量。
  • 策略:切换后保留旧机器一段时间只读待命(不立刻下线),给回滚留一扇门。

6. 变更留痕

  • 操作:以上每步的输出(diff 结果、清单比对表、探活报告)必须归档。
  • 价值:下一次迁移的基线,就是这一次的档案。

四、实战脚本:自动化比对与探活

为了将上述流程落地,这里提供两个通用脚本示意,可根据实际环境改造。

脚本一:切换前 Server_name 全量比对 (vhost_diff.sh)

此脚本用于在新旧机器分别运行,提取域名列表并找出差异。

bash 复制代码
#!/usr/bin/env bash
# vhost_diff.sh ------ 新旧机器各跑一次,diff 两份清单

# 【执行步骤】
# 1. 在旧机器执行: nginx -T2>/dev/null | grep -oP 'server_name\s+\K[^;]+' | sort -u > old.txt
# 2. 在新机器执行: nginx -T 2>/dev/null | grep -oP 'server_name\s+\K[^;]+' | sort -u > new.txt
# 3. 在任意机器运行本脚本进行比对

echo "=== 开始比对域名清单 ==="

# 找出旧机器有但新机器没有的 (MISSING)
missing=$(comm -23 old.txt new.txt)
if [ -n "$missing" ]; then
  echo "❌ 存在未迁移域名,禁止切流:"
  echo "$missing" | sed 's/^/MISSING_ON_NEW: /'
  exit 1
fi

# 找出新机器有但旧机器没有的 (NEW_ONLY)
new_only=$(comm -13 old.txt new.txt)
if [ -n "$new_only" ]; then
  echo "⚠️ 新机器多出以下域名(请确认是否为预期):"
  echo "$new_only" | sed 's/^/NEW_ONLY: /'
fi

echo "✅ 域名清单比对通过,无遗漏。"

脚本二:切换后按域名清单探活 (probe_all.sh)

此脚本基于切换前采集的指纹基准,逐域验证状态码和内容一致性。

前置准备 :生成 baseline.tsv 文件(两列:域名 <TAB> 切换前 body 的 md5)。

bash 复制代码
#!/usr/bin/env bash
# probe_all.sh ------ 域名清单 + 切换前指纹基准,逐域探活

BASELINE_FILE="baseline.tsv"

if [ ! -f "$BASELINE_FILE" ]; then
  echo "错误:未找到基准文件 $BASELINE_FILE"
  exit 1
fi

echo "=== 开始全量域名探活 ==="

while IFS=$'\t' read -r domain expect_md5; do
  # 获取当前响应体的 MD5 body_md5=$(curl -sS -m 10 "https://${domain}" | md5sum | cut -d' ' -f1)
  
  # 获取 HTTP 状态码
  code=$(curl -sS -m 10 -o /dev/null -w '%{http_code}' "https://${domain}")
  
  if [ "$code" != "200" ]; then
    echo "❌ FAIL $domain status=$code"
    continue
  fi
  
  if [ "$body_md5" != "$expect_md5" ]; then
    echo "⚠️ DIFF $domain fingerprint_changed (期望:$expect_md5, 实际:$body_md5)"
    # 注意:此处可加入白名单逻辑,忽略时间戳等动态内容的差异
  else
    echo "✅ PASS $domain"
  fi
done < "$BASELINE_FILE"

echo "=== 探活结束 ==="

💡 实现要点提示:

  • 指纹基准必须在切换前采集:事后没有「正确答案」可比。
  • 处理动态内容:指纹比对允许合理差异(如时间戳、随机数)。建议先跑一遍生成白名单,剩下的差异都要严格归因。

五、结语:迁移类事故的共同形状

这次 Nginx 事故的形状,在很多场景里都在重复出现:

  • 数据库换实例:只迁了业务库,漏了定时任务的辅助库;
  • 域名服务商更换:只转了主域,漏了散落的解析记录;
  • 容器重建:只备份了镜像,漏了挂载卷里的状态。

它们的共同点是:资产清单存在于人的记忆里,验收口径是单点指标。

解法始终一致:

  1. 先把「到底有多少东西」变成机器可对的清单(生效配置、解析记录、卷映射);
  2. 再把验收从「主入口正常」改成「逐条过清单 + 内容级校验」。

迁移的完整标准只有一个:清单上每一项,迁移前后各验一次,证据留档。


注:本文事故细节为真实故障的泛化叙述,未虚构时间线与技术栈;脚本为通用模式示意,生产环境使用前请务必测试。

相关推荐
dozenyaoyida23 分钟前
AI与大模型新闻日报 | 2026-11-08
人工智能·搜索引擎·ai·大模型·新闻
泯泷33 分钟前
AI Agent 工具设计:读完一百页 PDF,不等于真的看懂了
人工智能·llm·agent
泯泷3 小时前
AI 怎样"查资料"?——RAG 检索增强生成入门(三)
人工智能·llm
Solange__3 小时前
Blender 3D模型优化:普通复制、共享网格、实例、合并怎么选?
人工智能·3d·ai·自然语言处理·编辑器·blender·材质
师夷长技以自愈3 小时前
手搓 AI Agent 第 8 篇:从手写循环到画流程图——LangGraph 封装
人工智能·python
数据治理自习室3 小时前
2026最新:MCP开发与使用指南
人工智能
小小疯狐狸3 小时前
我踩过的Agent harness几个坑:上下文越跑越慢
人工智能
kaixin_啊啊4 小时前
【零基础学AI】第 30 章——对话记录与结构化输出
人工智能
泯泷5 小时前
让知识"长骨架"——RAPTOR、GraphRAG 与 OpenViking(四)
人工智能·llm