Docker网络之Weave

目录

简介

  1. Weave是由weaveworks公司开发的解决Docker跨主机网络的解决方案,它能够创建一个虚拟网络,用于连接部署在多台主机上的Docker容器,这样容器就像被接入了同一个网络交换机,那些使用网络的应用程序不必去配置端口映射和链接等信息
  2. 外部设备能够访问Weave网络上的应用程序容器所提供的服务,同时已有的内部系统也能够暴露到应用程序容器上。Weave能够穿透防火墙并运行在部分连接的网络上,另外,Weave的通信支持加密,所以用户可以从一个不受信任的网络连接到主机。
  3. 对容器来说,weave 就像一个巨大的以太网交换机,所有容器都被接入这个交换机,容器可以直接通信,无需 NAT 和端口映射。除此之外,weave 的 DNS 模块使容器可以通过 hostname 访问
  4. weave 不依赖分布式数据库(例如 etcd 和 consul)交换网络信息,每个主机上只需运行 weave 组件就能建立起跨主机容器网络。但是同样也是其缺点:主机不能动态加入节点网络,只能手动通过weave launch或connect加入Weave网络。不支持动态分配IP,所有IP需要手动管理及分配,难以保证分配的IP不冲突。
  5. 项目地址:https://github.com/weaveworks/weave

weave网络通信模型

  1. weave通过在docker集群的每个主机上启动虚拟路由器,将主机作为路由器,形成互联互通的网络拓扑,在此基础上,实现容器的跨主机通信。其主机网络拓扑参见下图

    Docker网络之Weave

  2. 在每一个部署Docker的主机上都部署有一个W(即weave router,它本身也可以以一个容器的形式部署)。weave网络是由这些weave routers组成的对等端点(peer)构成,并且可以通过weave命令行定制网络拓扑。

  3. 每个部署了weave router的主机之间都会建立TCP和UDP两个连接,保证weave router之间控制面流量和数据面流量的通过。控制面由weave routers之间建立的TCP连接构成,通过它进行握手和拓扑关系信息的交换通信。控制面的通信可以被配置为加密通信。而数据面由weave routers之间建立的UDP连接构成,这些连接大部分都会加密。这些连接都是全双工的,并且可以穿越防火墙

  4. 当容器通过weave进行跨主机通信时,其网络通信模型可以参考下图。对每一个weave网络中的容器,weave都会创建一个网桥,并且在网桥和每个容器之间创建一个veth pair,一端作为容器网卡加入到容器的网络命名空间中,并为容器网卡配置ip和相应的掩码,一端连接在网桥上,最终通过宿主机上weave router将流量转发到对端主机上。

    Docker网络之Weave

  5. 基本过程

    • 容器流量通过veth pair到达宿主机上weave router网桥上。
    • weave router在混杂模式下使用pcap在网桥上截获网络数据包,并排除由内核直接通过网桥转发的数据流量,例如本子网内部、本地容器之间的数据以及宿主机和本地容器之间的流量。捕获的包通过UDP转发到所其他主机的weave router端。
    • 在接收端,weave router通过pcap将包注入到网桥上的接口,通过网桥的上的veth pair,将流量分发到容器的网卡上。weave默认基于UDP承载容器之间的数据包,并且可以完全自定义整个集群的网络拓扑,但从性能和使用角度来看,还是有比较大的缺陷的:
      • weave自定义容器数据包的封包解包方式,不够通用,传输效率比较低,性能上的损失也比较大。
      • 集群配置比较负载,需要通过weave命令行来手工构建网络拓扑,在大规模集群的情况下,加重了管理员的负担。
  6. 网卡设备

    • 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两种网卡类型的数据包到指定的对端节点。

安装

  1. Weave不需要集中式的key-value存储,直接安装即可

  2. 安装环境:

    • Linux内核3.8及以上
    • docker 1.10.0及以上
    • 节点之间如果有防火墙时,必须彼此放行TCP 6783UDP 6783/6784端口,这是Weave控制和数据端口。
    • 主机名不能相同
  3. 安装

    $ sudo curl -L https://git.io/weave -o /usr/local/bin/weave
    $ sudo chmod a+x /usr/local/bin/weave
    测试是否安装成功
    $ weave version
    weave script 2.8.1
    weave 2.8.1
    
  4. 初始化Weave网络

    1. 安装必备依赖
    $ yum install -y bridge-utils  net-tools
    2. 这条命令是在容器中运行一个weave router,需要在每台主机上都启用这个服务。
    该服务需要三个docker容器来辅助运行,首次运行时会自动下载相关镜像
    $ weave launch 或者使用weave setup 预加载镜像
    设置环境变量,这样通过docker命令行启动的容器就会自动地连接到weave网络中了。
    $ eval $(weave env)
    3. 查看下载并运行的容器
    $ docker ps
    weaveworks/weaveexec                 2.8.1     e02bec83a27c   7 months ago    71.2MB
    weaveworks/weave                     2.8.1     8de39aae7c4e   7 months ago    61.2MB
    weaveworks/weavedb                   latest    19661b1dbf28   8 months ago    698B
    
    4. 还会生成一个名字叫weave的网桥,docker0是默认的。查看桥接
    $ brctl show
    bridge name			bridge id					STP 	enabled	interfaces
    docker0					8000.02429362485b	no
    weave						8000.4231bec3cf76	no		vethwe-bridge
    
    $ ifconfig weave
    weave: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1376
            inet6 fe80::4031:beff:fec3:cf76  prefixlen 64  scopeid 0x20<link>
            ether 42:31:be:c3:cf:76  txqueuelen 1000  (Ethernet)
            RX packets 14  bytes 936 (936.0 B)
            RX errors 0  dropped 0  overruns 0  frame 0
            TX packets 7  bytes 634 (634.0 B)
            TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
            
    docker中也会生成一个使用weave的网桥的自定义网络。
    $ docker network ls
    docker network ls
    NETWORK ID     NAME      DRIVER      SCOPE
    3dbd79b0c831   bridge    bridge      local
    b31f13c07393   host      host        local
    bc7e4b7556c4   none      null        local
    468375b4740b   weave     weavemesh   local
    
    5. weave的数据保存在每台机器上分配的名为weavedb的容器上的,
    它是一个data volume容器,只负责数据的持久化。
    

连接不同主机

  1. 机器:关闭两台机器的防火墙,如果打开防火墙,需要开放6783端口

    主机名 IP地址 软件环境
    docker1 192.168.100.140 Weave、Docker
    Docker2 192.168.100.141 Weave、Docker
  2. 从docker1连接到docker2。只需要在weave launch后面跟上docker2主机的ip或者hostname就行了。两台机器就会自动建立集群,并同步所有需要的信息。

    1. 在docker1(192.168.100.140)上执行
    这个命令相当于在本地启动了weave route,再通过weave connect 192.168.100.141来
    和
    $ weave launch 192.168.100.141
    29d7b8b5740b71e065beb4fef1e86b904aa4e776a6c855b28aee6c270a5de3b9
    
    2. 在docker2(192.168.100.141)上执行
    $ weave launch 192.168.100.140
    
    3. 查看状态信息
    $ weave status
    
            Version: 2.8.1 (up to date; next check at 2021/09/21 17:04:19)
    
            Service: router
           Protocol: weave 1..2
               Name: fe:f7:46:79:0c:d7(docker1)
         Encryption: disabled
      PeerDiscovery: enabled
            Targets: 1
        Connections: 1 (1 established)           				# 建立连接
              Peers: 2 (with 2 established connections) # 2 表示有两个节点
     TrustedSubnets: none
    
            Service: ipam
             Status: ready
              Range: 10.32.0.0/12
      DefaultSubnet: 10.32.0.0/12
    
            Service: dns
             Domain: weave.local.
           Upstream: 192.168.100.2
                TTL: 1
            Entries: 6
    
            Service: proxy
            Address: unix:///var/run/weave/weave.sock
    
            Service: plugin (legacy)
         DriverName: weave
    
    4. 查看状态详情
    $ weave status connections
    
  3. 如果要连接新的主机

    $ weave connect $NEW_HOST
    
  4. 断开连接

    $ weave forget $HOST
    
  5. 停止

    $ weave stop
    

集成Docker

  1. Weave和Docker进行集成,以便运行的容器跑在Weave网络中。

    • 使用weave env命令修改DOKCER_HOST环境变量的值,使docker clientweave交互,weavedocker daemon交互,自动为容器配置网络,对用户透明。
    • 使用weave plugin,在运行容器的时候使用--net=weave参数。
  2. 方式一:使用weave env方式

    1. 配置Weave Net环境,以便通过Docker命令行启动的容器自动附加到Weave网络
    $ eval $(weave env)
    $ docker run -it --rm --name docker1-busybox busybox 
    $ docker run -it --rm --name docker1-busybox busybox 
    
  3. 方式二:使用weave plugin直接运行容器

    1. 在docker1上启动容器
    $ docker run -it --rm --net=weave --name docker1-busybox busybox 
    2. 在docker2上启动容器
    $ docker run -it --rm --net=weave --name docker2-busybox busybox 
    
    3. 可以在容器中看到,会多出一个网卡ethwe0
    docker1下
    $ ifconfig
    ...省略...
    ethwe0    Link encap:Ethernet  HWaddr 7E:CA:30:FC:3E:8B  
              inet addr:10.40.0.0  Bcast:10.47.255.255  Mask:255.240.0.0
              UP BROADCAST RUNNING MULTICAST  MTU:1376  Metric:1
              RX packets:16 errors:0 dropped:0 overruns:0 frame:0
              TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:1244 (1.2 KiB)  TX bytes:798 (798.0 B)
    ...省略...
    
    docker2下
    $ ifconfig
    ...省略...
    ethwe0    Link encap:Ethernet  HWaddr C2:97:2B:BF:7E:A2  
              inet addr:10.32.0.1  Bcast:10.47.255.255  Mask:255.240.0.0
              UP BROADCAST RUNNING MULTICAST  MTU:1376  Metric:1
              RX packets:17 errors:0 dropped:0 overruns:0 frame:0
              TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
              collisions:0 txqueuelen:0 
              RX bytes:1342 (1.3 KiB)  TX bytes:798 (798.0 B)
    ...省略...
    
  4. 默认情况下不会使用weave的DNS,故不能用容器名进行访问。如果要使用容器主机名,可按以下方法:

    如果创建容器时指定了--name参数,在注册DNS时还是以hostname优先。
    $ docker run -it --rm --net=weave --name docker1-busybox -h c1.weave.local $(weave dns-args)  busybox 
    $ docker run -it --rm --net=weave --name docker2-busybox -h c2.weave.local $(weave dns-args)  busybox
    
    在docker中以下方式都可以通
    ping c1
    ping c2
    ping docker1-busybox
    ping docker2-busybox
    
    在宿主机查看
    $ weave dns-lookup c1.weave.local
    10.40.0.0
    $  weave dns-lookup c2.weave.local
    10.32.0.1
    
  5. 查看local domain

    $ weave status
    ...省略...
     Service: dns
      Domain: weave.local.
    Upstream: 192.168.100.2
         TTL: 1
     Entries: 4
    ...省略...
    
  6. 修改local domain

    $ weave launch --dns-domain="cluster.local."
    
  7. 可以通过DNS提供负载均衡

    1. 启动多个容器(c2.weave.local)
    $ docker run --net=weave --rm  --name docker21-busybox -h c2.weave.local $(weave dns-args) -ti busybox
    
    $ weave dns-lookup c2.weave.local
    10.32.0.1
    10.32.0.2
    

技巧

  1. IP手动分配:Weave会保证容器ip都是唯一的,并且自动负责容器ip的分配和回收,你不需要配置任何东西就能得到这个好处。如果对分配有特定需求也是可以自定义分配ip网段的。weave默认使用的网段是10.32.0.0/12,也就是从10.32.0.010.47.255.255。如果这个网段已经被占用,Weave就会报错,这个时候可以使用--ipalloc-range参数手动指定Weave要使用的网段

    $ weave launch --ipalloc-range 10.60.0.0/12
    
  2. 网络隔离:默认情况下,所有的容器都在同一个子网,不过可以通过--ipalloc-default-subnet指定分配的子网(子网必须在可分配网段里)。如果要实现容器网络的隔离,而不是集群中所有容器都能互相访问。Weave可以使用子网实现这个功能,同一个子网的容器互相连通,而不同的子网中容器是隔离的。一个容器可以在多个子网中,通过和多个网络里的容器互连。docker允许同一个机器上的容器互通,为了完全隔离,需要在docker daemon启动参数添加上 --icc=false

    $ weave launch --ipalloc-default-subnet 10.40.0.0/24 192.168.2.210
    
  3. 指定特定的IP地址

    • 通过设置环境变量

      $ eval $(weave env)
      $ docker run -e WEAVE_CIDR=10.35.1.1/24 --name c3 -it busybox sh
      /# ifconfig
      
    • 通过weave run命令实现

      $ weave run 10.36.1.1/24 --name c4 -it busybox sh
      $ docker exec -it c4 sh
      
    • 动态分配网络:如果在运行容器的时候还不能确定网络,可以使用-e WEAVE_CIDR=none参数先不分配网络信息。

      $ eval $(weave env)
      $ docker run -e WEAVE_CIDR=none --name c5 -it busybox sh
      / # ifconfig
      
      使用weave attach ${container_id}给运行中的容器分配网络
      $ weave attach b1f7a647aee3
      10.32.0.1
      
      如果要把容器从某个网络中移除,可以使用weave detach命令
      $ weave detach net:10.32.0.0/24 b1f7a647aee3
      10.32.0.1
      

外网连weave

  1. weave是一个私有的VxLAN网络,默认与外部网络隔离。外部网络如何才能访问到weave中的容器呢?

    • 首先将主机加入到weave网络。
    • 然后把主机当作访问weave网络的网关。要将主机加入到weave,执行weave expose
  2. 宿主机如何访问虚拟机中的Docker镜像

    1. macos
    $ sudo route add -net 10.32.0.0/12 -netmask  255.240.0.0 192.168.100.141
    2. linux
    $ ip route add 10.32.0.0/12 via 192.168.100.141
    

命令整理

  1. 命令

    1. 查看weave状态
    $ weave status
    2. 查看状态详情
    $ weave status connections
    3. 查看weave相互之间节点建立的关系
    $ weave status peers
    4. 查看当前分配的容器
    $ weave ps
    5. 查看weave当前版本
    $ weave version
    6. 启动并与其他主机建立连接,启动weave并下载镜像
    $ weave launch
    7. 进行连接 IP连接对端服务器
    $ weave launch <ip address>
    8. 使用weave代理
    $ weave env
    9. 执行输出|来自weave env的输出
    $ export DOCKER_HOST=unix:///var/run/weave/weave.sock
    10. 关闭weave
    $ weave stop
    11. 关闭weave env代理
    $ export DOCKER=OPTS=
    

常见问题

  1. 如果用虚拟机测试并且多个虚拟机是用同一虚拟机克隆的,所有机器的machine-id会是一样的。就会引起不同主机间连接失败,因为每台主机Weave网桥上的虚拟网卡分配的IP段是一样的。解决方法就是为每台机器重新生成不同的machine-id:

    $ rm /etc/machine-id /var/lib/dbus/machine-id
    $ dbus-uuidgen --ensure
    $ systemd-machine-id-setup
    $ reboot
    
上一篇:k8s Weave Scope 部署配置


下一篇:Docker Weave 命令整理