☰
Ubuntu 18.04 安装 Ryu 与 Mininet:SDN 实验环境搭建避坑指南
2026/10/20 3:31:42 网站建设 项目流程

搞SDN实验的人,十有八九都绕不开Ryu和Mininet这对组合。我上次在一台Ubuntu18.04上从头装了一遍,中间踩了不少坑,包括Python版本冲突、pip依赖编译不过、Mininet残留进程、OpenFlow握手失败,前前后后折腾了大半天。如果你也在准备搭一套SDN实验环境,或者想在公司内部快速做个网络自动化Demo,这篇记录可以直接照抄。我会把安装链路、参数选择、验证方法一次讲清楚,并标注哪些地方容易翻车。适合一边看一边敲。

1. 为什么是Ubuntu18.04 + Ryu + Mininet

1.1 Ryu和Mininet分别解决什么问题

Ryu是当下SDN实验里非常常用的控制器项目。说人话就是:它是一台“决策大脑”,交换机会把看不懂的数据包交给它,它决定怎么转发,再把转发规则下发给交换机。Ryu基于Python,支持OpenFlow多个协议版本,同时留了一套干净的应用接口,你可以用Python很轻松地写上层的网络策略。Mininet则是一台“网络模拟机”,它用进程和虚拟网卡在一台Linux主机上模拟出多个交换机、主机和链路,完全不需要真实硬件。两者配合,你可以在纯软件环境里跑通一整套OpenFlow协议流程,从拓扑启动、控制器握手、数据包上报、流表下发,到最终流量转发,全部能看见。

这套组合的实际价值很明确:用它验证算法、测试网络策略、写课程作业、做入门研究,都非常顺手。相比买交换机、搭真机拓扑,成本基本为零,而且复现别人实验的速度快多了。对刚接触SDN的人来讲,Ryu的代码可读性比Java系的控制器好很多,报错信息也更直白。我见过很多做网络方向的学生,第一个Demo都是在这套组合上跑通的。

1.2 为什么是这套组合,而不是其他控制器

有人会纠结,控制器还有Floodlight、ONOS、OpenDaylight这些,为什么非要用Ryu。我的看法很直接:如果你的目标是理解OpenFlow基础、快速写自定义应用,Ryu是学习曲线最平缓的一个。Floodlight走Java路线,模块化深度更大,但代码量摆在那里,打开工程先看半小时才能找到入口;ONOS和OpenDaylight更适合大型编排场景,启动之后一堆服务在跑,光排日志就要半天。Ryu只有一个进程,一个Python虚拟环境就能装完,启动命令就一行,对新手极度友好。

Mininet自带的默认控制器也值得一提。它只能让拓扑里的主机互相连通,本质上只是做一个简单的转发,谈不上自定义逻辑。你一旦想控制转发路径、做链路发现、做包分析,就必须外接正经控制器。Ryu和Mininet可以跑在同一台机器上,协议交互都走本机回环接口,不需要额外网络环境,这种“单机SDN实验床”是其他控制器给不了的便利。

至于系统为什么选Ubuntu18.04,纯粹是因为国内外的SDN相关资料大量基于这个版本。它的apt源里直接有Mininet包,Python3.6虽然老,但配合虚拟环境照样能跑Ryu。用更新的Ubuntu22.04也不是不行,但Python3.10下一些依赖包需要重新编译,折腾成本明显更高。实验环境宁可选择资料最多的版本,别追新。

2. 安装前的环境准备与总体规划

2.1 先花两分钟确认系统状态

我建议用虚拟机搭一个干净的系统,分配内存至少2GB,如果想同时跑多个交换机,最好给4GB。确认系统版本、架构、Python情况,打开终端一次跑完:

lsb_release -a uname -m python3 --version pip3 --version

Ubuntu18.04的默认Python版本是3.6.9,配套的pip版本比较老,后面需要升级。如果pip3不存在,先安装:

sudo apt update sudo apt install -y python3-pip git vim net-tools curl wget build-essential

为什么强调装build-essential?因为Ryu的部分依赖(比如eventlet相关的加密和链接库)在编译时少不了gcc和头文件,没有这些工具链,后面pip install会报一堆红字错误。

接下来做一次软件源升级:

sudo apt update && sudo apt upgrade -y

这一步耗时但值得。干净的系统如果不先升级,装上Mininet后很容易遇到依赖库版本过低导致的诡异问题。升级完成后我习惯执行一下sudo reboot,让系统以最新内核运行,实验环境能少很多干扰。

2.2 规划安装顺序和目录

这里给出我的顺序建议:先装Mininet,再装Ryu。Mininet安装脚本可能会带上Open vSwitch、Wireshark这些底层组件,它们不会和Ryu的Python库产生冲突。Ryu我们会单独放进虚拟环境,和系统Python隔离开,装完再也不会弄脏系统环境。

我习惯创建两个目录,源码和虚拟环境分开管理:

sudo mkdir -p /opt/sdn sudo chown $USER:$USER /opt/sdn mkdir -p ~/ryu-env

/opt/sdn用来放Mininet源码等需要编译安装的东西,~/ryu-env用于存放Python虚拟环境。这样以后想删掉环境,直接删除目录就行,不需要动系统任何包,比在全局环境里装Ryu清爽得多。

2.3 为什么非要用虚拟环境

直接执行sudo pip3 install ryu当然能装,但我不推荐。Ryu会拉入eventlet、oslo.config、netaddr、paramiko等一大串依赖,这些包又会去覆盖系统Python的对应版本。等哪一天系统某个工具依赖了旧版本,就被弄坏。更现实的问题是,后续你可能会同时研究多个控制器,有的写Ryu,有的写别的,虚拟环境能给你隔离出一块互不干扰的区域。

打个比方,虚拟环境相当于手机里的应用沙盒,系统Python是系统目录。你可以在沙盒里随意折腾Ryu,之后删掉沙盒,系统目录还是干净的。下面所有Ryu相关命令默认都做了虚拟环境处理,这也是很多初学者最忽略的一步。

3. 安装Mininet:能快则快,也要知道源码安装的路径

3.1 直接通过apt安装Mininet

最简单的方式,一条命令:

sudo apt install -y mininet

装完后验证版本:

mn --version

能看到版本号就说明核心装好了。apt安装的优势是省事,Ubuntu官方源里的版本虽然不算最新,但跑基本的pingall和Ryu实验完全足够。对绝大多数人来说,直接走这条路就行,没必要一上来就编译源码。如果你后面需要更多实验组件,也可能随时用apt补装openvswitch-switch、wireshark等。

安装过程中如果提示某些软件包无法安装,优先确认apt update有没有真正跑完。有时候是网络源连接超时,重新跑一次sudo apt update再安装就好,不要急着换源。

3.2 源码安装Mininet的完整路线

如果apt里的Mininet版本太老,或者你需要修改Mininet自己的源码,那就走源码安装。先进入/opt/sdn,拉取Mininet仓库:

cd /opt/sdn git clone 官方Mininet仓库地址 cd mininet

这里我不写具体仓库地址了,以你当时查到的官方地址为准。克隆完成后,查看安装脚本帮助:

./util/install.sh -h

常见参数我解释一下:

  • -n:只安装Mininet核心程序,速度最快;
  • -a:安装所有推荐依赖,包括Open vSwitch、Wireshark等,适合想一步到位的人;
  • -w:额外安装Wireshark,方便后面抓包。

如果你只想要一个能连Ryu的最小环境,用./util/install.sh -n就够了。不过我在实验中发现,很多SDN教程会用到Open vSwitch的高级功能,所以建议干脆用./util/install.sh -a。代价是编译时间会很长,可以去泡杯咖啡。

需要留意的是,源码安装结束后,Mininet可能会在~/mininet或/opt/sdn/mininet目录下运行,还要把mn命令的路径加入环境变量。如果用apt安装就不存在这个问题,这也是我推荐普通用户直接apt的原因。

3.3 安装后立即验证Mininet是否可用

不管用哪种方式装完,都跑一次最基本的连通性测试:

sudo mn --topo single,3 --mac --switch ovs --controller default

进入mininet>提示符后,执行:

mininet> pingall

如果看到所有主机之间都是OK,说明Mininet核心工作正常。这里的--mac参数让每台主机的MAC地址从00:00:00:00:00:01开始递增,方便后续抓包识别;--switch ovs明确使用Open vSwitch作为交换机实现。

测试完用exit退出。如果发现进程残留,比如直接关掉了终端,下次启动Mininet时可能报错,那就先执行:

sudo mn -c

这个命令会清理所有残留的网络命名空间和进程,算是Mininet玩家的必备口诀。

4. 安装Ryu控制器:把Python依赖坑踩平

4.1 先创建Python虚拟环境并检查pip

Ryu的安装在我看来难度比Mininet大,因为坑都藏在国内读者最容易忽略的Python环境里。先确保有python3-venv:

sudo apt install -y python3-venv python3-dev libffi-dev libssl-dev

然后创建虚拟环境:

python3 -m venv ~/ryu-env

创建完成后激活:

source ~/ryu-env/bin/activate

激活后,命令行前面会出现(ryu-env)标志。现在升级关键的构建工具:

pip install -U pip setuptools wheel

这一步很有必要。Ubuntu18.04自带的pip版本太老,直接装Ryu非常容易在处理setup.py时出错。升级完这些基础工具,后面会少很多问题。

顺便提一句:如果你的pip在安装依赖包时下载缓慢,可以临时指定一个网络延迟更低的镜像源,具体源名根据你自己所在网络环境去选,这里不展开。

4.2 安装Ryu本体和依赖库

在激活的虚拟环境中执行:

pip install ryu

安装过程会拉取几十个依赖包,其中eventlet、oslo.config、netaddr、paramiko都是重量级包。如果网络状况不好,过程中可能卡在下载某个包上。我第一次装的时候卡了快二十分钟,最后发现是pip版本太老导致的兼容问题,升级后重跑一次就顺利了。

如果安装过程中报错,十有八九是缺系统级编译依赖。比如看到和cffi、cryptography相关的错误,说明缺少libffi-dev或libssl-dev,按前面说的补装就行。装完之后重新执行:

pip install ryu

这次基本能顺利通过。装好后可以用:

pip list | grep ryu pip list | grep eventlet

确认Ryu和eventlet都出现在列表里。

4.3 验证Ryu能否正常启动

闲话不多说,先看版本号:

ryu-manager --version

能输出版本号,说明安装没问题。再启动一个最简单的二层交换机应用:

ryu-manager ryu/app/simple_switch_13.py

看到日志刷出来,最后变成类似join a single switch的状态就说明控制器已经起来了。此时不要关掉这个窗口,它在后台监听控制端口。另外开一个终端,查看监听端口:

sudo netstat -tlnp | grep ryu

注意看是6653还是6633,记下这个端口。不同版本、不同配置下默认端口有差异,后面Mininet连控制器时用错端口是头号排查点。

如果启动时报缺少某个Python模块,直接回到虚拟环境补装对应包即可。但千万别急着把所有依赖全部升级到最新,Ryu对一些库的版本有隐性要求,全量升级反而会造成新的不兼容。

5. 让Mininet连上Ryu:从安装到跑通的最后一步

5.1 先把控制器应用拉起来

在做连接测试之前,我强烈建议先启动Ryu,再启动Mininet。原因很简单,Mininet启动交换机会立刻发起OpenFlow连接,如果控制器还没就位,交换机会反复重连,虽然最终也能连上,但日志里会多一些无谓的报错。

在激活虚拟环境的情况下,启动Ryu:

source ~/ryu-env/bin/activate ryu-manager ryu/app/simple_switch_13.py

保持这个窗口在前台运行。simple_switch_13.py的作用是模拟一个二层自学习交换机,控制器收到未知目的地的包,会先学习源MAC,然后泛洪处理;等目标MAC也学习到位,后续相同流向的数据包就会直接命中流表,不再上报控制器。这是SDN流表机制最直观的演示。

如果想在后台启动,方便关掉终端继续干活,也可以用:

nohup ryu-manager ryu/app/simple_switch_13.py > /tmp/ryu.log 2>&1 &

不过调试阶段还是建议前台运行,日志看起来更直观。

5.2 启动Mininet并指定远程控制器

新开一个终端,启动Mininet:

sudo mn --topo linear,2 --mac --switch ovs --controller remote,ip=127.0.0.1,port=6653

把port改成你刚才netstat查到的实际端口。如果Ryu监听的是6633,就写6633。

这里的--topo linear,2表示两个交换机串联,每个交换机下面挂一台主机。拓扑逻辑是:

h1 -- s1 -- s2 -- h2

你可以在Mininet里用net命令查看当前网络结构,也可以用nodes列出所有节点。启动时如果看到Ryu日志窗口刷出交换机的连接信息,说明OpenFlow握手已经成功。正常情况下Ryu会识别到交换机的datapath_id,后续所有流表操作都围绕这个ID展开。

5.3 跑通pingall并查看流表

在Mininet提示符下执行:

mininet> pingall

如果四个方向的主机都能ping通,恭喜,Ryu和Mininet已经正式打配合了。第一次ping时,控制器的日志会频繁上报packet_in消息,因为交换机没有现成的流表,每个未知目的地的包都要交给控制器判断。等ping结束后,再执行:

mininet> dpctl dump-flows

能看到类似下面的流表项:

cookie=0x0, duration=..., table=0, n_packets=..., idle_timeout=..., priority=1, ip,in_port=1,nw_src=...,nw_dst=..., actions=output:2

这就是控制器下发的精确转发规则。你来回多ping几次,再执行dpctl dump-flows,会发现流表项数量逐渐稳定下来,而不是每次都有大量packet_in上报。这说明自学习机制生效了。

如果只想查看某个交换机的流表,也可以用:

sudo ovs-ofctl dump-flows s1

s1是Mininet创建的第一个OVS网桥的名字。

5.4 顺手做一次抓包分析

很多人装完环境就收工了,我建议再做一步抓包,因为OpenFlow报文交互过程永远看不腻。在Mininet运行期间,把数据包保存下来:

sudo tcpdump -i s1-eth2 -vv -w /tmp/of.pcap tcp port 6653

然后让h1 ping h2,等待几秒停掉tcpdump,用Wireshark打开临时目录下的pcap文件。重点看一次性连接后有没有Packet In、Packet Out、Flow Mod这三类OpenFlow消息。每一条消息对应控制器和交换机的一次对话。这一步会让你对流表下发机制理解得非常扎实。

6. 常见问题与排查技巧实录

6.1 端口对不上或OpenFlow握手没反应

我把这个问题排到第一位,因为八成的新手失败都栽在这里。现象是Mininet启动时没有任何报错,但Ryu日志里也什么都没有。这时候先查端口:

sudo netstat -tlnp | grep ryu

然后对照Mininet启动命令里的port=参数。很多教程默认写6653,但某些Ryu版本默认监听6633,参数一错,连接就建立不起来。另外确认Ryu是否真的运行在虚拟环境里,如果之前用全局Python装过,可能启动的是另一个残留进程。

还有一种情况是防火墙挡了本机回环,虽然用127.0.0.1通常不会触发防火墙,但如果你开了ufw,还是检查一下:

sudo ufw status

如果开启,直接放行对应端口,或者临时关闭ufw再测。

6.2 pip安装Ryu时依赖编译失败

我在乌班图18.04上遇到最多的是cryptography编译失败,日志末尾能看到“fatal error: openssl/opensslv.h: No such file or directory”。原因是系统缺少OpenSSL开发头文件。解决:

sudo apt install -y libssl-dev libffi-dev python3-dev

装完头文件,激活虚拟环境,重新升级pip和setuptools:

source ~/ryu-env/bin/activate pip install -U pip setuptools wheel pip install ryu

记住一个原则:失败后先把缺失的系统组件补齐,而不是反复重装Python包。系统组件是地基本,Python依赖是房屋。

6.3 Mininet启动时报缺少ovs-vsctl

如果在执行mn命令时出现“cannot find required executable ovs-vsctl”或者“could not find required executable ovs-vsctl”,基本是Open vSwitch没装或者没装全。用apt补齐:

sudo apt install -y openvswitch-switch

如果你当初是源码安装Mininet但只用了-n参数,现在补一条:

cd /opt/sdn/mininet ./util/install.sh -v

这个参数会专门安装Open vSwitch相关组件。装完再启动Mininet,大概率就好了。

6.4 重复实验后的残留进程

这个坑几乎每个人都踩过。实验做完不退出Mininet,直接关终端,下次再启动的时候报错说网络命名空间冲突,或者拓扑里的网桥一直创建不起来。最直接的清理命令:

sudo mn -c

如果清理完仍有问题,我习惯补上这几条:

sudo pkill -f ryu-manager sudo pkill -f ovs-vswitchd sudo systemctl restart openvswitch-switch

前提是当前没有其他重要的Open vSwitch业务,纯实验环境这么操作没问题。清理之后重新sudo mn启动,一切会恢复正常。

6.5 问题排查速查表

现象可能原因处理办法
Mininet连不上控制器端口不一致netstat查端口,启动命令里修改port
Ryu启动报缺少模块依赖没装全或venv未激活确认(ryu-env)前缀,补装依赖
pip编译报错系统头文件缺失安装libssl-dev、libffi-dev、python3-dev
mn找不到ovs-vsctlOVS未安装apt装openvswitch-switch
pingall不通流表残留或控制器未启动sudo mn -c清理,重新顺序启动
拓扑无法创建上次未正常退出sudo mn -c清理,重启交换机服务

最后分享一个我很喜欢的启动方式:把Ryu的启动过程封装成一个脚本,每次实验只敲一条命令,省得每次都要手动激活虚拟环境再敲一长串参数。脚本内容很简单:

#!/bin/bash source ~/ryu-env/bin/activate exec ryu-manager ryu/app/simple_switch_13.py

保存成~/sdn/start_ryu.sh,然后chmod +x ~/sdn/start_ryu.sh。Mininet那边也可以做类似封装,把固定的拓扑和remote参数写进脚本。这套组合在实际操作中最大的价值就是“可复现”,你今晚记录的命令,明天重启机器后照样能一键跑通。踩过几次坑之后,我现在装SDN环境都严格走这套流程,很少再被环境问题打断实验思路。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询