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节点,故障域更细,但跨节点访问比例上升,需要根据业务延迟敏感度权衡。
三、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形同虚设。
四、故障域划分的实操方法与判断依据
故障域划分不是画一张静态图,而是建立“部件—拓扑—业务”的映射。建议按以下顺序执行:
- 枚举部件与冗余状态:列出所有PSU、CPU Socket、NUMA节点、DIMM通道、PCIe插槽、网卡端口、存储控制器,标注是否有冗余配对。
- 读取拓扑关系:用
numactl --hardware、lspci -tv、lstopo确认每个设备所属的NUMA节点和Root Complex。 - 映射业务绑定:确认关键业务进程是否通过
numactl --cpunodebind或taskset绑定到特定NUMA节点,网卡中断是否绑定到对应CPU。 - 识别交叉单点:找出“多个冗余部件共享的公共上游”,例如双网卡共享同一Root Complex、双PSU共享同一PDU、双Socket共享同一xGMI链路。
- 评估失效后果:对每个故障域,判断失效后是“整机宕机”“局部不可用”还是“性能降级”,并据此决定是否需要上层HA或迁移策略。
下面这张图展示了一台双路EPYC服务器的故障域划分与NUMA/I/O拓扑关系。图中用不同颜色区分供电域、计算域、内存域和I/O域,并标出了两个典型的交叉单点:共享PDU和共享Root Complex。
五、从故障域到切换策略
完成故障域分析后,切换策略就有了明确依据。对于NUMA节点级故障,若业务已绑定到Node 0,则Node 0内存通道故障时,进程无法简单“迁移到Node 1继续运行”,而需要由上层集群(如Kubernetes、Pacemaker)在另一台服务器上重启。对于网卡级故障,若两块网卡分属不同Root Complex,则bonding可在毫秒级完成切换,业务几乎无感。对于存储控制器故障,若系统盘与数据盘共用控制器,则控制器失效会导致整机无法启动,必须依赖外部HA或双控制器方案。
因此,故障域分析的最终产出不是一张图,而是一份“故障域—影响范围—冗余状态—切换方式”的对照关系。它决定了哪些故障可以靠本机冗余扛过去,哪些必须靠集群切换,哪些必须提前改造拓扑(例如把系统盘从RAID卡移到板载接口、把双网卡分插到不同Root Complex)。只有把EPYC的NUMA与I/O拓扑真正读清楚,故障切换才不会停留在“配了双网卡就以为高可用”的层面。