Docker容器学习梳理--容器间网络通信设置

前面已经在Docker容器学习梳理--基础知识(2)这一篇中详细介绍了Docker的网络配置以及pipework工具,这里就不废话阐述了,下面就日常实操中的配置做一记录:

下面是centos7下部署的Docker容器里的操作
Dokcer通过使用Linux桥接提供容器之间的通信,docker0桥接接口的目的就是方便Docker管理。当Docker daemon启动时需要做以下操作:

1
2
3
4
a)如果docker0不存在则创建
b)搜索一个与当前路由不冲突的ip段
c)在确定的范围中选择 ip
d)绑定ip到 docker0

列出当前主机网桥

1
2
3
[root@localhost ~] # brctl show
bridge name    bridge id           STP enabled   interfaces
docker0        8000.02426f15541e   no            vethe833b02

查看当前 docker0 ip

1
2
3
4
5
6
7
8
9
10
[root@localhost ~] # ifconfig
docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
         inet 172.17.0.1  netmask 255.255.0.0  broadcast 0.0.0.0
         inet6 fe80::42:6fff:fe15:541e  prefixlen 64  scopeid 0x20<link>
         ether 02:42:6f:15:54:1e  txqueuelen 0  (Ethernet)
         RX packets 120315  bytes 828868638 (790.4 MiB)
         RX errors 0  dropped 0  overruns 0  frame 0
         TX packets 132565  bytes 100884398 (96.2 MiB)
         TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
................

在容器运行时,每个容器都会分配一个特定的虚拟机口并桥接到docker0。每个容器都会配置同docker0 ip相同网段的专用ip 地址,docker0的IP地址被用于所有容器的默认网关。
一般启动的容器中ip默认是172.17.0.1/24网段的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
[root@linux-node2 ~] # docker images
REPOSITORY                   TAG                 IMAGE ID            CREATED             SIZE
centos                       latest              67591570dd29        3 months ago        191.8 MB
 
[root@linux-node2 ~] # docker run -t -i --name my-test centos /bin/bash
[root@c5217f7bd44c /] #
 
[root@linux-node2 ~] # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS                    NAMES
c5217f7bd44c        centos              "/bin/bash"         10 seconds ago      Up 10 seconds                                my- test
[root@linux-node2 ~] # docker inspect c5217f7bd44c|grep IPAddress
             "SecondaryIPAddresses" : null,
             "IPAddress" : "172.17.0.2" ,
                     "IPAddress" : "172.17.0.2" ,

那么能不能在创建容器的时候指定特定的ip呢?这是当然可以实现的!

注意:宿主机的ip路由转发功能一定要打开,否则所创建的容器无法联网!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[root@localhost ~] # cat /proc/sys/net/ipv4/ip_forward
1
[root@localhost ~] #
[root@localhost ~] # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6e64eade06d1        docker.io /centos    "/bin/bash"         10 seconds ago      Up 9 seconds                            my-centos
[root@localhost ~] # docker run -itd --net=none --name=container1 docker.io/centos
5e5bdbc4d9977e6bcfa40e0a9c3be10806323c9bf5a60569775903d345869b09
[root@localhost ~] # docker attach container1
[root@5e5bdbc4d997 /] # ping www.baidu.com
PING www.a.shifen.com (61.135.169.121) 56(84) bytes of data.
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=1 ttl=53 time =2.09 ms
64 bytes from 61.135.169.121 (61.135.169.121): icmp_seq=2 ttl=53 time =2.09 ms
 
关闭ip路由转发功能,容器即不能联网
[root@localhost ~] # echo 0 > /proc/sys/net/ipv4/ip_forward
[root@localhost ~] # cat /proc/sys/net/ipv4/ip_forward
0
[root@5e5bdbc4d997 /] # ping www.baidu.com        //ping不通~

1)创建容器使用特定范围的IP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
Docker 会尝试寻找没有被主机使用的ip段,尽管它适用于大多数情况下,但是它不是万能的,有时候我们还是需要对ip进一步规划。
Docker允许你管理docker0桥接或者通过-b选项自定义桥接网卡,需要安装bridge-utils软件包。操作流程如下:
a)确保docker的进程是停止的
b)创建自定义网桥
c)给网桥分配特定的ip
d)以-b的方式指定网桥
  
具体操作过程如下(比如创建容器的时候,指定ip为192.168.5.1 /24 网段的):
[root@localhost ~] # service docker stop
[root@localhost ~] # ip link set dev docker0 down
[root@localhost ~] # brctl delbr docker0
[root@localhost ~] # brctl addbr bridge0
[root@localhost ~] # ip addr add 192.168.5.1/24 dev bridge0      //注意,这个192.168.5.1就是所建容器的网关地址。通过docker inspect container_id能查看到
[root@localhost ~] # ip link set dev bridge0 up
[root@localhost ~] # ip addr show bridge0
[root@localhost ~] # vim /etc/sysconfig/docker      //即将虚拟的桥接口由默认的docker0改为bridge0
OPTIONS= '--selinux-enabled --log-driver=journald'
改为
OPTIONS= '--selinux-enabled --log-driver=journald -b=bridge0'    // 即添加-b=bridge0
  
[root@localhost ~] # service docker restart
  
--------------------------------------------------------------------------------------
上面是centos7下的操作步骤,下面提供下ubuntu下的操作步骤:
$ sudo service docker stop
$ sudo ip link set dev docker0 down
$ sudo brctl delbr docker0
$ sudo brctl addbr bridge0
$ sudo ip addr add 192.168.5.1 /24 dev bridge0
$ sudo ip link set dev bridge0 up
$ ip addr show bridge0
$ echo 'DOCKER_OPTS="-b=bridge0"' >> /etc/default/docker
$ sudo service docker start
--------------------------------------------------------------------------------------
  
然后创建容器,查看下容器ip是否为设定的192.168.5.1 /24 网段的
[root@localhost ~] # docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io /ubuntu    latest              0ef2e08ed3fa        2 weeks ago         130 MB
centos7             7.3.1611            d5ebea14da54        3 weeks ago         311 MB
  
[root@localhost ~] # docker run -t -i --name test2 centos7:7.3.1611 /bin/bash
[root@224facf8e054 /] #
  
[root@localhost ~] # docker run -t -i --name test1 docker.io/ubuntu /bin/bash
root@f5b1bfc2811a:/ #
  
[root@localhost ~] # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
224facf8e054        centos7:7.3.1611    "/bin/bash"         46 minutes ago      Up 46 minutes                           test2
f5b1bfc2811a        docker.io /ubuntu    "/bin/bash"         47 minutes ago      Up 5 minutes                            test1
[root@localhost ~] # docker inspect --format='{{.NetworkSettings.IPAddress}}' f5b1bfc2811a
192.168.5.2
[root@localhost ~] # docker inspect --format='{{.NetworkSettings.IPAddress}}' 224facf8e054
192.168.5.3
 
[root@localhost ~] # brctl show
bridge name   bridge id           STP enabled     interfaces
bridge0       8000.ba141fa20c91   no              vethe7e227b
                                                   vethf382771

2)不同主机间的容器通信(pipework  config docker container ip)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
我的centos7测试机上的docker是yum安装的,默认自带pipework工具,所以就不用在另行安装它了。
---------------------------------------------------------------------------------------
如果没有pipework工具,可以安装下面步骤进行安装:
# git clone https://github.com/jpetazzo/pipework.git
# sudo cp -rp pipework/pipework /usr/local/bin/
    
安装相应依赖软件
#sudo apt-get install iputils-arping bridge-utils -y
---------------------------------------------------------------------------------------
   
查看Docker宿主机上的桥接网络
[root@linux-node2 ~] # brctl show
bridge name   bridge id           STP enabled   interfaces
docker0       8000.02426f15541e   no            veth92d132f
  
有两种方式做法:
1)可以选择删除docker0,直接把docker的桥接指定为br0;
2)也可以选择保留使用默认docker0的配置,这样单主机容器之间的通信可以通过docker0,而跨主机不同容器之间通过pipework新建docker容器的网卡桥接到br0,这样跨主机容器之间就可以通信了。
  
如果保留了docker0,则本机容器创建时不加--net=none参数,那么本机容器启动后就是默认的docker0自动分配的ip(默认是172.17.1.0 /24 网段),它们之间是可以通信的;
跨宿主机的容器创建时要加--net=none参数,待容器创建成功后通过pipework给容器指定ip,这样跨宿主机的容器ip是在同一网段内的同网段地址,因此可以通信。
docker0的存在可以忽略,它的存在不影响容器间通信。在创建容器的时都使用--net=none,容器创建后只要都通过pipework指定ip就可以了。
  
最好在创建容器的时候加上--net=none,防止自动分配的 IP 在局域网中有冲突。
若是容器创建后自动获取ip,下次容器启动会ip有变化,可能会和物理网段中的ip冲突
  
下面说下具体的网络通信设置操作:
Docker宿主机的私有网卡为em2,ip为192.168.1.23,私有网关为192.168.1.1
一定要有网关地址,不然加了--net=none参数创建容器,使用pipework给容器添加指定地址时就无效,因为容器没有地址可获取的。
  
1)保留默认虚拟桥接卡docker0的配置
[root@localhost ~] # cd /etc/sysconfig/network-scripts/
[root@localhost network-scripts] # cp ifcfg-em2 ifcfg-em2.bak
[root@localhost network-scripts] # cp ifcfg-em2 ifcfg-br0
[root@localhost network-scripts] # vim ifcfg-em2  //增加BRIDGE=br0,删除IPADDR,NETMASK,GATEWAY,DNS的设置
......
BRIDGE=br0
[root@localhost network-scripts] # vim ifcfg-br0  //修改DEVICE为br0,Type为Bridge,把em2的网络设置设置到这里来(里面应该有ip,网关,子网掩码或DNS设置)
......
TYPE=Bridge
DEVICE=br0
   
[root@localhost network-scripts] # service network restart
   
[root@localhost network-scripts] # service docker restart
   
开启一个容器
[root@localhost network-scripts] # docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
docker.io /ubuntu    latest              0ef2e08ed3fa        3 weeks ago         130 MB
docker.io /centos    latest              67591570dd29        3 months ago        191.8 MB
   
[root@localhost network-scripts] # docker run -itd --net=none --name=my-centos docker.io/centos /bin/bash
6e64eade06d1eb20be3bd22ece2f79174cd033b59182933f7bbbb502bef9cb0f
[root@localhost network-scripts] # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6e64eade06d1        docker.io /centos    "/bin/bash"         10 seconds ago      Up 9 seconds                            my-centos
   
接着给容器配置网络(可以使用上面启动的容器名my-centos,也可以使用容器ID:6e64eade06d1)
网络设置的格式:ip@网关
默认不指定网卡设备名,则默认添加为eth1。可以通过-i参数添加网卡设备名
[root@localhost network-scripts] # pipework br0 -i eth0 my-centos 192.168.1.150/24@192.168.1.1
   
[root@localhost network-scripts] # docker attach 6e64eade06d1
[root@6e64eade06d1 /] # ifconfig eth0                 //若没有ifconfig命令,可以yum安装net-tools工具
eth0      Link encap:Ethernet  HWaddr 86:b6:6b:e8:2e:4d
           inet addr:192.168.1.150  Bcast:0.0.0.0  Mask:255.255.255.0
           inet6 addr: fe80::84b6:6bff:fee8:2e4d /64 Scope:Link
           UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
           RX packets:8 errors:0 dropped:0 overruns:0 frame:0
           TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
           collisions:0 txqueuelen:1000
           RX bytes:648 (648.0 B)  TX bytes:690 (690.0 B)
   
[root@6e64eade06d1 /] # route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.1.1     0.0.0.0         UG    0      0        0 eth0
192.168.115.0   0.0.0.0         255.255.255.0   U     0      0        0 eth0
   
另外pipework不能添加静态路由,如果有需求则可以在run的时候加上--privileged= true 权限在容器中手动添加。
但这种安全性有缺陷,这就需要通过ip netns(--help参考帮助)添加静态路由,以避免创建容器使用--privileged= true 选项造成一些不必要的安全问题:
   
如下获取指定容器的pid
[root@localhost network-scripts] # docker inspect --format="{{ .State.Pid }}" 6e64eade06d1
7852
[root@localhost network-scripts] # ln -s /proc/7852/ns/net /var/run/netns/7852
[root@localhost network-scripts] # ip netns exec 7852 ip route add 192.168.0.0/16 dev eth0 via 192.168.1.1
[root@localhost network-scripts] # ip netns exec 7852 ip route    //添加成功
192.168.0.0 /16 via 192.168.1.1 dev eth0
   
同理,在其它宿主机进行相应的配置,新建容器并使用pipework添加虚拟网卡桥接到br0,如此创建的容器间就可以相互通信了。
 
2)删除虚拟桥接卡docker0的配置
[root@localhost ~] # service docker stop
[root@localhost ~] # ip link set dev docker0 down  
[root@localhost ~] # brctl delbr docker0
[root@localhost ~] # brctl addbr br0
[root@localhost ~] # ip link set dev br0 up        
[root@localhost ~] # ip addr del 192.168.1.23/24 dev em2  //删除宿主机网卡的IP
[root@localhost ~] # ip addr add 192.168.1.23/24 dev br0  //将宿主主机的ip设置到br0 
[root@localhost ~] # brctl addif br0 em2       //将宿主机网卡挂到br0上
[root@localhost ~] # ip route del default     //删除默认的原路由,其实就是em2上使用的原路由192.168.1.1(这步小心,注意删除后要保证机器能远程连接上,最好是通过外网ip远程连的。别删除路由后,远程连接不上,中断了)
[root@localhost ~] # ip route add default via 192.168.1.1 dev br0  //为br0设置路由
[root@localhost ~] # vim /etc/sysconfig/docker      //即将虚拟的桥接口由默认的docker0改为bridge0
OPTIONS= '--selinux-enabled --log-driver=journald'
改为
OPTIONS= '--selinux-enabled --log-driver=journald -b=br0'    // 即添加-b=br0
 
[root@localhost ~] # service docker start
 
启动一个手动设置网络的容器。这里最好不要让docker自动获取ip,下次启动会有变化而且自动获取的ip可能会和物理网段中的ip冲突
[root@localhost ~] # docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS              PORTS               NAMES
6e64eade06d1        docker.io /centos    "/bin/bash"         10 seconds ago      Up 9 seconds                            my-centos
[root@localhost ~] # docker run -itd --net=none --name=container1 docker.io/centos
 
为container1容器设置一个与桥接物理网络同地址段的ip@网关
[root@localhost ~] # pipework br0 -i eth0 container1 192.168.1.190/24@192.168.1.1
 
如此 容器便和宿主主机在同一个网段了,其他主机也做相同的操作,容器间便可以通信了。
***************当你发现自己的才华撑不起野心时,就请安静下来学习吧***************
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值