摘要

  • 这篇文章从 IP 纳管继续往前走,解决“知道这个地址存在,但不知道它属于谁”的建模问题。
  • 核心思路是借助 SNMP 做能力识别,再把 IP、接口和设备之间的关系自动补齐。
  • 读完它,你会更清楚 NetBox 为什么不能只做地址台账,而应该成为资产关系的事实中心。

在《NetBox进阶指南 1.0》中,已经完成了 NetBox 在 IP 资产管理层面的第一阶段工程化落地:

  • 通过 Orb-agent + Diode 实现全网 IP 自动发现与导入
  • 通过 Python + 钉钉 实现 IP 生命周期自动审计与告警

但在实际运维中,很快会遇到新的问题:

IP 已自动化,但它“属于哪台设备”仍需人工维护。

这意味着 NetBox 仍停留在“地址台账”,而非真正的“资产事实中心”。


一、2.0 的目标

在不破坏 1.0 架构的前提下,实现:

资产关系自动化建模(IP → 接口 → 设备)


二、架构演进

能力演进

2.1 1.0 能力回顾

text
网络 → Orb 扫描 → NetBox IPAM → 生命周期审计

2.2 2.0 能力升级

text
网络 → IP发现
     → SNMP能力识别
     → 绑定管理接口
     → 归属设备
     → 纳入统一审计体系

2.3 新增关键能力

能力层 说明
IP 能力识别 判断 IP 是否具备 SNMP 管理能力
资产关系建模 自动建立 IP → 接口 → 设备关系

三、整体架构

IP 与 Device 自动绑定链路

自动绑定

text
┌────────────┐
│  Orb-agent │  ← IP发现唯一来源
└─────┬──────┘
      ↓
┌────────────┐
│   Diode    │  ← 数据标准化
└─────┬──────┘
      ↓
┌──────────────────────────┐
│        NetBox 4.x        │
│  - IPAM                 │
│  - DCIM                 │
│  - Interface            │
│  - Device               │
└─────┬─────────┬─────────┘
      │         │
      │         ├─ SNMP 打标签(能力识别)
      │
      ├─ IP ↔ Device 自动绑定
      │
      └─ 生命周期审计(继承1.0)

四、核心设计原则

这是整个系统是否稳定运行的关键。

4.1 Orb 是唯一 IP 来源

  • 所有 IP 只能由 Orb-agent 创建
  • 禁止人工创建 IP

4.2 标签只用于能力描述

  • orb-agent:IP 来源
  • snmp-managed:具备 SNMP 能力

不引入业务标签,避免耦合


4.3 生命周期集中管理

  • 只有审计脚本可修改 IP 状态
  • 其他脚本必须保持:
text
无破坏性 + 幂等

五、SNMP 打标签(IP 能力识别)

5.1 设计目标

识别“真正的设备管理 IP”。


5.2 工作逻辑

  • 遍历 NetBox IP
  • 执行 SNMP GET
  • 成功 → 添加 snmp-managed 标签

5.3 环境变量

bash
NETBOX_URL=http://netbox.example.local
NETBOX_TOKEN=NETBOX_API_TOKEN
SNMP_COMMUNITY=public
SNMP_VERSION=2
SNMP_TIMEOUT=1

5.4 脚本示例

python
#!/usr/bin/env python3
import pynetbox
from easysnmp import Session, EasySNMPTimeoutError

NETBOX_URL = "http://netbox.example.local"
NETBOX_TOKEN = "NETBOX_API_TOKEN"

nb = pynetbox.api(NETBOX_URL, token=NETBOX_TOKEN)

def snmp_reachable(ip):
    try:
        s = Session(hostname=ip, community="public", version=2, timeout=1, retries=0)
        s.get(".1.3.6.1.2.1.1.1.0")
        return True
    except:
        return False

for ip in nb.ipam.ip_addresses.all():
    ip_addr = ip.address.split("/")[0]
    tags = {t.slug for t in ip.tags}

    tags.add("orb-agent")

    if snmp_reachable(ip_addr):
        tags.add("snmp-managed")

    ip.update({"tags": [{"slug": t} for t in tags]})

5.5 特性

  • 可周期执行
  • 不修改状态
  • 不删除数据

六、IP ↔ Device 自动绑定

6.1 设计目标

实现自动关系建模:

text
IP → 接口 → 设备

6.2 核心逻辑

  • 仅处理 snmp-managed IP
  • 自动创建设备
  • 创建管理接口(mgmt0)
  • 绑定 IP
  • 设置 primary_ip

6.3 脚本示例

python
#!/usr/bin/env python3
import pynetbox

NETBOX_URL = "http://netbox.example.local"
NETBOX_TOKEN = "NETBOX_API_TOKEN"

nb = pynetbox.api(NETBOX_URL, token=NETBOX_TOKEN)

for ip in nb.ipam.ip_addresses.filter(tag="snmp-managed"):
    address = ip.address.split("/")[0]
    device_name = f"device-{address}"

    device = nb.dcim.devices.get(name=device_name)
    if not device:
        device = nb.dcim.devices.create(
            name=device_name,
            device_role=1,
            device_type=1,
            site=1,
            status="active",
        )

    iface = nb.dcim.interfaces.get(device_id=device.id, name="mgmt0")
    if not iface:
        iface = nb.dcim.interfaces.create(
            device=device.id,
            name="mgmt0",
            type="1000base-t",
        )

    if not ip.assigned_object:
        ip.update({
            "assigned_object_type": "dcim.interface",
            "assigned_object_id": iface.id
        })

    if not device.primary_ip4:
        device.update({"primary_ip4": ip.id})

6.4 特性

  • 幂等执行
  • 无破坏性
  • 支持重复运行
  • 支持主设备绑定

七、自动化调度方案

推荐调度模型:

text
每天 00:00    Orb 全网扫描
每天 09:00    IP 生命周期审计
每周六 21:00  SNMP 打标签
每周六 23:00  IP ↔ Device 绑定

特点:

  • 稳定
  • 可控
  • 不冲突

八、2.0 总结

通过 2.0 架构,实现:

  • IP 不再是“地址记录”,而是资产入口
  • IP / 接口 / 设备关系自动建立
  • NetBox 成为真正的 Source of Truth

九、核心价值

该方案并非简单脚本堆叠,而是:

分层架构 + 单一数据源 + 幂等自动化设计


十、延伸方向

下一步可扩展:

  • SNMP → 设备信息自动采集(厂商/型号)
  • LLDP → 自动生成链路关系
  • 自动生成网络拓扑
  • 接入自动化变更平台

十一、参考

  • 《NetBox 进阶指南 1.0》