继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Pipework在CoreOS上的一个小bug

慕侠2389804
关注TA
已关注
手记 273
粉丝 55
获赞 156

Intro

某日办公室要断电维护,作为 IT 狗需要在断电之前把办公室的服务器都停掉,来电后再把这些服务器启起来,其中有台服务器,跑的是 CoreOS 系统,上面一堆的 docker container。系统起来后,我发现这些 docker container,一个都不通,显然,踩着大坑了......

环境

  • CoreOS stable (1185.5.0)

  • 4.7.3-coreos-r3

  • ip utility, iproute2-ss150210

  • Pipework 20150123

现象

简言之,就是用 net=none 启动的 docker 实例,用 Pipework 配置 ip 地址后 ping 不通,用代码表示是这样的:

docker run -i -t -d \
    --name=test \
    -h test \
    --net none \
    centos:6;
sudo pipework br0 \
    -i eth0 \    test \
    10.0.0.3/24@10.0.0.1;# br0 是桥,ip 地址是 10.0.0.2# enp0s25 是直接在 10.0.0.0/24 网段的物理设备# enp0s25 同时是桥 br0 的一个 interface# eth0 是 docker 的网卡设备名# 这个测试 docker 的 ip 地址是 10.0.0.3# 10.0.0.0/24 的网关是 10.0.0.1

结果 10.0.0.0/24 段的其他机器上 ping 不通 10.0.0.3,

docker exec -it test /bin/bash

进入 docker 实例 test 内部以后也 ping 不通网关 10.0.0.1

原因

最早怀疑是 proxy_arp 的问题,但实际证明不是,最后发现是由于 docker 建立的 veth 设备(宿主机这端的)没有正确添加到桥设备 br0 里去,从而导致怎么都不通。

解决起来也很简单,直接用

sudo brctl addif br0 vethlxxx# vethlxxx 是这个 docker 实例在宿主机侧的网络设备

然后就通了。

分析问题

找到表面原因容易,可为什么没能正确把 vethlxxx 设备加到桥设备 br0 里去呢?也不是第一次跑 Pipework 了,以前一直是好的。

看了看 Pipework 的代码,并调试执行了几遍,发现这个问题不是百分百出现的,只是有很大一部分概率。

最后大概定位问题在 Pipework 的这几句代码上:

(ip link set "$LOCAL_IFNAME" master "$IFNAME" > /dev/null 2>&1) \
    || (brctl addif "$IFNAME" "$LOCAL_IFNAME")

和后面的

ip link set "$LOCAL_IFNAME" up

为什么这么说呢,因为在附录的那个链接里,有段话说道:

To add an interface (e.g. eth0) into the bridge, its state must be up:

这也就是说将某个 interface 加入到桥设备之前,必须要先保证这个 interface 的状态是 up 的,但显然在 Pipework 这份代码里不是这样的,这里是先加入到 br0,然后再将这个 interface 设置为 up 的。

为了证明这个,写了一段 bash 脚本,来模拟这个情况,具体如下(文件名叫 test.sh):

#!/bin/bashset -x

IFNAME="brtest"MTU=1500

(ip link add dev "$IFNAME" type bridge ) \
    || (brctl addbr "$IFNAME")
ip link set "$IFNAME" upfor i in {10..90}; do
    LOCAL_IFNAME="vethltest${i}"
    GUEST_IFNAME="vethgtest${i}"
    ip link add name "$LOCAL_IFNAME" \
        mtu "$MTU" type veth \
        peer name "$GUEST_IFNAME" \
        mtu "$MTU"#   ip link show "$LOCAL_IFNAME"
    if ((${i}%2)); then
        ip link set "$LOCAL_IFNAME" down    else
        ip link set "$LOCAL_IFNAME" up    fi
    (ip link set "$LOCAL_IFNAME" master "$IFNAME") \
        || (brctl addif "$IFNAME" "$LOCAL_IFNAME")
    ip link set "$LOCAL_IFNAME" updone

在 CoreOS 上执行:

chmod +x test.sh # 这句执行一遍即可sudo ./test.sh

最后再

brctl show brtest

看结果,发现:

  • vethltest${i}(i 为偶数的设备)都被正确添加到 brtest 里

  • vethltest${i}(i 为奇数的设备)有一些没有被正确添加到 brtest 里

结论:

在我所测试的平台(CoreOS)上,Pipework 是有问题的,原因来自于调用的命令 ip(来自于软件包 iproute2)

多说一句

随后我把测试程序 test.sh 拷贝到一台 CentOS 7 上跑,发现 CentOS 7 没有这个问题。



作者:haw_haw
链接:https://www.jianshu.com/p/97f19d4ace3e


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP