一、Docker覆盖网络-简介¶
Docker提供了原生覆盖网络的支持,易于配置且非常安全。其背后是基于Libnetwork以及相应的驱动来创建的。 1、Libnetwork 2、驱动 Libnetwork是CNM的典型实现,从而可以通过插拔驱动的方式来实现不同的网络技术和拓扑结构。Docker提供了一些诸如Overlay的原生驱动,同时第三方也可以提供驱动。
二、Docker覆盖网络-详解¶
2.1 在Swarm模式下构建并测试Docker覆盖网络¶
2.1.1 环境介绍¶
两台Docker主机通过一个路由器上两个独立的二层网络连接在一起。节点位于不同网络之上。
| 主机名称 | 主机IP | 操作系统 |
|---|---|---|
| mgr1 | 192.168.101.130 | ubuntu 20.04 |
| wok1 | 192.168.100.110 | centos7.9 |
2.1.2 准备工作¶
2.1.2.1 开放端口 两台Linux主机需要开放以下端口: 1.2377/tcp 用于客户端与Swarm进行安全通信 2.7946/tcp和7946/udp 用于节点之间的通信 3.4789/udp 用于基于VXLAN的覆盖网络
Centos7主机开放端口,可参考Centos7如何开放指定端口 Ubuntu20.04主机开放端口,可参考Ubuntu20.04如何开放指定端口
2.1.2.2 Docker引擎 两台Linux主机安装好Docker引擎,可参考基于Ubuntu版本和Centos版本Docker 引擎(Engine)升级。
2.1.3 操作步骤¶
2.1.3.1 构建Swarm 1、在mgr1上执行docker swarm init命令使其成为管理节点。
root@zq-virtual-machine:~# docker swarm init --advertise-addr=192.168.101.130 --listen-addr=192.168.101.130:2377
Swarm initialized: current node (j8sjwc4bhuwwtnul5h0grscdj) is now a manager.
针对上面指令分解说明: * docker swarm init:通知Docker初始化一个新的Swarm,并将自身作为第一个管理节点,同时这个节点开启Swarm模式 * --advertise-addr:指定其他节点用来连接到当前管理节点的IP和端口。这是为了防止节点有多个IP不能确认 * --listen-addr:指定用于承载Swarm流量的IP和端口,这也是为了防止节点有多个IP不能确认
说明:Swarm模式下的操作默认运行2377端口!!! 2、如果mgr1在其他swarm群组里面,可执行docker swarm leave --force命令离开swarm集群
root@zq-virtual-machine:~# docker swarm leave --force
Node left the swarm.
3、执行docker info命令查看 swarm 的当前状态。观察到Swarm状态为active。
Swarm: active
NodeID: j8sjwc4bxxxxx0grscdj
Is Manager: true
ClusterID: bmcelide41o4x893kmf63spkc
Managers: 1
Nodes: 2
Default Address Pool: 10.0.0.0/8
SubnetSize: 24
Data Path Port: 4789
Orchestration:
Task History Retention Limit: 5
4、执行docker node ls命令列出Swarm中的节点。MANAGER一栏中显示【Leader】代表管理节点。
root@zq-virtual-machine:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
j8sjwxxxxxxxx0grscdj * zq-virtual-machine Ready Active Leader 20.10.18
说明:节点ID后面的【*】代表此时登录的节点!!!
5、在wok1执行docker swarm join命令添加工作节点
[root@localhost ~]# docker swarm join --token SWMTKN-1-4x6rei285kc2z038dwjm2xmxmuwjhi3qjzxxxxxxxxwvpqa-7ntsclbzx0uqvzncxnx7b39y4 192.168.100.130:2377
This node joined a swarm as a worker.
6、至此包含一个管理节点和一个工作节点的Swarm集群搭建完成。
root@zq-virtual-machine:~# docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
s1yjh999exxxxxxtuv0pj localhost.localdomain Ready Active 20.10.18
j8sjwc4bhxxxxxxl5h0grscdj * zq-virtual-machine Ready Active Leader 20.10.18
2.1.3.2 创建新的覆盖网络 1、在mgr1上执行docker network create -d overlay local-net命令创建一个名为local-net的覆盖网络。其中-d参数用于指定网络类型。
root@zq-virtual-machine:~# docker network create -d overlay local-net
fvuob6mb0g87rhov9fs63a0ec
2、在mgr1上继续执行docker network ls命令列出每个节点上的网络,这里观察到,名为local-net的覆盖网络已成功创建。
root@zq-virtual-machine:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
eafc7ec94e88 bridge bridge local
eb02f21bbab7 docker_gwbridge bridge local
0692b1905fd1 host host local
lvlni52grahq ingress overlay swarm
fvuob6mb0g87 local-net overlay swarm
3、在wok1执行docker network ls命令列出每个节点上的网络,观察到无法看到名为local-net的覆盖网络。这是因为只有当运行中的容器连接到覆盖网络的时候,网络才会变为可用状态。
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f72d8bd25765 bridge bridge local
8e3f74e2f68e docker_gwbridge bridge local
81ab398335fd host host local
lvlni52grahq ingress overlay swarm
a2cf1b22d749 localnet bridge local
2bc306370a20 none null local
2.1.3.3 将服务连接到新的覆盖网络 1、在mgr1上执行docker service create --name test --network local-net --replicas 2 alpine sleep infinity命令新建一个名为test的docker服务并接入到名为local-net的覆盖网络,其中Docker服务包含两个副本,一个运行在mgr1上,一个运行在wok1上。这样会自动将wok1节点接入local-net网络。
root@zq-virtual-machine:~# docker service create --name test --network local-net --replicas 2 alpine sleep infinity
u1dhiagmfca2n2mpbv326eebv
overall progress: 2 out of 2 tasks
1/2: running
2/2: running
verify: Service converged
针对上面指令分解说明: * docker service create:创建docker服务 * --name test:指定服务名称为test * --network local-net:指定网络类型为local-net * --replicas 2:指定创建两个副本(容器) * sleep infinity:通过sleep命令使docker容器保持运行状态
2、在mgr1上执行docker service ps test命令查看test服务
root@zq-virtual-machine:~# docker service ps test
ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
mei8...90z8j test.1 alpine:latest localhost.localdomain Running Running
ph4t...wkedz test.2 alpine:latest localhost.localdomain Running Running
3、在wok1上执行docker network ls命令查看wok1已自动接入local-net网络中。
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
fvuo...b0g87 local-net overlay swarm
2.1.3.4 测试覆盖网络 1、在mgr1上执行docker network inspect local-net命令查看被分配给覆盖网络的Subnet。观察到,local-net的子网是10.0.1.0/24。这里需要注意,这与两个节点的任意底层物理网络IP均不相符。
root@zq-virtual-machine:~# docker network inspect local-net
[
{
"Name": "local-net",
"Id": "fvuob6mb0g87rhov9fs63a0ec",
"Created": "2022-11-05T06:53:48.908331466Z",
"Scope": "swarm",
"Driver": "overlay",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "10.0.1.0/24",
"Gateway": "10.0.1.1"
}
]
},
...
...
2、在mgr1执行docker container ls命令获取容器ID
root@zq-virtual-machine:~# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
396c8b142a85 alpine:latest "sleep infinity" 2 hours ago Up2hrs
3、在mgr1执行docker container inspect 命令获取IP地址
root@zq-virtual-machine:~# docker container inspect --format='{{range .NetworkSettings.Networks}} {{.IPAddress}} {{end}}' 396c8b142a85
10.0.0.3
4、在wok1执行docker container ls命令获取容器ID
root@zq-virtual-machine:~# docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
222c8b142a85 alpine:latest "sleep infinity" 2 hours ago Up2hrs
5、在wok1执行docker container inspect 命令获取IP地址
root@zq-virtual-machine:~# docker container inspect --format='{{range .NetworkSettings.Networks}} {{.IPAddress}} {{end}}' 222c8b142a85
10.0.0.4
6、在mgr1上执行docker container exec -it 396c8b142a85 bash命令将Shell连接到一个运行中的容器终端。
root@zq-virtual-machine:~# docker container exec -it 396c8b142a85 bash
root@396c8b142a85:/#
7、在容器终端继续执行以下语句进行更新下载Ping工具包,这是因为ubuntu容器默认没有ping工具包,需要安装。
root@396c8b142a85:/# apt-get update
root@396c8b142a85:/# apt-get install iputils-ping
8、在容器终端继续执行ping语句检测是否连通。
root@396c8b142a85:/# ping 10.0.0.4
9、如果需要使用traceroute,则需要安装traceroute工具包
root@396c8b142a85:/# apt-get install iputils-tracepath
2.2 工作原理¶
2.2.1 VXLAN入门¶
VXLAN基于现有的三层IP网络创建了隧道,VXLAN隧道两端都是VXLAN隧道终端(VTEP),VTEP完成了封装和解压的步骤,以及一些功能实现所必需的操作。
2.2.2 通信示例¶
下面以两个容器间(C1和C2)的如何通信进行描述 1、C1发起Ping请求,目标IP为C2的地址10.0.0.4,请求流量通过连接到Br0虚拟交换机的veth接口发出。此时虚拟交换机不知道将包发送到哪里,因为虚拟交换机的MAC地址映射表(ARP映射表)中并没有与当前目的IP对应的MAC地址,所以虚拟机交换机会将该包发送到其上的全部端口。 2、连接到Br0的VTEP接口知道如何转发这个数据帧,所以会将自己的MAC地址返回。 3、虚拟交换机Br0根据返回结果学会了如何转发该包。虚拟交换机会更新自己的ARP映射表,将10.0.0.4映射到本地VTEP的MAC地址。 4、交换机将包转发到VTEP接口,VTEP完成数据帧的封装(把VXLAN Header信息添加以太帧中),这样在底层网络传输。
三、Docker覆盖网络-相关操作¶
3.1 创建网络¶
1、执行docker network create -d bridge localnet命令创建新的单机桥接网络,名为"localnet"。其中-d参数用于指定驱动(网络类型),-o encrypted对数据层进行加密
[root@localhost ~]# docker network create -d bridge localnet
1c731406ff136013a0aef3010053936511a9b6bc8f78b5ccdf329b76d1451503
2、执行docker network ls命令查看网络是否创建成功,这里观察到已成功创建成功
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
1c731406ff13 localnet bridge local
3.2 创建新容器并接入新建网络¶
1、执行docker container run -d --name c1 --network localnet alpine sleep 1d命令创建新容器c1并接入新建网络localnet
[root@localhost ~]# docker container run -d --name c1 --network localnet alpine sleep 1d
3.3 删除网络¶
1、执行docker network rm localnet命令删除名为localnet的网络
[root@localhost ~]# docker network rm localnet
localnet
2、执行docker network ls命令观察网络已删除
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
3.4 删除Docker主机未使用的网络¶
[root@localhost ~]# docker network prune
3.5 列出本地Docker主机网络¶
1、执行docker network ls命令列出运行在本地Docker主机上的全部网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f72d8bd25765 bridge bridge local
8e3f74e2f68e docker_gwbridge bridge local
81ab398335fd host host local
2bc306370a20 none null local
3.6 查看Docker网络详细配置¶
1、执行docker network inspect bridge命令提供Docker网络详细配置信息
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "f72d8bd257657c7a9ef682638a9f79c39dbf1b9fc947553f940b3634fc7eeb18",
"Created": "2022-11-05T08:53:34.516807186+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
3.7 查看docker0网桥¶
1、执行ip link show docker0命令查看docker0网络
[root@localhost ~]# ip link show docker0
6: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 02:42:8b:0f:97:d0 brd ff:ff:ff:ff:ff:ff
3.8 查看Linux网桥¶
1、执行brctl show命令使用brctl工具查看网桥,其中br-a2cf1b22d749与上述新建的网络localnet对应。
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
br-a2cf1b22d749 8000.0242bd03bc11 no
docker0 8000.02428b0f97d0 no
docker_gwbridge 8000.0242db9678df no
virbr0 8000.5254002fa5d0 yes virbr0-nic