前言:Docker的5种网络模式
Bridge
此时docker引擎会创建一个veth对,一端连接到容器实例并命名为eth0,另一端连接到指定的网桥中(比如docker0),因此同在一个主机的容器实例由于连接在同一个网桥中,它们能够互相通信。容器创建时还会自动创建一条SNAT规则,用于容器与外部通信时,类似家里上网用的ISP提供给我们的动态IP。如果用户使用了-p或者-P端口,还会创建对应的端口映射规则,使得外部请求能够访问容器的服务,但是你不能通过IP直接访问,本文提供了3种方式实现容器的跨主机访问。
Host
与宿主机共享网络,此时容器没有使用网络的namespace,宿主机的所有设备,会暴露到容器中,因此存在安全隐患。
None
不设置网络,相当于容器内没有配置网卡,用户可以手动配置。
Container
指定与某个容器实例共享网络
(国内工单技术支持群---群文件有这块说明可以自己download看下)
1. 使用直接路由方式打通跨主机的容器网络互通:
这种方式最简单,只需vpc里面添加自定义路由就可以实现,步骤如下:
(1)把主机网卡的转发开启,cat /proc/sys/net/ipv4/ip_forward cat /proc/sys/net/ipv4/conf/eth0/forwarding # 0代表关闭,1代表开启
(2)定义两个主机的docker网段,可以在/etc/docker/daemon.json 配置文件里面添加 "bip": "169.254.123.1/24" 来做定义 # 其中169.254.123.1/24可以替换为您真实想设置的网段类型,注意不要和vpc的交换机网段冲突!
2 实验环境配置如下
(1)vpc地址段:192.168.0.0/16 两个主机的docker网段信息如下:
docker1 i-8vb6dyu0clj3b538e1yh vpc:vpc-8vbuj466yjq2b5mjwwluu 私网IP地址:192.168.1.196 公网IP地址:39.103.187.202。docker网段:10.0.0.1/24
docker2 i-8vbbhvwcbk9yjeigcctn vpc:vpc-8vbuj466yjq2b5mjwwluu 私网IP地址:192.168.1.197 公网IP地址:39.103.138.241 docker网段: 10.1.0.1/24
(2) 创建container
vm1 执行:docker run -it --name=test1 centos,对应容器IP为:10.0.0.2
vm2执行:docker run -it --name=test1 centos,对应容器IP为:10.1.0.2
在vm1上的centos 容器中ping 10.1.0.2,和预期一致,是无法ping通的。
[root@0c577544fdd2 /]# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:0a:00:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.0.0.2/24 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::42:aff:fe00:2/64 scope link
valid_lft forever preferred_lft forever
[root@0c577544fdd2 /]# ping 10.1.0.2
PING 10.1.0.2 (10.1.0.2) 56(84) bytes of data.
梳理下docker及docker容器在Linux宿主机网络模块中做的操作,梳理清楚之后会发现打通不同宿主机上docker容器的方法非常简单。从宿主Linux系统的视角看操作系统中的网络设备,总结如下:
- docker0接口:网桥,在安装完docker后默认被创建,网段是172.17.0.0/16,网桥的默认IP地址为172.17.0.1,可以修改/etc/docker/daemon.json 文件修改默认的容器网段
- br-xxxx接口:网桥,在创建完自定义docker网络完被创建,网段是被用户指定的172.18.0.0/16,网桥的默认IP地址为172.18.0.1。
- vethxxxx接口:veth网络接口,在创建一个具体的docker容器后被创建,如果有N个运行的容器,就会有N个veth网络接口。容器中的eth0接口和宿主机的veth网络接口是一个veth网络对,Linux上的veth接口作为一个端口连接入docker网桥,如docker0或其他自定义网桥。这也是为什么一个宿主机上的docker容器能够默认通信的原因,因为它们创建后就被接入到了同一个网桥上。
可以看下上图,容器的请求会通过虚拟网卡转给docker0----然后docker0再把请求给vm1的eth0,这个情况可以利用vpc路由表直接实现网络的通信,配置如下
把访问10.0.0.0/24的流量,通过vpc路由表转给i-8vb6dyu0clj3b538e1yh做处理
把访问10.1.0.0/24的流量,通过vpc路由表转给i-8vbbhvwcbk9yjeigcctn做处理
配置完毕后,通过vm1的机器直接去访问10.1.0.2发现不通,通过抓包看请求已经到了vm2的eth0网卡上面,但是没有到vm2容器的网卡,这种情况一般有如下可能性:
(1)vm2的网卡转发没有开启,经过验证转发是没有问题的
(2)进一步分析iptables规则发现默认FORWARD这个转发连是拒绝了的,这个情况导致了请求被iptables拦截了,执行iptables -P FORWARD ACCEPT恢复!
ps:如果在遇到类似case可以把相关方案给客户,但是也告知客户这样做有潜在风险,不建议使用到生产上面,因为容器他的IP地址是不固定的,例如意外原因容器重建了就会导致IP地址发生变动,最优方案可以考虑使用hostnetwork 网络模式,直接通过宿主机的端口进行通信,或者使用Kubernetes!