(转) Docker - Docker1.12服务发现,负载均衡和Routing Mesh

 

看到一篇介绍 Docker swarm以及如何编排的好文章,挪放到这里,本身学习的同时也分享出来。
html

 

原文连接: http://wwwbuild.net/dockerone/414200.htmlnode

-----

Docker社区目前最热的话题莫过于Docker 1.12的发布, 明显的感受就是你们都在讨论Docker 1.12的新功能,各类关于1.12的使用手册,文章,深度教程层出不穷, 一句话总结来讲, 不知道Docker 1.12都很差意思跟人打招呼了。程序员

我的理解Docker 1.12最大的功能莫过于SwarmKit的引入,这应该算是Docker发展里程碑式的一个Release(上一个里程碑应该是runC和Containerd的剥离,标志着Docker公司本身孤独地玩到容器标准化概念引入),自此不再要说Docker是主机容器管理了, Docker已经可以管理一群主机上的容器了。概念上Docker引入了node、service、task甚至更高于service一层的stack, 自此你们会发现容器和网络已经不是Docker的first-class概念, 取而代之的是service、 stack和跨主机网络。Docker SwarmKit的引入给容器编排投入了一颗重磅炸弹, 给个人感受是原来容器编排还能够这么玩,终于不要某某sos和某8s的全家桶了, 在容器编排的远古时代(其实也不远,就是观念陈旧)不装个五六七八个组件都很差意思跟人说是编排, 真的有这个必要么? 固然了, Docker Swarm主要功能仍是是借鉴了“远古时代”的几款产品, 吸取了前人的优秀经验。 让我列几个牛哄哄的功能给你们吧:docker

  1. 内置Raft, 妈妈不再用担忧我还要依赖Zookeeper、Etcd、Consul了, 光部署这些东西就浪费我一成天外加三台机器。ubuntu

  2. 不区分管理节点和Worker节点,想让谁上就让谁上, 猜测是参考了人家Nomad吧, 关键还能运行时Promote、Demote, 太方便了。缓存

  3. Service,Stack外加DAB, 用过都说好, 方便。网络

  4. Rolling Update, Scale一个Service,灰度发布分分钟搞定(虽然有点鸡肋),这个不用说也是借鉴了Kubernetes。负载均衡

一张图展现一下Docker1.12的和老版本的功能对比。curl

固然当前Docker 1.12的功能还很初级,尚未据说过有人大规模生产级的应用(听说能管理2000个节点,10W个容器),不过看的出来SwarmKit team新功能推出的速度仍是至关快的。 我的很看好这一趋势。工具

下面分享一下Docker的一个服务是如何被外部访问的。

在没有Docker的时代咱们更喜欢的两种办法来部署一个服务 1, 单个机器上的单个进程,绑定到固定IP上的固定端口, 这种方式的优势是简单明了,程序员同窗们须要作的事情最大化的优化单个进程的处理能力, 保障这个进程不会由于各类问题退出, 由于一旦退出就没得玩了。 2, 单个机器上的多个进程绑定到固定端口, 前面放一个代理工具。

容器化后你们发现之前的作法或多或少须要作些调整, 第一,因为主机概念被弱化,集群概念被突出, 应用程序再也不依赖某个主机或者某个端口; 第二, 容器生命周期不固定, 容器能够随时被启动被中止, 容器的数量可多可少(这就是咱们常说的弹性)。因为上面提到的两个容器化的特性,一些新的问题被引入,聪明的工程师们想到了一些解决办法来应对这些问题, 第一个解决办法就是咱们要谈到的服务发现,针对的问题是服务对外地址不定和服务随时被启动中止。 服务被发现之后要解决是如何把任务按照必定规则负载到容器中, 这就是第二个咱们要谈的负载均衡。 负载均衡解决了单一入口负载到多个容器上问题, 可是因为容器调度以后可能落到多个机器上, 假如某些主机上面没有工做的容器,而对外服务时候又但愿服务能够被访问, Routing Mesh概念引入是解决多个入口点负载到单个容器的问题。

服务发现

单纯的服务发现很好实现, 无非就是监测Container的启动、中止, 根据这些变更记录下服务到底能够经过哪些IP+端口能够被访问, 理论上实现一个初级的可用的服务发现不会超过十行代码。成熟的服务发现还须要额外的工做好比健康检查, 注意到咱们以前是假设了容器启动就能够对外服务, 实际中状况可能远非如此, 一个应用启动以后可能要准备环境, 加载数据以后才能够对外服务,健康检查是保证服务可用以后再对外服务。 另一个成熟的服务发现必备条件是高可用, 明眼人可能已经发现以前的简单版本不具有高可用和状态一致性, 这也是为何Docker引入了Raft协议。

负载均衡

传统理解的负载均衡根据协议不一样能够分为7层的和4层的, 7层负载均衡特色是能够支持很复杂的用户规则,好比HTTP header、Cookie等应用逻辑, 而4层只能支持到IP地址负载不一样服务。

Docker1.12的服务发现和负载均衡是结合到一块儿的, 实现办法有两种,DNS轮询和IPVS。 理解这两种策略以前须要知道的一个前提是Docker为每一个服务都分配了一个虚拟IP, 这个IP对应的不是具体的一个Task或者一个具体的Container,而是专门为一个服务保留。

下面咱们举例子分别说明一下两种负载均衡实现:

首先准备一下环境。

第一步以下图所示用Go写一段小代码, 编译成二进制放在一个ubuntu基础镜像里, 同时个人ubuntu里面安装了一些基础的网络工具, 好比dig、curl、 ping等, 保存成镜像ubuntu-base。


第二步, 根据Docker官方安装文档 咱们在虚拟机环境里启动两个虚拟机, 构造一个Docker Swarm集群。

第三步, 建立一个Overlay网络, 取名overlay-test。

下面咱们试一下DNS轮训模式的服务发现和负载均衡, 设置一个服务使用DNS轮询仍是VIP, 只要设置好endpoint-mode这个参数就好, 以下图所示:

使用下面命令启动咱们的服务:

docker service create –network overlay-test –name demo –replicas=4 –endpoint-mode=dnsrr ubuntu-base

—network overlay-test是指定使用刚刚建立的Overlay网络, –replicas=4 指定task数量, –endpoint-mode=dnsrr使用dnsrr方式作负载均衡。

启动成功后以下图所示:

当前机器上运行docker ps会发现有只有两个容器生成, 缘由是另外两个task被调度到另一台主机上。

下一步咱们考虑进入容器中看一下虚拟出来的网络状况。

咱们以前明明指定了使用overlay-test网络, 按理应该只有两块网卡, 实际上Docker却为咱们生成了4块, 多出来的两块是Docker为容器作的手脚, 让我来一一讲解为何会有4块网卡的出现。

  1. lo网卡不用多说, 是本地网卡, 也叫回环网卡;

  2. eth2属于以前建立的overlay-test网络;

  3. eth1和docker_gwbridge网桥构成的网络可使容器内的服务能够在主机上访问, 主机上telnet 172.18.0.4能够访问到咱们的服务,以下图:

  4. eth0是ingress网络中的一块网卡, 是为了Routing Mesh而设,稍后咱们会详细说明。

继续回到容器里面看咱们查看一下服务状况, 执行命令:


你们会发现经过服务名或者容器ID都能找到IP地址, 区别是服务名发现了本机上全部提供服务的容器IP, 至此同时实现了服务发现和内部负载均衡。

以上就是经过DNS轮询实现的服务发现和负载均衡, 这样的负载均衡是有一些缺点的, 好比:

  1. 一些应用可能缓存DNS请求, 致使容器变化以后DNS不能实时更新;

  2. DNS生效时间也致使不能实时反映服务变化状况;

  3. 因为以上缘由致使的负载均衡不够准确。

下面我来演示一下VIP和IPVS模式的服务发现和负载均衡。 VIP和IPVS原理上比较容易理解, 就是Docker为每一个服务分配了一个VIP, DNS解析服务名称或者自定义的别名到这个VIP上。

因为VIP自己没有容器提供服务,Docker把到VIP的请求经过IPVS技术负载到后面的容器上。

Docker发布一个服务时候默认会选择VIP模式, 下面咱们用一样的镜像演示一下。

docker service create –network overlay-test –name demo –replicas=4 –endpoint-mode=vip —publish 8080:8080 ubuntu-base

启动服务以后咱们inspect一下, 会发现Virtual IPs有两个入口, 期中10.0.0.2就是overlay-test网络下面的一个Endpoint, 这个Endpoint是服务而非容器的。

咱们进入容器中执行dig命令会发现:

此时DNS解析出来的是一个虚拟地址, 虚拟地址经过IPVS和一系列的iptables规则动态转发到容器中。 这样的负载均衡屏蔽了DNS轮询的时效性问题,同时能够支持UDP等协议, 性能也很是好。 缺点是不能作好比回话保持, 基于URL等应用层协议的规则的转发。

下面聊聊Routing Mesh, Routing Mesh的目的是每一个主机上都为服务预留端口, 保证每台机器上均可以访问到服务。实现的办法就是Ingress网络, 以前咱们提到容器中会多出一块网络,咱们Inspect ingress网络,同时会发现网络对应的容器上多出一个容器 ingress-sbox

一个请求到主机端口8080以后, 数据包的流向以下所示:

主机端口8080 => Ingress-sbox-VIP:8080 => 容器Ingress-sbox => IPVS分发到containers。

你们能够看到访问主机以后数据包流到了一个特殊的Sandbox容器里, 这个容器和咱们的容器共享一个Ingress网络,经过Iptables和IPVS等重定向到了最终容器之上。 达到了服务在任何一台主机的8080端口均可达的目的。

已上就是我理解的Docker SwarmKit的几种功能, 一些新的网络技术你们也在讨论,好比Macvlan和Ipvlan等, 经过这些技术Docker的应用场景愈来愈丰富, 愈来愈成熟, 让咱们拭目以待。

 

国内首个基于Docker SwarmKit的容器管理面板——数人云Crane初版最新出炉,欢迎点击“阅读原文”申请体验,点赞or吐槽均可以。

相关文章
相关标签/搜索