docker 自定义网络

发布时间:2022-03-01 09:55:31 作者:yexindonglai@163.com 阅读(1114)

首先看看网卡的信息

通过ip addr命令可以看到,这里有三个网卡,

  • lo: 本机回环地址
  • etho : 默认网卡
  • docker0 :docker的网卡
  1. [root@VM_0_5_centos dockerFile]# ip addr
  2. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
  3. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  4. inet 127.0.0.1/8 scope host lo
  5. valid_lft forever preferred_lft forever
  6. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
  7. link/ether 52:54:00:6f:cb:a8 brd ff:ff:ff:ff:ff:ff
  8. inet 172.27.0.5/20 brd 172.27.15.255 scope global eth0
  9. valid_lft forever preferred_lft forever
  10. 3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
  11. link/ether 02:42:27:d8:f7:98 brd ff:ff:ff:ff:ff:ff
  12. inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
  13. valid_lft forever preferred_lft forever

docker网络原理

veth-pair技术

顾名思义,veth-pair 就是一对的虚拟设备接口,和 tap/tun 设备不同的是,它都是成对出现的。一端连着协议栈,一端彼此相连

我们每启动一个docker容器,docker就会给docker容器分配一个ip,并会生成一对(2个)网卡,因为我们在安装docker容器时就会安装一个docker专用的网卡;所以启动后,不但容器里面会有一个网卡,宿主机也有有一个网卡用来专门绑定容器用的;所以它们的网卡是一对一对出现的, 这就是veth-pair技术;
在这里插入图片描述

测试一下,现在我们启动2个容器,然后在宿主机上输入命令ip addr,结果如下 ,我们发现,除了刚刚那三个网卡之外,多出了115117这2个网卡,其中这2个网卡就是用来绑定容器使用的,仔细看

  • 115: veth69cdd46@if114: 最后面有个114,所以就可以肯定,宿主机的115网卡 绑定了 容器的 114网卡
  • 117: vethff2062e@if116 :同理,117绑定了容器内的116网卡
  1. [root@VM_0_5_centos ~]# ip addr
  2. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
  3. link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
  4. inet 127.0.0.1/8 scope host lo
  5. valid_lft forever preferred_lft forever
  6. 2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
  7. link/ether 52:54:00:6f:cb:a8 brd ff:ff:ff:ff:ff:ff
  8. inet 172.27.0.5/20 brd 172.27.15.255 scope global eth0
  9. valid_lft forever preferred_lft forever
  10. 3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
  11. link/ether 02:42:27:d8:f7:98 brd ff:ff:ff:ff:ff:ff
  12. inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
  13. valid_lft forever preferred_lft forever
  14. 115: veth69cdd46@if114: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
  15. link/ether 86:d1:9d:ae:1b:d6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
  16. 117: vethff2062e@if116: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP
  17. link/ether 06:b4:54:e7:d4:57 brd ff:ff:ff:ff:ff:ff link-netnsid 1

所以这2对网卡都公用一个路由器,这2对网卡都是由docker0网卡分配的;并且docker容器中所有的网卡都是虚拟的;虚拟网卡转发效率快;

每次连接或者ping的时候都需要写ip才能ping通,有了link之后我们就可以直接通过容器的名称来连接了;比如说我现在有2个centos的容器,想要在centos_1 通过 容器名称去ping centos_2,那么这时候在启动容器时就可以加上--link选项来实现

  1. # 1、先启动centos_2容器
  2. docker run -d -it --name centos_2 centos
  3. # 2、启动centos_1 容器,并且和centos_2产生连接
  4. docker run -d -it --name centos_1 --link centos_2 centos
  5. # 3、进入centos_1
  6. docker attach centos_1
  7. # 4、在容器centos_1内部直接ping centos_2 ,结果我们发现是可以ping通的
  8. [root@c5b2b47d5c52 /]# ping centos_2
  9. PING centos_2 (172.17.0.4) 56(84) bytes of data.
  10. 64 bytes from centos_2 (172.17.0.4): icmp_seq=1 ttl=64 time=0.098 ms
  11. 64 bytes from centos_2 (172.17.0.4): icmp_seq=2 ttl=64 time=0.051 ms
  12. 64 bytes from centos_2 (172.17.0.4): icmp_seq=3 ttl=64 time=0.054 ms

注意

这里有一点需要注意,目前我们只能在centos_1 去ping centos_2 ,在centos_2 里是不可以ping centos_1的。因为centos_2在启动的时候没有加--link选项;

容器互联底层原理
—link 是什么原理呢?它在内部是怎么做到的呢?其实非常简单,当我们在启动容器时加上 —link选项之后,docker在容器内部的 /etc/hosts 就加上了centos_2的配置,我们来看看就知道了,进入容器centos_1查看hosts文件,倒数第二行看到了吗,原理就是这么简单;

  1. [root@c5b2b47d5c52 /]# cat /etc/hosts
  2. 127.0.0.1 localhost
  3. ::1 localhost ip6-localhost ip6-loopback
  4. fe00::0 ip6-localnet
  5. ff00::0 ip6-mcastprefix
  6. ff02::1 ip6-allnodes
  7. ff02::2 ip6-allrouters
  8. 172.17.0.4 centos_2 126798c30683
  9. 172.17.0.5 c5b2b47d5c52

因为这个太简单了,所以目前已经不建议使用—link了;这也就是给新手用用而已;

容器互联 - 自定义网络

自定义容器可使不同的集群使用不通的网络,保证了集群是安全和健康的,
自定义网络的命令主要有以下几项

  1. # 查看本机docker所有网络
  2. docker network ls
  3. # 创建网络 --driver 是网络模式,--subnet是子网掩码,后面的/16表示可以生成6万多个ip, --gateway是网关地址
  4. docker network create 网络名称 --driver bridge --subnet 192.168.0.1/16 --gateway 192.168.0.2 mynet
  5. # 将容器加入到当前网络
  6. docker network connect 网络名称 容器名称
  7. # 断开容器的网络 (容器必须是运行状态才能断开连接)
  8. docker network disconnect 网络名称 容器名称
  9. # 查看网络的详细信息
  10. docker network inspect 网络id/网络名称
  11. #删除网络
  12. docker network rm 网络id/网络名称
  13. # 删除所有未使用的网络
  14. docker network prune --f

查看所有的docker网络

  1. [root@VM_0_5_centos ~]# docker network ls
  2. NETWORK ID NAME DRIVER SCOPE
  3. f77512c426f3 bridge bridge local
  4. 7a19c378ddd5 host host local
  5. 62ad5c8176f0 none null local
  6. # 说明
  7. NETWORK ID 网络id
  8. NAME 网络名称
  9. DRIVER 网络模式
  10. SCOPE 作用域

网络模式分类

  • bridge : 桥接(默认),B和C通过A来连接,A就是路由
  • none: 不配置网络
  • host: 主机模式,和宿主机共享网络;
  • container: 容器网络联通(用的少,局限性大)

启动说明

  1. 通常我们启动容器的命令是这样的
  2. docker run -d -P --name tomcat01 tomcat
  3. # 但其实,启动的命令中还隐藏了一个选项,就是网络的配置选项,
  4. # 如果你不加网络选项的话,默认的docker会帮我们加上一个配置,如下
  5. docker run -d -P --name tomcat01 --net bridge tomcat

创建自定义网络

  1. # --driver 是网络模式,--subnet是子网掩码,后面的/16表示可以生成6万多个ip, --gateway是网关地址
  2. docker network create --driver bridge --subnet 192.168.0.1/16 --gateway 192.168.0.2 mynet

查看一下docker网络,可以看到mynet已经创建号了

  1. [root@VM_0_5_centos ~]# docker network ls
  2. NETWORK ID NAME DRIVER SCOPE
  3. f77512c426f3 bridge bridge local
  4. 7a19c378ddd5 host host local
  5. 00373dcd1ddb mynet bridge local
  6. 62ad5c8176f0 none null local

启动容器后就可以指定自定义的网络了

  1. # 启动第一个使用了自定义网络的centos
  2. docker run -d -P -it --name centos01_mynet --net mynet centos
  3. # 启动第二个使用了自定义网络的centos
  4. docker run -d -P -it --name centos02_mynet --net mynet centos

centos01_mynet 和 centos02_mynet 之间都是可以互相ping通的

  1. # centos01_mynet ping centos02_mynet
  2. [root@VM_0_5_centos ~]# docker exec -it centos01_mynet ping centos02_mynet
  3. PING centos02_mynet (192.168.0.3) 56(84) bytes of data.
  4. 64 bytes from centos02_mynet.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.054 ms
  5. 64 bytes from centos02_mynet.mynet (192.168.0.3): icmp_seq=2 ttl=64 time=0.042 ms
  6. 64 bytes from centos02_mynet.mynet (192.168.0.3): icmp_seq=3 ttl=64 time=0.039 ms
  7. # centos02_mynet ping centos01_mynet
  8. [root@VM_0_5_centos ~]# docker exec -it centos02_mynet ping centos01_mynet
  9. PING centos01_mynet (192.168.0.1) 56(84) bytes of data.
  10. 64 bytes from centos01_mynet.mynet (192.168.0.1): icmp_seq=1 ttl=64 time=0.037 ms
  11. 64 bytes from centos01_mynet.mynet (192.168.0.1): icmp_seq=2 ttl=64 time=0.040 ms
  12. 64 bytes from centos01_mynet.mynet (192.168.0.1): icmp_seq=3 ttl=64 time=0.070 ms

隔离测试

启动一个使用了默认网络的centos

  1. docker run -d -P --name centos_1 -it centos

然后使用自定义网络的centos01_mynet 去 ping 默认网络的centos_1,我们发现是ping不通的

  1. [root@VM_0_5_centos ~]# docker exec -it centos02_mynet ping centos_1
  2. ping: centos_1: Name or service not known

打通自定义网络和默认网络的连接
刚刚我们测试过了,自定义网络和默认网络是不通的,这样就起到了隔离的作用,那如果我们想要打通这两个网络应该怎么办呢?其实很简答, ,docker已经帮我们想好了,只需要使用 connect 指令即可

  1. # 执行以下命令打通 默认网络和自定义网络
  2. docker network connect mynet centos_1

打通后,默认网络和自定义网络就可以互相ping啦

  1. # 默认网络的容器 ping 自定义网络的容器
  2. [root@VM_0_5_centos ~]# docker exec -it centos_1 ping centos01_mynet
  3. PING centos01_mynet (192.168.0.1) 56(84) bytes of data.
  4. 64 bytes from centos01_mynet.mynet (192.168.0.1): icmp_seq=1 ttl=64 time=0.037 ms
  5. 64 bytes from centos01_mynet.mynet (192.168.0.1): icmp_seq=2 ttl=64 time=0.051 ms
  6. 64 bytes from centos01_mynet.mynet (192.168.0.1): icmp_seq=3 ttl=64 time=0.048 ms
  7. # 自定义网络的容器 ping 默认网络的容器
  8. [root@VM_0_5_centos ~]# docker exec -it centos02_mynet ping centos_1
  9. PING centos_1 (192.168.0.4) 56(84) bytes of data.
  10. 64 bytes from centos_1.mynet (192.168.0.4): icmp_seq=1 ttl=64 time=0.038 ms
  11. 64 bytes from centos_1.mynet (192.168.0.4): icmp_seq=2 ttl=64 time=0.049 ms
  12. 64 bytes from centos_1.mynet (192.168.0.4): icmp_seq=3 ttl=64 time=0.048 ms

自定义网络的连接原理
当我们创建自定义网卡后,想要联通某个容器,它是直接和容器内的网卡连接的,而不是去连接自定义网络的网卡;它们之间的关系如下图

在这里插入图片描述

关键字Docker