一、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