Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

docker: how to get veth bridge interface pair easily?

i have 2 containers by docker, and bridge like this:

# 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

How can i get which container match veth* ?

ef99 => vethRQOy1I or ef99 => vethjKYWka

//----------------------------------------------------------

I know it works by ethtool, but is there any better way?

like image 539
user3300984 Avatar asked Feb 12 '14 09:02

user3300984


People also ask

What is Veth interface in Docker?

A virtual ethernet device or veth is a Linux networking interface that acts as a connecting wire between two network namespaces. A veth is a full duplex link that has a single interface in each namespace.

What is the Docker command to connect a running container to an existing user-defined bridge?

To connect a running container to an existing user-defined bridge, use the docker network connect command. The following command connects an already-running my-nginx container to an already-existing my-net network: $ docker network connect my-net my-nginx.

What is Veth interface?

The veth devices are virtual Ethernet devices. They can act as tunnels between network namespaces to create a bridge to a physical network device in another namespace, but can also be used as standalone network devices. veth devices are always created in interconnected pairs.


2 Answers

As far as I get it you need the virtual net device associated with a container?

You can get it by:

1:

docker exec -it <container> cat /sys/class/net/<physical-device>/iflink
# the output looks like this -> 20  

then

2:

# ip ad | grep <the output, like 20>:
 ip ad | grep 20:
# the output looks, like this:
# 20: vetha5531eb@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master br-0595ab5d7c95 state UP group default qlen 1000
# where vetha5531eb is what I think you're looking for.
like image 101
gai-jin Avatar answered Sep 22 '22 20:09

gai-jin


Try this script:

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

Explains:

  • avoid to execute commands in container.
  • avoid to create temporary folders and files.
  • MOST importantly, avoid to get incorrect answers for containers whose NetworkMode is host, none, or container:<name|id> (share network stack with another container's. For example: user's containers in one pod in kubernetes share the network stack with the pause pod container's network stack)
like image 35
Weike Avatar answered Sep 22 '22 20:09

Weike