4. 自动化发现与采集:网络设备自动发现、服务器硬件信息采集(IPMI/Redfish)、操作系统信息采集

设备注册流程里,最耗时、最容易出错的环节是什么?

我个人经验是——信息采集。以前靠人工登录设备,一条命令一条命令敲,再复制粘贴到Excel里。一台设备半小时,一百台就是两天。而且人总会犯错,漏个字段、写错个IP,后面排查起来要命。

所以自动化采集,是整个注册流程的基石。你采集不到准确信息,后面的CMDB、监控、自动化部署全是空中楼阁。这一章,我带你把这套体系搭起来。

4.1 网络设备自动发现

网络设备发现,说白了就是让系统自己去“找”设备。不是等用户手动录入,而是主动扫描、自动识别。

核心思路:先通过种子节点或IP段扫描,再用SNMP/SSH协议获取设备详细信息,最后自动入库。

4.1.1 发现策略

我常用的发现策略有三种,你可以根据网络规模选:

策略 适用场景 优点 缺点
种子节点扩散 已有核心设备,逐步扩展 精准,不浪费资源 依赖初始种子
IP段扫描 新建机房、未知网络 全覆盖,无遗漏 扫描时间长,可能误扫
LLDP/CDP邻居发现 已有网络拓扑,增量更新 实时,自动发现新设备 需要设备开启协议

我在项目中遇到过一个问题:用IP段扫描时,把打印机、摄像头也扫进来了。后来加了端口过滤,只扫SNMP 161端口和SSH 22端口,才把范围缩小到网络设备。

4.1.2 SNMP采集实现

SNMP是网络设备采集的标配。我建议用SNMPv3,安全性有保障。下面是一个Python采集示例:

from pysnmp.hlapi import *

def get_device_info(ip, community='public'):
    # 采集系统描述
    sys_descr = get_snmp_value(ip, community, '1.3.6.1.2.1.1.1.0')
    # 采集系统名称
    sys_name = get_snmp_value(ip, community, '1.3.6.1.2.1.1.5.0')
    # 采集接口数量
    if_number = get_snmp_value(ip, community, '1.3.6.1.2.1.2.1.0')
    
    return {
        'ip': ip,
        'model': parse_model(sys_descr),
        'hostname': sys_name,
        'interface_count': if_number
    }

def get_snmp_value(ip, community, oid):
    errorIndication, errorStatus, errorIndex, varBinds = next(
        getCmd(SnmpEngine(),
               CommunityData(community),
               UdpTransportTarget((ip, 161)),
               ContextData(),
               ObjectType(ObjectIdentity(oid)))
    )
    if errorIndication:
        return None
    return varBinds[0][1]

避坑指南:我曾经遇到一个坑——不同厂商的OID返回格式不一样。华为的设备型号在sysDescr里,思科的却在entPhysicalDescr里。建议你建一个OID映射表,按厂商做适配。

4.2 服务器硬件信息采集

服务器硬件采集,我分两条线走:老设备用IPMI,新设备用Redfish。为什么?因为IPMI是传统标准,几乎所有服务器都支持。但Redfish是新一代标准,基于RESTful API,更现代、更易用。

4.2.1 IPMI采集

IPMI通过BMC带外管理,不依赖操作系统。哪怕服务器没装系统,也能采集到硬件信息。

常用采集项:

  • CPU型号、核心数、频率
  • 内存容量、插槽信息
  • 硬盘型号、容量、健康状态
  • 电源状态、风扇转速、温度
  • 固件版本、BMC版本

用ipmitool命令行采集:

# 采集FRU信息(含厂商、型号、序列号)
ipmitool -H 192.168.1.100 -U admin -P password fru print

# 采集传感器信息(温度、电压、风扇)
ipmitool -H 192.168.1.100 -U admin -P password sdr list

# 采集电源状态
ipmitool -H 192.168.1.100 -U admin -P password chassis power status

注意:IPMI默认使用明文传输,建议在生产环境开启IPMI over LAN的加密,或者通过VPN访问。我曾经见过有人直接在公网暴露IPMI端口,结果被黑了。

4.2.2 Redfish采集

Redfish是DMTF推出的新标准,用HTTPS+JSON,比IPMI友好得多。我强烈建议新采购的服务器都支持Redfish。

Redfish采集示例(Python):

import requests
import json

def collect_redfish_info(bmc_ip, username, password):
    base_url = f"https://{bmc_ip}/redfish/v1"
    
    # 禁用SSL验证(生产环境请使用证书)
    session = requests.Session()
    session.verify = False
    session.auth = (username, password)
    
    # 获取系统信息
    systems_url = f"{base_url}/Systems"
    response = session.get(systems_url)
    systems = response.json()
    
    # 遍历所有系统
    for member in systems.get('Members', []):
        system_url = member.get('@odata.id')
        system_info = session.get(f"https://{bmc_ip}{system_url}").json()
        
        # 提取关键信息
        result = {
            'manufacturer': system_info.get('Manufacturer'),
            'model': system_info.get('Model'),
            'serial_number': system_info.get('SerialNumber'),
            'memory_gb': system_info.get('MemorySummary', {}).get('TotalSystemMemoryGiB'),
            'cpu_count': len(system_info.get('Processors', {}).get('Members', [])),
            'firmware_version': system_info.get('BiosVersion')
        }
        
        return result

我的经验:Redfish的API路径各厂商略有差异。比如戴尔的iDRAC和惠普的iLO,虽然都遵循标准,但扩展字段不同。建议先抓取完整的/redfish/v1/根目录,再根据返回的链接逐层采集。

4.3 操作系统信息采集

硬件信息有了,操作系统信息也不能少。这部分我通常通过SSH或Agent方式采集。

4.3.1 SSH采集

SSH采集适合Linux/Unix服务器,不需要安装额外Agent。用paramiko库实现:

import paramiko

def collect_os_info(host, username, password):
    client = paramiko.SSHClient()
    client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    client.connect(host, username=username, password=password)
    
    commands = {
        'hostname': 'hostname',
        'os_version': 'cat /etc/os-release | grep PRETTY_NAME',
        'kernel': 'uname -r',
        'cpu_cores': 'nproc',
        'memory': 'free -g | grep Mem | awk \'{print $2}\'',
        'disk': 'df -h / | tail -1 | awk \'{print $2}\'',
        'ip_address': 'ip addr show | grep "inet " | awk \'{print $2}\''
    }
    
    result = {}
    for key, cmd in commands.items():
        stdin, stdout, stderr = client.exec_command(cmd)
        result[key] = stdout.read().decode().strip()
    
    client.close()
    return result

4.3.2 Agent采集

对于Windows服务器或大规模集群,我建议用Agent方式。Agent可以采集更细粒度的信息,比如进程列表、服务状态、补丁版本等。

Agent采集架构:

  • Agent部署在每台服务器上,定时采集数据
  • 通过消息队列(如Kafka)上报到采集中心
  • 采集中心做数据清洗、去重、入库

关键点:Agent要支持断线续传。网络不稳定时,数据先缓存本地,恢复后自动补传。我遇到过Agent丢数据的情况,后来加了本地SQLite缓存,再也没丢过。

4.4 整体采集流程

下面这张图,是我设计的自动化采集整体流程。你看一眼就能明白各模块的关系。

自动化采集流程图 自动化采集整体流程 网络设备发现 服务器发现 操作系统发现 SNMP采集 IPMI/Redfish采集 SSH/Agent采集 数据汇聚与清洗 CMDB入库 说明:发现层负责定位设备,采集层负责获取数据,汇聚层做标准化,最终存入CMDB

4.5 采集策略与避坑

最后,我总结几个实战中容易踩的坑:

  1. 并发控制:别一次性采集所有设备。我建议用信号量控制并发数,比如同时采集20台。否则网络带宽被打满,正常业务受影响。
  2. 超时处理:设备可能离线或响应慢。设置合理的超时时间(SNMP建议5秒,SSH建议10秒),超时后重试2次,再失败就标记为异常。
  3. 数据去重:同一台设备可能被多个采集任务命中。用设备序列号或MAC地址做唯一键,入库前先检查是否存在。
  4. 增量采集:全量采集太慢。第一次全量,之后只采集变化的数据。比如CPU温度、内存使用率这些动态数据,可以定时增量采集。

重要提醒:采集频率不要太高。我曾经见过有人每5分钟采集一次所有设备,结果BMC被频繁请求搞挂了。建议网络设备1小时一次,服务器硬件30分钟一次,操作系统指标5分钟一次。

嗯,自动化采集这块,核心就是“发现-采集-汇聚-入库”四个步骤。你把这套流程跑通了,后面的设备注册、配置下发、监控告警,都会顺畅很多。