在以往Linux的使用中很少会涉及VLAN和网络的配置,因为多数的服务部署集中在应用层面而非底层网络(switch/route/vlan/interface),系统安装时默认生成的网络配置已经足够应对实际需求,近来需要部署一台服务器,涉及到众多VLAN的配置,因此重新梳理了下Linux系统在网络层面配置的基础内容,在常见的Linux发行版中CentOS类系统和Debain类系统在网络配置理念以及相应的实现上存在一定的区别,网络上流传的资料中则混淆了两者,也许之前的两类发行版确实存在配置的兼容性,但在两类系统的自我风格越来越明显的今天,很有必要对上述两类发行版区别对待了解其各自的配置理念和方法。
1.udev - Linux dynamic device management
本人至今没有关于udev的准确认知,只是大概的理解为Linux内核目前采用的设备文件管理方案,不满意这个解释的同学可以自行搜索资料,最简易的方法就是直接man udev查看udev的man手册,在udev的使用上各个发行版没有差别,毕竟使用的都是Linux内核,udev管理配置计算机所有可以称之为设备的设备,网络接口设备(俗称网卡)只是其中之一,udev使用所谓的rules文件描述和记录设备信息,网络设备rules文件名为70-persistent-net.rules,固定存储路径为/etc/udev/rules.d/70-persistent-net.rules,该文件内容格式如下:
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:13:99:70", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="oam"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:13:99:71", ATTR{dev_id}=="0x0", ATTR{type}=="1", KERNEL=="eth*", NAME="traffic"
文件中的item描述对应的physical network interface信息,从上述文件的描述中可以看出该系统有两块物理网卡,并使用NAME参数定义了接口在系统中的名字,因此该文件最常见的应用是自定义物理接口名字,一般网络接口会被系统命令为eth<n>的形式,在上述描述中第一块网口被命名为oam,第二块则命名为traffic。
该命名会显示在ifconfig -a命令回显的接口列表中,一般情况下,更改完70-persistent-net.rules文件后,CentOS类系统使用service network restart生效该设置,Debain类系统使用service networking restart生效该设置,或者直接重启系统生效。
经过验证CentOS类系统SUSE在系统安装完成后会自动生成70-persistent-net.rules文件,而Debain类系统Ubuntu则不会生成该文件,但可以使用系统自带的udev脚本生成该文件,脚本路径为/lib/udev/write_net_rules,该脚本为shell脚本,执行需要指定两个环境变量INTERFACE和MATCHADDR,前者为网口的名字,后者为网口的mac地址,因此建议先使用ifconfig -a命令查看物理网口的mac地址和name,然后定义上述环境变量,脚本每执行一次就会在rules文件中添加一行item。
export INTERFACE=“first”
export MATCHADDR=00:0c:29:15:b0:2d
2.interface configuration
一般情况下ifconfig -a命令回显列表中就只有物理网口和特殊的loopback接口,SUSE系统会为每一个physical & lo interface建立各自的配置文件/etc/sysconfig/network/ifcfg-<interface>,而Ubuntu系统所有的网口的配置都集中在一个配置文件/etc/network/interfaces。
关于ifcfg格式的配置文件信息可以man ifcfg,intefaces文件信息可以man interfaces。
CentOS - SUSE
该类发行版使用ifcfg格式配置文件,统一存放在/etc/sysconfig/network/目录下,文件与interface一一对应,命名格式为ifcfg-<interface>,常规文件内容如下:
bjad1:/etc/sysconfig/network # cat ifcfg-oam
BOOTPROTO='static'
BROADCAST=''
ETHTOOL_OPTIONS=''
IPADDR='10.117.174.140/23'
MTU='9000'
NAME='82573E Gigabit Ethernet Controller (Copper)'
NETWORK=''
REMOTE_IPADDR=''
STARTMODE='auto'
USERCONTROL='no'
配置Multiple IP Address(同网段)需要使用IPADDR<suffix>和LABEL<suffix>标签,示例如下:
BOOTPROTO='static'
IPADDR='10.117.174.140/23'
STARTMODE='auto'
USERCONTROL='no'
MTU='9000'
IPADDR_0='10.117.174.141/23'
LABEL_0='1'
IPADDR_1='10.117.174.142/23'
LABEL_1='2'
Debain - Ubuntu
该类发行版使用/etc/network/interfaces文件配置各个网口的信息,文件语法可以man interfaces。
auto lo
iface lo inet loopback
auto first
iface second inet dhcp
auto second
iface second inet static
address 192.168.20.1/24
配置Multiple IP Address(同网段)使用以下语句配置虚拟接口,类似于SUSE在一个interface上配置一系列IP的语法未找到,留待以后研究。
auto second
iface second inet static
address 192.168.20.13/24
auto second:<n>
iface second:<n> inet static
address 192.168.20.14/24
3.VLAN & vconfig
VLAN的概念就不做介绍了,交换网络里划分广播域的一种方法,实质上就是给数据包打标签(tag),要让系统支持VLAN需要安装vlan软件包zypper in vlan(SUSE) 和apt-get install vlan(Ubuntu),然后modprobe 8021q加载vlan module,可以使用lsmod | grep -i 8021q检查内核是否加载模块,如果遇见不会自动加载模块的系统使用echo "modprobe 8021q" > /etc/rc.local使其开机加载。
vconfig命令是vlan软件包的主命令,用来添加和移除VLAN interface,VLAN interface建立后才能对其配置IP和子网掩码。而所谓的VLAN interface则需要建立在物理接口的基础上,一般情况下划分VLAN的物理接口使用不分配IP的static method,SUSE接口配置如下:
hell:/etc/sysconfig/network # cat ifcfg-traffic
BOOTPROTO='static'
MTU='9000'
STARTMODE='auto'
USERCONTROL='no'
Ubuntu接口/etc/network/interfaces配置如下:
auto second
iface second inet static
voconfig命令格式如下:
vconfig add <interface> <vid>
vconfig rem <vlan interface>
默认的VLAN interface名字也因系统的不同而略有差异,在SUSE系统中默认VLAN interface名为vlan<vid>,而Ubuntu系统中默认的VLAN interface名为<interface>.<vid>,如下所示:
SUSE:
vconfig add traffic 32
vconfig rem vlan32
Ubuntu:
vconfig add second 32
vconfig rem second.32
到此阶段,VLAN interface就可以使用ifconfig命令配置IP使用,但并没有相应interface配置文件的定义,因此重启会失效。系统当前的VLAN配置可以在/proc/net/vlan/config文件中查看,VLAN接口文件则可在/proc/net/vlan/目录下找到。
cat /proc/net/vlan/config
ls -al /proc/net/vlan/
SUSE系统下:
bjdfr1:~ # cat /proc/net/vlan/config
VLAN Dev name | VLAN ID
Name-Type: VLAN_NAME_TYPE_PLUS_VID_NO_PAD
vlan1342 | 1342 | traffic
vlan32 | 32 | traffic
Ubuntu系统下:
root@ubuntu:/proc/net/vlan# cat /proc/net/vlan/config
VLAN Dev name | VLAN ID
Name-Type: VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD
second.32 | 32 | second
CentOS - SUSE VLAN interface配置文件
如之前提及,没有配置文件定义的VLAN interface会在系统重启后失效,因此一般都是通过配置文件直接配置VLAN,SUSE支持的VLAN interface名称比较广泛:
<interface>.<vid> <-> ifcfg-<interface>.<vid> (e.g. eth0.42 <-> ifcfg-eth0.42)
vlan<vid> <-> ifcfg-vlan<vid> (e.g. vlan42 <-> ifcfg-vlan42)
<angname> <-> ifcfg-<anyname>
由上可知SUSE支持三种interface及其ifcfg文件的命名方式,其中<interface>.<vid>的命名方式可以避免vlan<vid>命名方式产生的不同物理接口无法定义相同的VLAN ID的问题,<anyname>的方式最为灵活但并不直白,接口较多的情况下会让维护工作比较困难。
但无论哪种名称方式,ifcfg文件中都需要使用ETHERDEVICE指定所基于的物理interface,不像前两种方式在interface名称上就指明了VLAN ID,<anyname>的方式还需要在ifcfg文件内使用VLAN_ID指定VID。
blr10:/etc/sysconfig/network # cat ifcfg-vlan2022
OTPROTO='static'
BROADCAST=''
ETHTOOL_OPTIONS=''
IPADDR='100.1.42.52/22'
MTU='9000'
NAME='82573L Gigabit Ethernet Controller'
NETWORK=''
REMOTE_IPADDR=''
STARTMODE='auto'
USERCONTROL='no'
ETHERDEVICE='traffic'
VLAN='yes'
IPADDR_0='100.1.42.53/22'
LABEL_0='1'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bjdsf:/etc/sysconfig/network # cat ifcfg-traffic.42
BOOTPROTO='static'
BROADCAST=''
ETHTOOL_OPTIONS=''
IPADDR='192.168.245.46/24'
MTU=''
NAME='82573L Gigabit Ethernet Controller'
NETWORK=''
REMOTE_IPADDR=''
STARTMODE='auto'
USERCONTROL='no'
ETHERDEVICE='traffic'
VLAN='yes'
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
bjdsf:/etc/sysconfig/network # cat ifcfg-v1
BOOTPROTO='static'
BROADCAST=''
ETHTOOL_OPTIONS=''
IPADDR='192.168.221.45/24'
MTU=''
NAME='82573L Gigabit Ethernet Controller'
NETWORK=''
REMOTE_IPADDR=''
STARTMODE='auto'
USERCONTROL='no'
ETHERDEVICE='traffic'
VLAN='yes'
VLAN_ID=45
Debain - Ubuntu VLAN interface配置
该系统下支持的VLAN interface命名方式只有<interface>.<vid>一种,因此可以在/etc/network/interfaces文件中定义VLAN interface:
auto second
iface second inet static
auto second.32
iface second:32 inet static
address 192.168.23.25/24
但该完美的理论在我用虚拟机安装的Ubuntu上没有实现,还是需要手动执行vconfig add second 32才会读取intefaces文件里的配置,don’t know why~