引言
在研究协议实现细节时,动手实践是极其重要的一环。而搭建一个合适的环境用于协议实现测试,重要性也就不言而喻。这篇文章介绍了我用Libvirt搭建client-router-server拓扑的过程细节。
准备
确认虚拟化支持:
我是在fedora 上搭建的,其他 Linux 发行版也应类似。首先确认Host 支持虚拟化:
grep -E –color=auto "(vmx|svm)" /proc/cpuinfo
安装依赖包:
dnf install -y libguestfs-tools-c virt-install libvirt libvirt-daemon-config-network
下载OS镜像:
wget https://cloud.centos.org/centos/8/x86_64/images/CentOS-8-GenericCloud-8.3.2011-20201204.2.x86_64.qcow2
安装系统
我们将上面下载的镜像拷贝到/var/lib/libvirt/images下面,一般都放在这个位置。然后配置虚拟机配置,并直接从磁盘启动:
virt-install --name client --virt-type kvm --memory 512 --vcpus 1 --disk /var/lib/libvirt/images/client.qcow2,bus=virtio --import --network default --noautoconsole -v --os-variant rhel8
注意:这里的–noautoconsole -v 用来文本模式驱动虚拟机,而不用图形界面,后面我们通过virsh console来连入虚拟机文字界面。
列举virt-install支持的os类型:
osinfo-query os | grep -i cent
创建后的虚拟机配置文件都存放在:/etc/libvirt/qemu/下
连入系统
安装好后,我们就可以通过virsh命令来管理控制虚拟机了。比如,我们现在可以用console来连入刚刚创建的虚拟机:
virsh console client
但此时密码不对,进入不了系统,于是关机并修改密码:
virsh destroy client
virt-customize -a /var/lib/libvirt/images/client.qcow2 --root-password password:NewRootUserPasswordHere --uninstall cloud-init
改好密码后,重新启动并进入系统:
virsh start client
virsh console client
搭建网络拓扑
克隆虚拟机
首先,我们可以基于现在client虚拟机,直接clone出router和server:
virt-clone --original client --name router --file /var/lib/libvirt/images/router.qcow2
virt-clone --original client --name server --file /var/lib/libvirt/images/server.qcow2
建桥当网线
接下来,我们通过建立桥bridge来当网线,后面会用桥来将两个网口连起来,从而实现client和router 的连接、router和server的连接。首先在libvirt 里面建立两个bridge:
<network>
<name>net_client_router</name>
<bridge name="br0" stp='off' macTableManager="libvirt"/>
<mtu size="9216"/>
</network>
<network>
<name>net_router_server</name>
<bridge name="br1" stp='off' macTableManager="libvirt"/>
<mtu size="9216"/>
</network>
我们不需要bridge同设备交互,只希望他们安安静静地当网线,所以这里禁用STP协议。然后定义这两个桥:
virsh net-define ./client_router.xml
virsh net-define ./router_server.xml
可以看到桥已经建立:
virsh net-list --all
建立网卡,并连接到网线
我们安装系统后,默认只有default 网络,这个网络是用于上网用的,默认走NAT后访问外部网络。我们还需要给client、server分别添加一个网口用于测试,给路由器添加两个网口用于转发。并且把这些网口用上面的桥互相连接起来。以client为例,我们添加一个网口,并连接到br0
上:
virsh domiflist client # 查看虚拟机的网卡列表
virsh attach-interface --domain client --type network --source net_client_router --model virtio --config --live
通过brctl show
可以看到新添加的网口,已经add到了br0上:
[root@localhost lovelylich]# brctl show br0
bridge name bridge id STP enabled interfaces
br0 8000.525400679ecc no br0-nic
vnet3
同样把其他网口也添加,并按需连起来:
virsh attach-interface --domain router --type network --source net_client_router --model virtio --config
virsh attach-interface --domain router --type network --source net_client_router --model virtio --config
virsh attach-interface --domain server --type network --source net_router_server --model virtio --config
配置IP、路由、开启转发
网络拓扑搭好,router还没有成为真正的router,我们需要开启转发模式(也可以安装路由软件)实现路由转发:
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf
sysctl -p
最后分别配置client、router、server的ip地址和路由,并测试连通性即可。一定要注意要加路由,否则默认路由是nat的那个网卡,这样报文就不是按照我们预定拓扑来走了,如下:
client:
ip a a 1.1.1.1/24 dev eth1
ip route add to 2.2.2.0/24 via 1.1.1.2 dev eth1 src 1.1.1.1
router:
ip a a 1.1.1.2/24 dev eth1
ip a a 2.2.2.2/24 dev eth2
server:
ip a a 2.2.2.1/24 dev eth1
ip route add to 1.1.1.0/24 via 2.2.2.2 dev eth1 src 2.2.2.1
测试
最后,在client上ping server测试连通性:
[root@client ~]# ping 2.2.2.1
PING 2.2.2.1 (2.2.2.1) 56(84) bytes of data.
64 bytes from 2.2.2.1: icmp_seq=1 ttl=63 time=0.763 ms
64 bytes from 2.2.2.1: icmp_seq=2 ttl=63 time=4.90 ms
--- 2.2.2.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1003ms
rtt min/avg/max/mdev = 0.763/2.831/4.900/2.069 ms
[root@client ~]#
此后,我们就可以在client 部署客户端,router 配置延迟和丢包率(我一般用tc),在server部署服务端来测试网络协议的基本表现了。除了高并发下的中断均衡、锁争用等问题,其他一般问题基本都能通过该拓扑测试。
参考文档
https://www.brianlinkletter.com/2019/02/build-a-network-emulator-using-libvirt/