Docker默认的网络环境下,单台主机上的Docker容器可以通过docker0网桥直接通信,而不同主机上的Docker容器之间只能通过在主机上做端口映射进行通信。这种端口映射方式对很多集群应用来说极不方便。如果能让Docker容器之间直接使用自己的IP地址进行通信,会解决很多问题。按实现原理可分别直接路由方式、桥接方式(如pipework)、Overlay隧道方式(如flannel、ovs+gre)等

情景构造

如下图所示,我们有两个物理主机1和主机2,我们在各自宿主机上启动一个centos容器,启动成功之后,两个容器分别运行在两个宿主机之上,默认的IP地址分配如图所示,这也是Docker自身默认的网络。

image-20230915130720679

一、直接路由

通过在Docker主机上添加静态路由实现跨宿主机通信:

image-20230915130900332

具体实现

1.1、分别对主机1和主机2上的docker0进行配置

编辑主机1上的 /etc/docker/daemon.json 文件,添加内容: "bip":"ip/netmask"

"bip": "172.17.1.252/24"

编辑主机2上的 /etc/docker/daemon.json文件,添加内容: "bip":"ip/netmask"

"bip": "172.17.2.252/24"

1.2、 重启docker服务

主机1和主机2上均执行如下命令重启docker服务以使修改后的docker0网段生效

systemctl restart docker

1.3、 添加路由规则

主机1上添加路由规则如下:

route add -net 172.17.2.0 netmask 255.255.255.0 gw 10.0.0.2

主机2上添加路由规则如下:

route add -net 172.17.1.0 netmask 255.255.255.0 gw 10.0.0.2

1.4、配置iptables规则

主机1上添加如下规则:

iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.1.0/24 ! -d 172.17.0.0/16 -j MASQUERADE

主机2上添加如下规则:

iptables -t nat -F POSTROUTING
iptables -t nat -A POSTROUTING -s 172.17.2.0/24 ! -d 172.17.0.0/16 -j MASQUERADE

1.5、 启动容器

主机1上启动centos容器:

docker run -it --name container1 centos /bin/bash

主机2上启动centos容器:

docker run -it --name container2 centos /bin/bash

1.6、 容器间直接通信

好了,现在两容器可以互ping了

二、flannel

2.1、flannel概述

Flannel 使用etcd存储配置数据和子网分配信息。flannel 启动之后,后台进程首先检索配置和正在使用的子网列表,然后选择一个可用的子网,然后尝试去注册它。etcd也存储这个每个主机对应的ip。flannel 使用etcd的watch机制监视/coreos.com/network/subnets下面所有元素的变化信息,并且根据它来维护一个路由表。为了提高性能,flannel优化了Universal TAP/TUN设备,对TUN和UDP之间的ip分片做了代理。

image-20230915155453211

数据从源容器中发出后,经由所在主机的docker0虚拟网卡转发到flannel0虚拟网卡,这是个P2P的虚拟网卡,flanneld服务监听在网卡的另外一端。
Flannel通过Etcd服务维护了一张节点间的路由表,该张表里保存了各个节点主机的子网网段信息。
源主机的flanneld服务将原本的数据内容UDP封装后根据自己的路由表投递给目的节点的flanneld服务,数据到达以后被解包,然后直接进入目的节点的flannel0虚拟网卡,然后被转发到目的主机的docker0虚拟网卡,最后就像本机容器通信一样的由docker0路由到达目标容器。

2.2、etcd部署安装

环境准备:

主机名 IP 角色
harbor 10.0.0.100 etcd
docker01 10.0.0.101 docker
docker02 10.0.0.102 docekr
#下载安装
[root@harbor ~]# yum install -y etcd
#修改配置文件   //全部删除粘贴即可,或者手动修改,删除前考虑是否备份
[root@harbor ~]# vim /etc/etcd/etcd.conf
# [member]
ETCD_NAME=default
ETCD_DATA_DIR="/var/lib/etcd/default.etcd"
ETCD_LISTEN_CLIENT_URLS="http://10.0.0.100:2379,http://127.0.0.1:2379"
# #[cluster]
ETCD_INITIAL_CLUSTER_STATE="new"
ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"
ETCD_ADVERTISE_CLIENT_URLS="http://10.0.0.11:2379"
## 查看健康状态   //出现“cluster is healthy”表示OK
[root@harbor ~]# etcdctl -C http://10.0.0.100:2379 cluster-health
member 8e9e05c52164694d is healthy: got healthy result from http://10.0.0.101:2379
cluster is healthy
## 写入数据
[root@harbor ~]# etcdctl -C http://10.0.0.100:2379 set /testdir/testkey "hello
world"
hello world
## 查看数据
[root@harbor ~]# etcdctl -C http://10.0.0.100:2379 get /testdir/testkey
hello world

2.2.1、etcd web界面

github地址

#下载  //需要ssl证书验证,大概率下载失败,建议去网站下载
[root@harbor ~]# wget https://github.com/evildecay/etcdkeeper/releases/download/v0.7.6/etcdkeeper-v0.7.6-linux_x86_64.zip
#解压
[root@harbor ~]# unzip etcdkeeper-v0.7.6-linux_x86_64.zip 
#移动到解压目录
[root@harbor ~]# cd etcdkeeper/
#授权
[root@harbor ~]# chmod +x etcdkeeper 
#启动服务
[root@harbor ~]# ./etcdkeeper -h 0.0.0.0
#浏览器访问
10.0.0.100:8080

image-20230915163058500

image-20230915163226146

2.3、安装flannel

两台主机操作

# 安装flannel
[root@docker01 ~]# yum install -y flannel
[root@docker02 ~]# yum install -y flannel
# 修改flannel配置文件
[root@docker01 ~]# vim /etc/sysconfig/flanneld
FLANNEL_ETCD_ENDPOINTS="http://10.0.0.100:2379"
FLANNEL_ETCD_PREFIX="/atomic.io/network"
# 创建数据 以下命令二选一
[root@docker01 ~]# etcdctl mk /atomic.io/network/config '{"Network":"192.168.0.0/16"}'
{"Network":"192.168.0.0/16"}
[root@docker01 ~]# etcdctl -C http://10.0.0.101:2379 set /atomic.io/network/config
'{"Network":"192.168.0.0/16"}
# 启动flanneld
[root@docker02 cicd]# systemctl start flanneld

image-20230915160448709

image-20230915160523878

2.4、docker关联flannel

# 修改docker脚本  //添加下面两行,其中ExecStart替换原来的启动命令,原来的启动命令注释即可
[root@docker02 cicd]# vim /usr/lib/systemd/system/docker.service
EnviromentFile=/run/flannel/docker
ExecStart=/usr/bin/dockerd -H fd:// $DOCKER_NETWORK_OPTIONS
# 重启docker
[root@docker01 ~]# systemctl daemon-reload
[root@docker01 ~]# systemctl stop docker.socket
[root@docker01 ~]# systemctl stop docker.service
[root@docker01 ~]# systemctl start docker

#docker02操作如上

2.5、开启内核转发

# 开启内核转发
[root@docker01 ~]# echo 1 > /proc/sys/net/ipv4/ip_forward
# 防火墙加载规则
[root@docker01 ~]# systemctl start firewalld
[root@docker01 ~]# systemctl stop firewalld

#docker02操作如上

2.6、启动容器测试

[root@docker01 ~]# docker run -it busybox /bin/sh
[root@docker02 ~]# docker run -it busybox /bin/sh
#查看docker02容器IP,使用docker01 ping测试

image-20230915161039678

三、overlay

为支持容器跨主机通信,Docker 提供了 overlay driver,使用户可以创建基于 VxLAN 的 overlay 网络。VxLAN 可将二层数据封装到 UDP 进行传输,VxLAN 提供与 VLAN 相同的以太网二层服务,但是拥有更强的扩展性和灵活性。有关 VxLAN 更详细的内容可参考 CloudMan 在《每天5分钟玩转 OpenStack》中的相关章节。

3.1、安装consul

Docerk overlay 网络需要一个 key-value 数据库用于保存网络状态信息,包括 Network、Endpoint、IP 等。Consul、Etcd 和 ZooKeeper 都是 Docker 支持的 key-vlaue 软件。在这里我们使用consul。

#harbor上: consul存储ip地址的分配
[root@harbor ~]# docker run -d -p 8500:8500 -h consul --name consul progrium/consul -server -bootstrap
-p 8500:8500 指定映射端口8500
-h consul 指定主机名
--name consul 是容器的名字
progrium/consul 镜像名
-server 设置Agent是server模式
-bootstrap 设置服务为“bootstrap”模式
容器启动后,可以通过 http://10.0.0.100:8500 访问 Consul。

image-20230915164441031

docker01、docker02上修改添加:vim /etc/docker/daemon.json

#docker01
[root@harbor ~]# vim /etc/docker/daemon.json**
{
  "hosts":["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"],
  "cluster-store": "consul://10.0.0.100:8500",
  "cluster-advertise": "10.0.0.101:2375"                       
}
#docker02
[root@harbor ~]# vim /etc/docker/daemon.json**
{
  "hosts":["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"],
  "cluster-store": "consul://10.0.0.100:8500",
  "cluster-advertise": "10.0.0.102:2375"                       
}

docker01:

image-20230915165938170

docker02:

image-20230915170038280

  • host 开启和监听2375端口,同时使用docker.sock文件
  • --cluster-store指定 consul 的地址。
  • --cluster-advertise 告知 consul 自己的连接地址。

注意:记得修改docker.service.因为配置和daemon.json冲突

#修改 /usr/lib/systemd/system/docker.service
#将-H fd://去掉
ExecStart=/usr/bin/dockerd  --containerd=/run/containerd/containerd.sock

image-20230915165125713

修改后重启docker

systemctl daemon-reload
systemctl restart docker

创建好以上步骤后,我们就可以在网页上访问: http://10.0.0.100:8500

在KEY/VALUE -> docker -> nodes 下如果有你创建的两个节点node2(192.168.1.13),node3(192.168.1.14),说明成功。