美文网首页
2016-06-14

2016-06-14

作者: 周叶铨 | 来源:发表于2017-08-31 15:19 被阅读43次

    RHEL 7 网络初探

    Redhat Linux 7已经出来好久了,但是我一直没有仔细研究。
    现在因为项目需要,我需要弄明白Oracle Linux 7上面的网络配置。
    Oracle Linux其实和Redhat Linux 7是几乎完全一样的。
    所以我下面要写的东西对于两者应该是通用的。CentOS 7应该也可以。

    NetworkManager vs network

    在RHEL 6里面,其实已经有NetworkManager这个东西了。
    但是我们platform team总是给我们在ifcfg-*里面加上了NM_CONTROLLED=no,
    所以很长时间以来我们用的都是古老的network scripts。

    为了方便地做各种实验,我用vagrant创建一台两个网口的虚拟机:

    Vagrant.configure(2) do |config|
      config.vm.box = "OL7DockerBtrfs"
      config.vm.box_check_update = false
      config.vm.network "private_network", ip: "192.168.56.101"
      config.vm.provider "virtualbox" do |vb|
        vb.memory = "2048"
      end
    end
    
    

    这个Vagrantfile里面的box OL7DockerBtrfs是我自己用packer做出来的。
    换用标准的rhel 7或者centos 7应该行为没有差别。

    在我刚刚启动起来的OL7 vagrant虚拟机里面:

    [root@BasicOL7-Docker ~]# systemctl status network
    ● network.service - LSB: Bring up/down networking
       Loaded: loaded (/etc/rc.d/init.d/network)
       Active: active (exited) since Tue 2016-06-14 07:18:52 EDT; 1min 25s ago
         Docs: man:systemd-sysv-generator(8)
      Process: 652 ExecStart=/etc/rc.d/init.d/network start (code=exited, status=0/SUCCESS)
    
    Jun 14 07:18:52 BasicOL7-Docker systemd[1]: Starting LSB: Bring up/down network....
    Jun 14 07:18:52 BasicOL7-Docker network[652]: Bringing up loopback interface:  ...'
    Jun 14 07:18:52 BasicOL7-Docker network[652]: Could not load file '/etc/sysconf...'
    Jun 14 07:18:52 BasicOL7-Docker network[652]: Could not load file '/etc/sysconf...'
    Jun 14 07:18:52 BasicOL7-Docker network[652]: Could not load file '/etc/sysconf...'
    Jun 14 07:18:52 BasicOL7-Docker network[652]: [  OK  ]
    Jun 14 07:18:52 BasicOL7-Docker network[652]: Bringing up interface enp0s3:  [ ...]
    Jun 14 07:18:52 BasicOL7-Docker systemd[1]: Started LSB: Bring up/down networking.
    Hint: Some lines were ellipsized, use -l to show in full.
    [root@BasicOL7-Docker ~]# systemctl status NetworkManager
    ● NetworkManager.service - Network Manager
       Loaded: loaded (/usr/lib/systemd/system/NetworkManager.service; enabled; vendor preset: enabled)
       Active: active (running) since Tue 2016-06-14 11:18:46 EDT; 3h 58min left
     Main PID: 530 (NetworkManager)
       CGroup: /system.slice/NetworkManager.service
               ├─530 /usr/sbin/NetworkManager --no-daemon
               └─590 /sbin/dhclient -d -q -sf /usr/libexec/nm-dhcp-helper -pf /var/r...
    
    Jun 14 11:18:46 BasicOL7-Docker NetworkManager[530]: <info>  NetworkManager stat...
    Jun 14 11:18:46 BasicOL7-Docker NetworkManager[530]: <info>  Policy set 'enp0s3'...
    Jun 14 11:18:46 BasicOL7-Docker NetworkManager[530]: <info>  (enp0s3): Activatio...
    Jun 14 11:18:46 BasicOL7-Docker dhclient[590]: bound to 10.0.2.15 -- renewal in....
    Jun 14 07:18:52 BasicOL7-Docker NetworkManager[530]: <info>  startup complete
    Jun 14 07:18:58 BasicOL7-Docker NetworkManager[530]: <info>  ifcfg-rh: new conne...
    Jun 14 07:18:58 BasicOL7-Docker NetworkManager[530]: <warn>  ifcfg-rh: Ignoring ...
    Jun 14 07:18:58 BasicOL7-Docker NetworkManager[530]: <info>  (enp0s8): device st...
    Jun 14 07:18:58 BasicOL7-Docker NetworkManager[530]: <info>  (enp0s8): link disc...
    Jun 14 07:18:58 BasicOL7-Docker NetworkManager[530]: <info>  (enp0s8): link conn...
    Hint: Some lines were ellipsized, use -l to show in full.
    
    

    这里可以看到network和NetworkManager都起来了。
    这里的network.service是由systemd-sysv-generator在启动时创建的,为了兼容
    古老的网络启动脚本。

    启动网口

    Vagrant虚拟机运行起来之后,我可以用ip -4 addr看到,我要的两个网口都顺利
    拿到了IP地址:

    1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
        inet 127.0.0.1/8 scope host lo
           valid_lft forever preferred_lft forever
    2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        inet 10.0.2.15/24 brd 10.0.2.255 scope global dynamic enp0s3
           valid_lft 86111sec preferred_lft 86111sec
    3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
        inet 192.168.56.101/24 brd 192.168.56.255 scope global enp0s8
           valid_lft forever preferred_lft forever
    

    然后去看看这两个网卡的ifcfg文件:

    [root@BasicOL7-Docker ~]# cd /etc/sysconfig/network-scripts/
    [root@BasicOL7-Docker network-scripts]# ls ifcfg-*
    ifcfg-enp0s3  ifcfg-enp0s8  ifcfg-lo
    [root@BasicOL7-Docker network-scripts]# cat ifcfg-enp0s3
    # Generated by dracut initrd
    NAME="enp0s3"
    DEVICE="enp0s3"
    ONBOOT=yes
    NETBOOT=yes
    UUID="909dae31-7e36-4c00-a74f-d33399600fe0"
    IPV6INIT=yes
    BOOTPROTO=dhcp
    TYPE=Ethernet
    DEFROUTE=yes
    IPV4_FAILURE_FATAL=no
    IPV6_AUTOCONF=yes
    IPV6_DEFROUTE=yes
    IPV6_FAILURE_FATAL=no
    PEERDNS=yes
    PEERROUTES=yes
    IPV6_PEERDNS=yes
    IPV6_PEERROUTES=yes
    [root@BasicOL7-Docker network-scripts]# cat ifcfg-enp0s8
    #VAGRANT-BEGIN
    # The contents below are automatically generated by Vagrant. Do not modify.
    NM_CONTROLLED=no
    BOOTPROTO=none
    ONBOOT=yes
    IPADDR=192.168.56.101
    NETMASK=255.255.255.0
    DEVICE=enp0s8
    PEERDNS=no
    #VAGRANT-END
    

    看上去不错哦,一个网卡enp0s3是用network manager管理的,另一个enp0s8则是
    用传统方法管理的。
    这一点也可以在nmcli device的输出里面看出来:

    [root@BasicOL7-Docker network-scripts]# nmcli device
    DEVICE  TYPE      STATE      CONNECTION
    enp0s3  ethernet  connected  enp0s3     
    enp0s8  ethernet  unmanaged  --         
    lo      loopback  unmanaged  --   
    

    现在问题来了,如果我想让enp0s8也给network manager管理,怎么办?
    我试试看去掉NM_CONTROLLED=NO这一行,然后再次运行nmcli device,发现
    它依然是unmanaged。直到我运行过systemctl restart NetworkManager之后,
    设备enp0s8现在才是connected状态:

    [root@BasicOL7-Docker network-scripts]# nmcli device
    DEVICE  TYPE      STATE      CONNECTION
    enp0s3  ethernet  connected  enp0s3     
    enp0s8  ethernet  unmanaged  --         
    lo      loopback  unmanaged  --         
    [root@BasicOL7-Docker network-scripts]# systemctl restart NetworkManager
    [root@BasicOL7-Docker network-scripts]# nmcli device
    DEVICE  TYPE      STATE      CONNECTION
    enp0s3  ethernet  connected  enp0s3     
    enp0s8  ethernet  connected  enp0s8     
    lo      loopback  unmanaged  --        
    

    不重启NetworkManager可以吗?

    是可以的。
    只需要nmcli connection load /etc/sysconfig/network-scripts/ifcfg-enp0s8
    或者nmcli connection reload

    检查网口状态

    传统的命令当然还是能继续用的,比如说:

    • ip link show
    • ip -4 addr
    • ifconfig enp0s8

    现在,用nmcli,可以:

    • nmcli device show enp0s8
    • nmcli device status

    要改变网口状态,比方说要把一个网口断线,以前我们有这些命令:

    • ip link set enp0s8 down
    • ifconfig enp0s8 down
    • ifdown enp0s8

    现在,用nmcli,可以:

    • nmcli device disconnect enp0s8

    我测试里面发现,ifup enp0s8的效果和nmcli device connect enp0s8相同。
    应该ifup就是简单封装了一下nmcli device connect
    同样地,ifdownnmcli device disconnect效果相同。

    这两组命令执行完了之后,状态都可以通过nmcli device status看出来。

    但是,要小心了,底层的ip link命令和ifconfig就不一样了。仔细看下面的例子:

    [root@BasicOL7-Docker ~]# nmcli device show enp0s8
    GENERAL.DEVICE:                         enp0s8
    GENERAL.TYPE:                           ethernet
    GENERAL.HWADDR:                         08:00:27:D1:3F:20
    GENERAL.MTU:                            1500
    GENERAL.STATE:                          100 (connected)
    GENERAL.CONNECTION:                     System enp0s8
    GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/3
    WIRED-PROPERTIES.CARRIER:               on
    IP4.ADDRESS[1]:                         192.168.56.101/24
    IP4.GATEWAY:                            
    IP6.GATEWAY:                            
    [root@BasicOL7-Docker ~]# ip link set enp0s8 down
    [root@BasicOL7-Docker ~]# nmcli device show enp0s8
    GENERAL.DEVICE:                         enp0s8
    GENERAL.TYPE:                           ethernet
    GENERAL.HWADDR:                         08:00:27:D1:3F:20
    GENERAL.MTU:                            1500
    GENERAL.STATE:                          100 (connected)
    GENERAL.CONNECTION:                     System enp0s8
    GENERAL.CON-PATH:                       /org/freedesktop/NetworkManager/ActiveConnection/3
    WIRED-PROPERTIES.CARRIER:               off
    IP4.ADDRESS[1]:                         192.168.56.101/24
    IP4.GATEWAY:                            
    IP6.GATEWAY:          
    

    这里我做过了ip link set enp0s8 down之后,nmcli device show enp0s8看到的
    状态依旧是connected。不过有一个property发生了变化:WIRED-PROPERTIES.CARRIER变成了off。

    __ 也就是说,我们要看一个网卡是不是能收发数据,除了看state,还需要看carrier属性。 __

    监控网卡状态事件

    用传统办法监控网卡状态,我们可以用netlink socket,可是那需要编程啊,
    还挺费事的。

    NetworkManager有一个好处,它是挂到dbus上面的一个服务。借助于dbus,
    我们可以方便地查询状态、监控事件变化,还可以修改配置。

    比方说,我们用gdbus命令监视NetworkManager上面的事件:

    # gdbus monitor --system --dest org.freedesktop.NetworkManager
    

    当我在另一个窗口做ip link set enp0s8 up的时候,这个gdbus就会瞬间输出:

    /org/freedesktop/NetworkManager/Devices/1: org.freedesktop.NetworkManager.Device.Wired.PropertiesChanged ({'Carrier': <true>, 'AvailableConnections': <[objectpath '/org/freedesktop/NetworkManager/Settings/1']>},)
    

    这里看到Carrier属性变成了true。org.freedesktop.NetworkManager.Device.Wired.PropertiesChanged是一个signal,所以我们很容易写程序向dbus注册一个listener。

    __ TODO: 写一个python程序监控网口状态 __

    创建bond口

    现在我想把enp0s8变成bond0。这个bond口里面只有这一个slave。
    使用nmcli,这事情不难。

    # nmcli connection add con-name bond0 ifname bond0 type bond
    # nmcli connection modify bond0 bond.options "mode=active-backup,primary_reselect=failure"
    # nmcli connection modify enp0s8 connection.master bond0 connection.slave-type bond
    

    这就好了吗?
    做完了这些之后,我去看ifcfg-bond0,没问题。看ifcfg-enp0s8,也没问题。

    可是,下面的输出就奇怪了:

    [root@BasicOL7-Docker network-scripts]# cat /proc/net/bonding/bond0
    Ethernet Channel Bonding Driver: v3.7.1 (April 27, 2011)
    
    Bonding Mode: load balancing (round-robin)
    MII Status: up
    MII Polling Interval (ms): 100
    Up Delay (ms): 0
    Down Delay (ms): 0
    
    

    什么鬼?我不是已经把mode改成active-backup了吗?另外,为什么enp0s8还没有到slave里面?

    做一次nmcli connection reload试试看,不起作用。
    那么做一次nmcli connection down bond0nmcli connection up bond0
    效果怎样?

    Bonding Mode: fault-tolerance (active-backup)
    Primary Slave: None
    Currently Active Slave: None
    MII Status: up
    MII Polling Interval (ms): 100
    Up Delay (ms): 0
    Down Delay (ms): 0
    
    

    好了,mode变了,可喜可贺。可是为什么slave还不出来?

    再来做一次nmcli connection down enp0s8nmcli connection up enp0s8
    这一次终于生效了。

    __ 注意,这里发现了一个坑。修改bond options之后,必须connection down/up。 __
    __ 注意,修改了eth口的master之后,必须connection down/up。 __

    删除bond0口

    这个操作和上面的操作刚好相反。我已经有bond口了,怎么把它删掉呢?

    乍一看,简单嘛:nmcli connection connection delete bond0
    这一步做完了之后,的确ifcfg-bond0消失了。
    可是别忘了把slave网卡上面的master和slave属性去掉:

    # nmcli connection modify enp0s8 connection.master "" connection.slave-type ""
    

    这个命令执行完了之后,nmcli connection show enp0s8显示的确master属性没了。

    可是,可是……为什么检查ifcfg-enp0s8,这可恶的MASTER和SLAVE还在?

    而且我做一次nmcli connection reload之后,master和slave又回来了。

    __ 这肯定是一个bug。明天上班之后向Oracle Linux team报bug去。__

    今天就玩这么多,洗洗睡了。

    相关文章

      网友评论

          本文标题:2016-06-14

          本文链接:https://www.haomeiwen.com/subject/zfmqjxtx.html