SDN 控制器的发展

控制器算是 SDN 中相当重要的技术了,SDN 概念刚刚兴起时,各个控制器逐一展露头角,经过十几年的沉浮后,作为主流使用且仍旧蓬勃发展的却为数不多了。

2008年的时候,OpenFlow 论文问世,Nicira 开源了业界第一款 SDN 控制器 NOX,C++ 编写,算是控制器们的祖师爷,但当时只在学术圈有影响。 2009年,Nicira 团队又发布了 NOX 的纯 Python 实现版本 POX,目的是提供跨平台部署的便利性。

2012年,Ryu 诞生,Python 编写,能够与 OpenStack 整合,算是 POX 的后代。与此同时,Floodlight 也正式发布,Java 编写,称得上是接下来两款重量级控制器的妈。这两款仍属于轻量级控制器,它们在多控制器之间的交互协议上还是一片空白,没有一个统一的解决方案。

2013年,Linux 基金会和多家网络巨头(Cisco、Juniper、Broadcom 等)创立开源项目 OpenDaylight(ODL),开启一个崭新的时代。

OpenDaylight 不仅仅是一个SDN控制器,它更是一个庞大的开源项目,其中包含许多子项目,而 Controller 只是其中的一个子项目。从诞生到2014年底,OpenDaylight 风光无限,许多企业都基于它开发自己的控制器,管理数据中心网络。

直到2014年12月5日,由 ON.Lab 开发的 ONOS 问世,Java 编写,采用 OSGi 架构,其目标是打造一个开放的SDN网络操作系统。ONOS 底层模块直接借用 FloodLight 优秀的模块如 Switch 模块,不使用 YANG 语言(ODL 使用)建模,最新版本使用Raft作为分布式框架。

作为目前最受欢迎的两款开源控制器,OpenDaylight 和 ONOS 在业界非常的火,至于 Ryu/Floodlight 之类,更适合于科研场景。OpenDaylight作为 企业(数据中心场景) 主推的控制器,支持的功能较多,也更庞杂;而 ONOS运营商主推的控制器,更加贴近运营商的场景。

具体来讲,ODL 采取了更为平缓的 SDN 演进方式,从理念上更为贴近广义的 SDN,即不局限于 OpenFlow 协议,不局限于完全将控制平面从转发设备上剥离,通过已有的网络协议将部分的控制逻辑放到 Controller 上。

ONOS 更贴近于 SDN 诞生之初时狭义的 SDN 概念,即通过 OpenFlow 将控制平面和转发平面完全分离,网络设备只是进行转发的黑盒子,通过 Controller 完成一切计算。ONOS 所选择的理念与运营商自己的利益息息相关,只有将控制能力拿到自己手里,才能在整条产业链上逐步摆脱设备厂商的控制。

OpenDaylight

架构

如下图所示, OpenDaylight项目架构主要由网络应用服务层、控制平面层、南向接口层和数据平面层四层构成。

网络应用服务层主要负责为用户提供北向REST API。控制平面层包括一系列功能模块,可动态组合提供不同服务,其中主要包括拓扑管理、转发管理、主机检测、交换机管理等模块。南向接口层为硬件设备提供标准的南向接口,支持多种不同协议,如OpenFlow 1.0、OpenFlow 1.3、BEG-LS 等。数据平面层支持混合模式和经典OpenFlow交换机。

image-20220801195723546

核心技术

  1. OSGi 体系结构:将应用视为对等模块的相互协作,对功能进行隔离,可以动态地加载或者卸载,有利于拓展性,可以动态部署。OpenDaylight从HELIUM版本开始使用karaf作为底层架构,karaf是一个基于OSGi的运行环境,可以用于部署各种组件和应用程序。
  2. SAL(服务抽象层):架构中引入服务抽象层,使得北向REST API和南向接口之间的调用相互隔离,支持南向插件通过各种不同的协议与网络设备进行通信,屏蔽了不同协议之间的差异,为上层功能模块提供一致性的服务。
  3. MD(Model Drive):使用YANG工具,使用业务驱动模型工具来设计接口、实现业务功能,根据YANG文件,YANG工具可直接生成业务管理的“骨架”,使开发者真正专注于具体业务。
  4. Infinispan(分布式内存数据网格):实现数据的存储、查找以及监听,用开源的数据网格平台实现Controller集群,并且支持分布式。
  5. Netty:南向使用高性能稳定的开源框架Netty来管理底层的并发IO,监听消息服务。

快速使用

环境要求

由于新版本与老版本支持的组件差异较大,所以下面使用Oxygen版本测试。在Release Notes中有说明,OpenDaylight中已经包含了Karaf容器、OSGi bundles和Java class文件,运行要求具有JDK8。除此之外,开发需要Apache Maven 3.1.1及以上版本。

安装运行

Release 版本可以从官方文档中的下载页面找到,下载成功后解压。

tar -zxvf karaf-0.8.4.tar.gz

进入目录,运行 ./bin/karaf命令,OpenDaylight 成功启动。

image-20220801200643630

安装支持 REST API 的组件。

feature:install odl-restconf

安装支持 L2switch 的组件。

feature:install odl-l2switch-switch-ui

安装支持 dlux 应用界面查看的组件。

feature:install odl-dluxapps-applications

安装 dlux 应用界面所需的其他插件。

feature:install odl-dlux-core odl-dluxapps-nodes odl-dluxapps-topo logy odl-dluxapps-yangui odl-dluxapps-yangvisualizer odl-dluxappsyangman

访问 GUI,默认用户名和密码均为 admin

image-20220801201012563

使用 Mininet 连接 OpenDaylight。

mn --controller=remote,ip=<Controller IP> --topo=linear,3 --switch ovsk,protocols=OpenFlow13

image-20220801201117563

ONOS

架构

image-20220801201237907

ONOS 架构中有两个强大的北向抽象层:意图(Intent)框架和全局网络视图。

  • 意图框架屏蔽服务运行的复杂性,允许应用向网络请求服务而不需要了解服务运行的具体细节,这就意味着网络运营商和应用开发者可以进行高级编程。意图框架处理所有应用的请求,判断可以满足哪些应用,解决应用之间的冲突,执行管理者的策略,对网络编程提供请求的功能,交付请求的服务给应用。
  • 全局网络视图为应用提供了网络视图,包括主机、交换机以及网络相关的状态参数,如利用率。应用可以通过APIs对网络视图进行编程,一个API可以为应用以网络图的形式提供网络视图。

分布式核心:ONOS可以作为服务部署在服务器集群上,在每个服务器上运行相同的ONOS软件,因为对称性部署是一项很重要的设计考量,可以在ONOS服务器发生故障时可以快速地进行故障恢复。而且网络运营商可以在不发生中断的情况下添加服务器,轻松地扩容控制平面处理能力。ONOS实例协同工作形成被其它网络和应用视作单一的平台。应用和网络设备无需知道是和单一的ONOS实例交互还是和多个ONOS实例交互。这一特征实现了ONOS的可扩展性,可以无缝扩充ONOS容量。分布式核心提供实例间的通信、状态管理,领导选择等服务。事实上,多个实例表现为一个逻辑实体。通过使用Publish/Subscribe模型中的高速消息,ONOS实例可以将更新信息快速通知给其他实例。对设备而言,只有一个主ONOS实例,如果这个主实例出现故障,则连接另一个实例,无需重新创建新实例并重新同步流表。对于应用而言,可以通过网络图形抽象层持续获取网络的视图。此外,实例故障和数据平面的故障对应用来说是透明的,这样可以极大地简化应用开发和错误处理。

南向抽象层由网络组件构成,例如交换机、主机或是链路。ONOS的南向抽象层将每个网络组件表示为通用格式的对象。分布式核心可以实现南向接口协议和设备无感知。这个网络组件抽象层允许添加新设备和协议,以可插拔的形式支持扩展,插件根据规格映射(或翻译)通用网络组件描述或操控设备,反之亦然。所以,南向接口确保ONOS控管多个不同的设备,即使它们使用不同的协议(openflow、netconf)。ONOS通过协议与设备连接,协议细节被网络组件插件或适配器屏蔽。事实上,南向接口的核心是在不知道具体协议细节和网络组件的条件下维护网络组件对象(设备、主机、链路)。通过适配层API,分布式核心可以与网络组件对象状态保持一致,适配层API将分布式核心与协议细节和网络组件相隔离。

快速使用

因为要与 VNFs 做对接,ONOS 显然更符合 NFV 的思想,所以研究中选择 ONOS 作为主要开发的控制器。

虽然在 SDN 控制器中 ONOS 的文档算不错的了,但仍不是很全面,难免踩一些坑。我接下来文章中的一系列配置都以官方文档为主,外加一些自己喜好的使用方式。在搭建环境上,ONOS 有多种方式,这里先使用 Release 包,官方的 wiki 在这里

我使用的操作系统是 Ubuntu 18.04,首先需要确保下面这些端口开放:

  • 8181 - REST API 和 GUI
  • 8101 - ONOS CLI
  • 9876 - 集群内通信
  • 6653 - Openflow 通信
  • 6640 - OVSDB

我们要安装的是最新版的 ONOS,目前版本号是 2.4.0,依赖 Java 版本为 Java11,另外 curl 也需要安装。

sudo apt install openjdk-11-jdk
sudo apt-get install curl

假设要安装到 /opt 下,创建目录。

sudo mkdir /opt
cd /opt

根据版本下载 ONOS 压缩包,官方提供了一个下载页面,复制相应链接后即可下载,下载速度问题自行解决。

sudo wget -c https://repo1.maven.org/maven2/org/onosproject/onos-releases/2.4.0/onos-2.4.0.tar.gz
sudo tar xzf onos-2.4.0.tar.gz
sudo mv onos-2.4.0 onos

直接使用脚本开启 ONOS。

/opt/onos/bin/onos-service start

稍等片刻后,即可访问 GUI 界面。 在这里插入图片描述

默认用户名为 onos ,默认密码为 rocks 。登录后可以看到拓扑界面,因为还没有连接网络设备,所以暂无信息。在这里插入图片描述

在 **Applications **界面中可以看到目前集成的所有插件,选择 OpenFlow Provider Suite (支持 OpenFlow 协议)和 Reactive Forwording 安装。 我们先使用轻量级软件定义网络和测试平台——Mininet 来测试控制器,可以直接使用 apt 下载安装。

apt install mininet

安装后可以连接正在运行的 ONOS。

mn --controller=remote,ip=<Controller IP> --topo=linear,3 --switch ovsk,protocols=OpenFlow13

如果不安装 OpenFlow Provider Suite 插件,是无法正常连接的。连接成功后,拓扑界面会显示三个 switch,因为还没有数据包传输,所以 switch 还感知不到 host 的存在,界面上也没有相应的显示。在 mininet 中输入 pingall 命令,各个 host 间 ping 通,遵循 Reactive Forwording插件的包转发规则。

再回到拓扑界面,显示 switch 和 host。 image.png CLIGUI 的全部功能可以在文档中找到,这里就不过逐一介绍了。 为了让 ONOS 在后台长期运行,可以将它注册成服务,不过我更喜欢使用 docker 的方式,下一部分会主要介绍。

Docker 运行 ONOS

我一般将 ONOS 部署到内网中的一台服务器上运行,服务器多人使用,所以不方便随便修改环境,比如 ONOS 2.4.0 要求 JDK 11。docker 的虚拟环境可以解决这一问题,且官方提供镜像,又节省了配置环境的时间。 docker 的安装不过多介绍,网上的教程一搜一大把,最好配置下国内源。安装好后拉取官方镜像。

docker pull onosproject/onos:2.4.0

后台运行。

docker run -t -d -p 8181:8181 -p 8101:8101 -p 5005:5005 -p 830:830 -p 6633:6633 --name onos onosproject/onos:2.4.0

上面的命令已经完成了端口映射,即将容器内部的端口映射到主机的端口,允许外网访问容器。将 mininet 启动时的 ip 改为这台服务器的 ip,即可连接容器内运行的 ONOS。

上述的两条命令就完成了 ONOS 的部署,与手动安装相比,效率成倍提高。

开发环境

源码配置

作为一名开发者,Release 包不能满足所有的需要,下载源码成了绕不开的路。

git clone https://gerrit.onosproject.org/onos

ONOS 提供了很多利于开发的工具,将它们添加到 bash 配置文件中,就可以直接使用这些工具。ONOS 源码目录需要按自己的情况指定,我将配置写入到 /etc/profile 中。

export ONOS_ROOT="/root/onos"
source /root/onos/tools/dev/bash_profile

最新版本的 ONOS 可以使用 Bazel 进行源码构建运行,因为此前已通过 Docker 运行,Bazel 构建时速度又很慢,所以我在本地开发后直接推送到 Docker 中的控制器中,大家也可以按自己的需求选择合适的工作流。

安装依赖环境

ONOS 应用使用 Maven 构建和管理第三方包,可以直接使用 apt 安装。

apt install maven

Maven 官方下载通道速度很感人,强烈建议配置一下国内源,我的配置文件在 /etc/maven/settings.xml ,在 mirros 中加入阿里的源。

<mirror>
     <id>aliyunmaven</id>
     <mirrorOf>central</mirrorOf>
     <name>阿里云公共仓库</name>
     <url>https://maven.aliyun.com/repository/central</url>
</mirror>

IDE 我比较喜欢 IntelliJ IDEA,下载社区版就可以,完整版也可以使用学生邮箱免费使用,安装教程之前写过,这里直接发一下链接

建立工程

ONOS 插件化管理应用,官方提供了 onos-create-app 工具便于开发者创建工程结构。首先要指定使用哪个版本的 ONOS API 开发,最好将它也写入到 /etc/profile 中,如果缺少这步的话,可能无法正常建立工程。

export ONOS_POM_VERSION=2.4.0

在创建的过程中,需要指定 groupIdartifactId 和版本号,以及该应用的名称。

onos-create-app app org.foo foo-app 1.0-SNAPSHOT org.foo.app

创建过程中会自动从 Maven 拉取所需依赖,中途输入 y 确定创建。 image.png 创建成功后,执行命令的目录下面会生成一个 foo-app 目录,进入后预览一下生成的项目框架。 image.png 打开 IntelliJ IDEA,选择 Open 选项,因为该工程目录是基于 Maven 创建的,所以直接选中 foo-app 目录即可导入。注意在设置( Ctrl + Alt + s 打开)中修改 Maven 的目录和配置文件,否则 IDEA 会使用自带的配置文件,无法使用阿里源下载。 image.png 待第三方依赖全部下载导入成功后,即可开始开发应用。其中比较重要的是 AppComponent.javaactive() 为程序入口, deactive() 为应用删除时执行的部分。

构建发布

实际上,不对该工程做任何修改,它已经是一个可以正常构建发布的应用了。在右侧 maven 选项卡中,选择 install 进行构建,其实就相当于在工程目录下执行 mvn clean install 命令。 image.png 构建成功后,会在 target 目录下生成 foo-app-1.0-SNAPSHOT.oar 文件,这就是要发布到 ONOS 中的应用。执行下列命令,应用就自动发布到指定 ip 下的 ONOS 控制器 中。

onos-app 192.168.10.10 reinstall! target/foo-app-1.0-SNAPSHOT.oar

发布成功。 image.png 在 GUI 中搜索 foo ,找到刚刚发布的应用,启动后则可以正常运行。 image.png 这就是 ONOS 开发一个应用的完整流程,以后的开发则可以聚焦业务功能,无需被繁杂的环境配置搞混头脑。