KVM — 虚拟网络构建
构建虚拟网络是虚拟化及容器化的必备的核心技术
构架虚拟网络的基本组件相关命令
1.虚拟网卡接口管理命令 : ip link
- 创建虚拟网卡接口设备
一般虚拟网卡接口成对创建,类似于现实中的网卡加网线的作用
ip link <options> type veth [peer [ name ] NAME]
- 将成对的网卡接口的一端配置在另一个虚拟路由器上
ip link set IF_DEVICE netns NET_NAMESPACE
2.网络桥设备管理命令 : brctl
- 创建网络桥虚拟设备
brctl addbr <bridge>
- 向桥设备上添加虚拟网卡(成对出现)中的一个接口
将成对的虚拟网卡接口的一端配置在网桥设备上,类似于现实中将某网卡设备用网线连接至交换机(网桥)
brctl addif <bridge> DEVICE
- 删除桥设备
brctl delbr <bridge> DEVICE
- 删除桥设备上的网卡接口
brctl delif <bridge> DEVICE
3.网络名称空间管理命令 : ip netns
- 虚拟网络名称空间,用于隔离网络,可以理解为虚拟路由器
Usage: ip netns list
ip netns add NET_NAMESPACE
- 指定在某个 NET_NAMESPACE (网络名称空间) 中执行某个 COMMAND
ip netns exec NET_NAMESPACE COMMAND
构建虚拟网络过程演示
虚拟机与虚拟路由器连接通信演示
- 创建一对虚拟网卡接口设备
ip link add vethx.1 type veth peer name vethx.2
ip link show
#
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:99:ea:72 brd ff:ff:ff:ff:ff:ff
3: vethx.2@vethx.1: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether b2:43:00:1a:41:cf brd ff:ff:ff:ff:ff:ff
4: vethx.1@vethx.2: <BROADCAST,MULTICAST,M-DOWN> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 2e:d1:5d:79:3f:b6 brd ff:ff:ff:ff:ff:ff
- 创建虚拟路由器
ip netns add router1
ip netns list --all
#
router1
- 将虚拟网卡接口的一端配置在虚拟路由上
ip link set dev vethx.2 netns router1
ip link show
#
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:99:ea:72 brd ff:ff:ff:ff:ff:ff
3: vethx.1@if6: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 2e:d1:5d:79:3f:b6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
- 指定在 router1 (网络名称空间) 中执行 ifconfig -a 命令
ip netns exec router1 ifconfig -a
#
lo: flags=8<LOOPBACK> mtu 65536
loop txqueuelen 1 (Local Loopback)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
vethx.2: flags=4098<BROADCAST,MULTICAST> mtu 1500
ether b2:43:00:1a:41:cf txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 将虚拟网络名称空间 router1 中的网络接口 vethx.2 配置一个 IP 地址并查看结果
ip netns exec router1 ifconfig vethx.2 10.0.0.1/24 up
ip netns exec router1 ifconfig
#
vethx.2: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.0.2 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::b043:ff:fe1a:41cf prefixlen 64 scopeid 0x20<link>
ether b2:43:00:1a:41:cf txqueuelen 1000 (Ethernet)
RX packets 8 bytes 648 (648.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 给 vethx.1 网络接口配置 IP 地址并查看结果
ifconfig vethx.1 10.0.0.2/24 up
ifconfig vethx.1
#
vethx.1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.0.1 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::2cd1:5dff:fe79:3fb6 prefixlen 64 scopeid 0x20<link>
ether 2e:d1:5d:79:3f:b6 txqueuelen 1000 (Ethernet)
RX packets 8 bytes 648 (648.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 某个虚拟机与虚拟路由器通过 vethx.1 与 vethx.2 这对网络接口连接,虚拟机与路由器间可以通信了
ping 10.0.0.2
#
PING 10.0.0.2 (10.0.0.2) 56(84) bytes of data.
64 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.067 ms
^C
--- 10.0.0.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1000ms
rtt min/avg/max/mdev = 0.058/0.062/0.067/0.009 ms
- 删除网络接口
ip link delete vethx.1
#删掉一个,另一个会自动消失
ip netns exec router1 ifconfig
- 删除虚拟路由器
ip netns delete router1
ip netns list
一个具有 DHCP 服务的仅供内部虚拟机间通信的网络配置演示
此实验实现的网络模型,仅供宿主机内部的虚拟机之间通信,内部虚拟机无法与宿主机通信,类似于实现了 VMware 程序中的 除了 VMnet0 、VMnet1(仅主机模式) 、VMnet8(NAT模式) 之外的的其他自定义网络通道的功能。
多台虚拟机之间通过虚拟交换机设备(网络桥设备)通信,其中一台虚拟机提供 DHCP 网络服务
- 创建、激活并查看网络桥设备
brctl addbr br-int
ifconfig br-int up
ifconfig
#
br-int: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::fc47:88ff:fed1:2c42 prefixlen 64 scopeid 0x20<link>
ether fe:47:88:d1:2c:42 txqueuelen 1000 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 7 bytes 578 (578.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 配置虚拟机的虚拟网卡并将虚拟网卡连接至虚拟交换机,启动虚拟机
两个虚拟机需要预先安装好操作系统并设置硬盘启动
- 创建关联虚拟交换机的脚本
vim /etc/qemu-ifup
#!/bin/bash
#
bridge=br-int
if [ -n "$1" ];then
ip link set $1 up
sleep 1
brctl addif $bridge $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "No interface specified."
exit 2
fi
- 配置网络并启动第一个虚拟机 C1 进程
qemu-kvm -name c1 -m 256 -cpu host -smp 2,cores=2,sockets=1 -drive file=/vms/centos/cts1.img,if=virtio,media=disk,cache=writeback,format=qcow2 -drive file=/vms/ISOs/CentOS-7-x86_64-Minimal-1511.iso,media=cdrom -boot order=cd -net nic,model=virtio,macaddr=52:54:00:00:00:01 -net tap,script=/etc/qemu-ifup -vnc :0 -daemonize
- 配置网络并启动第二个虚拟机 C2 进程
第二台虚拟机需要修改:名称、磁盘映像文件、网卡接口的MAC地址、VNC的监听端口
qemu-kvm -name c2 -m 256 -cpu host -smp 2,cores=2,sockets=1 -drive file=/vms/centos/cts2.img,if=virtio,media=disk,cache=writeback,format=qcow2 -drive file=/vms/ISOs/CentOS-7-x86_64-Minimal-1511.iso,media=cdrom -boot order=cd -net nic,model=virtio,macaddr=52:54:00:00:00:02 -net tap,script=/etc/qemu-ifup -vnc :1 -daemonize
- 查看虚拟机运行状态
ps aux | grep qemu
#
root 7623 1.8 13.6 729268 277352 ? Sl 16:23 0:20 qemu-kvm -name c1 -m 256 -cpu host -smp 2,cores=2,sockets=1 -drive file=/vms/centos/cts1.img,if=virtio,media=disk,cache=writeback,format=qcow2 -drive file=/vms/ISOs/CentOS-7-x86_64-Minimal-1511.iso,media=cdrom -boot order=cd -net nic,model=virtio,macaddr=52:54:00:00:00:01 -net tap,script=/etc/qemu-ifup -vnc :0 -daemonize
root 7881 0.7 5.6 831664 115776 ? Sl 16:31 0:04 qemu-kvm -name c2 -m 256 -cpu host -smp 2,cores=2,sockets=1 -drive file=/vms/cirros/cirros2.img,if=virtio,media=disk,cache=writeback,format=qcow2 -net nic,model=virtio,macaddr=52:54:00:00:00:02 -net tap,script=/etc/qemu-ifup -vnc :1 -daemonize
ss -tunl
#
Netid State Recv-Q Send-Q Local Address:Port Peer Address:Port
udp UNCONN 0 0 * %virbr0:67 *:*
tcp LISTEN 0 1 *:5900 *:*
tcp LISTEN 0 1 *:5901 *:*
ifconfig
#
br-int: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::30a5:70ff:fe37:bca7 prefixlen 64 scopeid 0x20<link>
ether 46:53:ba:f9:9e:2e txqueuelen 1000 (Ethernet)
RX packets 160 bytes 25492 (24.8 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tap0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::a41f:2ff:fe60:c47d prefixlen 64 scopeid 0x20<link>
ether a6:1f:02:60:c4:7d txqueuelen 1000 (Ethernet)
RX packets 151 bytes 26298 (25.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 17 bytes 2082 (2.0 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tap1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::4453:baff:fef9:9e2e prefixlen 64 scopeid 0x20<link>
ether 46:53:ba:f9:9e:2e txqueuelen 1000 (Ethernet)
RX packets 9 bytes 1434 (1.4 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 98 bytes 16644 (16.2 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 使用命令 “vncviewer :0” 连接至虚拟机 C1
ifconfig ens33 10.0.0.1/24 up
- 使用命令 “vncviewer :1” 连接至虚拟机 C2
ifconfig ens33 10.0.0.2/24 up
- 两台主机间通信
ping 10.0.0.2
仅主机网络通信模型的实现
在以上实验的基础上,给网桥设备一个相同分段的 IP 地址,可以实现仅主机网络模式,即:宿主机可以和运行与其上虚拟机通信
虚拟设备 br-int 原来工作在OSI七层模型中的二层——数据链路层,当分配了IP地址后,br-int 设备工作在三层——网络层,br-int 在未分配IP地址前,可以理解为一个虚拟交换机设备,分配IP地址后,具备了虚拟路由器的功能。
- 为虚拟机之间的虚拟交换机设备配置一个同网段的IP地址
ifconfig br-int 10.0.0.254/24 up
[root@localhost cirros]# ifconfig br-int
#
br-int: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.0.0.254 netmask 255.255.255.0 broadcast 10.0.0.255
inet6 fe80::30a5:70ff:fe37:bca7 prefixlen 64 scopeid 0x20<link>
ether 46:53:ba:f9:9e:2e txqueuelen 1000 (Ethernet)
RX packets 416 bytes 67220 (65.6 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 8 bytes 648 (648.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
- 实现宿主机与虚拟机通信
ping 10.0.0.1
ping 10.0.0.2
* NAT 网络通信模型*的实现
在“仅主机”网络模型的基础上,添加 iptables 的 nat 规则(SNAT 或 DNAT), 即可以实现NAT网络模式,即:宿主机作为运行与其上虚拟机的正向代理,将公网上的通信请求转发至对应的虚拟机,而虚拟机以宿主机的身份向公网发出通信请求。
本实验旨在访问宿主机上运行的虚拟机的ssh服务,因为宿主机(172.16.50.18)也提供了ssh服务,所以需要做端口映射
- 将虚拟机 C1 ,C2 的网关指向 br-int 设备的 IP 地址
route add default gw 10.0.0.254
- 启用宿主机系统的核心转发功能
sysctl -w net.ipv4.ip_forward=1
#
net.ipv4.ip_forward = 1
- 配置 iptables 的 SNAT 规则
需要进行IP地址和端口映射
iptables -t nat -A PREROUTING -d 172.16.50.18 -p tcp --dport 22922 -j DNAT --to-destination 10.0.0.1:22
iptables -t nat -vnL
#结果为
Chain PREROUTING (policy ACCEPT 257 packets, 38061 bytes)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- * * 0.0.0.0/0 172.16.50.18 tcp dpt:22922 to:10.0.0.1:22
- 在某一台远程主机上使用ssh连接至 C1 虚拟机
ssh -p 22922 root@172.16.50.18
- 如果要连接另一台虚拟机,可以定义另一个端口。
配置内部网络的 DHCP 服务
- 在宿主机上安装dnsmasq程序
yum install dnsmasq dnsmasq
- 在宿主机上创建一对虚拟网卡接口设备,一端配置在 br-int 设备上,
ip link add vethy.1 type veth peer name vethy.2
ifconfig vethy.1 up
brctl addif br-int vethy.1
ip netns add dhcpsrv
ip link set dev vethy.2 netns dhcpsrv
ip netns exec dhcpsrv ifconfig -a
ip netns exec dhcpsrv ifconfig vethy.2 10.0.0.253/24 up
ip netns exec dhcpsrv ifconfig
ip netns exec dhcpsrv dnsmasq -F 10.0.0.20,10.0.0.100 -o 3,10.0.0.254
ip netns exec dhcpsrv ps aux | grep dnsmasq
- 重启虚拟机,查看状态
ifconfig
route -n
两台宿主机之上的虚拟机之间通信
可采用将两台宿主机桥接的方式
如果不想将宿主机之上的虚拟机暴露于公网之中,需要使用叠加网络模型(隧道网络)。