37

使用Docker容器构建ODL集群

 5 years ago
source link: https://www.sdnlab.com/22554.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

作者简介:智智方,西安电子科技大学硕士研究生,主要研究方向是SDN与网络安全,邮箱[email protected]

近期需要在控制器集群的环境下做一些实验,由于设备有限,很难找到多台计算机同时运行ODL控制器构成集群,在一台计算机上运行多个虚拟机又会造成计算机运行十分卡慢,在此跟大家分享一种使用Docker容器构建ODL集群的方法,希望能给大家带来帮助。

docker-odl-668x400.png

一、Docker容器简介

关于Docker容器技术的介绍很多,这里只做简单介绍,并说明为什么可以用Docker容器来构建ODL集群。Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。

下面两图展示了虚拟机和容器之间的区别:

docker-odl-1.png
docker-odl-2.png

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主机内核,容器内没有自己的内核,而且也没有进行硬件虚拟,因此容器要比传统虚拟机更为轻便。因此在单台计算机上通过Docker的方式构建ODL集群的运行速度会比直接开虚拟机的方式要快很多。

Docker包括三个基本概念:镜像(image)、容器(container)、仓库(Registry)。

Docker镜像:
我们都知道,操作系统分为内核和用户空间。对于Linux而言,内核启动后,会挂载 root 文件系统为其提供用户空间支持。而Docker镜像(image),就相当于是一个 root 文件系统。因此我们在使用Docker构建ODL集群时,需要在镜像中添加ODL控制器,就好比我们在本机运行ODL控制器时,需要下载ODL控制器发行版的压缩包或者是用maven生成ODL的基本项目框架。

因为镜像包含操作系统完整的 root 文件系统,其体积往往是庞大的,因此在Docker设计时,就充分利用Union FS的技术,将其设计为分层存储的架构。所以严格来说,镜像并非是像一个ISO那样的打包文件,镜像只是一个虚拟的概念,其实际体现并非由一个文件组成,而是由一组文件系统组成,或者说,由多层文件统联合组成。镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完就不会再发生改变,后一层上的任何改变只发生在自己这一层。

Docker容器:
镜像(image)和容器(container)的关系,就像是面向对象程序设计中的类和实例一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。

容器的实质是进程,但与直接在宿主机执行的进程不同,容器进程运行于属于自己的独立的命名空间。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主机的系统下操作一样。所以运行在不同容器中的ODL控制器会有不同的IP地址,不同的进程空间等,使用起来就像在不同虚拟机下运行ODL控制器一样。

Docker仓库:
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,我们就需要一个集中的存储、分发镜像的服务,Docker Registry就是这样的服务。

通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。

最常使用的Registry公开服务是官方的Docker Hub,这也是默认的Registry,并拥有大量的高质量的官方镜像。Docker Hub的网址为https://hub.docker.com,在Docker Hub上已经提供了ODL的镜像,大家可以直接使用docker pull命令下载并使用这些镜像,但是这些镜像所用的ODL版本可能并不包含最新的,而且这些镜像所用的ODL多是已经打包好的发行版,我们在构建ODL集群时也可能会使用自己根据特定需求开发后用maven编译打包的ODL控制器,所以这里给出构建ODL镜像的方法,大家可以根据自己的需要更改ODL的版本,本文提出的方法所构建的镜像是在Docker Hub提供的ubuntu:16.04镜像的基础之上构建的。

二、安装Docker

在Ubuntu系统下安装Docker相对简单,通过下述命令安装即可:

Java
sudo apt-get update sudo apt-get install -y docker.io
1
2
sudo apt-get update
sudo apt-get install-ydocker.io

安装完成后在终端输入sudo docker run hello-world出现以下显示结果说明Docker安装成功

docker-odl-3.png

三、构建Docker镜像

Docker镜像的构建可以利用commit命令由运行中的容器构建出镜像,也可以使用Dockerfile来构建镜像,在这里我们使用编写Dockerfile的方式来构建Docker镜像,Docker镜像是层层构建的,镜像的定制实际上就是定制每一层所添加的配置、文件。如果我们可以把每一层修改、安装、构建、操作的命令都写入Dockerfile脚本中,用这个脚本来构建、定制镜像,Dockerfile的内容如下:

Java

FROM ubuntu:16.04

RUN apt-get update &&\ apt-get install unzip -y &&\ apt-get install net-tools -y &&\ apt-get install iputils-ping -y &&\ apt-get install vim -y &&\ apt-get autoclean &&\ apt-get autoremove COPY distribution-karaf-0.6.2-Carbon.zip jdk-8u181-linux-x64.tar.gz /home/ WORKDIR /home RUN tar -zxvf jdk-8u181-linux-x64.tar.gz &&\ rm jdk-8u181-linux-x64.tar.gz &&\ unzip distribution-karaf-0.6.2-Carbon.zip &&\ rm distribution-karaf-0.6.2-Carbon.zip

ENV JAVA_HOME=/home/jdk1.8.0_181 ENV JRE_HOME=$JAVA_HOME/jre ENV CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH ENV PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH

EXPOSE 8181 6653 6633

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
FROM ubuntu:16.04
 
RUN apt-get update&&\
    apt-get install unzip-y&&\
    apt-get install net-tools-y&&\
    apt-get install iputils-ping-y&&\
    apt-get install vim-y&&\
    apt-get autoclean&&\
    apt-get autoremove
COPY distribution-karaf-0.6.2-Carbon.zip jdk-8u181-linux-x64.tar.gz/home/
WORKDIR/home
RUN tar-zxvf jdk-8u181-linux-x64.tar.gz&&\
    rm jdk-8u181-linux-x64.tar.gz&&\
    unzip distribution-karaf-0.6.2-Carbon.zip&&\
    rm distribution-karaf-0.6.2-Carbon.zip
 
ENV JAVA_HOME=/home/jdk1.8.0_181
ENV JRE_HOME=$JAVA_HOME/jre
ENV CLASSPATH=.:$JAVA_HOME/lib:$JRE_HOME/lib:$CLASSPATH
ENV PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
 
EXPOSE818166536633

FROM命令是指该镜像是以哪个镜像作为基础镜像来构建的,这里我们选用ubuntu:16.04,第一个RUN命令安装了解压缩工具以及必要的网络工具和文本编辑工具,COPY命令则是将构建镜像时的上下文环境中的ODL发行版和jdk等添加到镜像的/home文件夹当中,因此需要在本机上提前下载好ODL的发行版和jdk,大家也可以根据自己的需要更换ODL和jdk的版本,然后切换到镜像的/home路径下将两个压缩包解压,ENV命令则是用来设置镜像的环境变量,这里设置了Java的环境变量,最后的EXPOSE命令则是用来声明该镜像对外暴露哪些接口,即当基于这个镜像的容器运行时,我们可以访问它的哪些接口,8181接口可以访问ODL的Web界面,6653和6633接口则是OVS交换机通过Openflow协议连接的端口。

在使用Dockerfile构建镜像时,首先需要创建一个文件夹,同时在这个文件夹下将COPY命令后的打包文件以及Dockerfile文件复制到这个文件夹下,即这个文件夹下的内容为:

docker-odl-4.png

然后在这个文件夹下运行如下命令

Java
sudo docker build -t opendaylight .
1
sudo docker build-topendaylight.

其中-t是指构建出镜像的名称,最后的”.”则是指以当前路径为上下文构建,最后在终端出现如下结果说明镜像构建成功

docker-odl-5.png

四、启动容器构建ODL集群

在这里我们运行3个容器构建ODL集群,也可以根据自己的需要创建更多的容器构建规规模更大的集群,打开一个终端,在终端中输入如下命令:

Java
sudo docker run -it --name node1 -p 8181 -p 6653 -p 6633 opendaylight /bin/bash
1
sudo docker run-it--name node1-p8181-p6653-p6633opendaylight/bin/bash

docker run命令指启动一个容器,-it是指这是两个参数,一个是-i:交互式操作,一个是-t终端。这样就可以打开这个容器的终端,我们可以通过终端与这个容器进行交互;—name是指这个容器的名字,-p是指映射宿主机端口和容器端口,完整用法为-p <宿主机端口>:<容器端口>,其含义是指将宿主机的哪个端口映射为这个容器的端口,因此访问这个容器的端口的时候可以通过容器IP地址+容器端口的方式访问或者宿主机IP地址+映射端口的方式访问,这里只指明了容器的端口,意思是将宿主机的随机一个端口映射成这个容器的某一个端口,可以通过sudo docker inspect+容器名的方式来查看映射结果:

docker-odl-6.png

可见node1的6633、6653和8181端口分别被映射成本机的32773、32772和32771端口。
然后打开两个新的终端分别在两个终端下运行

Java
sudo docker run -it --name node2 -p 8181 -p 6653 -p 6633 opendaylight /bin/bash
1
sudo docker run-it--name node2-p8181-p6653-p6633opendaylight/bin/bash

Java
sudo docker run -it --name node3 -p 8181 -p 6653 -p 6633 opendaylight /bin/bash
1
sudo docker run-it--name node3-p8181-p6653-p6633opendaylight/bin/bash

然后将这三个容器的目录切换到/home/distribution-karaf-0.6.2-Carbon/bin下,运行其中的configure_cluster.sh脚本,这个脚本是配置集群的脚本它接收的参数格式为./configure_cluster.sh index seed_nodes_list,其中index是这个节点在集群中的索引,seed_nodes_list是这个集群中所有控制器的IP地址,IP地址之间用空格隔开,index也指当前控制器的IP地址是后边IP地址列表中的第几个,通过ifconfig命令可以查看到node1、node2和node3的IP地址分别为172.17.0.2、172.17.0.3和172.17.0.4,因此需要在node1中执行

Java
./configure_cluster.sh 1 172.17.0.2 172.17.0.3 172.17.0.4
1
./configure_cluster.sh1172.17.0.2172.17.0.3172.17.0.4

在node2中执行

Java
./configure_cluster.sh 2 172.17.0.2 172.17.0.3 172.17.0.4
1
./configure_cluster.sh2172.17.0.2172.17.0.3172.17.0.4

在node3中执行

Java
./configure_cluster.sh 3 172.17.0.2 172.17.0.3 172.17.0.4
1
./configure_cluster.sh3172.17.0.2172.17.0.3172.17.0.4

这样就完成了集群的配置,然后就可以开启控制器了,在三个容器中通过./karaf开启控制器,开启之后在三个控制器上安装如下feature

Java
feature:install odl-restconf odl-dluxapps-applications odl-openflowplugin-flow-services-ui odl-l2switch-switch-ui odl-mdsal-apidocs
1
feature:install odl-restconf odl-dluxapps-applications odl-openflowplugin-flow-services-ui odl-l2switch-switch-ui odl-mdsal-apidocs

注意这几个feature需要通过这一条命令同时安装,否则可能导致容器中运行的ODL控制器无法正常使用。上述feature安装完成之后再输入:

Java
feature:install odl-mdsal-clustering
1
feature:install odl-mdsal-clustering

注意要在其他feature安装完毕之后再安装odl-mdsal-clustering来启动集群功能,否则在安装过程中会报错,这样就完成了ODL集群的构建。

五、mininet连接实验

在本机安装好mininet以后打开一个新的终端,输入:

Java
sudo mn --controller=remote,ip=172.17.0.4,port=6653 --switch=ovsk,protocols=OpenFlow13
1
sudo mn--controller=remote,ip=172.17.0.4,port=6653--switch=ovsk,protocols=OpenFlow13

即使用mininet模拟一个拓扑图,注意这里的ip地址可以是集群中任意一个控制器的ip地址,因为这三个控制器已经构成集群。在mininet中输入pingall命令发现已经全部可以ping通:

docker-odl-7.png

然后从浏览器中打开三个控制器的web界面,从如下三张图中可以看到,这三个控制器的网络视图数据已经统一,说明ODL集群搭建成功,大家可以在此基础上做更多的实验。

docker-odl-8.png
docker-odl-9.png
docker-odl-10.png

六、总结

本文分享了一种用Docker容器来构建ODL集群的方法,在计算机数量不足以及计算机性能不高的情况下,是在单机上模拟ODL集群的一种不错的方法。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK