其他文章:
----------------------------------------------------------------
八、Docker网络原理
解决的问题:docker如何处理容器之间的网络访问
测试
# 一、查看本宿主机的 ip addr
[root@kk ~]# ip addr
1: 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
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 00:0c:29:c1:13:6d brd ff:ff:ff:ff:ff:ff
inet 192.168.204.130/24 brd 192.168.204.255 scope global noprefixroute ens33
valid_lft forever preferred_lft forever
inet6 fe80::62dc:f8a3:a777:e321/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 52:54:00:c3:d5:6c brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
4: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
link/ether 52:54:00:c3:d5:6c brd ff:ff:ff:ff:ff:ff
# 给docker分配了一个ip。只有安装启动了docker-server就会虚拟出一个docker的网卡:docker0,地址为172.17.0.1/16
# docker内部的容器都是通过这个docker0网卡的桥接方式进行通信的。
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:00:eb:57:0d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:ff:feeb:570d/64 scope link
valid_lft forever preferred_lft forever
# 二、启动tomcat,并查看容器内部的 ip addr
# 1.下载tomcat 以后台的方式进行运行
docker run -d -it -P --name tomcat01 tomcat
# 2. 查看容器tomcat01的内部ip eth0@if27 此地址为 docker自动生成 地址为:172.17.0.2/16
[root@kk ~]# docker exec -it tomcat01 ip addr # 不进入容器,直接查看ip
1: 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
26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
#3. 在宿主机上测试容器内部ip地址能否通信 ping 172.17.0.2
[root@kk ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.070 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.048 ms
# 三、在宿主机中再次ip addr 发现 多了一个 网卡
[root@kk ~]# ip addr
5: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:00:eb:57:0d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:ff:feeb:570d/64 scope link
valid_lft forever preferred_lft forever
# 此处即是 启动容器后 产生的新的网卡
27: veth8a743b7@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 02:9f:47:48:82:cc brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet6 fe80::9f:47ff:fe48:82cc/64 scope link
valid_lft forever preferred_lft forever
# 再次启动第二个tomcat02容器后,又多了一对网卡
29: veth56293aa@if28: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
link/ether 36:ec:01:06:de:d7 brd ff:ff:ff:ff:ff:ff link-netnsid 1
inet6 fe80::34ec:1ff:fe06:ded7/64 scope link
valid_lft forever preferred_lft forever
# 四、测试两个容器tomcat01和tomcat02之间的通信
# 查看容器tomcat02的内部ip eth0@if29 此地址为 docker自动生成 地址为:172.17.0.3/16
[root@kk ~]# docker exec tomcat02 ip addr
1: 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
28: eth0@if29: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 查看容器tomcat01的内部ip eth0@if27 此地址为 docker自动生成 地址为:172.17.0.2/16
[root@kk ~]# docker exec tomcat01 ip addr
1: 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
26: eth0@if27: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 两个容器之间可以完美通信(tomcat02容器可以ping通comcat01的ip)
[root@kk ~]# docker exec tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.170 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.074 ms
原理
- 我们发现每个容器启动后,会在容器内部生成一个网卡,同时会在宿主机中生成一个网卡,这两个网卡是对应的,有关联关系,并且是成对出现的。
- veth-pair就是一对的虚拟设备接口,他们都是成对出现的
- 一段连着协议,一段彼此相连正因为有这个特性,veth-pair充当一个桥梁,连接各种虚拟网络设备的
- 只要容器删除,对应网桥一对就没了!
小结
tomcat01和 tomcat02是公用的一个路由器, docker0所有的容器不指定网络的情况下,都是 docker0路由的, docker会给我们的容器分配一个默认的可用。
可以通过docker run --net=网络名称
指定使用名称。默认--net=docker0
。
容器网络连通方式:–-link
思考一个场景,我们编写了一个微服务, database url:=ip:,项目不重启,数据库ip换掉了,我们希望可以处理这个问题,可以名字来进行访问容器?
测试
# 1.直接用容器名称ping 不通
[root@kk ~]# docker exec -it tomcat01 ping tomcat02
ping: tomcat02: Name or service not known
#2. 用 --link 命令启动 单向可以ping 通
[root@kk ~]# docker run -d -it -P --name tomcat03 --link tomcat01 tomcat
02978b9e75c3d8c094ecc8cb74cb32ed4fbf92ef2f6eb53331eff5677c2a47ab
[root@kk ~]# docker exec -it tomcat01 ping tomcat03
ping: tomcat03: Name or service not known
[root@kk ~]# docker exec -it tomcat03 ping tomcat01
PING tomcat01 (172.17.0.2) 56(84) bytes of data.
64 bytes from tomcat01 (172.17.0.2): icmp_seq=1 ttl=64 time=0.325 ms
64 bytes from tomcat01 (172.17.0.2): icmp_seq=2 ttl=64 time=0.085 ms
单向联通的原因
[root@kk ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 tomcat01 2b05ac88444c # tomcat03 中直接指明了 tomcat01 的ip
172.17.0.4 02978b9e75c3
[root@kk ~]# docker exec -it tomcat01 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
172.17.0.2 2b05ac88444c # tomcat01 中没有 tomcat03的地址
本质探究
link就是我们在 tomcat03 的 hosts配置中增加了一个172.17.0.2 tomcat01 2b05ac88444c
我们现在玩 Docker已经不建议使用link了
上面的测试都是基于docker0网卡!能不能自定义网络?
docker问题:他不支持容器名连接访问
自定义网络连接
网络模式
- bridge:桥接 docker0 (默认,自己创建也使用 bridge模式)
- none:不配置网络
- host:和宿主机共享网络
- container:容器网络连通!(用的少!局限很大)
#我们可以自定义一个网络
# --driver bridge
#-- subnet 192.168.0.0/16
#-- gateway 192.168.0.1
[root@kk ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
21501df4c37c77fcbb0c61b3bdd776ede7a29802c8234413bbb85e525722a087
[root@kk ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
275762873e27 bridge bridge local
9293b8c12edf host host local
21501df4c37c mynet bridge local
dca3d5c20357 none null local
# 查看自定义网络的信息
[root@kk ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "21501df4c37c77fcbb0c61b3bdd776ede7a29802c8234413bbb85e525722a087",
"Created": "2021-04-16T20:30:22.78506401+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
在自定义的网络里启动两个tomcat
# 使用 --net mynet指定网络 默认是docker0
[root@kk ~]# docker run -d -P --name tomcat-net-01 --net mynet tomcat
6f693e658afec4ac39c6c7f762c0bfa5be5da2bfe1730b7a8ae059e441edb1d5
[root@kk ~]# docker run -d -P --name tomcat-net-02 --net mynet tomcat
38934ce91b2b6ddf51ae3933b7733818ce4319620cf520d88c262ed403b49459
# 查看自定义的网络,发现里面多了两个容器的信息
[root@kk ~]# docker network inspect mynet
[
...
"Containers": {
"38934ce91b2b6ddf51ae3933b7733818ce4319620cf520d88c262ed403b49459": {
"Name": "tomcat-net-02",
"EndpointID": "2a1baa06127e83037dfbc53523f7a749b3246026489de88a1c566739c7a315eb",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
"......: {
"Name": "tomcat-net-01",
"EndpointID": "........",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
...
]
# 两个容器之间相互用 名称 ping
[root@kk ~]# docker exec tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.073 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.066 ms
[root@kk ~]# docker exec tomcat-net-02 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.055 ms
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=2 ttl=64 time=0.078 ms
小结
我们自定义的网络 docker都已经帮我们维护好了对应的关系。
推荐我们平时这样使用网络!
好处:
redis 不同的集群使用不同的网络,保证集群是安全和健康的
mysql 不同的集群使用不同的网络,保证集群是安全和健康的
两个网络之间的联通
docker自带的网络是docker0,上面我们自定义的网络是mynet,这两个网络中的容器如何通讯?
# 1.在默认的 dockers0 下开启一个 tomcat
[root@kk ~]# docker run -d -P --name tomcat01 tomcat
4d46cb8b8200848e6ba095d7d0fb76a73470653b72efbbf7a480fce6c4070d8b
#2.测试 该 docker0 下的 tomcat 与 mynet 下的 tomcat-net-02 之间的通信 无法联通
[root@kk ~]# docker exec tomcat01 ping tomcat-net-02
ping: tomcat-net-02: Name or service not known
[root@kk ~]# docker network connect --help
Usage: docker network connect [OPTIONS] NETWORK CONTAINER
Connect a container to a network
Options:
--alias strings Add network-scoped alias for the container
--driver-opt strings driver options for the network
--ip string IPv4 address (e.g., 172.30.100.104)
--ip6 string IPv6 address (e.g., 2001:db8::33)
--link list Add link to another container
--link-local-ip strings Add a link-local address for the container
#3.使用 docker network connect 将容器和网络联通
# tomcat01本来在docker0网络,这里再加入到mynet网络,相当于一台服务器有两个ip,内网ip和外网ip.
[root@kk ~]# docker network connect mynet tomcat01
[root@kk ~]# docker network inspect mynet
[
...
"Containers": {
"38934ce91b2b6ddf51ae3933b7733818ce4319620cf520d88c262ed403b49459": {
"Name": "tomcat-net-02",
"EndpointID": "2a1baa06127e83037dfbc53523f7a749b3246026489de88a1c566739c7a315eb",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
},
#4. 发现此处多了一个 容器 即 tomcat01 有两个地址,一个在网络 docker0 一个就是 mynet
"4d46cb8b8200848e6ba095d7d0fb76a73470653b72efbbf7a480fce6c4070d8b": {
"Name": "tomcat01",
"EndpointID": "39f637c20175499052aa4474ba9022de1bf23ffe2a86fbcdd5155ac5f3f7309a",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"6f693e658afec4ac39c6c7f762c0bfa5be5da2bfe1730b7a8ae059e441edb1d5": {
"Name": "tomcat-net-01",
"EndpointID": "ecc240f9051d0d64ee773eba961761e739cd31d4d83e1f6a4d04df4f712c75d8",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
}
...
]
# 5.再次测试 两者之间的联通情况 成功ping通,相互均可访问
[root@kk ~]# docker exec tomcat01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.148 ms
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.066 ms
[root@kk ~]# docker exec tomcat-net-01 ping tomcat01
PING tomcat01 (192.168.0.4) 56(84) bytes of data.
64 bytes from tomcat01.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.076 ms
64 bytes from tomcat01.mynet (192.168.0.4): icmp_seq=2 ttl=64 time=0.080 ms
结论: 假设要跨网络操作,就需要使用 docker network connect连通!。
实战 部署redis集群
快速部署,高可用,主机故障后从机可以使用。
略。