我有2个docker容器,桥接器是这样的。
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef99087167cb images.docker.sae.sina.com.cn/ubuntu:latest /bin/bash -c /home/c 2 days ago Up 21 minutes 0.0.0.0:49240->22223/tcp night_leve3
c8a7b18ec20d images.docker.sae.sina.com.cn/ubuntu:latest /bin/bash -c /home/c 2 days ago Up 54 minutes 0.0.0.0:49239->22223/tcp night_leve2
#brctl show cbr0
bridge name bridge id STP enabled interfaces
docker0 8000.72b675c52895 no vethRQOy1I
vethjKYWka
我怎么才能得到哪个容器匹配 veth*
?
ef99 => vethRQOy1I or ef99 => vethjKYWka
我知道它的工作原理是 ethtool
但有什么更好的方法吗?
这是上面提到的ethtool技巧的一个变体,其实不用ethtool。
function veth_interface_for_container() {
# Get the process ID for the container named ${1}:
local pid=$(docker inspect -f '{{.State.Pid}}' "${1}")
# Make the container's network namespace available to the ip-netns command:
mkdir -p /var/run/netns
ln -sf /proc/$pid/ns/net "/var/run/netns/${1}"
# Get the interface index of the container's eth0:
local index=$(ip netns exec "${1}" ip link show eth0 | head -n1 | sed s/:.*//)
# Increment the index to determine the veth index, which we assume is
# always one greater than the container's index:
let index=index+1
# Write the name of the veth interface to stdout:
ip link show | grep "^${index}:" | sed "s/${index}: \(.*\):.*/\1/"
# Clean up the netns symlink, since we don't need it anymore
rm -f "/var/run/netns/${1}"
}
有多种 "黑客 "方法可以做到这一点:
LOG
规则。最后一种方案,IMHO,是比较可靠的方案(也是最容易使用的方案),但它还是很黑。这个想法非常简单。
添加一个iptables规则来记录例如ICMP流量到达Docker桥的情况
sudo iptables -I INPUT -i docker0 -p icmp -j LOG
向你想识别的容器发送一个ping。
IPADDR=$(docker inspect -format='{{.NetworkSettings.IPAddress}}' 0c33)
ping -c 1 $IPADDR
检查内核日志
dmesg | grep $IPADDR
你会看到这样一行字
[…] IN=docker0 OUT= PHYSIN=vethv94jPK MAC=fe:2c:7f:2c:ab:3f:42:83:95:74:0b:8f:08:00 SRC=172.17.0.79 …
如果你想玩点花哨的,只需要解压一下就可以了 PHYSIN=…
用awk或sed。
删除iptables日志规则(除非你想留下它,因为你会定期ping容器来识别它们)。
如果你需要一个防弹版本,你可以安装 ulogd
并使用 ULOG
目标。它不只是将数据包头写入内核日志,而是通过netlink套接字发送,然后用户国程序就可以正确地处理它们。
试试这个脚本。
get_network_mode() {
docker inspect --format='{{.HostConfig.NetworkMode}}' "$1"
}
created_by_kubelet() {
[[ $(docker inspect --format='{{.Name}}' "$1") =~ ^/k8s_ ]]
}
for container_id in $(docker ps -q); do
network_mode=$(get_network_mode "${container_id}")
# skip the containers whose network_mode is 'host' or 'none',
# but do NOT skip the container created by kubelet.
if [[ "${network_mode}" == "host" || \
$(! created_by_kubelet "${container_id}") && "${network_mode}" == "none" ]]; then
echo "${container_id} => ${network_mode}"
continue
fi
# if one container's network_mode is 'other container',
# then get its root parent container's network_mode.
while grep container <<< "${network_mode}" -q; do
network_mode=$(get_network_mode "${network_mode/container:/}")
# skip the containers whose network_mode is 'host' or 'none',
# but do NOT skip the container created by kubelet.
if [[ "${network_mode}" == "host" || \
$(! created_by_kubelet "${container_id}") && "${network_mode}" == "none" ]]; then
echo "${container_id} => ${network_mode}"
continue 2
fi
done
# get current container's 'container_id'.
pid=$(docker inspect --format='{{.State.Pid}}' "${container_id}")
# get the 'id' of veth device in the container.
veth_id=$(nsenter -t "${pid}" -n ip link show eth0 |grep -oP '(?<=eth0@if)\d+(?=:)')
# get the 'name' of veth device in the 'docker0' bridge (or other name),
# which is the peer of veth device in the container.
veth_name=$(ip link show |sed -nr "s/^${veth_id}: *([^ ]*)@if.*/\1/p")
echo "${container_id} => ${veth_name}"
done
解释一下:
container
.NetworkMode
是 host
, none
或 container:<name|id>
(份额 network stack
与另一个容器的。比如说。user's
容器在一个 pod
在kubernetes中共享 network stack
随着 pause pod
容器的 network stack
)如果有人还对这个感兴趣。我在docker邮件列表中找到了这个。http:/permalink.gmane.orggmane.comp.sysutils.docker.user3182。
你可以通过传递lxc-conf参数 "lxc.network.veth.pair "来自己定义veth的名称。例如
docker run -rm -i -t --lxc-conf="lxc.network.veth.pair=foobar" ubuntu binbash
创建一个带有名为 "foobar "的veth接口的容器。
更多方便的lxc-conf参数请看本页。http:/manpages.ubuntu.commanpagespreciseman5lxc.conf.5.html)。
我不知道如何正确地获得它,但你使用一个黑客:你可以在运行容器后扫描syslog添加接口。
#!/bin/sh
JOB=$(sudo docker run -d ...)
sleep 1s
INTERFACE=$(grep "docker0: port" /var/log/syslog | tail -n 1 | sed -r s/^.*\(veth[^\)]+\).*$/\\1/)
echo "job: $JOB interface: $INTERFACE"
dmesg --clear
for i in $(docker inspect $(docker ps -a -q) | grep IPAddress | cut -d\" -f4); do ping -c 1 -w 1 $i >/dev/null; done
while read line
do
IPADDRESS=$(docker inspect $line | grep IPAddress | cut -d\" -f4)
NAME=$(docker inspect $line | grep Name | cut -d/ -f2 | cut -d\" -f1)
FOUND=$(dmesg | grep $IPADDRESS | grep -Po 'vet[A-Za-z0-9]+' | sort -u)
echo "GEVONDEN $IPADDRESS MET NAAM : $NAME en INTERFACE: $FOUND" | grep NAAM
done < <(docker ps -a -q)
这只是乔尔-迪斯在2015年2月19日给出的答案的更新。
原代码(2015年有效)
# Get the interface index of the container's eth0:
local index=$(ip netns exec "${1}" ip link show eth0 | head -n1 | sed s/:.*//)
# Increment the index to determine the veth index, which we assume is
# always one greater than the container's index:
let index=index+1
# Write the name of the veth interface to stdout:
ip link show | grep "^${index}:" | sed "s/${index}: \(.*\):.*/\1/"
其结果是:
$ index=$(sudo ip netns exec "ns-4012085" ip link show eth0 | head -n1 | sed s/:.*//)
$ echo $index
3
$ let index=index+1
$ echo $index
4
$ sudo ip link show | grep "^${index}:" | sed "s/${index}: \(.*\):.*/\1/"
cbr0
而..:
index=$(sudo ip netns exec "ns-4012085" ip link show type veth | grep eth0 | sed s/.*@if// | sed s/:.*// )
$ echo $index
14
$ ip link show | grep "^${index}:" | sed "s/${index}: \(.*\):.*/\1/"
veth240a8f81@if3
希望能帮到大家:)
P.S.我是在这里从 这条.