Docker系列04—跨主机网络方案(overlay/weave)

在前面详细讲解了几种网络模式:none,host,bridge,container。他们解决了单个主机间的容器的通信问题,并不能实现多个主机容器之间的通信。

 

跨主机网络方案包括两大类:

1,docker原生的:overlay和macvlan

2,第三方方案:flannel、weave和calico

 

overlay

Docker overlay网络需要一个key-value数据库用于保存网络状态信息,包括Network、Endpoint、IP等。

consul、Etcd、Zookeeper都是Docker支持的key-value软件,这里我们使用consul。

 

在docker主机docker01(10.0.0.11)和docker02(10.0.0.12)上实践各种跨主机网络方案,在10.0.0.11上部署支持的组件,比如consul。

 

第一步:启动路由转发功能

【两台主机都需开启】

[root@docker01 ~]# echo "1" > /proc/sys/net/ipv4/ip_forward
[root@docker02 ~]# echo "1" > /proc/sys/net/ipv4/ip_forward

 

第二步:运行consul

以容器的方式运行consul

 

[root@docker01 ~]# systemctl restart docker
[root@docker01 ~]# systemctl enable docker
[root@docker01 ~]# docker pull progrium/consul
Using default tag: latest
latest: Pulling from progrium/consul

[root@docker01 ~]# docker run -d -p 8500:8500 -h consul --name consul --restart=always progrium/consul -server -bootstrap
### 其中 -h 为指定容器内部的主机名;--restart=always 为docker启动时,此容器自动启动;-server -bootstrap 表示当在群集中,加上这两个选项可以使其以master的身份出现

[root@docker01 ~]# netstat -lntp | grep 8500
tcp6       0      0 :::8500                 :::*                    LISTEN      1576/docker-proxy

  

第三步:浏览器访问

通过ip+port的方式访问

 

第四步:修改docker启动文件

需要修改的是docker01和docker02的docker daemon 的配置文件。

【注】在这里我们使用的是两台。如果是3台,可以为3台都设置:表示这3台准备跨主机;也可以将第一台设置为只存放consul,2,3台修改配置文件即可:表示后两台准备跨主机。

【注】只修改[Service]内容即可

 

[root@docker01 ~]# cat /usr/lib/systemd/system/docker.service
...
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://10.0.0.11:8500 --cluster-advertise=eth0:2376
# ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
...

### 各项解释如下
# /var/run/docker.sock 表示Docker的一个编程接口;
# '-H tcp://0.0.0.0:2376' 表示使用本机的2376/tcp端口;
# '--cluster-store=consul://10.0.0.11:8500' 表示运行了consul的服务器IP和端口
# '--cluster-advertise=eth0:2376' 表示从本机的eth0网卡通过2376端口收集网络信息,也有可能是ens33。

  

[root@docker02 ~]# cat /usr/lib/systemd/system/docker.service
...
[Service]
Type=notify
# the default is not to use systemd for cgroups because the delegate issues still
# exists and systemd currently does not support the cgroup feature set required
# for containers run by docker
ExecStart=/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --cluster-store=consul://10.0.0.11:8500 --cluster-advertise=eth0:2376
# ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
ExecReload=/bin/kill -s HUP $MAINPID
TimeoutSec=0
RestartSec=2
Restart=always
...

 

重新加载docker daemon,修改了文件的服务都需要重启

[root@docker01 ~]# systemctl daemon-reload
[root@docker01 ~]# systemctl restart docker

 

这里注意,如果consul容器没有设置为自启,那么需要手动启动

[root@docker02 ~]# systemctl daemon-reload
[root@docker02 ~]# systemctl restart docker

第五步:浏览器查看

这时发现两个主机已经注册上去了

 

第六步:创建overlay网络

在docker01上创建网络ov_ken

[root@docker01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c8d69c4c3ffe        bridge              bridge              local
f5d3339712b4        host                host                local
93359dad0336        none                null                local

[root@docker01 ~]# docker network create -d overlay ov_ken

[root@docker01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c8d69c4c3ffe        bridge              bridge              local
f5d3339712b4        host                host                local
93359dad0336        none                null                local
70c2c8b47ead        ov_ken              overlay             global

### 这个时候docker02上不用添加就会自动添加
[root@docker02 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
7c9560f3b566        bridge              bridge              local
e76394dcf8f8        host                host                local
4cdde3f7dce2        none                null                local
70c2c8b47ead        ov_ken              overlay             global
### 因为创建ov_ken时docker01将overlay网络信息存入了consul,docker02从consul读取了新网络的数据。

 

查看网络信息

[root@docker01 ~]# docker network inspect ov_ken
[
    {
        "Name": "ov_ken",
        "Id": "70c2c8b47ead8af423a6b562aba42f1106454b58577c27cf47143a9eacdb419a",
        "Created": "2020-04-13T11:47:08.079686153+08:00",
        "Scope": "global",
        "Driver": "overlay",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": {},
            "Config": [
                {
                    "Subnet": "10.0.0.0/24",
                    "Gateway": "10.0.0.1"
                }
            ]
        },
### 由此可以看出docker自动为ov_ken分配的ip地址空间为10.0.0.0/24
 

 

在overlay网络中运行容器

 

运行一个busybox容器并使用overlay网络

[root@docker01 ~]# docker run -d -it --name busybox --network ov_ken busybox:latest
3492931078a8d2cf2a7e77b7a8518c3f89f64c0b803a79ffc9742965581d96fa

 

6.1 跨主机连通

在docker02上运行新的容器

[root@docker02 ~]# docker run -it -d --name busybox_02 --network ov_ken busybox:latest
53e708b68a31d5f08bce6f949426e64ce333e4ee9f28396271b2a6eb3daad182

 

查看容器的网络

[root@docker02 ~]# docker exec busybox_02 ip r
default via 172.18.0.1 dev eth1 
10.0.0.0/24 dev eth0 scope link  src 10.0.0.3 
172.18.0.0/16 dev eth1 scope link  src 172.18.0.2

 

测试使用docker01上的容器ping docker02上的容器

[root@docker01 ~]# docker exec busybox ip r
default via 172.18.0.1 dev eth1 
10.0.0.0/24 dev eth0 scope link  src 10.0.0.2 
172.18.0.0/16 dev eth1 scope link  src 172.18.0.2 

[root@docker01 ~]# docker exec busybox ping -c 2 10.0.0.3
PING 10.0.0.3 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=3.657 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.351 ms
--- 10.0.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.351/2.004/3.657 ms
 

 

至此:overlay容器是可以直接通信,同时docker也实现了DNS服务。

 

 

6.2 overlay网络隔离

不同的overlay网络是相互隔离的。我们创建第二个overlay网络ov_ken2并运行容器

[root@docker01 ~]# docker network create -d overlay ov_ken2
0dd70337a3f1504c9d24891c9e37d74af35abcad0ce3751ac0efa5ad138cb12c

[root@docker01 ~]# docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
c8d69c4c3ffe        bridge              bridge              local
2436e5e8c848        docker_gwbridge     bridge              local
f5d3339712b4        host                host                local
93359dad0336        none                null                local
70c2c8b47ead        ov_ken              overlay             global
0dd70337a3f1        ov_ken2             overlay             global

[root@docker01 ~]# docker run -d -it --name busybox_03 --network ov_ken2 busybox:latest
a5963fd6a9b863613269f773069fa99630fc88d7af49a3b355e78c9060858699

[root@docker01 ~]# docker exec busybox_03 ip r
default via 172.18.0.1 dev eth1 
10.0.1.0/24 dev eth0 scope link  src 10.0.1.2 
172.18.0.0/16 dev eth1 scope link  src 172.18.0.3
### 在这里我们能看到docker给第二个overlay分配的ip地址为10.0.1.0/24

[root@docker01 ~]# docker exec busybox_03 ping -c 2 10.0.0.3
PING 10.0.0.3 (10.0.0.3): 56 data bytes
--- 10.0.0.3 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss
### 在这里我们发现ov_ken和ov_ken2并不互通

  

如果要实现busybox_03和busybox_02的互通,可以将busybox_03也连接到ov_ken网络上

[root@docker01 ~]# docker network connect ov_ken busybox_03
### 意思为,将busybox_03添加到ov_ken网络

[root@docker01 ~]# docker exec busybox_03 ip r
default via 172.18.0.1 dev eth1 
10.0.0.0/24 dev eth2 scope link  src 10.0.0.4 
10.0.1.0/24 dev eth0 scope link  src 10.0.1.2 
172.18.0.0/16 dev eth1 scope link  src 172.18.0.3 
###  这个时候会发现busybox_03会被添加一个新的ov_ken的网段IP

[root@docker01 ~]# docker exec busybox_03 ping -c 2 10.0.0.3
PING 10.0.0.3 (10.0.0.3): 56 data bytes
64 bytes from 10.0.0.3: seq=0 ttl=64 time=6.571 ms
64 bytes from 10.0.0.3: seq=1 ttl=64 time=0.411 ms
--- 10.0.0.3 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.411/3.491/6.571 ms

 

 

 

 

weave

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

 

一、安装部署weave

weave安装非常简单,在docker01和docker02上执行如下命令:

[root@docker01 ~]# curl -L git.io/weave -o /usr/local/bin/weave
[root@docker01 ~]# chmod a+x /usr/local/bin/weave
 


[root@docker02 ~]# curl -L git.io/weave -o /usr/local/bin/weave
[root@docker02 ~]# chmod a+x /usr/local/bin/weave
 

 

在docker01上启动weave

[root@docker01 ~]# weave launch

 

注:在执行weave launch命令,启动weave相关服务。weave所有的组件都是以容器的方式运行的,会自动从docker hub上获取最新的image并启动容器

 

查看启动的容器

[root@docker01 ~]# docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS  NAMES
e089485df46f        weaveworks/weave:2.6.2   "/home/weave/weaver …"   55 seconds ago      Up 54 seconds              weave

weave运行了一个容器:

weave是主程序,负责建立weave网络,收发数据,提供DNS服务等

 

 

在docker01中启动容器

[root@docker01 ~]# eval $(weave env)
[root@docker01 ~]# docker run -d -it --name busybox_01 --rm busybox:latest
a1a4f0931a65b36067f8d27e6474fee584d003ac302e9c7ac4e517f48b0d46a2

注意:在这里因为是测试,用到了 --rm :关闭即删除,删除,删除 !!

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

 

查看当前容器busybox_01的网络配置

[root@docker01 ~]# docker exec busybox_01 ip r
default via 172.17.0.1 dev eth0 
10.32.0.0/12 dev ethwe scope link  src 10.32.0.1 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.2 
224.0.0.0/4 dev ethwe scope link 

### 由此可以看出,docker给其分配的地址为10.32.0.0/12网段,并且IP地址为10.32.0.1
### 而且busybox_01有两个网络接口eth0和ethwe,其中eth0是默认连接的bridge网络,即网桥docker0。分配的IP 10.32.0.1/12 ethwe与weave相关

 

在当前主机上再运行一个容器

[root@docker01 ~]# docker run -d -it --name busybox_02 --rm busybox:latest
88f208a2ca486eccc346ed7239f44836587796ce7898f48b65e162bfebe522e6

[root@docker01 ~]# docker exec busybox_02 ip r
default via 172.17.0.1 dev eth0 
10.32.0.0/12 dev ethwe scope link  src 10.32.0.2 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.3
224.0.0.0/4 dev ethwe scope link 
 

 

测试同一个主机上的busybox_01和busybox_02的连通性

[root@docker01 ~]# docker exec busybox_01 ping -c 2 busybox_02
PING busybox_02 (10.32.0.2): 56 data bytes
64 bytes from 10.32.0.2: seq=0 ttl=64 time=0.051 ms
64 bytes from 10.32.0.2: seq=1 ttl=64 time=0.050 ms

--- busybox_02 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 0.050/0.050/0.051 ms

### 在这里是可以连通的,并且还可以解析

 

 

二、weave跨主机通信

第一步:再docker02上执行以下命令

[root@docker02 ~]# weave launch 10.0.0.11
## 格式 weave launch [docker01的ip地址]

这里必须指定docker01的ip地址,这样docker01和docker02才能加入到同一个weave网络。

 

第二步:开启路由转发功能

[root@docker01 ~]# echo "1">/proc/sys/net/ipv4/ip_forward
[root@docker02 ~]# echo "1">/proc/sys/net/ipv4/ip_forward

 

第三步:启动容器

[root@docker02 ~]# docker run -d -it --name busybox_03 --rm busybox:latest
82503c97ee984d5a330f635eeca825edc795c7ef96a8fc592da9dc8598764594

 

第四步:测试连通性

[root@docker02 ~]# docker exec busybox_03 ping -c 2 busybox_02
PING busybox_02 (10.32.0.2): 56 data bytes
64 bytes from 10.32.0.2: seq=0 ttl=64 time=1.477 ms
64 bytes from 10.32.0.2: seq=1 ttl=64 time=1.187 ms

--- busybox_02 ping statistics ---
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max = 1.187/1.332/1.477 ms

### 可以发现主机docker02上运行的容器可以与docker01上的容器通信,而且可以解析主机名

 

三、weave网络隔离

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

[root@docker02 ~]# docker run -d -it -e WEAVE_CIDR=net:10.32.2.0/24 --name busybox_04 --rm busybox:latest
d3a4430bbc111c9f7eca1ab9c4b6f432f63d9e45d66ea0d0d66b3dfecfa75eb6

 

在这里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到busybox_02。

[root@docker02 ~]# docker exec busybox_04 ping -c 2 busybox_02
PING busybox_02 (10.32.0.2): 56 data bytes
--- busybox_02 ping statistics ---
2 packets transmitted, 0 packets received, 100% packet loss

当然也无法ping同同主机上的busybox_03

 

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

[root@docker02 ~]# docker run -d -it -e WEAVE_CIDR=ip:10.32.6.6/24 --name busybox_05 busybox:latest
b2eccb69e37e5da8558237163103f050a3efc118cf71bf11c62c68b572e2b8a6
[root@docker02 ~]# docker exec busybox_05 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.4 
224.0.0.0/4 dev ethwe scope link 

 

四、weave与外网的连通性

weave是一个私有的VLAN网络(容器可以访问外网),默认与外部网络隔离。外部网络如何才能访问到weave中的容器呢?

答案:

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

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

 

第一步:要将主机加入到weave,执行weave expose。

[root@docker02 ~]# weave expose
10.32.2.129

 

第二步:查看ip

这个10.32.2.129会被配置到host2的weave网桥上。

[root@docker02 ~]# ip a
...
13: weave: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1376 qdisc noqueue state UP qlen 1000
    link/ether c6:77:0c:f6:e2:29 brd ff:ff:ff:ff:ff:ff
    inet 10.32.2.129/12 brd 10.47.255.255 scope global weave
       valid_lft forever preferred_lft forever
    inet6 fe80::c477:cff:fef6:e229/64 scope link 
       valid_lft forever preferred_lft forever 

 

第三步:测试连通性

ping同一主机的busybox_03

[root@docker02 ~]# docker exec busybox_03 ip r
default via 172.17.0.1 dev eth0 
10.32.0.0/12 dev ethwe scope link  src 10.44.0.0 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.2 
224.0.0.0/4 dev ethwe scope link 


[root@docker02 ~]# ping -c 2 10.44.0.0
PING 10.44.0.0 (10.44.0.0) 56(84) bytes of data.
64 bytes from 10.44.0.0: icmp_seq=1 ttl=64 time=0.123 ms
64 bytes from 10.44.0.0: icmp_seq=2 ttl=64 time=0.048 ms
--- 10.44.0.0 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.048/0.085/0.123/0.038 ms

 

ping docker01上的busybox_01

[root@docker01 ~]# docker exec busybox_01 ip r
default via 172.17.0.1 dev eth0 
10.32.0.0/12 dev ethwe scope link  src 10.32.0.1 
172.17.0.0/16 dev eth0 scope link  src 172.17.0.2 
224.0.0.0/4 dev ethwe scope link 

[root@docker02 ~]# ping -c 2 10.32.0.1
PING 10.32.0.1 (10.32.0.1) 56(84) bytes of data.
64 bytes from 10.32.0.1: icmp_seq=1 ttl=64 time=2.16 ms
64 bytes from 10.32.0.1: icmp_seq=2 ttl=64 time=0.337 ms

--- 10.32.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 0.337/1.252/2.168/0.916 ms
 

 

接下来要让其他非weave主机访问到busybox_01和busybox_03,只需要将网关指向docker01。例如在新的主机docker03上添加如下路由:

[root@docker03 ~]# ip route add 10.32.0.0/12 via 10.0.0.11

[root@docker03 ~]# ping -c 2 10.32.0.1
PING 10.32.0.1 (10.32.0.1) 56(84) bytes of data.
64 bytes from 10.32.0.1: icmp_seq=1 ttl=63 time=1.45 ms
64 bytes from 10.32.0.1: icmp_seq=2 ttl=63 time=2.25 ms
--- 10.32.0.1 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1002ms
rtt min/avg/max/mdev = 1.450/1.852/2.254/0.402 ms

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

weave launch --ipalloc-range 10.2.0.0/16

不过需要确保所有的host都使用相同的subnet

 

【注意】如果出现以下情况

[root@docker02 ~]# docker ps
Cannot connect to the Docker daemon at unix:///var/run/weave/weave.sock. Is the docker daemon running?

需要执行

[root@docker02 ~]# eval $(weave env --restore)
posted @ 2020-08-21 10:31  子禾org  阅读(415)  评论(0编辑  收藏  举报