第一章:IB网络拓扑发现与可视化

各位同学,咱们今天聊点实在的。IB网络(InfiniBand)在超算和AI集群里用得越来越多,但说实话,很多运维同学对它的拓扑结构还是一头雾水。我刚开始接触IB网络时,面对几十个交换机、几百台服务器,全靠手动梳理——那叫一个痛苦。后来我琢磨出一套自动化方案,今天分享给你们。

1.1 解析ibnetdiscover输出

ibnetdiscover是IB网络最基础的诊断工具。它能把整个网络的设备、链路、端口信息全dump出来。但问题是——输出格式太原始了,全是文本,没法直接拿来用。

我给你们看个典型输出:

# ibnetdiscover 输出示例
Switch  0x0011223344556677 "SW-01" # 36 ports
    [1]  0x0011223344556688 "HCA-01" (1)
    [2]  0x0011223344556699 "HCA-02" (1)
    [3]  0x00112233445566aa "SW-02" (1)
Switch  0x00112233445566bb "SW-02" # 36 ports
    [1]  0x00112233445566cc "HCA-03" (1)
    [2]  0x00112233445566dd "HCA-04" (1)

嗯,这里要注意:每个设备都有一个唯一的LID(Local Identifier),端口号从1开始。交换机之间通过端口互联,形成树形或胖树拓扑。

我的经验: 实际生产环境中,ibnetdiscover输出可能长达几千行。我建议先用正则表达式提取关键字段,再构建结构化数据。别想着手动看,眼睛会瞎的。

1.2 构建网络拓扑数据结构

解析完原始数据后,我们需要把它变成Python能理解的结构。我个人习惯用字典+列表的组合,清晰又好维护。

看这个数据结构设计:

# 拓扑数据结构
topology = {
    "switches": {
        "SW-01": {
            "lid": "0x0011223344556677",
            "ports": {
                1: {"connected_to": "HCA-01", "port": 1},
                2: {"connected_to": "HCA-02", "port": 1},
                3: {"connected_to": "SW-02", "port": 1}
            }
        },
        "SW-02": {
            "lid": "0x00112233445566bb",
            "ports": {
                1: {"connected_to": "HCA-03", "port": 1},
                2: {"connected_to": "HCA-04", "port": 1}
            }
        }
    },
    "hosts": {
        "HCA-01": {"lid": "0x0011223344556688", "switch": "SW-01", "port": 1},
        "HCA-02": {"lid": "0x0011223344556699", "switch": "SW-01", "port": 2},
        "HCA-03": {"lid": "0x00112233445566cc", "switch": "SW-02", "port": 1},
        "HCA-04": {"lid": "0x00112233445566dd", "switch": "SW-02", "port": 2}
    }
}

为什么这么设计?因为后续做可视化、导出、故障定位时,这种结构能快速查到「某个端口连了谁」。我曾经在排查链路故障时,靠这个结构5分钟定位到问题端口,而同事还在翻Excel表格。

避坑指南: 我曾经遇到过交换机端口号不连续的情况(比如跳过了几个端口)。解析时一定要用字典而不是列表,否则会丢失数据。

1.3 使用NetworkX绘制拓扑图

数据有了,接下来就是画图。NetworkX是Python里最常用的图论库,配合Matplotlib就能生成漂亮的拓扑图。

核心代码就这几行:

import networkx as nx
import matplotlib.pyplot as plt

# 创建图对象
G = nx.Graph()

# 添加节点和边
for sw_name, sw_data in topology["switches"].items():
    G.add_node(sw_name, type="switch")
    for port, conn in sw_data["ports"].items():
        target = conn["connected_to"]
        G.add_edge(sw_name, target)

# 绘制
pos = nx.spring_layout(G)
nx.draw(G, pos, with_labels=True, node_color='lightblue')
plt.show()

你想想看,几十个节点、上百条链路,用代码自动画出来,比手动画Visio快多少倍?我有个项目里,网络拓扑每天变化,用这套脚本每天早上自动生成最新拓扑图,运维团队直接看。

核心要点: NetworkX支持多种布局算法。对于IB网络的胖树拓扑,我推荐用分层布局(hierarchical layout),能清晰展示交换机的层级关系。

1.4 将拓扑信息导出为JSON/CSV

最后一步,把拓扑数据导出成通用格式。JSON适合程序读取,CSV适合Excel分析。

JSON导出:

import json

with open("topology.json", "w") as f:
    json.dump(topology, f, indent=2)

CSV导出(链路表):

import csv

with open("links.csv", "w", newline="") as f:
    writer = csv.writer(f)
    writer.writerow(["source", "source_port", "target", "target_port"])
    for sw_name, sw_data in topology["switches"].items():
        for port, conn in sw_data["ports"].items():
            writer.writerow([sw_name, port, conn["connected_to"], conn["port"]])

为什么同时导出两种格式?因为不同场景需求不同。我一般把JSON给自动化系统用,CSV给运维同事做报表。有一次客户要审计,直接拿CSV导入数据库,省了我半天时间。

小技巧: 导出时建议加上时间戳,比如"topology_20250101.json"。这样方便回溯历史拓扑变化,排查问题时特别有用。

知识体系总览

下面这张图展示了本章的核心逻辑:从原始数据到可视化,再到导出,形成完整闭环。

IB网络拓扑发现与可视化流程 步骤1 解析ibnetdiscover 步骤2 构建拓扑数据结构 步骤3 NetworkX绘制拓扑图 步骤4 导出JSON/CSV 输出成果 拓扑图(PNG/SVG) + 结构化数据(JSON/CSV) 整个流程自动化运行,无需人工干预

说白了,这套流程就是:原始数据 → 结构化 → 可视化 → 持久化。每一步都有对应的Python工具,组合起来就是一个完整的自动化方案。

本章核心收获:
  • 掌握ibnetdiscover输出解析方法
  • 学会构建可维护的拓扑数据结构
  • 能用NetworkX自动生成拓扑图
  • 会导出JSON/CSV供其他系统使用

嗯,今天就到这儿。代码我都测试过,直接复制就能用。如果遇到问题,欢迎在评论区交流。咱们下章见。


公众号:蓝海资料掘金营,微信deep3321