Overlay网络是指在不改变现有网络基础设施的前提下,经过某种约定通讯协议,把二层报文封装在IP报文之上的新的数据格式。java
这样不但可以充分利用成熟的IP路由协议进程数据分发,并且在Overlay技术中采用扩展的隔离标识位数,可以突破VLAN的4000数量限制,node
支持高达16M的用户,并在必要时可将广播流量转化为组播流量,避免广播数据泛滥。linux
所以,Overlay网络其实是目前最主流的容器跨节点数据传输和路由方案。nginx
Overlay网络的实现方式能够有许多种,其中IETF(国际互联网工程任务组)制定了三种Overlay的实现标准web
1. 虚拟可扩展LAN(VXLAN)docker
2. 采用通用路由封装的网络虚拟化(NVGRE)apache
3. 无状态传输协议(SST)centos
Docker内置的Overlay网络是采用IETF标准的VXLAN方式,而且是VXLAN中广泛认为最适合大规模的云计算虚拟化环境的SDN Controller模式。bash
Docker的Overlay网络功能与其Swarm集群是紧密整合的,所以为了使用Docker的内置跨节点通讯功能,最简单的方式就是采纳Swarm做为集群的解决方案。服务器
在 docker 1.9 中,要使用 Swarm + overlay 网络架构,还须要如下几个条件:
1. 全部Swarm节点的Linux系统内核版本不低于3.16 (在 docker 1.10 后面版本中,已经支持内核3.10,升级内核实在是一个麻烦事情)
2. 须要一个额外的配置存储服务,例如Consul、Etcd或ZooKeeper
3. 全部的节点都可以正常链接到配置存储服务的IP和端口
4. 全部节点运行的Docker后台进程须要使用『--cluster-store』和『--cluster-advertise』参数指定所使用的配置存储服务地址
-------------------------------------------------------------------------------------------
服务器3台 以下:
10.6.17.12
10.6.17.13
10.6.17.14
------------------------------------------------------------------------------------------
docker version
Client:
Version: 1.10.0-rc1
API version: 1.22
Go version: go1.5.3
Git commit: 677c593
Built: Fri Jan 15 20:50:15 2016
OS/Arch: linux/amd64
------------------------------------------------------------------------------------------
首先要作的是 修改主机名
10.6.17.12 管理节点可不修改
10.6.17.13 = hostnamectl --static set-hostname swarm-node-1
10.6.17.14 = hostnamectl --static set-hostname swarm-node-2
------------------------------------------------------------------------------------------
上面的4个条件中,第一个条件在docker 1.10 RC 版本中已经默认就知足了。
下面咱们来建立第二个条件中的 配置存储服务,配置存储服务按照你们的使用习惯,本身选择一个配置存储。
因为咱们java 项目一直在使用 ZooKeeper ,因此这边选择 ZooKeeper 做为存储服务,为了方便测试,这边只配置 单机的 ZooKeeper 服务
-------------------------------------------------------------------------------------------
pull 一个 centos 的镜像下来
[10.6.17.12]# docker pull centos
如下是 zookeeper 的 Dockerfile
-------------------------------------------------------------------------------------------
FROM centos
MAINTAINER jicki@qq.com
USER root
# 添加erepo 源
RUN rpm --import https://www.elrepo.org/RPM-GPG-KEY-elrepo.org && rpm -Uvh http://www.elrepo.org/elrepo-release-7.0-2.el7.elrepo.noarch.rpm
RUN yum -y install --enablerepo base wget java tar.x86_64 && mkdir -p /opt/local && wget -q -O - http://apache.fayea.com/zookeeper/zookeeper-3.4.6/zookeeper-3.4.6.tar.gz | tar -xzf - -C /opt/local/ && mv /opt/local/zookeeper-3.4.6 /opt/local/zookeeper && cp /opt/local/zookeeper/conf/zoo_sample.cfg /opt/local/zookeeper/conf/zoo.cfg && mkdir -p /opt/local/zookeeper/data && mkdir -p /opt/local/zookeeper/log
ENV JAVA_HOME /usr/
ADD start.sh /start.sh
WORKDIR /opt/local/zookeeper
#修改配置文件
RUN sed -i 's/dataDir=\/tmp\/zookeeper/dataDir=\/opt\/local\/zookeeper\/data/g' /opt/local/zookeeper/conf/zoo.cfg
ENTRYPOINT ["/start.sh"]
# 保证前台运行
CMD ["start-foreground"]
-------------------------------------------------------------------------------------------
[10.6.17.12]# docker build -t="zookeeper" .
[10.6.17.12]# docker run --restart=always -d -v /opt/data/zookeeper/data:/opt/local/zookeeper/data -v /opt/data/zookeeper/log:/opt/local/zookeeper/log -p 2181:2181 zookeeper
zookeeper 建立完之后,须要修改每一个主机Docker后台进程启动脚本里的变量内容,并配置swarm节点.
[10.6.17.12]# sed -i 's/-H fd:\/\//-H tcp:\/\/10.6.17.12:2375 --cluster-store=zk:\/\/10.6.17.12:2181/store --cluster-advertise=10.6.17.12:2376/g' /lib/systemd/system/docker.service
[10.6.17.13]# sed -i 's/-H fd:\/\//-H tcp:\/\/10.6.17.13:2375 --cluster-store=zk:\/\/10.6.17.12:2181/store --cluster-advertise=10.6.17.13:2376/g' /lib/systemd/system/docker.service
[10.6.17.14]# sed -i 's/-H fd:\/\//-H tcp:\/\/10.6.17.14:2375 --cluster-store=zk:\/\/10.6.17.12:2181/store --cluster-advertise=10.6.17.14:2376/g' /lib/systemd/system/docker.service
修改完 变量内容,执行
systemctl daemon-reload
并 重启 docker
systemctl restart docker.service
因为修改和重启Docker后台进程自己是比较麻烦的事情,若是用户业务可能会使用到跨节点网络通讯,建议在架设Docker集群的时候就事先准备配置存储服务,而后直接在添加主机节点时就能够将相应参数加入到Docker的启动配置中了。
接下来建立Overlay网络,咱们要建的这个网络是横跨全部节点的,也就是说在每一个节点都应该有一个名称、ID和属性彻底一致的网络,它们之间还要相互承认对方为本身在不一样节点的副本。如何实现这种效果呢?目前的Docker network命令还没法作到,所以只能借助于Swarm,下面咱们建立Swarm 群集
首先咱们选择 10.6.17.12 这台机器作为 master 节点 建立 swarm:
[10.6.17.12]# docker -H tcp://10.6.17.12:2375 run --name master --restart=always -d -p 8888:2375 swarm manage zk://10.6.17.12:2181/swarm
在其余两台Docker业务容器运行的节点上运行Swarm Agent服务:
[10.6.17.13]# docker -H tcp://10.6.17.13:2375 run --name node_1 --restart=always -d swarm join --addr=10.6.17.13:2375 zk://10.6.17.12:2181/swarm
[10.6.17.14]# docker -H tcp://10.6.17.14:2375 run --name node_2 --restart=always -d swarm join --addr=10.6.17.14:2375 zk://10.6.17.12:2181/swarm
查看全部节点上的信息:
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5fc7753caa2c swarm "/swarm join --addr=1" Less than a second ago Up Less than a second 2375/tcp swarm-node-1/node_1
330b964ba732 swarm "/swarm join --addr=1" Less than a second ago Up Less than a second 2375/tcp swarm-node-2/node_2
至此 swarm 集群已经搭建完成了。
Swarm提供与Docker服务彻底兼容的API,所以能够直接使用docker命令进行操做。
注意上面命令中建立Master服务时指定的外部端口号8888,它就是用来链接Swarm服务的地址。
如今咱们就能够建立一个Overlay类型的网络了:
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 network create --driver=overlay ovr0
这个命令被发送给了Swarm服务,Swarm会在全部Agent节点上添加一个属性彻底相同的Overlay类型网络。
在每一个节点上面 使用 docker network ls 能够查看 到已经有一个 ovr0 的 overlay 网络
在Swarm的网络里面,每一个网络的名字都会加上节点名称做为前缀,
如: swarm-node-1/node_1
swarm-node-2/node_2
但Overlay类型的网络是没有这个前缀的,这也说明了这类网络是被全部节点共有的。
下面咱们在Swarm中建立两个链接到Overlay网络的容器,并用Swarm的过滤器限制这两个容器分别运行在不一样的节点上。
-------------------------------------------------------------------------------------------
FROM centos
MAINTAINER jicki@qq.com
RUN yum -y update; yum clean all
RUN yum -y install epel-release; yum clean all
RUN yum -y install wget; yum clean all
ADD ./nginx.sh /root/
RUN /bin/bash /root/nginx.sh
RUN rm -rf /root/nginx.sh
RUN rm -rf /opt/local/nginx/conf/nginx.conf
ADD ./nginx.conf /opt/local/nginx/conf/
RUN mkdir -p /opt/local/nginx/conf/vhost
ADD ./docker.conf /opt/local/nginx/conf/vhost
RUN chown -R upload:upload /opt/htdocs/web
EXPOSE 80 443
CMD ["/opt/local/nginx/sbin/nginx", "-g", "daemon off;"]
-------------------------------------------------------------------------------------------
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 run --name nginx_web_1 --net ovr0 --env="constraint:node==swarm-node-1" -d -v /opt/data/nginx/logs:/opt/local/nginx/logs nginx
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 run --name nginx_web_2 --net ovr0 --env="constraint:node==swarm-node-2" -d -v /opt/data/nginx/logs:/opt/local/nginx/logs nginx
建立完两个容器之后,下面来来测试一下 ovr0 这个网络的连通性
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 exec -it nginx_web_1 ping nginx_web_2
PING nginx_web_2 (10.0.0.3) 56(84) bytes of data.
64 bytes from nginx_web_2.ovr0 (10.0.0.3): icmp_seq=1 ttl=64 time=0.360 ms
64 bytes from nginx_web_2.ovr0 (10.0.0.3): icmp_seq=2 ttl=64 time=0.247 ms
64 bytes from nginx_web_2.ovr0 (10.0.0.3): icmp_seq=3 ttl=64 time=0.234 ms
64 bytes from nginx_web_2.ovr0 (10.0.0.3): icmp_seq=4 ttl=64 time=0.241 ms
64 bytes from nginx_web_2.ovr0 (10.0.0.3): icmp_seq=5 ttl=64 time=0.212 ms
如上所示 咱们已经在Docker的Overlay网络上成功的进行了跨节点的数据通讯。
测试两个 ssh 的服务,建立两个 容器,查看容器所属 IP 。
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 run --name ssh-1 --net ovr0 --env="constraint:node==swarm-node-1" -d -p 8001:22 ssh
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 run --name ssh-2 --net ovr0 --env="constraint:node==swarm-node-2" -d -p 8001:22 ssh
建立容器 IP 为 DHCP 分配, 按照从下向上分配, 重启不会改变overlay 的IP 。
首先建立 ssh-1 分配IP为 10.0.0.4 建立 ssh-2 分配IP为 10.0.0.5
销毁 ssh-1 再次建立 分配IP 为 10.0.0.4
销毁 ssh-1 ssh-2 先建立 ssh-2 分配 IP 为 10.0.0.4
在 docker 1.10 后面的版本中 --net-alias=[] 的使用!!
在docker run 的时候 可指定相同的 alias ,能够实现 故障切换的效果。。
具体命令如:
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 run --name nginx_web_1 --net ovr0 --net-alias="nginx" --env="constraint:node==swarm-node-1" -d -v /opt/data/nginx/logs:/opt/local/nginx/logs nginx
[10.6.17.12]# docker -H tcp://10.6.17.12:8888 run --name nginx_web_2 --net ovr0 --net-alias="nginx" --env="constraint:node==swarm-node-2" -d -v /opt/data/nginx/logs:/opt/local/nginx/logs nginx
当咱们进入 机器里面的时候 使用 dig 查看 nginx A记录 看到的是一个,可是 一个容器 挂掉之后
A记录会自动绑定到另一台机器中。
在 docker 1.11 后面的版本中 --net-alias=[] 已经支持 负载均衡。
当咱们使用 dig 查看 A记录 时能够看到多个 A记录
docker network disconnect 与 docker network connect 命令的使用! 使用这两个命令可达到 A B 测试 以及 快速 回滚 的效果。
docker network connect ----> 加入 指定网络
docker network disconnect ----> 退出 指定网络
具体命令使用:
docker network disconnect ovr0 nginx_web_2 nginx_web_2 这个容器退出 ovr0 这个网络。
docker network connect ovr0 nginx_web_2 nginx_web_2 这个容器从新加入 ovr0 这个网络。