NetBox 完全指南:IPAM/DCIM 部署、数据建模、API 自动化与排障
NetBox 是网络基础设施的「唯一真相源」(Source of Truth):不是监控工具,不是拓扑图工具,而是一个结构化的 IP 地址管理(IPAM) + 数据中心基础设施管理(DCIM) 数据库。本文覆盖 NetBox 与 LibreNMS/NetDisco 的定位区别、Docker 部署、核心数据模型层级关系(Site→Rack→Device→Interface→IP)、IPAM IP 地址与前缀管理、VLAN/VRF/ASN、DCIM 机架设备线卡、数据录入实操(GUI + REST API + pynetbox + Ansible 动态清单)、自定义字段与导出模板、Webhooks 集成、以及 12 个高频排障场景。
一、NetBox 是什么
定位:Source of Truth,不是监控
| 维度 | NetBox | LibreNMS | NetDisco | Zabbix |
|---|---|---|---|---|
| 核心定位 | IPAM + DCIM 数据库 | 网络监控 + 告警 | L2 拓扑发现 | 全栈监控 |
| 数据来源 | 人工录入 + API + Discovery | SNMP 自动采集 | SNMP/CDP/LLDP 自动 | SNMP/Agent 采集 |
| 拓扑图 | ❌ 插件实现 | 基础 | 自动 | 无 |
| 实时监控 | ❌ | ✅ | ❌ | ✅ |
| IP 地址管理 | ⭐ 核心能力 | 基础 | 基础 | ❌ |
| API | ⭐ REST + GraphQL | REST | REST | API |
| 适合谁 | 运维团队 / 网络工程师 | NOC 值班 | 网络工程师 | 全栈运维 |
一句话:NetBox 是你网络的「CMDB」——你把 IP 分配、设备信息、线缆连接录进去,它帮你做结构化管理、防冲突、查询、给自动化提供数据源。它不扫描网络,是你告诉它网络长什么样。
为什么需要 NetBox
| 痛点 | Excel / Wiki | NetBox |
|---|---|---|
| IP 分配记录在 Excel | 多人编辑冲突、格式乱、不知道谁改了 | 数据库 + 权限 + 变更日志 |
| 新设备分配 IP | 翻 Excel 找没用的,经常撞 | 自动分配,防冲突 |
| VLAN 谁在用 | 查多个文档 | 一个页面查全 |
| 机架里有什么 | Visio 图过期 | 结构化设备 + 机架视图 |
| Ansible 清单 | 手动维护 hosts 文件 | 动态从 NetBox API 拉 |
| 谁改了什么 | 不知道 | 变更日志全程记录 |
适用场景
| 场景 | 适合度 | 说明 |
|---|---|---|
| 中大型机房 IP 管理 | ⭐⭐⭐⭐⭐ | 核心设计目标 |
| 多站点数据中心 | ⭐⭐⭐⭐⭐ | Site + Rack 层级 |
| Ansible/Terraform 数据源 | ⭐⭐⭐⭐⭐ | REST API 完美适配 |
| VLAN/VRF 统一管理 | ⭐⭐⭐⭐⭐ | IPAM 核心功能 |
| 线缆连接文档 | ⭐⭐⭐⭐ | Cable 管理 |
| 小型办公网络 | ⭐⭐⭐ | 有点重,Excel 可能够 |
| 实时监控/告警 | ⭐ | 不是这个工具 |
| 自动拓扑发现 | ⭐⭐ | 需配合 NetDisco/Discovery 插件 |
二、部署
1.1 环境要求
| 资源 | 最低 | 推荐 | 生产 |
|---|---|---|---|
| CPU | 2 核 | 4 核 | 8 核 |
| 内存 | 4 GB | 8 GB | 16 GB |
| 磁盘 | 10 GB | 50 GB | 100 GB+ SSD |
| OS | Linux 任意 | Ubuntu 22.04 / Debian 12 | 同左 |
| PostgreSQL | 12+(NetBox 4.0 起;4.3+ 需 14+) | 15+ | 16+ |
| Redis | 4.0+(NetBox 4.x 起) | 7+ | 7+ |
| Docker | 20.10+ | 24.0+ | 24.0+ |
1.2 Docker Compose 部署(推荐)
# 1. 克隆官方 docker 仓库
git clone https://github.com/netbox-community/netbox-docker.git
cd netbox-docker
# 2. 复制环境变量模板(官方推荐用 env/ 目录下的文件,不是根目录 .env)
cp env/netbox.env.example env/netbox.env
cp env/postgres.env.example env/postgres.env
cp env/redis.env.example env/redis.env
# 3. 编辑 env/netbox.env,至少改这几项:
# SECRET_KEY(用 python3 -c "import secrets; print(secrets.token_urlsafe(50))" 生成)
# ALLOWED_HOSTS=localhost netbox.example.com
# DB_NAME / DB_USER / DB_PASSWORD(与 postgres.env 一致)
# REDIS_PASSWORD(与 redis.env 一致)
# 注:变量名是 SECRET_KEY(非 DJANGO_SECRET_KEY),ALLOWED_HOSTS 用空格分隔域名,不要写 0.0.0.0
# 4. 编辑 env/postgres.env:POSTGRES_DB / POSTGRES_USER / POSTGRES_PASSWORD
# 5. 编辑 env/redis.env:REDIS_PASSWORD
# 6. 启动
docker compose -f docker-compose.yml up -d
# 7. 查看状态
docker compose ps
# 8. 创建管理员
docker compose exec netbox /opt/netbox/netbox/manage.py createsuperuser启动后访问 http://localhost:8000(容器内监听 8080,映射到宿主机 8000),用创建的管理员账号登录。
1.3 多容器架构
flowchart TB
subgraph DC["Docker Compose"]
direction TB
NB["netbox<br/>Web + API + GraphQL<br/>容器内:8080 → 宿主机:8000"]
NW["netbox-worker<br/>后台异步任务:Webhook / 清理"]
NH["netbox-housekeeping<br/>定期清理任务(session、变更日志等)"]
PG[("postgres<br/>数据存储<br/>:5432")]
RD[("redis<br/>缓存 + 队列<br/>:6379")]
NB --> PG
NB --> RD
NW --> PG
NW --> RD
NH --> PG
NH --> RD
end| 容器 | 职责 | 端口 |
|---|---|---|
netbox | Django Web UI + REST API + GraphQL | 8080(容器内)→ 8000(宿主机) |
netbox-worker | 后台异步任务(Webhook 发送、缓存清理等) | — |
netbox-housekeeping | 定期清理过期 session、变更日志、报告 | — |
postgres | 数据库 | 5432 |
redis | 缓存 + Celery 任务队列 | 6379 |
1.4 关键配置项
# env/netbox.env 关键项
# Django 密钥(必须改)
SECRET_KEY='你的50字符随机字符串'
# 允许访问的主机名(空格分隔,不要写 0.0.0.0)
ALLOWED_HOSTS=localhost netbox.example.com
# 数据库(env/netbox.env 中用 DB_*,env/postgres.env 中用 POSTGRES_*)
DB_NAME=netbox
DB_USER=netbox
DB_PASSWORD=强密码
# Redis
REDIS_PASSWORD=强密码
# 可选:LDAP/OIDC 认证
# 在 configuration/configuration.py 里配
# 可选:邮件
# EMAIL_HOST / EMAIL_PORT / EMAIL_HOST_USER / EMAIL_HOST_PASSWORD1.5 Nginx 反向代理 + HTTPS
server {
listen 443 ssl http2;
server_name netbox.yourdomain.com;
ssl_certificate /etc/ssl/certs/netbox.pem;
ssl_certificate_key /etc/ssl/private/netbox.key;
client_max_body_size 25M;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 80;
server_name netbox.yourdomain.com;
return 301 https://$host$request_uri;
}在 .env 里加:
ALLOWED_HOSTS=netbox.yourdomain.com1.6 升级
# 备份
docker compose exec postgres pg_dump -U netbox netbox > netbox-backup-$(date +%Y%m%d).sql
# 拉新镜像
docker compose pull
# 重启(自动迁移数据库)
docker compose up -d
# 检查迁移日志
docker compose logs netbox | grep -i migrat三、核心数据模型
2.1 层级关系图
flowchart TB ORG["Organization(组织)"] ORG --> SITE["Site(站点 / 机房)"] ORG --> TEN["Tenant(租户 / 业务线)"] SITE --> LOC["Location(区域 / 楼层)"] LOC --> RACK["Rack(机架)"] RACK --> DEV["Device(设备)"] DEV --> IF["Interface(接口)"] DEV --> CP["Console Port(串口)"] DEV --> PP["Power Port(电源口)"] DEV --> MOD["Module(线卡模块)"] IF --> IP["IP Address"] IF --> CAB["Cable(线缆)"] IF --> MAC["MAC Address"] DEV -. 型号 .-> DT["Device Type(型号)"] DT --> MFR["Manufacturer(厂商)"] DT --> IT["Interface Template"] DT --> CPT["Console Port Template"] SITE --> VLAN["VLAN(虚拟局域网)"] VLAN -. 属于 .-> VG["VLAN Group"] SITE --> VRF["VRF(虚拟路由转发)"] SITE --> PFX["Prefix(IP 前缀)"] PFX --> IP SITE --> CLU["Cluster(集群)"] CLU -. 类型 .-> CT["Cluster Type"] CLU --> VM["Virtual Machine"] VM --> VIF["VM Interface"] VIF --> IP SITE --> ASN["ASN(自治系统号)"] SITE --> CIRC["Circuit(专线电路)"] CIRC -.-> CTP["Circuit Type / Provider"] SITE --> PWR["Power Panel / Power Feed"]
2.2 关键对象说明
| 对象 | 作用 | 示例 | 必填前置 |
|---|---|---|---|
| Site | 物理位置(机房/数据中心) | BJ-IDC-1 北京机房1 | — |
| Location | 站点内区域(楼层/区域) | Floor-3-Rack-Row-A | Site |
| Rack | 机架(U 位管理) | Rack-A01 | Site/Location |
| Manufacturer | 设备厂商 | Cisco / Huawei / Dell | — |
| Device Type | 设备型号(模板) | Catalyst 9300-48P | Manufacturer |
| Device | 具体设备实例 | core-sw-01 | Device Type + Site |
| Interface | 设备上的接口 | GigabitEthernet0/1 | Device |
| IP Address | IP 地址 | 10.10.10.1/24 | Interface(可选) |
| Prefix | IP 前缀(子网) | 10.10.10.0/24 | VRF / VLAN(可选) |
| VLAN | 虚拟局域网 | VLAN 100 (Servers) | VLAN Group / Site |
| VRF | 虚拟路由转发实例 | prod-vrf | — |
| Tenant | 租户/业务线 | Finance-Team | — |
| Cluster | VM 集群 | vmware-cluster-1 | Cluster Type + Site |
| Virtual Machine | 虚拟机 | web-server-01 | Cluster |
| Cable | 物理线缆连接 | 接口 A ↔ 接口 B | 两个 Interface |
| ASN | 自治系统号 | AS65001 | — |
| Circuit | 专线电路 | MSTP-100M-To-IDC2 | Circuit Type + Provider |
2.3 录入顺序(推荐流程)
1. Organization/Tenant → 先建组织和业务线
2. Site/Location/Rack → 建站点、区域、机架
3. Manufacturer/DevType → 建厂商和设备型号(模板)
4. Device → 录入具体设备到机架
5. Interface → 设备上的接口(可从模板自动生成)
6. VLAN/VRF/Prefix → 建 VLAN、VRF、IP 前缀
7. IP Address → 分配 IP 到接口
8. Cable → 连接设备间的线缆
9. Cluster/VM → 虚拟机和集群四、IPAM:IP 地址管理
3.1 Prefix(前缀)管理
Prefix 是 IP 子网管理的基础单位。
IPAM → Prefixes → Add
┌───────────────────────────────────────────┐
│ Prefix: 10.10.10.0/24 │
│ Site: BJ-IDC-1 │
│ VRF: (none) / prod-vrf │
│ VLAN: VLAN 100 (Servers) │
│ Status: Active │
│ Role: Production Server Network │
│ Description: 服务器区生产网段 │
│ Tags: [production] │
└───────────────────────────────────────────┘Status(状态)取值:
| 状态 | 含义 | 颜色 |
|---|---|---|
| Active | 在用 | 绿 |
| Reserved | 保留(不分配) | 蓝 |
| Deprecated | 废弃 | 红 |
| Container | 容器(包含子前缀) | 灰 |
Role(角色)取值(可自定义):
| 角色 | 说明 |
|---|---|
| Production | 生产网段 |
| Management | 管理网(OOB/IPMI) |
| Staging | 预发布 |
| Loopback | 设备 loopback |
| Point-to-Point | 点对点链路 |
3.2 IP 地址分配
IPAM → IP Addresses → Add
┌────────────────────────────────────────────┐
│ Address: 10.10.10.11/24 │
│ Interface: core-sw-01 → Vlan100 │ ← 绑定到具体设备接口
│ VRF: (none) │
│ Tenant: Finance-Team │
│ Status: Active │
│ DNS Name: web-01.prod.example.com │
│ Description: Web 服务器 01 │
└────────────────────────────────────────────┘IP 分配的三种方式:
# 方式 1:手动指定 IP
GUI → IP Addresses → Add → 填 10.10.10.11/24
# 方式 2:从 Prefix 自动分配下一个可用 IP
# API:
curl -X POST http://localhost:8000/api/ipam/prefixes/1/available-ips/ \
-H "Authorization: Token YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"description": "auto-assigned"}'
# 返回自动选的下一个可用 IP
# 方式 3:批量分配
curl -X POST http://localhost:8000/api/ipam/prefixes/1/available-ips/ \
-H "Authorization: Token YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{"quantity": 10}'
# 一次分配 10 个 IP3.3 前缀层级与聚合
NetBox 支持前缀嵌套,自动计算聚合:
10.0.0.0/8 (Container)
├─ 10.10.0.0/16 (Container)
│ ├─ 10.10.10.0/24 (Active, Servers)
│ ├─ 10.10.20.0/24 (Active, Management)
│ └─ 10.10.30.0/24 (Active, Storage)
└─ 10.20.0.0/16 (Container)
└─ 10.20.10.0/24 (Active, DMZ)在 Prefix 列表页,可以用树状视图查看嵌套关系。
3.4 VLAN 管理
IPAM → VLANs → Add
┌────────────────────────────────────────────┐
│ VID: 100 │
│ Name: Servers │
│ VLAN Group: BJ-IDC-1-VLANs │ ← 按 Site 分组
│ Site: BJ-IDC-1 │
│ Status: Active │
│ Role: Production │
│ Description: 服务器区 VLAN │
└────────────────────────────────────────────┘VLAN 与 Prefix 关联:一个 Prefix 可以关联到一个 VLAN,表示这个子网跑在这个 VLAN 上:
Prefix 10.10.10.0/24 → VLAN 100 (Servers)
Prefix 10.10.20.0/24 → VLAN 200 (Management)3.5 VRF 管理
VRF(Virtual Routing and Forwarding)用于多租户/多网络隔离:
IPAM → VRF → Add
┌────────────────────────────────────────────┐
│ Name: prod-vrf │
│ RD: 65001:100 │ ← Route Distinguisher
│ Description: 生产环境 VRF │
│ Tenant: Finance-Team │
└────────────────────────────────────────────┘Prefix 和 IP Address 都可以关联 VRF。不同 VRF 下同一个 IP 不算冲突(因为在不同路由表里)。
五、DCIM:数据中心基础设施管理
4.1 机架管理
DCIM → Racks → Add
┌─────────────────────────────────────────────┐
│ Name: Rack-A01 │
│ Site: BJ-IDC-1 │
│ Location: Floor-3-Row-A │
│ Status: Active │
│ Type: 4-post cabinet(机架形态:2-post/4-post/wall/cabinet)│
│ Width: 19 inches │
│ Height: 42U(U 数,不是 Type 字段) │
│ Descending units: ☐ (从下往上编号) │
└─────────────────────────────────────────────┘机架视图展示每个 U 位被什么设备占用:
┌───┐
│42 │
│41 │ ┌──────────────┐
│40 │ │ core-sw-01 │ 2U
│39 │ │ Catalyst 9300│
│38 │ └──────────────┘
│37 │ (空)
│36 │ ┌──────────────┐
│35 │ │ server-01 │ 1U
│34 │ └──────────────┘
│.. │ ...
│ 1 │ ┌──────────────┐
│ │ │ PDU │ 1U
│ │ └──────────────┘
└───┘4.2 设备型号(Device Type)
Device Type 是设备模板,定义接口规格,不绑定具体实例。
DCIM → Device Types → Add
┌────────────────────────────────────────────┐
│ Manufacturer: Cisco │
│ Model: C9300-48P │
│ Part Number: C9300-48P-A │
│ Height (U): 1 │
│ Is Full Depth: ☑ (前后都有端口) │
│ Subdevice Role: Parent (支持子模块) │
│ │
│ Interface Templates: │
│ Management 0 → 1000BASE-T (mgmt) │
│ 1-48 → 1000BASE-T(48 口千兆电口,P=PoE+)│
│ 49-52 → 10GBASE-X(4 口 SFP+ 上联) │
│ │
│ Console Port Templates: │
│ Console 0 → RJ45 │
│ │
│ Power Port Templates: │
│ Power 0 → C13 │
│ Power 1 → C13 │
└────────────────────────────────────────────┘Device Type 的导入方式:
# 方法 1:从官方仓库导入(推荐)
# https://github.com/netbox-community/devicetype-library
# 里面有 4000+ 常见设备型号
git clone https://github.com/netbox-community/devicetype-library.git
# NetBox → Administration → Import Data → 选择 JSON/CSV 文件
# 方法 2:手动创建
# 方法 3:API 批量导入(见第六节)4.3 设备实例(Device)
DCIM → Devices → Add
┌────────────────────────────────────────────┐
│ Name: core-sw-01 │
│ Device Type: C9300-48P │
│ Site: BJ-IDC-1 │
│ Rack: Rack-A01 │
│ Position (U): 39 │ ← 机架 U 位
│ Face: Front │ ← 前面/后面
│ Status: Active │
│ Serial Number: FOC1234567 │
│ Asset Tag: ASSET-001 │
│ Tenant: Finance-Team │
│ Primary IP4: 10.10.10.1/24 │ ← 管理 IP
│ Description: 核心交换机 01 │
└────────────────────────────────────────────┘创建设备后,接口会从 Device Type 的模板自动生成。
4.4 接口(Interface)
DCIM → Devices → core-sw-01 → Interfaces
┌─────────────────────────────────────────────┐
│ Name Type Enabled MTU │
│ │
│ GigabitEthernet1 1000BASE-T ✓ 1500 │
│ GigabitEthernet2 1000BASE-T ✓ 1500 │
│ ... │
│ TenGigabitEthernet49 10GBASE-X ✓ 9216 │
│ ... │
│ Vlan100 virtual ✓ 9216 │ ← SVI 接口类型是 virtual(非 L2VLAN)
│ │ │
│ │ └─ IP: 10.10.10.1/24 │ ← IP 绑定到 VLAN 接口
│ │ └─ VRF: (none) │
│ │ └─ DNS: core-sw-01.prod.local │
│ │ │
│ Management0 1000BASE-T ✓ 1500 │
│ │ │
│ │ └─ IP: 192.168.1.11/24 (Management VRF) │
│ └──────────────────────────────────────────┘4.5 线缆连接(Cable)
DCIM → Cables → Add
┌───────────────────────────────────────────┐
│ Termination A: │
│ Device: core-sw-01 │
│ Interface: FortyGigabitEthernet49 │
│ │
│ Termination B: │
│ Device: dist-sw-01 │
│ Interface: FortyGigabitEthernet49 │
│ │
│ Type: Cat6a (铜缆) / SMF (单模光纤) │
│ Length: 3 m │
│ Color: Yellow (光纤黄色) │
│ Status: Connected │
└───────────────────────────────────────────┘线缆连接后,两侧接口的状态自动变为 Connected,在设备拓扑视图能看到连线关系。
六、虚拟化与集群
5.1 集群(Cluster)
Virtualization → Clusters → Add
┌───────────────────────────────────────────┐
│ Name: vmware-cluster-1 │
│ Type: VMware vSphere │
│ Site: BJ-IDC-1 │
│ Tenant: Finance-Team │
└───────────────────────────────────────────┘5.2 虚拟机(Virtual Machine)
Virtualization → Virtual Machines → Add
┌────────────────────────────────────────────┐
│ Name: web-server-01 │
│ Cluster: vmware-cluster-1 │
│ Status: Active │
│ Role: Web Server │
│ Tenant: Finance-Team │
│ Platform: Ubuntu 22.04 LTS │
│ vCPUs: 4 │
│ Memory (MB): 8192 │
│ Disk (GB): 100 │
│ Primary IP4: 10.10.10.11/24 │
│ Description: Nginx Web 服务器 │
└────────────────────────────────────────────┘VM 也有 Interface,可以绑定 IP Address,和物理设备的 Interface 模型一致。
七、REST API 自动化
6.1 获取 API Token
NetBox Web UI → 右上角用户名 → API Tokens → Add
┌────────────────────────────────────────┐
│ Description: Ansible 自动化 │
│ Write Enabled: ☑ │
│ Expires: (none) │
│ [Create] │
│ │
│ Token: 0123456789abcdef0123456789abc │ ← 只显示一次,保存好
└────────────────────────────────────────┘6.2 curl 示例
TOKEN="0123456789abcdef0123456789abcdef01234567"
BASE="http://localhost:8000/api"
# 列出所有 Site
curl -s -H "Authorization: Token $TOKEN" $BASE/dcim/sites/ | python3 -m json.tool
# 列出所有 Prefix
curl -s -H "Authorization: Token $TOKEN" "$BASE/ipam/prefixes/?limit=0" | python3 -m json.tool
# 从 Prefix 自动分配一个 IP
curl -s -X POST "$BASE/ipam/prefixes/1/available-ips/" \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"description": "web-server-01"}' | python3 -m json.tool
# 创建设备
curl -s -X POST "$BASE/dcim/devices/" \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "access-sw-01",
"device_type": 1,
"site": 1,
"rack": 1,
"position": 35,
"face": "front",
"status": "active"
}' | python3 -m json.tool
# 创建 IP 地址并绑定到接口
curl -s -X POST "$BASE/ipam/ip-addresses/" \
-H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"address": "10.10.10.12/24",
"assigned_object_type": "dcim.interface",
"assigned_object_id": 5,
"description": "web-server-02"
}' | python3 -m json.tool
# 搜索:所有属于 VLAN 编号 100 的 Prefix(vlan_vid 按编号过滤,vlan_id 按数据库主键过滤)
curl -s -H "Authorization: Token $TOKEN" \
"$BASE/ipam/prefixes/?vlan_vid=100&limit=0" | python3 -m json.tool6.3 pynetbox(Python 库)
pip install pynetboximport pynetbox
nb = pynetbox.api(
'http://localhost:8000',
token='0123456789abcdef0123456789abcdef01234567'
)
# ── 查询 ──
# 列出所有活跃设备
devices = nb.dcim.devices.filter(status='active')
for d in devices:
print(f"{d.name} @ {d.site.name} → {d.device_type.model}")
# 查某个 Site 的所有接口
interfaces = nb.dcim.interfaces.filter(device_id=1)
for iface in interfaces:
print(f"{iface.name} {iface.type} enabled={iface.enabled}")
# 查某 Prefix 下已分配的 IP(status=active)
assigned_ips = nb.ipam.ip_addresses.filter(parent='10.10.10.0/24', status='active')
# 查某 Prefix 下的空闲 IP(走 available-ips 端点,不能用 filter)
prefix = nb.ipam.prefixes.get(prefix='10.10.10.0/24')
free_ips = prefix.available_ips.list()
# ── 创建 ──
# 创建设备
device = nb.dcim.devices.create(
name='access-sw-02',
device_type=1,
site=1,
rack=1,
position=33,
face='front',
status='active'
)
# 从 Prefix 自动分配 IP
new_ip = nb.ipam.ip_addresses.create(
address='10.10.10.12/24',
assigned_object_type='dcim.interface',
assigned_object_id=5,
description='auto-assigned'
)
# ── 更新 ──
# 更新设备状态
device = nb.dcim.devices.get(name='access-sw-02')
device.status = 'decommissioning'
device.save()
# ── 批量操作 ──
# 批量创建接口
nb.dcim.interfaces.create([
{'device': 1, 'name': 'GigabitEthernet0/1', 'type': '1000base-t'},
{'device': 1, 'name': 'GigabitEthernet0/2', 'type': '1000base-t'},
{'device': 1, 'name': 'GigabitEthernet0/3', 'type': '1000base-t'},
])6.4 Ansible 动态清单
# ansible.cfg
[inventory]
enable_plugins = netbox.netbox.nb_inventory
# 安装 collection(推荐,替代旧版 pip install ansible-modules-netbox)
ansible-galaxy collection install netbox.netbox# netbox.yml
plugin: netbox.netbox.nb_inventory
api_endpoint: http://localhost:8000
token: 0123456789abcdef0123456789abcdef01234567
validate_certs: false
# 按设备角色/站点/标签分组
# 注:NetBox 4.0 起 DeviceRole 已泛化为 Role,字段用 role
group_by:
- role
- sites
- tags
# 只取活跃设备
query_filters:
- status: active# 使用动态清单
ansible all -i netbox.yml -m ping
# 只 ping 某个 Site 的设备
ansible -i netbox.yml -m ping "site_BJ-IDC-1"
# 从 NetBox 获取变量
ansible-inventory -i netbox.yml --host web-server-01 --vars6.5 Ansible Playbook 示例
---
- name: 配置交换机接口
hosts: "site_BJ-IDC-1"
vars:
netbox_url: http://localhost:8000
netbox_token: 0123456789
tasks:
# 从 NetBox 拉设备信息
- name: 获取设备信息
uri:
url: "{{ netbox_url }}/api/dcim/devices/?name={{ inventory_hostname }}"
headers:
Authorization: "Token {{ netbox_token }}"
return_content: yes
register: device_info
# 从 NetBox 拉接口列表(接口是独立 API 端点,设备 API 不含 interfaces 字段)
- name: 获取设备接口列表
uri:
url: "{{ netbox_url }}/api/dcim/interfaces/?device_id={{ (device_info.content | from_json).results[0].id }}"
headers:
Authorization: "Token {{ netbox_token }}"
return_content: yes
register: interface_info
# 用接口信息配置交换机
- name: 配置接口
cisco.ios.ios_interfaces:
config:
- name: "{{ item.name }}"
enabled: "{{ item.enabled }}"
loop: "{{ (interface_info.content | from_json).results }}"八、自定义与扩展
7.1 自定义字段(Custom Fields)
给任何对象加业务属性:
Admin → Customization → Custom Fields → Add
┌─────────────────────────────────────────────┐
│ Name: asset_owner │
│ Type: Text │
│ Object Types: ☑ dcim.device │
│ ☑ virtualization.virtualmachine │
│ Required: ☐ │
│ Default: (none) │
│ Description: 资产归属人 │
│ Filter Logic: Filterable │
└─────────────────────────────────────────────┘加完后,设备/VM 页面会多一个 asset_owner 字段,可以在列表里过滤搜索。
7.2 自定义链接(Custom Links)
在设备页面加外部链接:
Admin → Customization → Custom Links → Add
┌────────────────────────────────────────────┐
│ Name: Open in Grafana │
│ Object Type: dcim.device │
│ URL: https://grafana.example.com/d/dashboard?var-device={{ object.name }} │
│ Button Class: Info │
│ New Window: ☑ │
└────────────────────────────────────────────┘7.3 Webhooks
设备状态变更时自动触发外部操作:
Admin → Operations → Webhooks → Add
┌────────────────────────────────────────────┐
│ Name: Device-Status-Change │
│ Content Type: dcim.device │
│ HTTP Method: POST │
│ URL: http://ansible-tower:8080/api/v2/job_templates/5/launch/ │
│ HTTP Content Type: application/json │
│ Body: {"device": "{{ object.name }}", "status": "{{ object.status }}"} │
│ Secret: webhook-auth-token │
│ Conditions: {"and":[{"attr":"status.value","op":"ne","value":"active"}]} │ ← JSON 逻辑表达式(示意:status != active)│7.4 导出模板
用 Jinja2 模板生成自定义报告:
Admin → Customization → Export Templates → Add
┌────────────────────────────────────────────┐
│ Name: device-rack-report │
│ Object Type: dcim.device │
│ Template: │
│ {% for device in queryset %} │
│ {{ device.name }},{{ device.site.name }},{{ device.rack.name }},U{{ device.position }} │
│ {% endfor %} │
└────────────────────────────────────────────┘使用:设备列表页 → 导出 → 选 device-rack-report。
7.5 GraphQL 查询
NetBox 内置 GraphQL(2.11+,v4.0 起迁移至 Strawberry 引擎):
# 查询某站点的所有设备和 IP
curl -s -H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-X POST http://localhost:8000/graphql/ \
-d '{
"query": "{ site(name: \"BJ-IDC-1\") { devices { name device_type { model manufacturer { name } } interfaces { name ip_addresses { address } } } } }"
}' | python3 -m json.tool九、常用 API 速查
| 操作 | API 路径 | 方法 |
|---|---|---|
| 列出所有 Site | /api/dcim/sites/ | GET |
| 列出所有 Rack | /api/dcim/racks/ | GET |
| 列出所有 Device | /api/dcim/devices/ | GET |
| 列出所有 Interface | /api/dcim/interfaces/ | GET |
| 列出所有 Prefix | /api/ipam/prefixes/ | GET |
| 列出所有 IP Address | /api/ipam/ip-addresses/ | GET |
| 列出所有 VLAN | /api/ipam/vlans/ | GET |
| 列出所有 VRF | /api/ipam/vrfs/ | GET |
| 列出所有 Cable | /api/dcim/cables/ | GET |
| 列出所有 VM | /api/virtualization/virtual-machines/ | GET |
| 从 Prefix 分配 IP | /api/ipam/prefixes/{id}/available-ips/ | POST |
| 查可用 IP | /api/ipam/prefixes/{id}/available-ips/ | GET |
| 查前缀内可用前缀 | /api/ipam/prefixes/{id}/available-prefixes/ | GET |
| 按关键字搜索设备 | /api/dcim/devices/?name__ic=core(模糊)/ ?name=core(精确) | GET |
| 按 Site 过滤 | /api/dcim/devices/?site_id=1 | GET |
| 按 VLAN 编号过滤 Prefix | /api/ipam/prefixes/?vlan_vid=100(vlan_id 是数据库主键) | GET |
| 按租户过滤 IP | /api/ipam/ip-addresses/?tenant_id=1 | GET |
| 更新设备 | /api/dcim/devices/{id}/ | PATCH |
| 删除设备 | /api/dcim/devices/{id}/ | DELETE |
分页参数:
| 参数 | 作用 |
|---|---|
limit=0 | 返回所有(不分页,大查询慎用) |
limit=50 | 每页 50 条(默认 50) |
offset=100 | 跳过前 100 条 |
十、排障
排障 1:无法登录 / 403 Forbidden
# 1. 检查 ALLOWED_HOSTS 是否包含你的域名(Docker 模式下从环境变量注入,不在 configuration.py)
docker compose exec netbox env | grep ALLOWED
# 2. 检查 Token 是否正确
curl -H "Authorization: Token YOUR_TOKEN" http://localhost:8000/api/dcim/sites/
# 返回 403 → Token 写错了或没权限
# 3. 检查用户是否激活
docker compose exec netbox /opt/netbox/netbox/manage.py shell
>>> from django.contrib.auth.models import User
>>> u = User.objects.get(username='admin')
>>> print(u.is_active, u.is_superuser)排障 2:Docker 容器启动失败
# 1. 看 postgres 起了没
docker compose ps postgres
# 如果 Exited → 磁盘满或密码不对
# 2. 看 redis 起了没
docker compose ps redis
# 3. 看 netbox 日志
docker compose logs netbox | tail -30
# 常见报错:
# "could not connect to server" → postgres 没起或网络不通
# "relation does not exist" → 数据库没迁移 → docker compose exec netbox /opt/netbox/netbox/manage.py migrate排障 3:数据库迁移失败
# 手动执行迁移
docker compose exec netbox /opt/netbox/netbox/manage.py migrate
# 如果报 "already exists" → 数据库和代码版本不匹配
# 方法 1:降级回旧版镜像
# 先编辑 docker-compose.yml 将 netbox 服务的 image 改为 netboxcommunity/netbox:v3.5.0
docker compose pull netbox
docker compose up -d
# 方法 2:从备份恢复
cat netbox-backup.sql | docker compose exec -T postgres psql -U netbox排障 4:API 返回空结果
# 1. 检查过滤条件
curl -s -H "Authorization: Token $TOKEN" \
"http://localhost:8000/api/dcim/devices/?site_id=999" | python3 -m json.tool
# site_id=999 不存在 → 返回空 results 但不是报错
# 2. 检查权限
# 某些 Token 只读 → 不能 POST
curl -s -X POST -H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"test"}' http://localhost:8000/api/dcim/sites/
# 返回 403 → Token 没开 Write
# 3. 检查分页
# 默认只返回前 50 条
curl -s -H "Authorization: Token $TOKEN" \
"http://localhost:8000/api/dcim/devices/?limit=0" # limit=0 = 全部排障 5:IP 冲突 / 无法分配
# 看看这个 IP 是不是已经被占用了
curl -s -H "Authorization: Token $TOKEN" \
"http://localhost:8000/api/ipam/ip-addresses/?address=10.10.10.11"
# 如果有结果 → 这个 IP 已被分配
# 强制使用已被分配的 IP → 先删除旧的或改 status=reserved
curl -s -X PATCH -H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"status": "deprecated"}' \
"http://localhost:8000/api/ipam/ip-addresses/5/"排障 6:Device Type 导入失败
# 常见原因:Manufacturer 不存在
# Device Type 必须关联一个已存在的 Manufacturer
# 先建 Manufacturer
curl -s -X POST -H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "Cisco", "slug": "cisco"}' \
http://localhost:8000/api/dcim/manufacturers/
# 再导入 Device Type
# 从 devicetype-library 仓库拉 JSON
# 或手动创建排障 7:机架视图 U 位不显示设备
原因:设备没填 Position (U) 或设备 U 数为 0# 检查设备
curl -s -H "Authorization: Token $TOKEN" \
"http://localhost:8000/api/dcim/devices/?name=core-sw-01" | python3 -m json.tool
# 看 "position" 和 "device_type" 的 "u_height"
# 修复:设置 position
curl -s -X PATCH -H "Authorization: Token $TOKEN" \
-H "Content-Type: application/json" \
-d '{"position": 39, "face": "front"}' \
"http://localhost:8000/api/dcim/devices/1/"排障 8:Cable 连接不显示
原因:Cable 的两个 Termination 之一状态不对检查:
1. 两个 Interface 都存在且 enabled
2. 两个 Interface 不能在同一个 Device 上
3. Interface 类型兼容(以太网↔以太网,串口↔串口)
4. 创建 Cable 后 Interface 状态自动变 Connected排障 9:Redis 连接失败
docker compose logs netbox | grep -i redis
# 报 "Error 111 connecting to redis" → redis 容器没起
# 修复
docker compose up -d redis
# 等 redis 健康后再起 netbox
docker compose restart netbox排障 10:升级后页面 500
# 大概率是静态文件没收集
docker compose exec netbox /opt/netbox/netbox/manage.py collectstatic --noinput
# 还是 500 → 看详细错误
docker compose exec netbox /opt/netbox/netbox/manage.py runserver 0.0.0.0:8000
# 直接看 traceback排障 11:Nginx 502 / Connection Refused
# netbox 在跑吗
docker compose ps netbox
# 如果 Exited → docker compose logs netbox 看报错
# 端口对不对
ss -tlnp | grep 8000
# 没有监听 → netbox 没起或端口没映射
# Nginx 反代配置里 proxy_pass 地址对不对
# 应该是 http://127.0.0.1:8000排障 12:pynetbox 报 ObjectNotFound
# 用 .get() 找不到时报 ObjectNotFound
# 原因:名字写错或对象不存在
# 排查
import pynetbox
nb = pynetbox.api('http://localhost:8000', token='...')
# 列出所有看名字
for d in nb.dcim.devices.all():
print(d.name)
# 用 filter 而不是 get
devices = nb.dcim.devices.filter(name__isw='core') # isw = starts with(大小写不敏感)
# 包含匹配用 name__ic='core',精确匹配用 name='core'十一、最佳实践
10.1 数据录入规范
- 先建厂商和设备型号:从 devicetype-library 仓库批量导入 4000+ 型号,省去手动创建
- IP 管理用 API 不用手动:自动分配防冲突,人类手动填必出错
- VLAN 统一编号:全公司 VLAN ID 唯一,不要每个站点自己编一套
- VRF 区分多租户:不同业务线共享 IP 段时用 VRF 隔离
- Cable 必填:不画线缆连接的 NetBox 只是半个 CMDB
- Device Serial Number 必填:保修和资产追踪靠这个
- Tenant 给所有资源打标签:按租户/业务线过滤是最常用查询
10.2 与其他工具集成
| 工具 | 集成方式 | 用途 |
|---|---|---|
| Ansible | 动态清单 + API | 用 NetBox 数据驱动配置 |
| Terraform | Provider | 用 NetBox 做 IP 分配 |
| Grafana | JSON API 数据源 | 仪表盘展示基础设施状态 |
| Prometheus | NetBox Exporter | 监控指标 + CMDB 关联 |
| NetDisco | API 对账 | NetDisco 自动发现 → 写入 NetBox |
| GitLab CI | API | 管道里自动注册设备 |
10.3 安全建议
| 项 | 建议 |
|---|---|
| Token 权限 | 按需开 Write,只读 Token 更安全 |
| 用户管理 | 开 LDAP/OIDC,别只用本地密码 |
| HTTPS | 生产必须反代 + 证书 |
| 备份 | pg_dump 每天 cron |
| 审计 | Webhook 记录变更到外部系统 |
| 升级 | 先备份 → 再升级 → 看迁移日志 |
10.4 推荐插件
| 插件 | 功能 | 安装 |
|---|---|---|
| netbox-topology-views | 拓扑图可视化 | pip install netbox-topology-views |
| netbox-bgp | BGP 会话管理 | pip install netbox-bgp |
| netbox-ddns | DNS 动态更新 | pip install netbox-ddns |
| netbox-plugin-dns | DNS 记录管理 | pip install netbox-plugin-dns |
| (已弃用)netbox-reports | 自定义合规检查 | NetBox 3.5 弃用、v4.0 移除,功能并入 Custom Scripts(内置) |
# 安装插件
# 1. Docker 模式:在 configuration/plugins.py 里加
echo "PLUGINS = ['netbox_topology_views']" >> /opt/netbox/netbox/netbox/configuration/plugins.py
# 2. 重启
docker compose restart netbox
# 3. 迁移
docker compose exec netbox /opt/netbox/netbox/manage.py migrate十二、运维常用操作
# 查看 NetBox 版本(无 manage.py version 子命令,走 API)
curl -s -H "Authorization: Token $TOKEN" http://localhost:8000/api/status/ | python3 -m json.tool | grep netbox_version
# 创建超级用户
docker compose exec netbox /opt/netbox/netbox/manage.py createsuperuser
# 重置用户密码
docker compose exec netbox /opt/netbox/netbox/manage.py changepassword admin
# 收集静态文件
docker compose exec netbox /opt/netbox/netbox/manage.py collectstatic --noinput
# 数据库迁移
docker compose exec netbox /opt/netbox/netbox/manage.py migrate
# 进入 Django shell
docker compose exec netbox /opt/netbox/netbox/manage.py shell
# 备份数据库
docker compose exec postgres pg_dump -U netbox netbox > backup-$(date +%Y%m%d).sql
# 恢复
cat backup-20260828.sql | docker compose exec -T postgres psql -U netbox
# 清理旧 session
docker compose exec netbox /opt/netbox/netbox/manage.py clearsessions
# 清理变更日志(保留 90 天)
docker compose exec netbox /opt/netbox/netbox/manage.py \
shell -c "from datetime import datetime, timedelta; from extras.models import ObjectChange; ObjectChange.objects.filter(time__lt=datetime.now()-timedelta(days=90)).delete()"