虚拟化网络进阶管理
软件模拟网络设备
交换机
路由器
防火墙
负载均衡器
...
Linux内核加载8021q协议
#虚拟交换机支持vlan功能 modinfo 8021q modeprobe 8021q
vlan配置工具
安装
1 yum info vconfig 2 yum install -y vconfig
使用
1 vconfig --help
Use Linux Network Namespace
网络命名空间隔离,使得各个命名空间的网络,互相不可见
一个网络名称空间可以看做是一个路由器,既分割网络,也能分割命令作用域
工具
CentOS7直接使用
ip netns help
CentOS6需要更新ip命令版本
Usage
ip netns list ip netns add NAME ip netns set NAME NETNSID ip [-all] netns delete [NAME] ip netns identify [PID] ip netns pids NAME ip [-all] netns exec [NAME] cmd ... ip netns monitor ip netns list-id ip netns exec NAME ifconfig -a ip netns exec NAME route -n
简单网络实验
目的
使得内部虚拟能通过命名空间的DHCP服务器获取地址,并通过NAT功能正常访问外网
架构
准备KVM虚拟机 yum install -y qemu-kvm ln -sv /usr/libexec/qemu-kvm /usr/bin modprobe kvm modprobe kvm_intel mkdir -pv /images/kvm; cd /images/kvm wget https://launchpad.net/cirros/trunk/0.3.0/+download/cirros-0.3.0-x86_64-disk.img cp /images/kvm/cirros-0.3.0-x86_64-disk.img test1.qcow1 cp /images/kvm/cirros-0.3.0-x86_64-disk.img test2.qcow2 vim /etc/qemu-ifup #! /bin/bash # bridge=br-in if [ -n "$1" ];then ip link set $1 up sleep 1 brctl addif $bridge $1 [ $? -eq 0 ] && exit 0 || exit 1 else echo "Error: no interface scpecified." exit 1 fi chmod +x /etc/qemu-ifup bash -n /etc/qemu-ifup qemu-kvm -m 128 -name vm1 -smp 1 -drive file=/images/kvm/test1.qcow2,if=virtio,media=disk,cache=writeback,format=qcow2 \ -net nic,macaddr=52:54:00:00:00:01 -net tap,ifname=vif1.0,script=/etc/qemu-ifup --nographic qemu-kvm -m 128 -name vm1 -smp 1 -drive file=/images/kvm/test2.qcow2,if=virtio,media=disk,cache=writeback,format=qcow2 \ -net nic,macaddr=52:54:00:00:00:02 -net tap,ifname=vif2.0,script=/etc/qemu-ifup --nographic # 查看桥接属性,可以看到两个虚拟机的tap设备都桥接到br-in上了 brctl show 打开网络间转发功能 vim /etc/sysctl.conf net.ipv4.ip_forward = 1 sysctl -p 准备虚拟交换机 # 一下方式不持久,持久化必须写进文件中 brctl addbr br-in ip link set br-in up 创建网卡对,在内部虚拟交换机上使用 ip link help ip link add vinr type veth peer name vins ip link set vint up ip link set vins up ip link show brctl addif br-in vins 划分名称空间 ip netns add internal ip netns list 将br-in连接到虚拟路由器上 ip link set vinr netns internal ip link show ip netns exec internal ip config -a ip netns exec internal ip link set vinr name eth0 ip netns exec internal ip link set eth0 up ip netns exec internal ifconfig eth0 10.0.1.254/24 up 修改两个虚拟机的IP地址 VM1 sudo su - ifconfig eth0 10.0.1.1/24 up ping 10.0.1.254 route add default gw 10.0.1.254 VM2 sudo su - ifconfig eth0 10.0.1.2/24 up ping 10.0.1.254 route add default gw 10.0.1.254 准备虚拟物理交换机 # 一下方式不持久,持久化必须写进文件中 brctl addbr br-ex ip link set br-ex up ip addr del 192.168.180.128/24 dev ens33; ip addr add 192.168.180.128/24 dev br-ex; brctl addif br-ex ens33 ifconfig # 持久方式 cp /etc/sysconfig/network-script/ifcfg-ens33 /etc/sysconfig/network-script/ifcfg-br-ex vim /etc/sysconfig/network-script/ifcfg-br-ex BOOTPROTO=static DEVICE=br-ex TYPE=Bridge NM_CONTROLLED=no IPADDR=192.168.180.128 NETMASK=255.255.255.0 GATEWAY=192.168.180.1 DNS1=114.114.114.144 DNS2=8.8.8.8 vim /etc/sysconfig/network-script/ifcfg-ens33 BOOTPROTO=none DEVICE=ens33 NM_CONTROLLED=no ONBOOT=yes BRIDGE=br-ex systemctl stop NetworkManager chkconfig NetworkManager off systemctl restart network 创建网卡对,在虚拟物理交换机上使用 ip link add vexr type veth peer name vexs ip link set vexr up ip link set vexs up ip link show brctl addif br-ex vexs 将br-ex连接到虚拟路由器上 ip link set vexr netns internal ip link show ip netns exec internal ip config -a ip netns exec internal ip link set vexr name eth1 ip netns exec internal ip link set eth1 up ip netns exec internal ifconfig eth1 192.168.180.200/24 up 为了使内部虚拟机地址能访问外网,我们在网络名称空间internal中配置NAT规则 ip netns exec internal iptables -t nat -A POSTROUTING -s 10.0.0.1/24 ! -d 10.0.0.1/24 -j SNAT --to-source 192.168.180.200 ip netns exec internal iptables -t nat -L -n 为虚拟机配置一台DNS服务器 yum install -y dnsmasq ip netns exec internal dnsmasq --dhcp-range=10.0.1.100,10.0.1.120 --dhcp-option=option:router,10.0.1.254 ip netns exec internal ps aux | grep dnsmasq 虚拟机尝试获取DHCP分配地址 udhcp -R ping 10.0.78.25 VM3、VM4类似,自行配置即可
OVS
基于C语言开发
特性
支持802.1q协议
NIC bounding
NetFlow,sFlow
Qos
GRE 通用路由封装
VxLAN
IPsec
基于Linux实现高性能转发
OVS组成部分
* ovs-vswitchd OVS守护进程 实现数据报文交换功能 和Linux兼容模块一同实现基于流交换技术 * ovsdb-server 轻量级的数据库服务 存储OVS交换机上的接口、接口配置、VLAN等 ovs-vswitched基于此配置信息交换数据 ovs-dpctl * ovs-vsctl 用于获取、更改ovs-vswitched的配置信息 操作结果存储于ovsdb-server ovs-appctl ovsdbmonitor 显示监控信息 ovs-controller 流控制工具 ovs-ofctl ovs-pki
ovs-vsctl常用命令
show 显示ovsdb配置内容 add-br 添加桥设备 del-br 删除桥设备 add-port 显示所有定义已定义桥 del-port 删除指定桥上的指定PORT list-br 将PORT添加至指定桥设备 list-ports 显示指定桥上的所有PORT list-ifaces 显示指定桥上的接口信息 list Interface 显示数据库中接口的详细信息 list Port 显示数据库中PORT的详细信息 find Port name = "ens37" 条件查询数据库的指定PORT set TBL REC COL[:KEY]=VALUE set COLumn values in RECord in TBL add TBL REC COL [KEY=]VALUE add (KEY=)VALUE to COLumn in RECord in TBL remove TBL REC COL [KEY=]VALUE remove (KEY=)VALUE from COLumn clear TBL REC COL clear values from COLumn in RECord in TBL create TBL COL[:KEY]=VALUE create and initialize new record destroy TBL REC delete RECord from TBL
实例:单节点虚拟机互相通信
架构 计算节点 Node1 OS: CentOS7 ens33: 192.168.180.135/24 此处网络连接管理网络和外网网络 ens37: 172.16.0.1/24 节点数据网络 VM1 eth0: 10.0.0.1/24 VM2 eth0: 10.0.0.2/24 VM3 eth0: 10.0.0.3/24 以下配置全部在Node1上进行 安装openvswitch yum -y install openssl-devel kernel-devel yum groupinstall "Development Tools" -y adduser ovswitch su - ovswitch wget http://openvswitch.org/releases/openvswitch-2.3.0.tar.gz tar xfz openvswitch-2.3.0.tar.gz mkdir -p ~/rpmbuild/SOURCES cp openvswitch-2.3.0.tar.gz ~/rpmbuild/SOURCES # 去除Nicira提供的openvswitch-kmod依赖包,创建新的spec文件 sed 's/openvswitch-kmod, //g' openvswitch-2.3.0/rhel/openvswitch.spec > openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec rpmbuild -bb --without check ~/openvswitch-2.3.0/rhel/openvswitch_no_kmod.spec yum -y localinstall /home/ovswitch/rpmbuild/RPMS/x86_64/openvswitch-2.3.0-1.x86_64.rpm rpm -qf `which ovs-vsctl` # 由于SELinux会影响Open vSwitch的运行,比如报错: # error: /etc/openvswitch/conf.db: failed to lock lockfile (No such file or directory)原因是没有权限修改/etc/openvswitch的owner # 如果环境允许可用关掉SELinux;想保持enabled需要做如下修改: mkdir /etc/openvswitch semanage fcontext -a -t openvswitch_rw_t "/etc/openvswitch(/.*)?" restorecon -Rv /etc/openvswitch # 启动服务 systemctl start openvswitch.service # 查看各软件包路径 rpm -ql openvswitch 添加虚拟桥设备 ovs-vsctl add-br br-in 准Xen虚拟化环境或KVM虚拟化环境 Xen:http://www.cnblogs.com/cq146637/p/8931844.html KVM:http://www.cnblogs.com/cq146637/p/8932135.html 脚本编写 vim /etc/if-up #!/bin/bash # bridge="br-in" if [ -n "$1" ]; then ip link set $1 up sleep 1 ovs-vsctl add-port $bridge $1 [ $? -eq 0 ] && exit 0 || exit 1 else echo "Error: no port scpecified." exit 2 fi vim /etc/if-down #!/bin/bash # bridge="br-in" if [ -n "$1" ]; then ip link set $1 down sleep 1 ovs-vsctl del-port $bridge $1 [ $? -eq 0 ] && exit 0 || exit 1 else echo "Error: no port scpecified." exit 2 fi chmod +x /etc/if-up chmod +x /etc/if-down bash -n /etc/if-up bash -n /etc/if-down 创建虚拟机 mkdir -pv /images/cirros/ cd /images/cirros/ wget https://launchpad.net/cirros/trunk/0.3.0/+download/cirros-0.3.0-x86_64-disk.img cp cirros-0.3.0-x86_64-disk.img test1.img cp cirros-0.3.0-x86_64-disk.img test2.img cp cirros-0.3.0-x86_64-disk.img test3.img # 此处采用qemu-kvm创建虚拟机 qemu-kvm -name "VM1" -m 128 -smp 1 -drive file=/images/cirros/test1.img,media=disk,if=virtio \ -net nic,model=virtio,macaddr=52:54:00:00:00:01 \ -net tap,ifname=vif1.0,script=/etc/if-up,downscript=/etc/if-down -daemonize qemu-kvm -name "VM2" -m 128 -smp 1 -drive file=/images/cirros/test2.img,media=disk,if=virtio \ -net nic,model=virtio,macaddr=52:54:00:00:00:02 \ -net tap,ifname=vif2.0,script=/etc/if-up,downscript=/etc/if-down -daemonize 修改虚拟机的IP地址 VM1 vncviewer :5900 & ifconfig eth0 10.0.0.1 netmask 255.255.255.0 up VM2 vncviewer :5901 & ifconfig eth0 10.0.0.2 netmask 255.255.255.0 up 测试此时的联通性 VM1 ping VM2 # 结果可以ping通 将两台虚拟机tap分别添加到vlan中 ovs-vsctl set port vif1.0 tag=10 # 此时测试连通性,结果是不通的 # 同一网段,不在同一vlan则不能通信 ovs-vsctl set port vif2.0 tag=20 # 此时测试连通性,结果是连通的 在创建一台虚拟机,使得不同虚拟机交换机中,同一vlan的虚拟机能互相通信 ovs-vsctl add-br br-test cp if-up if-up-test bridge="br-test" cp if-down if-down-test bridge="br-test" 创建 VM3 qemu-kvm -name "VM3" -m 128 -smp 1 -drive file=/images/cirros/test3.img,media=disk,if=virtio \ -net nic,model=virtio,macaddr=52:54:00:00:00:03 \ -net tap,ifname=vif3.0,script=/etc/if-up,downscript=/etc/if-down -daemonize VM3 vncviewer :5902 & ifconfig eth0 10.0.0.3 netmask 255.255.255.0 up ip link add vs3.0 type veth peer name vs3.1 ip link set vs3.0 up ip link set vs3.1 up ovs-vsctl add-port br-in vs3.0 ovs-vsctl add-port br-test vs3.1 # 此时ping与其它两台虚拟机不能通 # 因为VM3的tap没有添加到vlan10中 ovs-vsctl set port vif3.0 tag=10 # 此时ping与其它两台虚拟机就可以互相通信了 # 因为默认情况下,虚拟两台交换机自动协商为trunk模式
实验:多节点虚拟机互相通信
架构 计算节点 Node1 OS: CentOS7 ens33: 192.168.180.135/24 此处网络连接管理网络和外网网络 ens37: 172.16.0.1/24 节点数据网络 VM1 eth0: 10.0.0.1/24 VM2 eth0: 10.0.0.2/24 VM3 eth0: 10.0.0.3/24 Node2 OS: CentOS7 ens33: 192.168.180.136/24 此处网络连接管理网络和外网网络 ens37: 172.16.0.2/24 节点数据网络 VM4 eth0: 10.0.0.4/24 VM5 eth0: 10.0.0.5/24 准备须知 在上一个环境的基础上,继续配置添加新节点和虚拟机 此次实验使用GRE协议,协助数据包在不同节点上传输 GRE Generic Routing Encapsulation 通用路由封装协议,类似隧道技术 在点对点的基础上,对数据包进行封装解封装,完成隧道通信 所有节点打开网络间转发功能 vim /etc/sysctl.conf net.ipv4.ip_forward = 1 sysctl -p 节点二: 拷贝Node1上的脚本文件 scp root@192.168.47.135:/etc/{if-up,if-down} /etc/. 安装openvswitch ... 配置虚拟网桥 ovs-vsctl add-br br-in 准Xen虚拟化环境或KVM虚拟化环境 ... 创建虚拟机 mkdir -pv /images/cirros/ cd /images/cirros/ wget https://launchpad.net/cirros/trunk/0.3.0/+download/cirros-0.3.0-x86_64-disk.img cp cirros-0.3.0-x86_64-disk.img test4.img cp cirros-0.3.0-x86_64-disk.img test5.img # 此处采用qemu-kvm创建虚拟机 qemu-kvm -name "VM4" -m 128 -smp 1 -drive file=/images/cirros/test4.img,media=disk,if=virtio \ -net nic,model=virtio,macaddr=52:54:00:00:00:04 \ -net tap,ifname=vif1.0,script=/etc/if-up,downscript=/etc/if-down -daemonize qemu-kvm -name "VM5" -m 128 -smp 1 -drive file=/images/cirros/test5.img,media=disk,if=virtio \ -net nic,model=virtio,macaddr=52:54:00:00:00:05 \ -net tap,ifname=vif2.0,script=/etc/if-up,downscript=/etc/if-down -daemonize 修改虚拟机的IP地址 Node2 VM4 vncviewer :5900 & ifconfig eth0 10.0.0.4 netmask 255.255.255.0 up VM5 vncviewer :5901 & ifconfig eth0 10.0.0.5 netmask 255.255.255.0 up VM4 ping VM5 能Ping通 此次添加DNS服务器,使得虚拟机自动获取地址 Node1 yum update -y iproute yum install -y dnsmasq ip netns add internal ip link add vsifs type veth peer name vsifr ip link set vsifs up ip link set vsifr up ip link set vsifr netns internal ovs-vsctl add-port br-in vsifs ip netns exec internal ip link set vsifr up ip netns exec internal ifconfig ip netns exec internal ip addr add 10.0.0.254/24 dev vsifr ip netns exec internal dnsmasq -F 10.0.0.1,10.0.0.253,86400 --dhcp-option=option:router,10.0.0.254 -i vsifr VM1尝试获取DHCP分配地址,进入控制台 # 注意先把vif1.0的tag标记位去了,才能获取到地址 udhcpc -R Node2 无须配置,网络链路连通后,VM3、VM4也能通过Node1上DNS服务器获取IP地址 使用ens37物理网卡传输节点数据 注意 ens37网卡无须添加到br-in上,ovs可以借助ens37传输gre封装的数据包 Node1上,自定义一个IP地址给ens37,可以将修改内容写进文件中达到持久化的效果 ip addr add 172.16.0.1/24 dev ens37 Node2上,自定义一个IP地址给ens37 ip addr add 172.16.0.2/24 dev ens37 在br-in上添加端口,用于gre封装数据包 两个节点都要做 ovs-vsctl add-port br-in gre0 设置接口ger0属性,使它工作于gre模式 Node1 ovs-vsctl set interface gre0 type=gre options:remote_ip=172.16.0.1 Node2 ovs-vsctl set interface gre0 type=gre options:remote_ip=172.16.0.2 配置VLAN使得VM1能和VM3通信,VM2能和VM4通信,VM1不能和VM2通信,VM3不能和VM4通信 Node1 ovs-vsctl set port vif1.0 tag=10 -- set port vif2.0 tag=20 -- set port vif3.0 tag=10 Node2 ovs-vsctl set port vif1.0 tag=10 -- set port vif2.0 tag=20 查看使用GRE通信内容 VM1: ping VM3_IP 抓包查看GRE内容 tcpdump -i ens37 -nn 删除所有节点gre配置 ovs-vsctl del-port br-in gre0 此时实验将通信协议GRE,改用为VxLAN协议 在br-in上添加端口,用于gre封装数据包 两个节点都要做 ovs-vsctl add-port br-in vxlan0 设置接口ger0属性,使它工作于gre模式 Node1 ovs-vsctl set interface vxlan0 type=vxlan options:remote_ip=172.16.0.2 Node2 ovs-vsctl set interface vxlan0 type=vxlan0 options:remote_ip=172.16.0.1 查看使用VxLAN通信内容 VM1: ping VM3_IP 抓包查看VxLAN内容 tcpdump -i ens37 -nn 14:14:43.056888 IP 172.16.0.1 > 172.16.0.2: GREv0, length 50: ARP, Request who-has 10.0.0.2 tell 10.0.0.3, length 28 14:14:43.329817 IP 172.16.0.2 > 172.16.0.1: GREv0, length 106: IP 10.0.0.29 > 10.0.0.1: ICMP echo request, id 2305, seq 88, length 64 14:14:43.330376 IP 172.16.0.1 > 172.16.0.2: GREv0, length 106: IP 10.0.0.1 > 10.0.0.29: ICMP echo reply, id 2305, seq 88, length 64
实验:多节点虚拟机访问外网
架构 计算节点 Node1 OS: CentOS7 ens33: 172.16.100.1/24 管理网络 ens37: 172.16.0.1/24 节点数据网络 VM1 eth0: 10.0.0.1/24 VM2 eth0: 10.0.0.2/24 VM3 eth0: 10.0.0.3/24 Node2 OS: CentOS7 ens33: 172.16.100.2/24 管理网络 ens37: 172.16.0.2/24 节点数据网络 VM4 eth0: 10.0.0.4/24 VM5 eth0: 10.0.0.5/24 Network Node OS: CentOS7 ens33: 172.16.100.3/24 管理网络 ens37: 172.16.0.254/24 节点数据网络 ens38: 192.168.47.137 外网网络 准备须知 在上一个环境的基础上,删除所有节点vlan配置,vxlan配置 ovs-vsctl remove port vif1.0 tag 10 -- remove port vif2.0 tag 20 remove port vif3.0 tag 10 ovs-vsctl del-port br-in vxlan0 添加新的节点,我们称之为网络节点 准备虚拟物理交换机 # 一下方式不持久,持久化必须写进文件中 brctl addbr br-ex ip link set br-ex up ip addr del 192.168.47.137/24 dev ens38; ip addr add 192.168.47.137/24 dev br-ex; brctl addif br-ex ens38 ifconfig # 持久方式 cp /etc/sysconfig/network-script/ifcfg-ens33 /etc/sysconfig/network-script/ifcfg-br-ex vim /etc/sysconfig/network-script/ifcfg-br-ex BOOTPROTO=static DEVICE=br-ex TYPE=Bridge NM_CONTROLLED=no IPADDR=192.168.47.137 NETMASK=255.255.255.0 GATEWAY=192.168.180.1 DNS1=114.114.114.144 DNS2=8.8.8.8 vim /etc/sysconfig/network-script/ifcfg-ens38 BOOTPROTO=none DEVICE=ens38 NM_CONTROLLED=no ONBOOT=yes BRIDGE=br-ex systemctl stop NetworkManager chkconfig NetworkManager off systemctl restart network 安装openvswitch 与第一个实验相同 准备OVS虚拟交换机 # 一下方式不持久,持久化必须写进文件中 brctl addbr br-in ip link set br-in up 在网络节点上创建网络名称空间 yum update -y iproute ip netns add external 创建网卡对,将网络名称空间和br-in连接起来,将br-ex和网络名称空间连接起来 ip link add vins type veth peer name vinr ip link add vexs type veth peer name vexr ip link set vins up ip link set vexs up ip link vins netns external ip link vexs netns external ovs-vsctl add-port br-in vins brctl addif br-ex vexs 修改实验一中网络名称空间internal中为各虚拟机配置的网关IP,将网关IP写到external Node1 ip netns exec internal ifconfig vsifr 10.0.0.100/24 up Network Node ip netns exec external ifconfig vinr 10.0.0.254/24 up ip netns exec external ifconfig vexr 192.168.47.138/24 up ip netns exec external sysctl -w net.ipv4.ip_forward=1 使用GRE协议让计算节点和网络节点通信 注意 ens37网卡无须添加到br-in上,ovs可以借助ens37传输gre封装的数据包 Node1上,自定义一个IP地址给ens37 ip addr add 172.16.0.1/24 dev ens37 Node2上,自定义一个IP地址给ens37 ip addr add 172.16.0.2/24 dev ens37 网络节点上,自定义一个IP地址给ens37,用于节点数据传输 ip addr add 172.16.0.254/24 dev ens37 在br-in上添加端口,用于gre封装数据包 所有节点都要做 ovs-vsctl add-port br-in gre0 设置接口ger0属性,使它工作于gre模式 Node1 ovs-vsctl set interface gre0 type=gre options:remote_ip=172.16.0.254 Node2 ovs-vsctl set interface gre0 type=gre options:remote_ip=172.16.0.254 网络节点 ovs-vsctl set interface gre0 type=gre options:remote_ip=172.16.0.1 # 其他节点继续添加即可 在external中添加SNAT规则 ip netns exec external iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j SNAT --to-source 192.168.47.138 可实现Node1中的虚拟机可以ping通外网 使用SNAT、DNAT把服务器向互联网开放 清空external中的规则 ip netns exec external iptables -t nat -F 在external添加一个外网地址,将此地址映射为内网虚拟机,专门为某台虚拟机提供访问互联网的能力 ip netns exec external ifconfig vexr:0 192.168.47.139/24 ip netns exec external iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -j SNAT --to-source 192.168.47.139 ip netns exec external iptables -t nat -A PREROUTING -d 192.168.47.139 -j DNAT --to-destination 10.0.0.1 # 如果需要更多节点对外访问继续添加DNAT规则即可