主机清单:
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。