资讯专栏INFORMATION COLUMN

docker 网络工具 pipework 分析

Betta / 972人阅读

摘要:地址给一个简单的例子来说下,比如,我要为我创建的使用一个我指定的分析下,第一行,创建容器,注意其中的标示,不用自带的分配模式。第二行,我为这个容器分配,掩码位,对应的为,并将这个添加到上。待加入到容器中。

pipework介绍

docker 使用中,网络部分是其中最重要的一环,对docker容器进行网络设置,官方提供了 fannel ,同时也可以借助高大上的ovs来搞,但是这里也有一个小巧的工具 pipework,可以针对单个docker容器实现简单的网络设置,虽然不比上述两者全面,但是小、简是pipework的优势,个人非常喜欢这个工具。

pipework 地址:https://github.com/jpetazzo/pipework
给一个简单的例子来说下,比如,我要为我创建的docker使用一个我指定的ip:

$did=$(docker run -it -d --net=none baseimage:v1)
pipework br0 $did 172.30.36.100/16@172.30.0.254

分析下,第一行,创建docker容器,注意其中的 --net=none 标示,不用自带的net分配模式。
第二行,我为这个容器分配ip:172.30.36.100,掩码16位,对应的gateway为:172.30.0.254,并将这个ip添加到bridge br0上。
在容器中查看:

~# docker exec $did ifconfig 
~# eth1      Link encap:Ethernet  HWaddr CA:81:40:85:5E:EA  
          inet addr:172.30.36.100  Bcast:0.0.0.0  Mask:255.255.0.0
          inet6 addr: fe80::c881:40ff:fe85:5eea/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:118503937 errors:0 dropped:1545004 overruns:0 frame:0
          TX packets:389952 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:9431032966 (8.7 GiB)  TX bytes:70378592 (67.1 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:345910 errors:0 dropped:0 overruns:0 frame:0
          TX packets:345910 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:42510919 (40.5 MiB)  TX bytes:42510919 (40.5 MiB)
~# docker exec $did route -n
~# Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         172.30.0.254    0.0.0.0         UG    0      0        0 eth1
172.30.0.0      0.0.0.0         255.255.0.0     U     0      0        0 eth1

ok,下面我们来看下,它这条命令究竟干了什么。

pipework流程代码解析

首先我先创建一个 net=none的容器:

docker run -it -d --net=none baseimage:v1

得到containerid : cdb492d88f1e

接下来进行操作

pipework br0 cdb492d88f1e 172.30.36.200/16@172.30.0.254

第一步,必然是先获取对应的变量值,在这里:
IFNAME=br0
GUESTNAME=cdb492d88f1e
IPADDR=172.30.36.100/16@172.30.0.254

之后判断br0的类型:

if [ -d "/sys/class/net/$IFNAME" ]
  then
    if [ -d "/sys/class/net/$IFNAME/bridge" ]; then
      IFTYPE=bridge
      BRTYPE=linux
    fi
fi

这时,IFTYPE=bridge,BRTYPE=linux

第二步,找到这个guest,目前只支持LXC container, 先找到cgroup地址:

while read _ mnt fstype options _; do
  [ "$fstype" != "cgroup" ] && continue
  echo "$options" | grep -qw devices || continue
  CGROUPMNT=$mnt
done < /proc/mounts

此时, CGROUPMNT=/sys/fs/cgroup/devices (笔者使用的是centos7 x86_64,可能因人而异)
之后,从docker中获取对应的pid:

DOCKERPID=$(docker inspect --format="{{ .State.Pid }}" "$GUESTNAME")

此时, DOCKERPID=21927(因人而异),即 所对应docker容器中的init进程在宿主机上对应的pid;

分解 gateway:

GATEWAY="${IPADDR#*@}"
GATEWAY="${GATEWAY%%@*}"
IPADDR="${IPADDR%%@*}"

此时,GATEWAY=172.30.0.254, IPADDR=172.30.36.100/16

第三步,预操作结束,开始实际操作。

首先,添加net namespace,可参考文章 "linux network namespace 学习 "
因为ip netns list直接读取/var/run/netns中的内容,于是

rm -f "/var/run/netns/$DOCKERPID"
ln -s "/proc/$DOCKERPID/ns/net" "/var/run/netns/$DOCKERPID"  
#将网络命名空间文件软链接到/var/run/netns,以便ip netns能够读取

之后创建一个veth pair

[ "$IFTYPE" = bridge ] && {
  LOCAL_IFNAME="v${CONTAINER_IFNAME}pl${NSPID}"
  GUEST_IFNAME="v${CONTAINER_IFNAME}pg${NSPID}"
  # Does the link already exist?
  if ip link show "$LOCAL_IFNAME" >/dev/null 2>&1; then
    # link exists, is it in use?
    if ip link show "$LOCAL_IFNAME" up | grep -q "UP"; then
      echo "Link $LOCAL_IFNAME exists and is up"
      exit 1
    fi
    # delete the link so we can re-add it afterwards
    ip link del "$LOCAL_IFNAME"
  fi
  ip link add name "$LOCAL_IFNAME" mtu "$MTU" type veth peer name "$GUEST_IFNAME" mtu "$MTU"
  (ip link set "$LOCAL_IFNAME" master "$IFNAME" > /dev/null 2>&1) || (brctl addif "$IFNAME" "$LOCAL_IFNAME")
  ip link set "$LOCAL_IFNAME" up
}

在这里,创建了一对veth pair ,LOCAL_IFNAME=veth1pl24305, GUEST_IFNAME=veth1pg24305
LOCAL_IFNAME 已和本地br0相绑定。
GUEST_IFNAME 待加入到容器中。

然后,将GUEST_IFNAME添加入docker 容器中:

ip link set "$GUEST_IFNAME" netns "$DOCKERPID"
ip netns exec "$DOCKERPID" ip link set "$GUEST_IFNAME" name "$CONTAINER_IFNAME"

这样,容器内就添加了一个veth网卡和宿主机做了关联,但是现在在容器内部还看不见他,最后执行:

ip netns exec "$DOCKERPID" ip addr add "$IPADDR" dev "$CONTAINER_IFNAME"
[ "$GATEWAY" ] && {
      ip netns exec "$DOCKERPID" ip route delete default >/dev/null 2>&1 && true
}
ip netns exec "$DOCKERPID" ip link set "$CONTAINER_IFNAME" up
[ "$GATEWAY" ] && {
    ip netns exec "$DOCKERPID" ip route get "$GATEWAY" >/dev/null 2>&1 || 
    ip netns exec "$DOCKERPID" ip route add "$GATEWAY/32" dev "$CONTAINER_IFNAME"
    ip netns exec "$DOCKERPID" ip route replace default via "$GATEWAY"
}

OK,让我来查看下:

~# docker exec 17e5e58553ae ifconfig
~# eth1 Link encap:Ethernet  HWaddr 2A:E8:48:5C:77:9F  
          inet addr:172.30.36.200  Bcast:0.0.0.0  Mask:255.255.255.255
          inet6 addr: fe80::28e8:48ff:fe5c:779f/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:960 (960.0 b)  TX bytes:960 (960.0 b)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:16 errors:0 dropped:0 overruns:0 frame:0
          TX packets:16 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:960 (960.0 b)  TX bytes:960 (960.0 b)

搞定! 最后来个清理:

rm -f "/var/run/netns/$DOCKERPID"

Done

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/26499.html

相关文章

  • 使用ovs构建docker网络,实现跨主机通信与网络隔离

    摘要:干的具体的事是容器的虚拟网卡设备划分处理的原理也非常简单,包进入到时打上,发出去时去掉,发出去的端口与包的不匹配时不处理,这便实现了二层隔离。 初始化环境 升级内核: rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org rpm -Uvh http://www.elrepo.org/elrepo-r...

    Lorry_Lu 评论0 收藏0
  • Docker 高级网络配置

    摘要:默认指定了接口的地址和子网掩码,让主机和容器之间可以通过网桥相互通信。解决方法是创建一对接口,分别放到两个容器中,配置成点对点链路。点到点链路不需要子网和子网掩码。 容器访问控制 检查本地系统的转发支持 sysctl net.ipv4.ip_forward sysctl -w net.ipv4.ip_forward=1 # 手动打开 如果在启动Docker服务的时候设定--ip-fo...

    jhhfft 评论0 收藏0
  • 实录分享|kubernetes 在腾讯游戏的应用实践

    摘要:大家好今天我分享的主题与游戏行业相关,为大家介绍的是在腾讯游戏中的应用实践。随着技术的兴起,我们开始调研在游戏容器化方面的应用。也就是说,将不同游戏业务部署到同一台母机,采用绑定核的方式。在母机上架部署时,创建设备和设备并将它们进行关联。 今天小数的推送内容来自腾讯互娱高级工程师黄惠波,让我们一起来看看吧~~~ 黄惠波,腾讯互娱高级工程师目前主要负责游戏计算资源容器化平台的研发工作,包...

    DangoSky 评论0 收藏0
  • 虚拟化实践

    摘要:本文并非虚拟化的科普文章,主要将我们在私有云实践过程中的一些思想和遇到的问题拿出来跟大家讨论分享。我们虚拟化实践包含了传统的基于协议的以及目前流行的。 引言 这里的虚拟化等于私有云。本文并非虚拟化的科普文章,主要将我们在私有云实践过程中的一些思想和遇到的问题拿出来跟大家讨论分享。我们虚拟化实践包含了传统的基于libvirt协议的KVM以及目前流行的docker。 为什么要虚拟化 虚拟化...

    newsning 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<