第339篇:SRv6 骨干网部署案例
关键词
SRv6、Segment Routing、IPv6、骨干网、流量工程、网络编程、SDN、TE
一、案例背景
1.1 为什么要部署 SRv6
传统 MPLS 骨干网的痛点:
协议栈复杂:
┌──────────────────────────────────────────┐
│ LDP(标签分发)+ RSVP-TE(流量工程) │
│ + BGP-LU(跨域标签)+ MPLS 转发 │
│ └─ 控制面协议太多,运维复杂 │
└──────────────────────────────────────────┘
流量工程能力有限:
┌──────────────────────────────────────────┐
│ RSVP-TE 需要逐条建立隧道 │
│ 隧道数量受限于设备规格 │
│ 网络变化时需要重新建立 │
│ 不支持随流检测 │
└──────────────────────────────────────────┘
运维复杂:
┌──────────────────────────────────────────┐
│ MPLS 标签管理复杂 │
│ 标签分配、标签栈、标签转发路径排障难 │
│ 跨域需要方案 B/C │
│ IPv4 地址空间紧张 │
└──────────────────────────────────────────┘
SRv6 的优势:
┌──────────────────────────────────────────┐
│ 简化协议栈:只要 IS-IS/BGP + IPv6 │
├─ 无需 LDP/RSVP-TE │
├─ 原生流量工程(TE) │
├─ 网络可编程(Segment List) │
├─ 原生随流检测(iFIT) │
└─ 平滑演进(现网升级) │
└──────────────────────────────────────────┘
1.2 部署目标
某运营商骨干网 SRv6 部署目标:
现网规模:
节点:50 台核心路由器 链路:120 条 100GE/400GE 流量:峰值 12 Tbps 业务:MPLS L3VPN + L2VPN + Internet
部署目标:
- 全部节点支持 SRv6
- 控制面使用 IS-IS Extensions for SRv6
- 部署 SRv6 BE(Best Effort)
- 部署 SRv6 TE(流量工程)
- 保留传统 MPLS 能力(平滑演进)
- 零业务中断完成升级
二、SRv6 基础配置
2.1 IS-IS SRv6 扩展
# srv6_basic_config.py — SRv6 基础配置
def generate_srv6_underlay():
"""IS-IS SRv6 Underlay 配置"""
config = """
sysname PE-R1
# ========== IPv6 基础 ==========
ipv6
interface LoopBack0
ipv6 enable
ipv6 address 2001:DB8:1::1/128
interface GigabitEthernet0/0/0
ipv6 enable
ipv6 address 2001:DB8:10::1/64
isis ipv6 enable 1
interface GigabitEthernet0/0/1
ipv6 enable
ipv6 address 2001:DB8:11::1/64
isis ipv6 enable 1
# ========== IS-IS for SRv6 ==========
isis 1
is-level level-2
network-entity 49.0001.0000.0000.0001.00
#
# IPv6 地址族使能
ipv6 enable topology ipv6
#
# SRv6 能力通告
segment-routing ipv6
locator PE1-LOCATOR ipv6-prefix 2001:DB8:100::/48
opcode 1 end # END SID
opcode 2 end-x # END.X SID
#
locator PE1-LOCATOR2 ipv6-prefix 2001:DB8:200::/48
opcode 1 end
# ========== Locator 配置 ==========
segment-routing ipv6
encapsulation source-address 2001:DB8:1::1
locator PE1-LOCATOR ipv6-prefix 2001:DB8:100::/48
# 每个 locator 可以分配 65536 个 SID
opcode 1 end # END: 节点 SID (2001:DB8:100:0:1::)
opcode 2 end-x # END.X: 邻接 SID (2001:DB8:100:0:2::)
#
# 自动分配的 SID 范围
static 32 # 静态 SID 数量
auto 4096 # 自动分配 SID 数量
"""
return config
def generate_srv6_te_config():
"""SRv6 TE Policy 配置"""
config = """
sysname PE-R1
# ========== SRv6 TE Policy ==========
segment-routing ipv6
#
# TE Policy 定义
traffic-engineering
#
# 策略 1:低延迟路径
policy TE-POLICY-LOW-LATENCY
color 100
endpoint 2001:DB8:2::2 # 目的 PE
candidate-paths
preference 100
explicit segment-list LOW_LAT_PATH
#
# 策略 2:高带宽路径
policy TE-POLICY-HIGH-BW
color 200
endpoint 2001:DB8:2::2
candidate-paths
preference 100
explicit segment-list HIGH_BW_PATH
# ========== Segment List ==========
segment-routing ipv6
traffic-engineering
segment-list LOW_LAT_PATH
index 10 sid 2001:DB8:100:0:1:: # R1 (END)
index 20 sid 2001:DB8:200:0:5:: # R5 (END)
index 30 sid 2001:DB8:300:0:2:: # R2 (END)
segment-list HIGH_BW_PATH
index 10 sid 2001:DB8:100:0:1:: # R1
index 20 sid 2001:DB8:400:0:3:: # R3
index 30 sid 2001:DB8:500:0:4:: # R4
index 40 sid 2001:DB8:300:0:2:: # R2
# ========== 验证命令 ==========
# display segment-routing ipv6 locator
# display segment-routing ipv6 te policy
# display segment-routing ipv6 te tunnel
"""
return config
三、部署实施方案
3.1 平滑升级方案
SRv6 平滑演进步骤:
阶段 1:评估和规划(1 个月)
□ 确认所有设备硬件支持 SRv6 □ 确认软件版本支持 □ 设计 SRv6 Locator 和 SID 规划 □ 制定分批次升级计划 □ 制定回退计划
阶段 2:控制面升级(夜间窗口,每批 5 台)
批次 1(测试节点) └─ 升级 2 台边缘路由器 └─ 验证 IS-IS SRv6 扩展正常 └─ 验证 Locator 发布 └─ 验证现有 MPLS 业务不受影响 批次 2-4(核心节点) └─ 每次升级 5 台核心路由器 └─ 验证 IS-IS 邻居不中断 └─ 验证 SRv6 BE 转发 批次 5(全部完成) └─ 所有节点 IS-IS SRv6 使能 └─ 全网 SRv6 BE 就绪
阶段 3:业务迁移(周末窗口)
- 在 PE 上配置 SRv6 VPN
- 建立 SRv6 L3VPN 隧道
- 验证 SRv6 VPN 业务正常
- 逐个 VRF 迁移到 SRv6
- 保留 MPLS VPN 作为回退
- 确认所有 VPN 迁移完成后关 MPLS
阶段 4:流量工程部署
- 部署 SRv6 TE Policy
- 配置 BGP SR Policy
- 对接控制器(SDN)
- 构建随流检测(iFIT)
3.2 自动化部署脚本
# srv6_deploy.py — SRv6 自动化部署
from netmiko import ConnectHandler
import json
import time
from concurrent.futures import (
ThreadPoolExecutor, as_completed
)
class SRv6Deployer:
"""SRv6 自动化部署器"""
def __init__(self, inventory: str):
with open(inventory, "r") as f:
self.devices = json.load(f)
def check_srv6_capability(self, device: dict) -> dict:
"""检查设备 SRv6 能力"""
try:
conn = ConnectHandler(**device)
output = conn.send_command(
"display segment-routing ipv6 capability"
)
support = "support" in output.lower()
version = conn.send_command("display version")
conn.disconnect()
return {
"device": device.get("hostname", ""),
"srv6_support": support,
"version": version.splitlines()[0] if version else "",
}
except Exception as e:
return {"device": device.get("hostname", ""), "error": str(e)}
def deploy_srv6_base(self, device: dict) -> bool:
"""部署 SRv6 基础配置"""
try:
conn = ConnectHandler(**device)
conn.enable()
hostname = conn.find_prompt().rstrip("#>")
config_lines = [
"ipv6",
"isis 1",
" ipv6 enable topology ipv6",
" segment-routing ipv6",
f" locator {hostname}-LOCATOR"
f" ipv6-prefix 2001:DB8:100::/48",
" opcode 1 end",
" opcode 2 end-x",
" segment-routing ipv6",
f" encapsulation source-address"
f" 2001:DB8:1::{device.get('id', 1)}",
f" locator {hostname}-LOCATOR"
f" ipv6-prefix 2001:DB8:100::/48",
" static 32",
" auto 4096",
]
output = conn.send_config_set(config_lines)
has_error = "Error" in output
conn.save_config()
conn.disconnect()
return not has_error
except Exception as e:
print(f"部署失败: {e}")
return False
def verify_srv6(self, device: dict) -> dict:
"""验证 SRv6 部署"""
try:
conn = ConnectHandler(**device)
conn.enable()
results = {
"locator": conn.send_command(
"display segment-routing ipv6 locator"
),
"sid_list": conn.send_command(
"display segment-routing ipv6 sid"
),
"te_policy": conn.send_command(
"display segment-routing ipv6"
" te policy"
),
}
# 检查 IS-IS SRv6 扩展
results["isis_srv6"] = conn.send_command(
"display isis segment-routing ipv6"
)
conn.disconnect()
return results
except Exception as e:
return {"error": str(e)}
def deploy_all(self, batch_size: int = 5):
"""批量部署 SRv6"""
results = {"success": [], "failed": []}
with ThreadPoolExecutor(
max_workers=batch_size
) as executor:
futures = {
executor.submit(
self.deploy_srv6_base, dev
): dev
for dev in self.devices
}
for future in as_completed(futures):
dev = futures[future]
host = dev.get("hostname", "unknown")
try:
if future.result():
results["success"].append(host)
print(f"✅ {host}: SRv6 部署成功")
else:
results["failed"].append(host)
print(f"❌ {host}: SRv6 部署失败")
except Exception as e:
results["failed"].append(host)
print(f"❌ {host}: 异常 - {e}")
return results
四、SRv6 VPN 业务
4.1 SRv6 L3VPN
# srv6_vpn_config.py — SRv6 VPN 配置
def generate_srv6_l3vpn():
"""SRv6 L3VPN 配置"""
config = """
sysname PE-R1
# ========== VRF ==========
ip vpn-instance CUSTOMER-A
ipv6 enable
route-distinguisher 100:1
vpn-target 100:1 export-extcommunity
vpn-target 100:1 import-extcommunity
# ========== CE 接口 ==========
interface GigabitEthernet0/0/2
description to-CE
ip binding vpn-instance CUSTOMER-A
ip address 10.10.0.1 255.255.255.252
# ========== SRv6 VPN(替代传统 MPLS VPN) ==========
bgp 100
router-id 10.0.0.1
peer 2001:DB8:2::2 as-number 100 # 对端 PE
peer 2001:DB8:2::2 connect-interface LoopBack0
#
# SRv6 SID 分配
segment-routing ipv6
locator PE1-LOCATOR
#
ipv4-family vpn-instance CUSTOMER-A
segment-routing ipv6 # 使用 SRv6 封装
peer 10.10.0.2 as-number 65001
#
ipv6-family vpn-instance CUSTOMER-A
segment-routing ipv6
#
ipv4-family vpnv4
peer 2001:DB8:2::2 enable
peer 2001:DB8:2::2 segment-routing ipv6
"""
return config
def generate_srv6_evpn():
"""SRv6 EVPN VXLAN 配置"""
config = """
sysname LEAF-1
# ========== SRv6 EVPN ==========
evpn
vpn-instance EVPN-A
route-distinguisher 100:1
vpn-target 100:1 export-extcommunity
vpn-target 100:1 import-extcommunity
bridge-domain 10
vxlan vni 10010
evpn
route-distinguisher 100:1
vpn-target 100:1 export-extcommunity
vpn-target 100:1 import-extcommunity
interface Nve1
source 2001:DB8:1::1
vni 10010 head-end peer-list protocol bgp
bgp 100
router-id 10.0.0.1
peer 2001:DB8:2::2 as-number 100
l2vpn-family evpn
policy vpn-target
peer 2001:DB8:2::2 enable
peer 2001:DB8:2::2 segment-routing ipv6 # SRv6 EVPN
"""
return config
五、验证与排障
5.1 验证命令
# SRv6 部署验证命令集
# 1. Locator 和 SID
display segment-routing ipv6 locator
display segment-routing ipv6 sid
# 2. IS-IS SRv6 扩展
display isis segment-routing ipv6 capability
display isis route ipv6
# 3. TE Policy
display segment-routing ipv6 te policy
display segment-routing ipv6 te tunnel
# 4. SRv6 转发
display segment-routing ipv6 forwarding
# 5. SRv6 VPN
display bgp vpnv4 all routing-table
display ip routing-table vpn-instance CUSTOMER-A
# 6. 端到端连通性
ping ipv6 2001:DB8:2::2
ping -vpn-instance CUSTOMER-A 10.20.0.1
# 7. SRv6 隧道封装验证
display ipv6 routing-table 2001:DB8:2::2
5.2 常见问题
SRv6 部署常见问题:
问题 1:SID 分配失败
原因:Locator 前缀冲突 修复:确保全网 Locator 前缀唯一 验证:display segment-routing ipv6 locator
问题 2:SRv6 隧道不建立
原因:IS-IS SRv6 Capability 不通告 修复: 验证:display isis segment-routing ipv6 display isis lsdb
问题 3:SRv6 VPN 不通
原因:SID 解析失败 修复:检查 Locator 路由是否可达 验证:ping ipv6 2001:DB8:100::1
问题 4:MTU 问题
原因:SRv6 封装增加 IPv6 头(40 字节) + SRH(8-40 字节) 修复:调整接口 MTU 或配置 TCP MSS
六、经验总结
SRv6 骨干网部署关键经验:
1. 硬件先行
┌─ 确认所有硬件支持 SRv6(NP 芯片支持)
├─ 确认软件版本符合要求
├─ 注意不同厂商 SRv6 实现差异
└─ 测试环境充分测试后再上线
2. Locator 规划至关重要
┌─ Locator 前缀全网唯一
├─ 建议按地域/功能分配 Locator 段
├─ 预留足够的 SID 空间
└─ 好的规划避免后期大规模调整
3. 平滑演进策略
┌─ 先 SRv6 BE,再 SRv6 TE
├─ 保留传统 MPLS 作为回退
├─ 逐步迁移业务,不要"大爆炸"
└─ 每步验证通过后才继续
4. 自动化部署
┌─ 批量部署脚本(Ansible/Python)
├─ 配置模板化(Jinja2)
├─ 验证自动化(pyATS/Genie)
└─ 监控 Telemetry 数据
5. 运维转型
┌─ 传统 MPLS 排障经验不完全适用
├─ SRv6 排障重点是 SID 和 Locator
├─ 需要掌握 IPv6 路由协议
└─ 建设 SRv6 可视化运维平台
下篇预告:第340篇《EVPN_VXLAN数据中心互联案例》——通过DCI互联案例,掌握EVPN VXLAN跨数据中心的部署与排障。
下篇预告:第340篇《EVPN_VXLAN数据中心互联案例》——通过DCI互联案例,掌握EVPN VXLAN跨数据中心的部署与排障。