RouteFlow与LXC学习 ( by quqi99 )
开源的基于Openflow的路由虚拟化开源项目,Openflow解决的是交换机上的流表生成和下发的数据平面问题,Routeflow的目的是解决控制平面路由协议及计算的问题。直接上图:
要点:
Quagga用于产生路由表,RouteFlow client用于将路由表和ARP表转换成流表,通过RouteFlow Proxy及Pox下发流表到openflow datapath。全局RouteFlow Server用于存储
要安装rfclient的话如下,其他的安装rfcserver等类似。
git clonehttps://github.com/CPqD/RouteFlow.git
sudo yum install make automake gcc gcc-c++kernel-devel git boost-devel boost-program-options boost-threadboost-filesystem iproute-devel openvswitch mongodb pymongo
make rfclient
一个例子见:https://github.com/CPqD/RouteFlow/wiki/Tutorial-1
RouteFlow真正要做的事情就是,举个例子:一个物理机上通过ovs连了两个虚机的话,当vm1ping vm2后,物理上通过arp-a命令看就会多出两条arp记录(mac与ip的映射),如:
ubuntu@rfvm1:~$ sudo arp -a
? (172.31.1.2) at
02:b1:b1:b1:b1:b1
[ether] on eth1
? (192.169.1.1) at aa:48:2d:aa:da:41 [ether] on eth0
? (172.31.2.2) at
02:b2:b2:b2:b2:b2
[ether] on eth2
RouteFlow真正要做的事情就是就根据上述变化的ARP表或者RIB路由表来生成下列的openflow的FIB流表。
sudo ovs-ofctl dump-flows switch1
...
cookie=0x0, duration=204.649s, table=0, n_packets=0, n_bytes=0, idle_timeout=300,priority=32800,ip,dl_dst=12:a1:a1:a1:a1:a1,nw_dst=172.31.2.2 actions=mod_dl_src:12:a1:a1:a1:a1:a1,mod_dl_dst:
02:b2:b2:b2:b2:b2
,output:2
cookie=0x0, duration=203.97s, table=0, n_packets=0, n_bytes=0, idle_timeout=300,priority=32800,ip,dl_dst=12:a1:a1:a1:a1:a1,nw_dst=172.31.1.2 actions=mod_dl_src:12:a1:a1:a1:a1:a1,mod_dl_dst:
02:b1:b1:b1:b1:b1
,output:1
最初可以在虚机里运行内部路由协议在一个路由器的下面的同一tenant的同一子网下的机器的东西向流量带来好处,将来也可以在虚机里再分配一个浮动ip后直接参与和外部路由的路由交换从而实现跨数据中心的三层网络SDN化。
LXC容器简介,一种不同于KVM的另类的虚拟化实现方案,容器有效地将由单个OS管理的资源(计算,存储,网络)划分到孤立的组中,与传统的虚拟化相比,这样不需要指令级模拟。避免了虚拟化中系统调用替换中的复杂性。容器是下列两个技术的结合,在chroot的基础上,使用namespace增强chroot环境的隔离性,使之成为有效的容器:
chroot,在linux系统中,根目录就是”/”,但使用chroot可以用任意指定的目录作根目录
namespace, 相当于单独的TCP/IP进程,用于网络资源的隔离
通过提供一种创建(创建容器就是将一个名称与一个配置文件关联,lxc-create-n name -f configfile)和进入容器的方式(ssh,VNC (GUI), VT: tty (text),VT:X(GUI),操作系统让应用就像在独立的机器上运行一样,但又能共享很多底层的资源。LXC配置文件的例子如下:
lxc.utsname = my_ssh_container lxc.network.type = veth lxc.network.flags = up lxc.network.link = br0 lxc.network.ipv4 = 10.0.2.16/24 lxc.network.name = eth0 lxc.mount = ./fstab lxc.rootfs = ./rootfs
mkdir -p ./rootfs/{bin,dev,etc,lib,lib64,proc,sbin,sys,usr,var}
$ cat./fstab
/bin /bak/lxc/rootfs/bin none ro,bind 0 0
/sbin /bak/lxc/rootfs/sbin none ro,bind 0 0
/lib /bak/lxc/rootfs/lib none ro,bind 0 0
/lib64 /bak/lxc/rootfs/lib64 none ro,bind 0 0
/etc /bak/lxc/rootfs/etc none ro,bind 0 0
/usr /bak/lxc/rootfs/usr none ro,bind 0 0
/dev /bak/lxc/rootfs/dev none ro,bind 0 0
/dev/pts /bak/lxc/rootfs/dev/pts none ro,bind 0 0
/proc /bak/lxc/rootfs/proc proc defaults 0 0
/sys /bak/lxc/rootfs/sys sysfs defaults 0 0
无论配置文件如何,用LXC工具启动的容器有自己的系统进程视图,以及自己的挂载树和可用的进程间通信(IPC)资源视图。除了这些以外,当一个容器启动时,配置中未提到的任何类型的资源都被认为是与主机共享。
一些命令:
创建容器:lxc-create -n name -f configfile
列出容器: lxc-info -n name 显示容器中的进程:lxc-ps 启动系统容器,系统容器类似于虚拟机,但比虚拟机的隔离级别要低:lxc-start -n name init 启动应用容器,应用容器只是创建一个隔离一个应用程序的单独的名称容间:lxc-execute -n name cmd 发信号到某个容器的所有进程 :lxc-kill -n name -s SIGNAL 暂停,相当于级容器的所有进程发SIGSTOP信号:lxc-freeze -n name 恢复: lxc-unfreeze -n name 停止容器,将杀死容器内的所有进程:lxc-stop -n name
2013.9.29添加:
使用Libvirt管理LXC
1, 定义虚机(/etc/libvirt/lxc/lxc1.xml),相比于qemu虚拟机,lxc不需要设置cdrom、hd等硬件配置,设置信息较少。
$ sudo virsh -c lxc:/// define /bak/lxc/lxc1.xml
$ cat /bak/lxc/lxc1.xml
<domain type='lxc'>
<name>lxc1</name>
<memory>512000</memory>
<vcpu>1</vcpu>
<cputune>
<shares>1000</shares>
</cputune>
<os>
<type arch='x86_64'>exe</type>
<init>/bin/sh</init>
</os>
<devices>
<console type='pty'/>
<interface type = 'bridge'>
<source bridge = 'br-phy'/>
<virtualport type='openvswitch'/>
</interface>
</devices>
</domain>
说明,上面只是一个应用容器,和上面不同的地方在于:
1) 执行根文件系统的init脚本
<os>
<type arch='x86_64'>exe</type>
<init>/sbin/init</init>
</os>
2)在<devices>里可以添加一个根文件系统,这样虚机就可以使用自己的lib,bin等自己的内容了,对于应用容器也可以这样隔离目录但不能隔离根目录(用的就是mount --bind, 如:mount --bind /tmp/hosts /etc/hosts)。
<filesystem type='mount' accessmode='passthrough'>
<source dir='/bak/images/mylinux'/>
<target dir='/'/>
</filesystem>
我们可以用下列方法现场做一个根文件系统,
例如linux-0.2.img是一个采用kvm虚机安装的raw格式的镜像,现在将它转成linux内核认识的ext4格式的根文件系统。/mnt/ext4即是我们要用的根。
1), sudo mkdir -p /mnt/{raw,ext4} && sudo mount -o loop linux-0.2.img /mnt/raw
2), dd if=/dev/zero of=linux-0.2.ext4 bs=1M count=22
mkfs.ext4 linux-0.2.ext4
sudo mount -o loop linux-0.2.ext4 /mnt/ext4
3), sudo cp -r /mnt/raw/* /mnt/ext4/
2, 命令说明,实际上命令和用操作qemu虚机的一模一样,只不过添加了"-c lxc:///"参数,libvirt默认的是"-c qemu:///"
启动虚机,sudo virsh -c lxc:/// start lxc1
连接虚机,sudo virsh -c lxc:/// console lxc1 ,退出输入“Ctrl+]”。不要使用其他命令退出,如使用“Ctrl+d”,将导致lxc被停止、销毁等。
取消定义, sudo virsh -c lxc:/// undefine lxc1
销毁虚机, sudo virsh -c lxc:/// destroy lxc1
3, 在Virtual Machine Manager图形化界面中操作lxc时,直接创建一个LXC的连接即可。
总结:
从上面我们可以看出,LXC的隔离性做的不大好,它对cpu, memory, network的隔离还好一点,但对存储的隔离不够,尤其对于应用容器,甚至可以从lxc虚机可以访问宿主机的根目录,当然,我们可以自己做一个根文件系统然后使用操作系统容器来隔离。但lxc在这块支持不够啊,全要自己实现,所以还有两个项目docker和dockerlite似乎弥补了这些(我还没来得及看)。
dockerlite 利用 LXC(Linux 容器)实现运行时资源隔离,并利用 Btrfs 文件系统的快照功能完成状态保持和虚拟环境克隆。所谓轻量级虚拟化,也指代操作系统级别的虚拟化,通过内核和用户态进程组的支持,实现的独立网络 IP、进程树等类似虚拟机的隔离运行环境,但是和宿主机运行同样的内核。dockerlite 和另一款用 Go 语言实现的docker的区别有:
docker的主要特性如下:
- 文件系统隔离:每个进程容器运行在完全独立的根文件系统里。
- 资源隔离:可以使用cgroup为每个进程容器分配不同的系统资源,例如CPU和内存。
- 网络隔离:每个进程容器运行在自己的网络命名空间里,拥有自己的虚拟接口和IP地址。
- 写时复制:采用写时复制方式创建根文件系统,这让部署变得极其快捷,并且节省内存和硬盘空间。
- 日志记录:Docker将会收集和记录每个进程容器的标准流(stdout/stderr/stdin),用于实时检索或批量检索。
- 变更管理:容器文件系统的变更可以提交到新的映像中,并可重复使用以创建更多的容器。无需使用模板或手动配置。
- 交互式Shell:Docker可以分配一个虚拟终端并关联到任何容器的标准输入上,例如运行一个一次性交互shell
Docker的使用的大致步骤如下,如果使用dockerlite的话步骤一一对应即可:
1, 安装docker, 首先关闭SELinux, 然后使用一个叫 Naresh Kumar制作的docker安装源。
cd /etc/yum.repos.d/
sudo wget -c http://www.hop5.in/yum/el6/hop5.repo
sudo yum install docker-io
docker-io-0.6.2-1.el6.x86_64.rpm
lxc-0.9.0-1.el6.x86_64.rpm
lxc-libs-0.9.0-1.el6.x86_64.rpm
kernel-ml-aufs-3.10.5-3.el6.x86_64.rpm
2, 启动,
$ sudo docker -d
Loading containers: done.
2013/09/30 10:31:36 WARNING: Your kernel does not support cgroup swap limit.
2013/09/30 10:31:36 Listening for HTTP on /var/run/docker.sock (unix)
3, 下载镜像
查找镜像,docker search archlinux
$ sudo docker search archlinux
Found 8 results matching your query ("archlinux")
NAME DESCRIPTION
schmidh/arch-base Basic Archlinux installation with base, base-devel, yaourt, packer-color, bash-completion and emacs-nox. K...
schmidh/cassandra Archlinux Cassandra installation using JDK 7.25 and Cassandra 1.2.8.
schmidh/immutant Archlinux Immutant 1.0.0 installtion with Torquebox overlay, JDK 7.25, Clojure 1.5.1, leiningen 2.
schmidh/clojure Archlinux with Clojure and ClojureScript under Oracle JDK 7.25.
schmidh/vertx-clj Archlinux Vert.x 2.0.1 installation with mod-lang-clojure 0.1.
schmidh/redis Archlinux Redis 2.6.15 installation.
schmidh/vertx-base Archlinux Vertx 2.0.1 base installation.
schmidh/vertx-mod-redis Archlinux Vertx mod-redis installation.
下载镜像,sudo docker pull schmidh/arch-base ,存储在/var/lib/docker/目录
查看镜像,docker images
4, 容器操作, 有了镜像之后,就可以使用run命令来创建容器了,它会在容器内部执行。当命令执行完后,容器就会自动被销毁。(注意:只是容器 被销毁了,镜像还在)
在容器内运行命令,docker run schmidh/arch-base cat /etc/os-release
查看运行过的容器的状态, docker ps -l
运行虚机内部的shell, 可使用exit退出shell, docker run -t -i schmidh/arch-base bash
5,保存操作,无论在容器内做何种操作,原始的镜像都是不会被改变的。只有通过commit命令进行提交,才能把对镜像的修改保存下来。这类似于对虚拟机磁盘做snapshot。
例如:在刚才的 arch-base 镜像中安装了一个nginx ,然后进行保存:
docker run schmidh/arch-base pacman -S --noconfirm nginx
docker ps -l
docker commit 80db3f jianingy/arch-nginx
docker images
docker run jianingy/arch-nginx /sbin/nginx -v
docker run schmidh/arch-base /sbin/nginx -v
6, 虚拟机容器无法连接外网, 须保证:
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -I FORWARD 1 -i docker+ -j ACCEPT
不管怎么说,研究LXC的根本还应该是cgroup, http://www.cnblogs.com/yjf512/p/3298582.html
Reference:
http://cpqd.github.io/RouteFlow/
lxc,http://www.ibm.com/developerworks/cn/linux/l-lxc-containers/
chroot,http://www.ibm.com/developerworks/cn/linux/l-cn-chroot/
RouteFlow PPT, http://changeofelia.info.ucl.ac.be/pmwiki/uploads/SummerSchool/Program/session_007.pdf