如何配置Mininet使其单次仅连集群SDN控制器并实现故障切换
实现Mininet单控制器连接+故障自动切换
核心问题分析
你之前的配置会让Mininet同时连接多个控制器,是因为通过--controller=remote,ip=xxx重复添加了多个控制器实例,导致OVS交换机同时注册到所有控制器上。要实现单次连一个、故障自动切换的需求,有三种可行方案:
方案1:基于OVS原生机制的自动切换(推荐)
利用OVS自带的控制器故障切换功能,无需修改Mininet脚本,直接配置OVS即可实现按顺序尝试连接控制器,仅当前控制器故障时才切换到下一个。
操作步骤
- 启动不带预设控制器的Mininet:
mn --topo=tree,2 --controller=none - 在Mininet CLI中,为每个交换机配置控制器列表和故障模式:
# 给交换机s1添加控制器列表(按优先级排序,优先连接第一个) !ovs-vsctl set-controller s1 tcp:192.168.1.10:6633 tcp:192.168.1.11:6633 tcp:192.168.1.12:6633 # 设置故障模式为secure,确保控制器故障时交换机保留流表并尝试连接下一个控制器 !ovs-vsctl set-fail-mode s1 secure - 验证:手动关闭当前连接的控制器,OVS会自动尝试连接列表中的下一个控制器,无需人工干预。
方案2:Mininet命令行手动切换(适合测试场景)
如果只是临时测试切换逻辑,可以先启动Mininet连接单个控制器,故障时手动在CLI中切换。
操作步骤
- 启动Mininet并指定单个控制器:
mn --controller=remote,ip=192.168.1.10,port=6633 --topo=tree,2 - 当当前控制器故障时,在Mininet CLI中执行以下命令切换:
# 删除当前控制器实例 py net.delController(c0) # 添加新的控制器实例 py c1 = net.addController('c1', controller=RemoteController, ip='192.168.1.11', port=6633) # 将所有交换机绑定到新控制器 py for s in net.switches: s.setController(c1)
方案3:自定义Mininet脚本实现自动切换(适合自动化场景)
通过编写Python脚本,集成控制器故障检测逻辑,实现全自动切换。
示例脚本
from mininet.net import Mininet from mininet.node import RemoteController, OVSSwitch from mininet.cli import CLI from mininet.log import setLogLevel, info import time import socket def check_controller(ip, port): """检测控制器是否可达""" sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(2) try: return sock.connect_ex((ip, port)) == 0 finally: sock.close() def main(): setLogLevel('info') # 按优先级排序的控制器列表 ctrl_list = [('192.168.1.10', 6633), ('192.168.1.11', 6633), ('192.168.1.12', 6633)] current_idx = 0 curr_ip, curr_port = ctrl_list[current_idx] # 初始化网络,连接第一个控制器 net = Mininet(controller=RemoteController, switch=OVSSwitch) info(f"连接初始控制器: {curr_ip}:{curr_port}\n") main_ctrl = net.addController('c0', ip=curr_ip, port=curr_port) # 定义拓扑(可根据需求修改) s1 = net.addSwitch('s1') h1 = net.addHost('h1') h2 = net.addHost('h2') net.addLink(s1, h1) net.addLink(s1, h2) net.start() info("网络启动完成\n") # 后台监控控制器状态的线程 def monitor_and_switch(): nonlocal current_idx, main_ctrl while True: time.sleep(5) # 检测当前控制器状态 if not check_controller(ctrl_list[current_idx][0], ctrl_list[current_idx][1]): info(f"\n控制器 {ctrl_list[current_idx][0]}:{ctrl_list[current_idx][1]} 故障!\n") # 删除旧控制器 net.delController(main_ctrl) # 切换到下一个控制器(循环切换) current_idx = (current_idx + 1) % len(ctrl_list) new_ip, new_port = ctrl_list[current_idx] info(f"切换到备用控制器: {new_ip}:{new_port}\n") # 添加新控制器并绑定到所有交换机 main_ctrl = net.addController('c0', ip=new_ip, port=new_port) for switch in net.switches: switch.setController(main_ctrl) info("控制器切换完成\n") # 启动监控线程 import threading monitor_thread = threading.Thread(target=monitor_and_switch) monitor_thread.daemon = True monitor_thread.start() # 启动Mininet CLI CLI(net) net.stop() if __name__ == '__main__': main()
脚本说明
- 采用定时检测控制器端口可达性的方式判断故障(也可替换为监听OpenFlow的ECHO超时事件,更精准)
- 控制器列表按优先级排序,故障时循环切换
- 后台线程自动处理切换逻辑,无需人工干预
内容的提问来源于stack exchange,提问作者Titus
相关产品推荐
相关产品推荐

