docker(7、容器网络6) weave 网络 Weave 跨主机的连通和隔离特性

weave 是 Weaveworks 开发的容器网络解决方案。weave 创建的虚拟网络可以将部署在多个主机上的容器连接起来。对容器来说,weave 就像一个巨大的以太网交换机,所有容器都被接入这个交换机,容器可以直接通信,无需 NAT 和端口映射。除此之外,weave 的 DNS 模块使容器可以通过 hostname 访问。https://www.weave.works/docs/cloud/latest/install/installing-agents/#weave-cloud

介绍

Weave在Docker主机之间实现Overlay网络,使用业界标准VXLAN封装,基于UDP传输,也可以加密传输。 Weave Net创建一个连接多个Docker主机的虚拟网络,类似于一个以太网交换机,所有的容器都连接到这上面,互相通信。 Weave Net由多个peer组成,Weave路由器运行不同Docker主机上,是一个用户空间的进程;每个peer都有一个名称,重启保持不变。它们通过TCP连接彼此,建立后交换拓扑信息。 Weave Net可以在具有编号拓扑的部分连接的网络中路由数据包。

特点

# IP地址管理(IPAM)
Weave自动为容器分配唯一的IP地址。可通过weave ps查看
# 命名和发现
命名的容器自动会注册到Weave DNS中,并可以通过容器名称访问。
注:weave自己维护了一个微型的dns服务器。可以实现主机名通信。
# 负载均衡
允许注册多个相同名称的容器,Weave DNS随机为每个请求返回地址,提供基本的负载均衡功能。
注:如果访问容器名相同,则会自动轮询访问该容器,实现负载均衡。
# 手动指定IP地址
docker run –it –e WEAVE_CIDR=10.32.0.100/24 busybox
# 动态拓扑
可以在不停止或重新配置剩余Docker主机的情况下添加主机到Weave网络中或从Weave网络中删除
# 容错
weave peer不断交换拓扑信息,监视和建立与其他peer的网络连接。如果有主机或网络出现故障,Weave会绕过这个主机,保证两边容器可以继续通信,当恢复时,恢复完全连接

Docker Weave 工作原理

网卡设备
Container eth0:      eth0是容器主机的默认网络,主要提供容器访问外网所提供的服务,走的默认docker网络架构,只不过他创建了docker_gwbridge这个网桥。
docker_gwbridge:     docker_gwbridge是容器所创建的网桥它替代了docker0的服务。
Contailner ethwe:    它是veth pair虚拟设备对,与其他容器通信的网络虚拟网卡。
vethwe-bridge:       是ethwe设备对创建的weave网桥。网桥内分配的具体的IP与网关。
weave:               weave网桥,通过route路由表找到目标,通过端口将数据包转发到对端端口节点。
eth0:                真机网卡与外界网卡连接得真机网卡,它用来转发,容器VXLAN与NAT两种网卡类型的数据包到指定的对端节点。
注:weave会将相邻的节点互相学习,通过route路由表进行相互通信,并通过单独的端口发送数据。类似于静态路由。

Contailner ethwe 发送数据包到对端容器通信

1、ethwe 会将数据包发送给vethwe-bridge网桥。
2、vethwe-bridge接收到数据包后由weave去处理这个数据,通过UDP6783数据端口依照weave的路由表转发到下一路由节点。
3、如果该节点就是目的地,本地weave会把信息转发到内核的TCP协议站,再转发到目的节点。

实验环境描述

weave 不依赖分布式数据库(例如 etcd 和 consul)交换网络信息,每个主机上只需运行 weave 组件就能建立起跨主机容器网络。我们会在 host1 和 host2 上部署 weave 并实践 weave 的各项特性

Weave不需要集中式的key-value存储,所以安装和运行都很简单。直接把Weave二进制文件下载到系统中就可以了

192.168.1.122   部署docker  weave           主机名:host1 
192.168.1.123 部署docker  weave           主机名:host2


 

 

1、设置主机名及绑定hosts
[root@host1 ~]# hostnamectl --static set-hostname  host1
2、关闭防火墙
[root@host1 ~]# systemctl disable firewalld.service
[root@host1 ~]# systemctl stop firewalld.service
3、安装docker
[root@host1 ~]# yum install -y docker
[root@host1 ~]# systemctl daemon-reload && systemctl start docker      #启动docker
[root@host1 ~]# chkconfig docker on         #加入开机启动
4、下载weave 到/usr/local/bin/weave
[root@host1 ~]# curl -L git.io/weave -o /usr/local/bin/weave
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
100   595  100   595    0     0    217      0  0:00:02  0:00:02 --:--:--  581k
100 52227  100 52227    0     0  13476      0  0:00:03  0:00:03 --:--:--  112k
5、赋予权限/usr/local/bin/weave
[root@host1 ~]# chmod a+x /usr/local/bin/weave  
6、启动weave
###host1上启动wave,wave组建以容器方式运行
[root@host1 ~]# weave launch 
2.6.2: Pulling from weaveworks/weave
Digest: sha256:6f6839774ca225076116790145a415fa99706133310bcf7a56ce29fd89c245d3
Status: Downloaded newer image for weaveworks/weave:2.6.2
docker.io/weaveworks/weave:2.6.2
latest: Pulling from weaveworks/weavedb
72bf8a6af285: Pull complete 
Digest: sha256:7badb003b9c0bf5c51bf801be2a4d5d371f0738818f9cbe60a508f54fd07de9a
Status: Downloaded newer image for weaveworks/weavedb:latest
docker.io/weaveworks/weavedb:latest
Unable to find image 'weaveworks/weaveexec:2.6.2' locally
2.6.2: Pulling from weaveworks/weaveexec
Digest: sha256:a28b3c098a049d923fb08231a1bba22e6d57c83710257e41220c28ffccb2d66c
Status: Downloaded newer image for weaveworks/weaveexec:2.6.2
217ed2e604a7e2c5f9ab5d2557c088ccb0b41d23df6373152cd1ce5eb047
7、weave组建以容器方式运行
[root@host1 ~]# docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS               NAMES                            bbox1
217ed2e604a7        weaveworks/weave:2.6.2   "/home/weave/weaver …"   12 hours ago        Up 12 hours                             weave
[root@host1 ~]# 

8、weave 会创建一个新的 Docker 网络 weave

[root@host1 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
3be562ae8342        bridge              bridge              local
8a47585430f3        host                host                local
14925807ce29        none                null                local
5d669a4aaa5e        weave               weavemesh           local   #weave网络
[root@host1 ~]# 

9、查看weave网络地址段

driver 为 weavemesh,IP 范围 10.32.0.0/12

[root@host1 ~]# docker network inspect 5d669a4aaa5e
[
    {
        "Name": "weave",
        "Id": "5d669a4aaa5e80345d2b341aa436bc777b80ad5b292bef107fe378292b361407",
        "Created": "2020-03-12T18:54:23.262355683-04:00",
        "Scope": "local",
        "Driver": "weavemesh",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "weavemesh",
            "Options": null,
            "Config": [
                {
                    "Subnet": "10.32.0.0/12"  #weave地址段
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {},
        "Options": {
            "works.weave.multicast": "true"
        },
        "Labels": {}
    }
]
[root@host1 ~]#

10 在host1上运行容器

[root@host1 ~]# weave env
export DOCKER_HOST=unix:///var/run/weave/weave.sock
#将命令发给weave proxy,如果不需要了执行:# eval $(weave env --restore)
[root@host1 ~]# eval $(weave env)
[root@host1 ~]# docker run -itd  --name bbox1 busybox
d0a4d7c482ed69ee920f97cd809e978e3813d2e5f76c3c3e343361f7f9840c89
[root@host1 ~]# 

首先执行 eval $(weave env) 很重要,其作用是将后续的 docker 命令发给 weave proxy 处理。如果要恢复之前的环境,可执行 eval $(weave env --restore)

11、容器网络分析

查看host1上容器bbox1的ip

查看一下当前容器 bbox1 的网络配置:

[root@host1 ~]#  docker exec -it  bbox1 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0   #默认连接docker0的bridge网络
       valid_lft forever preferred_lft forever        
26: ethwe@if27: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1376 qdisc noqueue 
    link/ether ee:96:74:3b:d3:00 brd ff:ff:ff:ff:ff:ff
    inet 10.32.0.1/12 brd 10.47.255.255 scope global ethwe    #连接到主机的weave网络接口
       valid_lft forever preferred_lft forever
[root@host1 ~]# 

bbox1 有两个网络接口 eth0 和 ethwe,其中 eth0 连接的是默认 bridge 网络,即网桥 docker0。

现在我们重点分析 ethwe。从命名和分配的 IP 10.32.0.1/12 可以猜测 ethwe 与 weave 相关,ethwe@if27 告诉我们与 ethwe 对应的是编号 27 的 interface。从 host1 的 ip link 命令输出中找到该 interface:

[root@host1 ~]#  ip link show
.........
27: vethwepl8618@if26: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue master weave state UP mode DEFAULT group default 
    link/ether a6:39:fa:a4:a4:74 brd ff:ff:ff:ff:ff:ff link-netnsid 2  #这个接口是与容器相连的接口
[root@host1 ~]# 

 vethwepl8618@if26 与 ethwe 是一对 veth pair,而且  vethwepl8618 挂在 host1 的 Linux bridge weave 上。

[root@host1 ~]# brctl show
bridge name	bridge id		STP enabled	interfaces
docker0		8000.024286810522	no		veth24ed3f2
weave		8000.0e8e2735b12c	no		vethwe-bridge
							vethwepl8618

除了 ethwepl8618 ,weave 上还挂了一个 vethwe-bridge,这是什么?让我们更深入的分析一下,查看 ip -d link 输出:

这里出现了多个新 interface: 
① vethwe-bridge 与 vethwe-datapath 是 veth pair。 
② vethwe-datapath 的父设备(master)是 datapath。 
③ datapath 是一个 openvswitch。 
④ vxlan-6784 是 vxlan interface,其 master 也是 datapath,weave 主机间是通过 VxLAN 通信的。

weave 网络包含两个虚拟交换机:Linux bridge weave 和 Open vSwitch datapath,veth pair vethwe-bridge 和 vethwe-datapath 将二者连接在一起。
weave 和 datapath 分工不同,weave 负责将容器接入 weave 网络,datapath 负责在主机间 VxLAN 隧道中并收发数据。

host1上运行第二个容器 在bbox1 ping bbox2 支持dns name

[root@host1 ~]# docker run --name bbox2 -itd busybox
61d93aa29198d445ac454ef02487f703febb7644079943a909ebac577b0cb591
[root@host1 ~]#  docker exec -it  bbox1 ping -c 4 bbox2
PING bbox2 (10.32.0.2): 56 data bytes
64 bytes from 10.32.0.2: seq=0 ttl=64 time=0.244 ms
64 bytes from 10.32.0.2: seq=1 ttl=64 time=0.084 ms
^C
--- bbox2 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.084/0.164/0.244 ms

当前 host1 网络结构为:

 

Weave 跨主机的连通和隔离特性

host2安装weave

1、设置主机名及绑定hosts
[root@host2 ~]# hostnamectl --static set-hostname  host2
2、关闭防火墙
[root@host2 ~]# systemctl disable firewalld.service
[root@host2 ~]# systemctl stop firewalld.service
3、安装docker
[root@host2 ~]# yum install -y docker
[root@host2 ~]# systemctl daemon-reload && systemctl start docker      #启动docker
[root@host2 ~]# chkconfig docker on         #加入开机启动
4、下载weave 到/usr/local/bin/weave
[root@host1 ~]# curl -L git.io/weave -o /usr/local/bin/weave
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
  0     0    0     0    0     0      0      0 --:--:--  0:00:01 --:--:--     0
100   595  100   595    0     0    217      0  0:00:02  0:00:02 --:--:--  581k
100 52227  100 52227    0     0  13476      0  0:00:03  0:00:03 --:--:--  112k
5、赋予权限/usr/local/bin/weave
[root@host2 ~]# chmod a+x /usr/local/bin/weave  

6、启动weave
###host2上启动wave,启动weave指向host1的weave:wave组建以容器方式运行 

这里必须指定 host1 的 IP 192.168.1.122,这样 host1 和 host2 才能加入到同一个 weave 网络。

[root@host2 ~]# weave launch 192.168.1.122
2.6.2: Pulling from weaveworks/weave
Digest: sha256:6f6839774ca225076116790145a415fa99706133310bcf7a56ce29fd89c245d3
Status: Downloaded newer image for weaveworks/weave:2.6.2
docker.io/weaveworks/weave:2.6.2
latest: Pulling from weaveworks/weavedb
72bf8a6af285: Pull complete 
Digest: sha256:7badb003b9c0bf5c51bf801be2a4d5d371f0738818f9cbe60a508f54fd07de9a
Status: Downloaded newer image for weaveworks/weavedb:latest
docker.io/weaveworks/weavedb:latest
Unable to find image 'weaveworks/weaveexec:2.6.2' locally
2.6.2: Pulling from weaveworks/weaveexec 
Digest: sha256:a28b3c098a049d923fb08231a1bba22e6d57c83710257e41220c28ffccb2d66c
Status: Downloaded newer image for weaveworks/weaveexec:2.6.2
a85d5a20516466b6e2c5f9ab5d2557c088ccb0b41d23df6373152cd1ce5eb047
[root@host2 ~]# docker  ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS               NAMES
a85d5a205164        weaveworks/weave:2.6.2   "/home/weave/weaver …"   13 seconds ago      Up 13 seconds                           weave
[root@host2 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
22c93b1df59e        bridge              bridge              local
e75a72e83f90        host                host                local
ac72879f7ab4        none                null                local
0fdf77b12596        weave               weavemesh           local

在host2上运行容器 bbox3:


[root@host2 ~]# eval $(weave env)
[root@host2 ~]# docker run --name bbox3 -itd busybox
Unable to find image 'busybox:latest' locally
latest: Pulling from library/busybox
0669b0daf1fb: Pull complete 
Digest: sha256:b26cd013274a657b86e706210ddd5cc1f82f50155791199d29b9e86e935ce135
Status: Downloaded newer image for busybox:latest
0a0a544571db1c036f83cb46f42a09e5643a35ad4d5f4ac70a6d30a551045fce
[root@host2 ~]# docker exec bbox3 ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue 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
12: eth0@if13: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
14: ethwe@if15: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1376 qdisc noqueue 
    link/ether 46:eb:01:77:ba:1d brd ff:ff:ff:ff:ff:ff
    inet 10.44.0.0/12 brd 10.47.255.255 scope global ethwe   
       valid_lft forever preferred_lft forever

weave 网络连通性

bbox3 能够直接 ping bbox1 和 bbox2。

bbox1、bbox2 和 bbox3 的 IP 分别为 10.32.0.1/12、10.32.0.2/12 和 10.44.0.0/12,注意掩码为 12 位,实际上这三个 IP 位于同一个 subnet 10.32.0.0/12。通过 host1 和 host2 之间的 VxLAN 隧道,三个容器逻辑上是在同一个 LAN 中的,当然能直接通信了。bbox3 ping bbox1 的数据流向如下图所示:

① 数据包目的地址为 10.32.0.1,根据 bbox3 的路由表,数据从 ethwe 发送出去。

② host2 weave 查询到目的地主机,将数据通过 VxLAN 发送给 host1。

③ host1 weave 接受到数据,根据目的 IP 将数据转发给 bbox1。

weave 网络隔离

默认配置下,weave 使用一个大 subnet(例如 10.32.0.0/12),所有主机的容器都从这个地址空间中分配 IP,因为同属一个 subnet,容器可以直接通信。如果要实现网络隔离,可以通过环境变量 WEAVE_CIDR 为容器分配不同 subnet 的 IP,举例如下:

[root@host1 ~]# docker run -e WEAVE_CIDR=net:10.32.2.0/24 -itd --name bbox4 busybox
ec3f37554696cf51b88740e11942f3f86a0244adea52f1b8438ed7c5eade85f0

[root@host1 ~]# docker exec bbox4 ip r
default via 172.17.0.1 dev eth0 
10.32.2.0/24 dev ethwe scope link  src 10.32.2.1 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.4 
224.0.0.0/4 dev ethwe scope link 

[root@host1 ~]# docker exec bbox4 ping -c 4 bbox1
PING bbox1 (10.32.0.1): 56 data bytes

--- bbox1 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
[root@host1 ~]# 

 WEAVE_CIDR=net:10.32.2.0/24 的作用是使容器分配到 IP 10.32.2.2由于 10.32.0.0/12 与 10.32.2.0/24 位于不同的 subnet,所以无法 ping 到 bbox1

除了 subnet,我们还可以直接为容器分配特定的 IP:

[root@host1 ~]# docker run -e WEAVE_CIDR=ip:10.32.6.6/24 -itd --name bbox5  busybox
036e2885c5eeedd202b2b023035f3cc4d5ebbb1c0a5d42d80361ff7468eeb59f
[root@host1 ~]# docker exec bbox5 ip r
default via 172.17.0.1 dev eth0 
10.32.6.0/24 dev ethwe scope link  src 10.32.6.6 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.5 
224.0.0.0/4 dev ethwe scope link 
[root@host1 ~]# docker exec bbox5 ping -c 4 bbox1
PING bbox1 (10.32.0.1): 56 data bytes

--- bbox1 ping statistics ---
4 packets transmitted, 0 packets received, 100% packet loss
[root@host1 ~]# 

10.32.0.0/12 与 10.32.6.6/24 位于不同的 subnet,所以无法 ping 到 bbox1

Weave 与外网通信

  1. 首先将主机加入到 weave 网络。

  2. 然后把主机当作访问 weave 网络的网关。

要将主机加入到 weave,执行 weave expose

[root@host1 ~]# weave expose
10.32.0.3
[root@host1 ~]# 

这个 IP 10.32.0.3 会被配置到 host1 的 weave 网桥上

[root@host1 ~]# ip a  show weave 
6: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP group default qlen 1000
    link/ether 0e:8e:27:35:b1:2c brd ff:ff:ff:ff:ff:ff
    inet 10.32.0.3/12 brd 10.47.255.255 scope global weave
       valid_lft forever preferred_lft forever
    inet6 fe80::c8e:27ff:fe35:b12c/64 scope link 
       valid_lft forever preferred_lft forever
[root@host1 ~]# 

weave 网桥位于 root namespace,它负责将容器接入 weave 网络。给 weave 配置同一 subnet 的 IP 其本质就是将 host1 接入 weave 网络。 host1 现在已经可以直接与同一 weave 网络中的容器通信了,无论容器是否位于 host1。

在 host1 中 ping 同一主机的 bbox1(10.32.0.1):

 ping host2 上的 bbox3(10.44.0.0):

接下来要让其他非 weave 主机访问到 bbox1 和 bbox3,只需将网关指向 host1。例如在 192.168.1.101 上添加如下路由:

例如一台新的机器上添加   ip route add 10.32.0.0/12 via 192.168.1.104  

 

通过上面的配置我们实现了外网到 weave 这个方向的通信,反方向呢?

其实答案很简单:因为容器本身就挂在默认的 bridge 网络上,docker0 已经实现了 NAT,所以容器无需额外配置就能访问外网。

IPAM

10.32.0.0/12 是 weave 网络使用的默认 subnet,如果此地址空间与现有 IP 冲突,可以通过 --ipalloc-range 分配特定的 subnet。

weave launch --ipalloc-range 10.2.0.0/16

不过请确保所有 host 都使用相同的 subnet。

weave --help  #查看帮助
weave ps #查看weave路由状态:weave ps
weave connect  OTHER_HOST  #可以把一台主机连接到weave网络
weave attach #动态添加网络对于不是通过weave启动的容器,可以通过weave attach 10.0.1.1/24  $ContainerId来添加网络(weave  detach删除网络)
weave expose #不使用docker的原生网络容器和宿主机之间是无法互通的 , weave expose ip/24这个命令会把宿主机加入到weave 网络中, 宿主机就可以和容器之间自由通信了
weave launch -password #安全性:可以通过weave launch -password wEaVe设置一个密码用于weave peers之间加密通信

例如 weave ps

[root@host1 ~]# weave ps
weave:expose 0e:8e:27:35:b1:2c 10.32.0.3/12
036e2885c5ee 5a:e8:2a:bb:b8:b0 10.32.6.6/24
ec3f37554696 e2:7b:d0:be:ef:dd 10.32.2.1/24
0e626d17939b 72:1e:81:47:20:b0 10.32.0.2/12
1ccdad419a19 72:d6:1d:15:3b:99 10.32.0.1/12

1.eval $(weave env) 将docker命令代理给weave 执行,(如果先执行这个, docker命令启动的容器就会被自动加入weave网络,并自动分配IP)
2.docker run -d --rm nginx (正常启动容器)
如果没有执行步骤一直接启动的docker容器是不能自动加入到weave网络中的, 可以使用下列命令添加到weave网络

  • weave attach IP/24 ContainerId #将容器加入到weave网络并分配指定IP(24为网络地址范围,决定了该网络中最多可以有多少台计算机)
  • weave attach ContainerId IP #将容器加入到weave网络并自动分配IP
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章