Docker网络
理解Docker0
docker是如何处理容器网络访问的?
只要安装了docker,就会有一个默认的docker0(桥接模式),每启动一个容器,就会给它分配一个IP,使用的技术是evth-pair。举例。
当前宿主机ip中有个默认的docker0 :172.17.0.1 是因为安装了docker,这里的docker0类似于路由器。
有一个39: veth81a50d0@if38是因为创建了一个容器
[root@lzk ~]# 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: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 link/ether fa:16:3e:ce:26:35 brd ff:ff:ff:ff:ff:ff inet 192.168.0.15/24 brd 192.168.0.255 scope global noprefixroute dynamic eth0 valid_lft 83848sec preferred_lft 83848sec inet6 fe80::f816:3eff:fece:2635/64 scope link valid_lft forever preferred_lft forever 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default link/ether 02:42:ac:28:65:03 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:acff:fe28:6503/64 scope link valid_lft forever preferred_lft forever 39: veth81a50d0@if38: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default link/ether 82:8c:75:6a:26:6a brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet6 fe80::808c:75ff:fe6a:266a/64 scope link valid_lft forever preferred_lft forever
#创建并运行一个tomcat [root@lzk ~]# docker run -d -P --name tomcatlzk tomcat Unable to find image 'tomcat:latest' locally latest: Pulling from library/tomcat 0ecb575e629c: Pull complete 7467d1831b69: Pull complete feab2c490a3c: Pull complete f15a0f46f8c3: Pull complete 26cb1dfcbebb: Pull complete 242c5446d23f: Pull complete f22708c7c9c1: Pull complete d8b7e17ca4bc: Pull complete 91588c31829d: Pull complete d97abf351b5d: Pull complete Digest: sha256:7f29cf0cb11a16bd3ff22c5716e655a7da872fb9b508b501588e30b2901ae446 Status: Downloaded newer image for tomcat:latest 4c9972c8a2181b2f1a02c98735cc503323b0901060c2c6976f3427180ed6e79b [root@lzk ~]#
#查看 容器网络ip 为172.17.0.2 [root@lzk ~]# docker exec -it tomcatlzk 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 38: eth0@if39: <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
注意!
在Linux中是这样的
39: veth81a50d0@if38
在容器中是这样的
38: eth0@if39:
evth-pair技术:就是一对的虚拟设备接口,他们都是成对出现的
正因为这个特性,evth-pair充当了一个桥梁打通了网络连接各种虚拟网络设备。
OpenStac、Docker容器之间都是使用这个技术 。
结论:容器和容器之间,和外部都是可以互相通的,docker所有的网络接口都是虚拟的,虚拟的转发效率很高。docker每次启动都将重新分配IP。
思考:假设有个数据库,IP一直变是不是访问就很麻烦了,那么通过服务名(容器名)来调用就可以避免这个问题。
解决办法1(不推荐使用):通过--link来联通容器,类似于做了个网络链接(单向的)
举例:
[root@lzk ~]# docker run -d -P --name tomcatlzk2 --link tomcatlzk1 tomcat ff6408c8865d199cf506c67b8cff6c586d9c7a32a8f7dd01577956dfa3e694a4 [root@lzk ~]# docker exec -it tomcatlzk2 ping tomcatlzk1 PING tomcatlzk1 (172.17.0.3) 56(84) bytes of data. 64 bytes from tomcatlzk1 (172.17.0.3): icmp_seq=1 ttl=64 time=0.093 ms 64 bytes from tomcatlzk1 (172.17.0.3): icmp_seq=2 ttl=64 time=0.059 ms 64 bytes from tomcatlzk1 (172.17.0.3): icmp_seq=3 ttl=64 time=0.059 ms
解决办法2(推荐使用):通过自定义网络,不使用docker0。
首先查看当前docker 网络
[root@lzk ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 728402d8b53a bridge bridge local 8514a8d98188 host host local 62eb5328d157 none null local
网络模式分类:
bridge桥接:在docker上面搭桥 docker0(默认)
nono:不配置网络
host:主机模式,和宿主机共享网络
container:容器内网络联通(不建议用,局限性很大)
分析
我们原来的启动模式
docker -run -d -P --name tomcat01 tomcat
其实就等同于
docker -run -d -P --name tomcat01 --net bridge tomcat
docker0是默认的,域名不能访问,--link可以打通但是不方便
那么我们现在自己定义一个网络
[root@lzk ~]# docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 lzknet fdae71ce5cdd7f91c421345c751bd5a6978d4c8d4632b41be37f2f84d2cdb884 [root@lzk ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 728402d8b53a bridge bridge local 8514a8d98188 host host local fdae71ce5cdd lzknet bridge local 62eb5328d157 none null local
这里自己的网络就创建好了
查看自己定义的网络的信息
[root@lzk ~]# docker network inspect lzknet [ { "Name": "lzknet", "Id": "fdae71ce5cdd7f91c421345c751bd5a6978d4c8d4632b41be37f2f84d2cdb884", "Created": "2022-11-28T23:16:54.348802294+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": {} } ]
当我们创建容器的时候就直接把默认的改成我们自己的就是了
docker -run -d -P --name tomcat01 --net lzknet tomcat
这样和通过--link到docker0的网络中有什么区别呢,区别就在于自定义的网络可以直接ping服务名(容器名),容器之间的网络关系就自动维护了,对于不同的集群使用不同的网络互相隔离
那又应该怎么打通被隔离后的不同集群之间的网络呢?
情景:假设A集群(192.168.0.0)想要和B集群(172.168.0.0)打通
思路:将A集群的netmork连接到B集群的一个容器中(反之同理),这种方式叫一个容器,两个IP
docker network connect lzknet tomcat01
注意仅仅限于集群B中的容器tomcat01 和lzknet是通的,集群B中的其他容器是未打通的。