添加新的veth界面时运行脚本

时间:2014-05-02 22:49:23

标签: linux ubuntu networking docker sysadmin

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

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

我想限制这些新veth接口的带宽。我找到了一种方法来做奇迹。但是我想自动化这个。

有没有办法在每次附加新的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 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

udev规则是其中一种方法,但是那里存在一些信息短缺,即没有可靠而简单的方法来了解veth与哪个容器相关联。我不确定在您的情况下是否足以简单地设置主机的带宽限制' veth对的结束,这可能是停止,但在容器的命名空间中还有另一端,您可以使用ip netns或{{nsenter来查看它1}}命令。因此,如果您确实需要在veth对的两端进行操作,那么最好拥有容器ID,这样您就可以查找PID和与之关联的网络命名空间。一种方法是运行docker events并解析它的输出,但更好的方法是使用Docker的域套接字API。对于我之前使用的用例,向docker events发送shell就足够了,这是我编写的脚本,它的作用是在容器内添加一个路由并用{{1来关闭校验和卸载}}

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命令捕获网络事件的方法。但是,通过这种方式,您仍然没有容器ID,类似于ip monitor方法。