2台主机的docker互相通信的方法

主机清单:

192.168.6.132 主机名 vm132 系统centos7

192.168.6.132 主机名 vm132 系统centos7

安装docker

wget -O /etc/yum.repos.d/docker-ce.repo https://download.docker.com/linux/centos/docker-ce.repo
sed -i 's+download.docker.com+mirrors.cloud.tencent.com/docker-ce+' /etc/yum.repos.d/docker-ce.repo
yum makecache fast
yum install docker-ce  -y

给2台主机配置不同的网段

192.168.6.132 (vm132)的/etc/docker/daemon.json增加如下配置

{
  "bip": "172.17.132.1/24",
  ......
}

192.168.6.136 (vm136)的/etc/docker/daemon.json增加如下配置

{
  "bip": "172.17.136.1/24",
  ......
}

重启docker服务 sudo systemctl restart docker

docker访问外网原理解析

在任意一台主机执行:

[root@vm132 ~]# docker run  -itd --name alpine  alpine   #启动一个alpine容器
[root@vm132 ~]# docker exec  -it alpine sh                #进入容器
/ # ping baidu.com                                        #在容器内ping百度是可以ping通的
PING baidu.com (39.156.69.79): 56 data bytes
64 bytes from 39.156.69.79: seq=0 ttl=127 time=43.406 ms

为什么可以ping通百度呢

[root@vm132 ~]# iptables -t nat  -L -n
...省略
Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.132.0/24      0.0.0.0/0
MASQUERADE  all  --  172.17.0.0/16        0.0.0.0/0
...省略

查看iptables的nat表发现来源是容器网段的IP在访问时做了SNAT,类似于局域网访问外网(如:百度)。

docker(172.17.132.2)访问外网的过程如下(做了SNAT):
包出vm132时做了SNAT,  SNAT之后包的源地址就是vm132的IP  
包出路由器时又做了SNAT, SNAT之后包的源地址就是路由器的公网IP

包回到路由器时,根据路由器的conntrack(链接跟踪表),把包的目的IP修改为vm132的IP(因为包出vm132时做了SNAT源IP从docker修改为vm132的IP)
包回到vm132时,根据vm132的conntrack(链接跟踪表),把包的目的IP修改为docker的IP。整体通讯过程打通
如果docker访问外网不做SNAT,流程是这样的。
包出vm132时没做SNAT,  包的源地址就是172.17.132.2
包出路由器时做了SNAT, SNAT之后包的源地址就是路由器的公网IP  (源IP从172.17.132.2修改为路由器公网IP)

包回到路由器时,根据路由器的conntrack(链接跟踪表),把包的目的IP修改为docker的IP。
此时路由器懵了,他只知道各主机的IP,不知道docker的IP在哪儿。通讯失败

查看主机路由表

[root@vm132 ~]# route -n
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.6.2     0.0.0.0         UG    0      0        0 ens33
172.17.132.0    0.0.0.0         255.255.255.0   U     0      0        0 docker0
192.168.6.0     0.0.0.0         255.255.255.0   U     0      0        0 ens33

如果vm132主机的docker要跟vm136主机的docker通讯,目的地址是172.17.136.0/24网段,因此需要按如下命令修改路由表内容。为保证2台服务器的docker容器可以互相通讯,vm132和vm136的主机各增加了一条路由表信息。意思时:目的IP如果是对方主机的docker,把网关设置为对方主机。

vm132服务器执行下面的命令:
[root@vm132 ~]# route add -net  172.17.136.0/24  gw 192.168.6.136

vm136服务器执行下面的命令:
[root@vm136 ~]# route add -net  172.17.132.0/24  gw 192.168.6.132

思考:如果只是让2台主机的docker可以通讯,iptables的SNAT需要吗?
答案:不需要。用SNAT的原因是包回来的时候不知道找谁,上面2条路由信息可以让2台服务器的容器互相找到对方,是不需要SNAT的。

但是如果docker需要访问外网,SNAT是需要的,对应的iptables规则也需要保留。

清除iptables规则,修改默认规则为ACCEPT

2台主机同时操作,命令如下:

iptables   -F
iptables  -t  nat  -F

然后检查有没有默认规则不对的,如有默认规则不是ACCEPT,修改一下,如:
iptables  -P FORWARD  ACCEPT

2台主机的docker此时已经可以互相通信了

各位自己试

思考:

1、如果2台主机也不在同一网段,主机间的docker要通讯,需要做SNAT不?
2、局域网内k8s中2台主机的docker互相访问如果做了SNAT,容器的日志记录的是各主机的IP合适吗?该怎么办才能使得日志记录的是容器IP。

猜你喜欢

转载自blog.csdn.net/sinat_24354307/article/details/118464993