当添加新的veth接口时运行脚本

7
Docker为其创建的每个容器都创建了一个连接到桥接口(docker0)的veth接口。

http://docs.docker.io/use/networking/

我希望限制这些新的veth接口的带宽。我找到了使用wondershaper实现此目的的方法。但是,我想自动化这个过程。

是否有一种方法可以在每次连接新的veth接口时运行脚本的钩子?

我已经尝试将脚本添加到/etc/network/if-up.d/中,但它们仅在引导时运行,而不在添加veth时运行。

以下是一些系统日志,我正在尝试获取关于其的通知。我知道我可以跟踪这些日志,但该方法似乎有些hacky,必须有一种通过操作系统获取此事件通知的方法。

May  2 23:28:41 ip-10-171-7-2 kernel: [22170163.565812] netlink: 1 bytes leftover after parsing attributes.
May  2 23:28:42 ip-10-171-7-2 kernel: [22170163.720571] IPv6: ADDRCONF(NETDEV_UP): veth5964: link is not ready
May  2 23:28:42 ip-10-171-7-2 kernel: [22170163.720587] device veth5964 entered promiscuous mode
May  2 23:28:42 ip-10-171-7-2 avahi-daemon[1006]: Withdrawing workstation service for vethdc8c.
May  2 23:28:42 ip-10-171-7-2 kernel: [22170163.743283] IPv6: ADDRCONF(NETDEV_CHANGE): veth5964: link becomes ready
May  2 23:28:42 ip-10-171-7-2 kernel: [22170163.743344] docker0: port 27(veth5964) entered forwarding state
May  2 23:28:42 ip-10-171-7-2 kernel: [22170163.743358] docker0: port 27(veth5964) entered forwarding state
May  2 23:28:48 ip-10-171-7-2 kernel: [22170170.518670] docker0: port 26(vethb06a) entered forwarding state
May  2 23:28:57 ip-10-171-7-2 kernel: [22170178.774676] docker0: port 27(veth5964) entered forwarding state
2个回答

3
你应该编写一条自定义的udev规则,使得每次添加新的接口时都会运行你的脚本。这是Debian用于处理接口“hotplug”的方法。
`/etc/udev/rules.d/90-my-networking.rules`:
SUBSYSTEM=="net",           RUN+="/usr/local/bin/my-networking-agent.sh"

/usr/local/bin/my-networking-agent.sh:

#!/bin/sh
logger "hey I just got interface ${INTERFACE} with action ${ACTION}"

编辑

以下是测试方法:

# modprobe dummy0
# ifconfig dummy0 up
# tail -n1 /var/log/syslog
May  3 01:48:06 ernst logger: hey I just got interface dummy0 with action add

非常感谢!我在查阅Ubuntu网络手册,但是没有找到任何有用的信息。 - AnandKumar Patel

1
udev规则是其中一种方法,但是信息有些不足,即没有可靠和简单的方法来确定veth与哪个容器相关联。我不确定在你的情况下是否仅在主机端设置带宽限制就足够了,这可能是停止的原因,但是还有另一端位于容器命名空间中,可以使用ip netns或nsenter命令查看。因此,如果您确实需要操作veth对的两端,则最好具有容器ID,以便您可以查找PID和与其关联的网络命名空间。一种方法是运行docker events并解析其输出,而更好的方法是使用Docker的域套接字API。对于我早期的用例,仅外壳到docker事件就足够了,这是我编写的脚本,它的作用是在容器内添加路由并关闭ethtool的校验和卸载。
#!/bin/sh -x

[ ! $# = 2 ] && exit 1;

container_interface="$1"
add_route="$2"

docker events | while read event
do
    echo $event | grep -q -v '\ start$' && continue

    container_id=`echo $event | sed 's/.*Z\ \(.*\):\ .*/\1/'`

    nsenter="nsenter -n -t {{ .State.Pid }} --"
    ip_route_add="ip route add ${add_route} dev ${container_interface} proto kernel scope link src {{ .NetworkSettings.IPAddress }}"
        ethtool_tx_off="ethtool -K ${container_interface} tx off >/dev/null"

    eval `docker inspect --format="${nsenter} ${ip_route_add}; ${nsenter} ${ethtool_tx_off};" ${container_id}`
done

除了使用docker events外,还可以使用ip monitor命令来捕获网络事件。但是,这种方法仍然无法获取容器ID,类似于udev方法。

1
也许可以使用 docker events --filter 'event=start' 而不是第一个 grep? - Bryan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接