💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
[TOC] ## 一 容器网络的类型 Docker 网络从覆盖范围可分为单个 host 上的容器网络和跨多个 host 的网络,多host网络又分为原生网络和第三方网络,如下: * 原生单机网络 * None:不为容器配置任何网络功能,`--net=none ` * Host:与主机共享Network Namespace,`--net=host ` * Container:与另一个运行中的容器共享网络名称空间,`--net=container:ID ` * Bridge:Docker设计的,默认的NAT网络模型,`--net=bridge` * 原生多机网络 * overlay:基于vxlan的隧道网络 * macvlan:基于网卡虚拟化的大局域网 * 第三方多机网络[本章不讨论] * flannel * weave * calico > 原生网络和单机网络都是通过不同的driver来实现的,未来可能还会有更多的开源driver ## 二 原生单机网络 docker安装好后,默认会创建三个网络,分别是none,host和bridge,用docker network ls命令查看如下 ```sh [root@docker01 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 3cb9e3ca4456 bridge bridge local 4cc3166d4351 host host local f61ddbb4efdf none null local ``` ### A. none网络 none 网络就是什么都没有的网络。挂在这个网络下的容器除了 lo,没有其他任何网卡。容器创建时,可以通过 `--network=none` 指定使用 none 网络。 ``` docker run -it --rm --network=none centos:6.9 [root@5fa702165cb2 /]# ifconfig lo Link encap:Local Loopback inet addr:127.0.0.1 Mask:255.0.0.0 ``` 封闭意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用 none 网络。 比如某个容器的唯一用途是生成随机密码,就可以放到 none 网络中避免密码被窃取。 ### B. host网络 连接到 host 网络的容器共享 Docker host 的网络栈,容器的网络配置与 host 完全一样。可以通过 `--network=host` 指定使用 host 网络。 在容器中可以看到 host 的所有网卡,并且连 hostname 也是 host 的。 ``` docker run -it --rm --network=host busybox / # hostname docker01 / # ip l|egrep ^[1-9]|awk '{print $1,$2}' 1: lo: 2: eth0: 3: docker0: 9: vethccf4863@if8: ``` Docker host 的网络最大的好处就是性能,如果容器对网络传输效率有较高要求,可以选择 host 网络,但要考虑端口冲突问题 另一个用途是让容器可以直接配置 host 网路。如某些跨 host 的网络解决方案,本身也是以容器方式运行的,需要对网络进行配置,比如管理 iptables ### C. Container网络 container网络严格来说并不是一种网络类型,因为它只是让一个容器使用主容器的网络名称空间,主容器的网络是什么类型都不影响 1. 创建主容器并查看网卡信息 ```sh docker run -d --name bbx --rm busybox sleep 900 [root@docker01 ~]# docker exec -it bbx ip a|egrep eth0|awk '{print $1,$2}' 34: eth0@if35: inet 172.17.0.2/16 ``` 2. 创建新容器并使用主容器网络 ```sh [root@docker01 ~]# docker run --network=container:bbx busybox ip a|grep eth0|awk '{print $1,$2}' 34: eth0@if35: inet 172.17.0.2/16 ``` 3. 用途说明 可以明显看出来,上诉两个容器使用的是同一个网卡,其他整个网络名称空间用的都是一个,用这种方式组织的容器,容器间通信十分便捷,效率也很高 ## 三 **bridge 网络** ### A. bridge网络入门解释 如果不指定`--network`,创建的容器默认都会挂到 `docker0` 上,docker0是安装时创建的linux bridge网络(可以理解为NAT),可以用linux管理bridge的命令进行查看和管理 ```sh yum install bridge-utils docker container rm -f `docker container ls -a -q` [root@docker01 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.024277f99a61 no ``` 可以看到网桥docker0的信息,可以把docker0理解为一个虚拟交换机,现在这个交换机上没有接设备,我们启动一个容器看看结果 ```sh docker run -d --name bbx --rm busybox sleep 900 [root@docker01 ~]# brctl show bridge name bridge id STP enabled interfaces docker0 8000.024277f99a61 no veth0652c67 ``` 交换机docker0已近连接了虚拟接口对(veth pair)的接口`veth0652c67`,该虚拟接口对的另一个接口连接到了刚刚新建的容器bbx中 >veth pair 是一种成对出现的特殊网络设备,可以想象成由一根虚拟网线连接起来的一对网卡,网卡的一头在容器中,另一头挂在网桥 `docker0` 上 ```sh [root@docker01 ~]# ip a|grep veth0652c67|awk '{print $1,$2}' 33: veth0652c67@if32: [root@docker01 ~]# docker exec -it bbx sh / # ip a|grep eth0|awk '{print $1,$2}' 32: eth0@if33: [root@docker01 ~]# docker network inspect bridge |grep -A1 Subnet "Subnet": "172.17.0.0/16", "Gateway": "172.17.0.1" ``` 上面代码解释说明: * docker主机中多了一块网卡,编号33,名称veth0652c67,对端网卡编号if32 * bbx容器中有一个网卡,编号32,名称eth0,对端网卡边哈if33,正好是一对 * 默认分配的IP地址段是`172.17.0.0/16`,网关IP就是docker0的IP ### B. bridge网络自定义 默认的bridge网络是自动创建的,已有的信息不能修改,但docker支持自定义新的bridge网络,子网段、网关、是否自动分配等都可以自定义 1. 创建简单的自定义bridge网络 ```sh docker network create --driver bridge noah_net [root@docker01 ~]# brctl show bridge name bridge id STP enabled interfaces br-a83f1d0be49e 8000.0242e25e18d4 no docker0 8000.024277f99a61 no [root@docker01 ~]# docker network inspect noah_net |grep -A1 Subnet "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" ``` 2. 创建自定义网段的bridge网络 ```sh docker network create --driver bridge \ --subnet 192.168.4.0/24 \ --gateway 192.168.4.1 \ noah_net2 [root@docker01 ~]# docker network inspect noah_net2 |grep -A1 Subnet "Subnet": "192.168.4.0/24", "Gateway": "192.168.4.1" ``` 3. 使用自定义网络创建容器 以上两个自定义网络创建好以后,创建容器时只要指定--network=xxx,就可以使用新的bridge网络了. 使用`--subnet`创建的网络,还可以通过--ip手动分配IP,非`--subnet`参数创建的网络不能手动分配IP,会报错 ```sh [root@docker01 ~]# docker run -it --rm --network=noah_net busybox ip addr|grep "172" inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0 [root@docker01 ~]# docker run -it --rm --network=noah-net2 --ip 192.168.4.99 busybox ip addr|grep "192" inet 192.168.4.99/24 brd 192.168.4.255 scope global eth0 ``` ### C. bridge网络之间通信 先说结论: * 相同bridge网络下的容器互相之间可以通过IP通信 * 不同bridge网络下的容器互相之间不能通过IP通信 * 不同bridge网络之间不能通过添加路由解决通信问题 * iptables DROP 掉了不同bridge网络间的通信 基于以上原因,要解决不同bridge网络之间的通信问题,常用的解决办法就是为容器配置多个bridge的网卡,通过`docker network connect` 命令实现。 ```sh docker run -d --name bbx1 --network=noah_net busybox sleep 900 docker network connect noah-net2 bbx1 [root@docker01 ~]# docker exec -it bbx1 ip a|grep inet inet 127.0.0.1/8 scope host lo inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0 inet 192.168.4.2/24 brd 192.168.4.255 scope global eth1 [root@docker01 ~]# docker exec -it bbx1 ping -c1 192.168.4.1 PING 192.168.4.1 (192.168.4.1): 56 data bytes 64 bytes from 192.168.4.1: seq=0 ttl=64 time=0.192 ms ``` --- ## 四 macvlan网络 ### A. 什么是macvlan: macvlan 本质上是一种网卡虚拟化技术 macvlan 本身是 linux kernel 模块,允许在同一个物理网卡上配置多个 MAC 地址,即多个 interface,每个 interface 可以配置自己的 IP。 使用macvlan可以实现容器跨主机通信: ### B. 创建macvlan: 首先需要再开一台虚拟机,创建好docker环境,然后两台机器都执行下列命令 ``` docker network create --driver macvlan --subnet 10.0.0.0/24 --gateway 10.0.0.254 -o parent=eth0 macvlan_1 ``` >说明:docker不会为macvlan创建网关,所以这里的网关要事先存在 macvlan最好自己手动管理IP地址,不要自动分配,容易IP冲突 两台docker主机上分别创建容器测试: 1. docker01: `docker run -it --network macvlan_1 --ip=10.0.0.111 busybox:latest /bin/sh ` 2. docker02: `docker run -it --network macvlan_1 --ip=10.0.0.112 busybox:latest /bin/sh ` ## 五 overlay网络 overlay网络是基于 VxLAN 的 隧道网络,VxLAN 可将二层数据封装到 UDP 进行传输,VxLAN 提供与 VLAN 相同的以太网二层服务,但是拥有更强的扩展性和灵活性。 不同overlay网络是互相隔离的,要相互通信的话,也是需要把容器加入多个网络才行. Docerk overlay 网络需要一个 key-value 数据库用于保存网络状态信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都支持,这里使用 Consul。 ### A. 环境准备工作 1. 分别修改docker配置文件 docker01、02上都增加如下配置在daemon.json文件中 ```sh vim /etc/docker/daemon.json { "cluster-store": "consul://10.0.0.11:8500", "cluster-advertise": "10.0.0.12:2376" } systemctl daemon-reload systemctl restart docker # cluster-store是consul的地址 # cluster-advertise是自己的地址 ``` 2. docker01上运行consul ```sh docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap ``` 运行成功后,可以访问consul的web页:http://10.0.0.11:8500/ui/#/dc1/kv/ ### B. overlay网络功能测试 1. 创建overlay网络(任意主机) 由于overlay信息会写入数据库,所以在docker02上创建overlay网络,docker01上是可以看到的 ```sh [root@docker02 ~]# docker network create -d overlay olay-1 [root@docker01 ~]# docker network ls|grep olay-1 bda0ae8345d8 olay-1 overlay global [root@docker01 ~]# docker network inspect olay-1|grep -A1 Subnet "Subnet": "10.0.1.0/24", "Gateway": "10.0.1.1" ``` 2. 启动容器测试 ```sh [root@docker01 ~]# docker run --rm --network olay-1 busybox ip a s|grep inet inet 127.0.0.1/8 scope host lo inet 10.0.1.2/24 brd 10.0.1.255 scope global eth0 inet 172.19.0.2/16 brd 172.19.255.255 scope global eth1 [root@docker02 ~]# docker run --rm --network olay-1 busybox ip a s|grep inet inet 127.0.0.1/8 scope host lo inet 10.0.1.2/24 brd 10.0.1.255 scope global eth0 inet 172.18.0.2/16 brd 172.18.255.255 scope global eth1 ``` 3. 测试结果说明 上面的结果中,每个容器都分别有eth0和eth1两个网卡,其中eth0属于overlay网络,用于跨主机通信,eth1用于与宿主机通信 overlay网络支持docker dns server,支持使用容器名进行通信 ### B. overlay IPAM docker 默认为 overlay 网络分配 24 位掩码的子网(10.0.X.0/24),所有主机共享这个 subnet,容器启动时会顺序从此空间分配 IP。当然我们也可以通过`--subnet`指定 IP 空间。 ``` docker network create -d overlay --subnet 10.22.1.0/24 ov_net3 ```