场景背景与需求
某公司新买一台服务器, 服务器资源(cpu,内存,硬盘)比较多,并且有多个网卡。
运维工程师为了节省资源,在服务器上搭建多个服务,希望通过多个网卡实现流量分流。
但由于运维工程师对网络理解不够深入,将服务器的多个网卡都配置了同一个网段。
最后的结果是并不能正常的访问这多个服务。
场景分析
- 网卡设置了IP地址后,会产生一个与IP地址同网段的路由条目, 并与当前网卡名对应。
- 如果多个网卡设置同网段IP地址后,会产生多个同网段的路由条目,并与不同网卡名对应。
假设两个网卡eth0,eth1分别配置10.1.1.5/24与10.1.1.6/24. 则会产生以下路由
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
如果不同客户端通过这两个IP进来访问不同的服务。进来会从不同网卡进,但回去时就会都从eth0回去(因为路由会从上往下读取,所以默认只会读上面一条)
测试实验:
1, 准备一个虚拟机模拟服务器,开两个网卡,都为同一个网络, 配置两个同网段IP。
server# ip addr |grep eth -A 1
eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 52:54:00:41:e4:22 brd ff:ff:ff:ff:ff:ff
inet 10.1.1.5/24 brd 10.1.1.255 scope global br0
eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 52:54:00:39:c0:e6 brd ff:ff:ff:ff:ff:ff
inet 10.1.1.6/24 brd 10.1.1.255 scope global eth1
2, 用另一台机器模拟客户端,使用ping来访问以上2个IP。
client# ip neigh |grep -E "^10.1.1.5 |^10.1.1.6 "
10.1.1.5 dev eth0 lladdr 52:54:00:41:e4:22 REACHABLE
10.1.1.6 dev eth0 lladdr 52:54:00:41:e4:22 REACHABLE
说明:
- 按照arp协议原理, 访问哪个IP它才会回应mac地址。
- 而现在的结果是mac地址都为10.1.1.5对应的mac地址。
- 这是因为linux系统内核参数默认做了设置, 访问同台机器的网卡IP,如果这个网卡挂了,另外一个同网段的网卡会帮助回应。可以比喻成(张三,李四两个网卡同一台机器,就是一家人,找张三,张三回,找李四,也张三回)
3,在服务器上修改内核参数
server# vim /etc/sysctl.conf # 添加以下参数
net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
net.ipv4.conf.eth1.arp_ignore = 1
net.ipv4.conf.eth1.arp_announce = 2
net.ipv4.conf.all.arp_ignore = 1
net.ipv4.conf.all.arp_announce = 2
server# sysctl -p # 用此命令让其生效
说明: 这几个参数的目的就是把上面的一家人(张三又回应张三也回应李四)的情况变成了原本的arp情况(张三只能回张三,李四只能回李四)
4, 再次客户端测试
client# arp -d 10.1.1.5
client# arp -d 10.1.1.6
说明: arp -d
可清除arp协议访问的mac地址缓存。建议清除再测试
最终结果:
客户端只能ping通10.1.1.5了, ping不通10.1.1.6了(这就对了,因为一台机器双网卡同网段会路由冲突)
这个实验就验证了场景中的情况:
- 服务器多网卡同网段,客户端从不同网卡IP访问进来,却都从第1个网卡回应
- 如果修改内核参数,则客户端只能访问第一张网卡的服务
场景解决方案
如果以上场景已经发生,如何解决?
- 将多网卡改成不同网段IP(这样做可能项目要修改的工作量很大,很多配置要重配)
- 通过策略路由来解决(不需要修改IP,只需要添加路由表将多个网卡流量分开)
策略路由的做法也非常简单,在服务器上做以下操作
server# echo 100 server1 >> /etc/iproute2/rt_tables
server# echo 200 server2 >> /etc/iproute2/rt_tables
server# ip rule add from 10.1.1.5 table server1
server# ip rule add from 10.1.1.6 table server2
server# ip route add default via 10.1.1.5 table server1
server# ip route add default via 10.1.1.6 table server2
说明:
- 增加了server1与server2两个路由表
- 两个路由表里的规则为访问10.1.1.5将由10.1.1.5回应,访问10.1.1.6将由10.1.1.6回应
场景总结与经验值
此解决方案主要是用到了linux上的多路由表功能。
工作中物理服务器与虚拟机有多网卡时都不要犯这种多网卡同网段的错误。
如果真的需要用到多服务隔离的话,可考虑虚拟化或容器化环境。