3. 故障域分析与EPYC系统拓扑

在讨论业务连续性与故障切换之前,必须先回答一个更基础的问题:故障发生时,影响范围到底有多大?这个影响范围就是“故障域”(Fault Domain)。故障域分析的目标,是把一台EPYC服务器拆解成若干可独立失效的边界,判断每个边界失效后会波及哪些资源、哪些业务,以及系统是否还有冗余路径继续提供服务。对EPYC平台而言,故障域不能只看“有没有双电源”这种硬件数量,还必须结合NUMA内存拓扑与PCIe I/O拓扑来判断——因为同一块网卡插在不同PCIe Root Complex下,其故障影响面可能完全不同。

一、从物理部件到故障域:EPYC服务器的分层结构

一台典型的双路EPYC服务器可以按“供电—计算—内存—I/O—存储”五个层次划分故障域。每一层都存在单点故障(SPOF)的可能,但并非所有单点故障都会导致整机宕机,有些只会造成性能降级或局部不可用。

  • 电源故障域:双电源模块(PSU)分别接入A/B两路PDU时,单路市电或单个PSU失效不会导致宕机;但若两个PSU接在同一路PDU上,则该PDU就是单点故障。此外,主板上的VRM(电压调节模块)为CPU供电,若某相VRM失效,可能只影响一个Socket,也可能导致整机保护性关机。
  • CPU故障域:双路EPYC中,每个Socket是独立的计算故障域。一个Socket失效时,若操作系统和业务未做跨Socket绑定,运行在该Socket上的进程会全部丢失;但另一个Socket及其直连内存、I/O仍可工作。
  • 内存故障域:EPYC的8个或12个内存通道分别挂在对应Socket的UMC(统一内存控制器)下。单条DIMM故障通常由ECC纠正,但同一通道多DIMM失效或UMC故障,会导致该通道对应的NUMA节点内存不可用。
  • 网卡故障域:网卡本身、其所插的PCIe插槽、以及该插槽所属的Root Complex,构成一个I/O故障域。若业务网卡是单卡单口,则网卡即SPOF;若为双口绑定,还需确认两口是否位于不同Root Complex。
  • 存储控制器故障域:RAID卡或HBA卡失效会切断其下挂所有磁盘的访问路径。若系统盘与数据盘共用同一控制器,控制器故障将同时影响启动与数据。

二、NUMA拓扑如何决定内存故障域边界

EPYC采用Chiplet设计,每个Socket内部由多个CCD(Core Complex Die)和一个I/O Die组成。内存控制器位于I/O Die中,每个Socket提供8个或12个DDR5通道。操作系统会将每个Socket的内存划分为一个NUMA节点(NPS1模式),或进一步细分为NPS2/NPS4,使每个NUMA节点对应更少的内存通道和更近的CPU核心。

以双路EPYC 9004系列、NPS1模式为例,系统呈现2个NUMA节点:Node 0对应Socket 0及其8通道内存,Node 1对应Socket 1及其8通道内存。跨节点访问需经过xGMI(Socket间互连),延迟明显高于本地访问。此时若Node 0的某条内存通道整体失效,Node 0上运行的进程可能因内存不足或访问异常而崩溃,但Node 1仍可继续服务。因此,NUMA节点是内存故障域的自然边界。在NPS4模式下,每个Socket被拆成4个NUMA节点,故障域更细,但跨节点访问比例上升,需要根据业务延迟敏感度权衡。

判断内存故障域时,不要只数DIMM数量,而要看“同一UMC/同一NUMA节点下有多少DIMM”。同一NUMA节点内多通道同时失效,才会导致该节点整体不可用。

三、PCIe与I/O拓扑:网卡和存储控制器的真实故障边界

EPYC的I/O Die提供128条PCIe 5.0通道,分为多个Root Complex。不同插槽可能挂在不同的Root Complex甚至不同的I/O Die分区下。这意味着:两块网卡插在物理上相邻的插槽,未必属于不同故障域。如果它们共享同一个Root Complex或同一路xGMI链路,该链路故障会同时切断两块网卡。

实际分析时,可通过以下命令查看PCIe与NUMA的对应关系:

# 查看网卡所在NUMA节点与PCIe路径
lspci -vv -s 41:00.0 | grep -i numa
cat /sys/class/net/ens1f0/device/numa_node

# 查看NUMA节点与CPU、内存的对应
numactl --hardware
lstopo --of console

# 查看PCIe Root Complex拓扑
lspci -tv

假设一台双路EPYC服务器有两块25GbE网卡:ens1f0位于Socket 0的Root Complex下,ens1f1位于Socket 1的Root Complex下。若将二者做bonding,则单块网卡或单个Root Complex故障时,另一块仍可承载流量,故障域被有效隔离。反之,若两块网卡都在Socket 0下,则Socket 0的I/O故障会同时切断两条网络路径,bonding形同虚设。

四、故障域划分的实操方法与判断依据

故障域划分不是画一张静态图,而是建立“部件—拓扑—业务”的映射。建议按以下顺序执行:

  1. 枚举部件与冗余状态:列出所有PSU、CPU Socket、NUMA节点、DIMM通道、PCIe插槽、网卡端口、存储控制器,标注是否有冗余配对。
  2. 读取拓扑关系:用numactl --hardware、lspci -tv、lstopo确认每个设备所属的NUMA节点和Root Complex。
  3. 映射业务绑定:确认关键业务进程是否通过numactl --cpunodebind或taskset绑定到特定NUMA节点,网卡中断是否绑定到对应CPU。
  4. 识别交叉单点:找出“多个冗余部件共享的公共上游”,例如双网卡共享同一Root Complex、双PSU共享同一PDU、双Socket共享同一xGMI链路。
  5. 评估失效后果:对每个故障域,判断失效后是“整机宕机”“局部不可用”还是“性能降级”,并据此决定是否需要上层HA或迁移策略。

下面这张图展示了一台双路EPYC服务器的故障域划分与NUMA/I/O拓扑关系。图中用不同颜色区分供电域、计算域、内存域和I/O域,并标出了两个典型的交叉单点:共享PDU和共享Root Complex。

双路EPYC服务器故障域与NUMA/I/O拓扑 供电故障域 PDU-A PDU-B PSU-1 PSU-2 ⚠ 若PDU-A与PDU-B来自同一上游配电,则该上游为交叉单点 计算故障域 · Socket 0 EPYC CPU 0 CCD × 8 + I/O Die NUMA Node 0 8×DDR5 通道 Root Complex 0 PCIe 5.0 × 64 通道 计算故障域 · Socket 1 EPYC CPU 1 CCD × 8 + I/O Die NUMA Node 1 8×DDR5 通道 Root Complex 1 PCIe 5.0 × 64 通道 xGMI 互连 网卡 ens1f0 25GbE · RC0 RAID 控制器 RC0 · 系统盘+数据盘 网卡 ens1f1 25GbE · RC1 NVMe 存储 RC1 · 数据盘 故障域判断要点 • Socket 0 失效:Node 0 内存与 RC0 下网卡/RAID 同时不可用,业务需迁移至 Socket 1 • ens1f0 与 ens1f1 分属 RC0/RC1,bonding 可跨 Root Complex 冗余;若同属 RC0 则 bonding 无效 • RAID 控制器同时承载系统盘与数据盘,是存储路径上的单点故障,建议系统盘改用板载 SATA/M.2 分离

五、从故障域到切换策略

完成故障域分析后,切换策略就有了明确依据。对于NUMA节点级故障,若业务已绑定到Node 0,则Node 0内存通道故障时,进程无法简单“迁移到Node 1继续运行”,而需要由上层集群(如Kubernetes、Pacemaker)在另一台服务器上重启。对于网卡级故障,若两块网卡分属不同Root Complex,则bonding可在毫秒级完成切换,业务几乎无感。对于存储控制器故障,若系统盘与数据盘共用控制器,则控制器失效会导致整机无法启动,必须依赖外部HA或双控制器方案。

因此,故障域分析的最终产出不是一张图,而是一份“故障域—影响范围—冗余状态—切换方式”的对照关系。它决定了哪些故障可以靠本机冗余扛过去,哪些必须靠集群切换,哪些必须提前改造拓扑(例如把系统盘从RAID卡移到板载接口、把双网卡分插到不同Root Complex)。只有把EPYC的NUMA与I/O拓扑真正读清楚,故障切换才不会停留在“配了双网卡就以为高可用”的层面。