(转) Docker - Docker1.12服务发现,负载均衡和Routing Mesh
看到一篇介绍 Docker swarm以及如何编排的好文章,挪放到这里,自己学习的同时也分享出来。
原文链接: http://wwwbuild.net/dockerone/414200.html
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主要功能还是是借鉴了“远古时代”的几款产品, 吸收了前人的优秀经验。 让我列几个牛哄哄的功能给大家吧:
内置Raft, 妈妈再也不用担心我还要依赖Zookeeper、Etcd、Consul了, 光部署这些东西就浪费我一整天外加三台机器。
不区分管理节点和Worker节点,想让谁上就让谁上, 猜想是参考了人家Nomad吧, 关键还能运行时Promote、Demote, 太方便了。
Service,Stack外加DAB, 用过都说好, 方便。
Rolling Update, Scale一个Service,灰度发布分分钟搞定(虽然有点鸡肋),这个不用说也是借鉴了Kubernetes。
一张图展示一下Docker1.12的和老版本的功能对比。
当然当前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块网卡的出现。
lo网卡不用多说, 是本地网卡, 也叫回环网卡;
eth2属于之前创建的overlay-test网络;
eth1和docker_gwbridge网桥构成的网络可以使容器内的服务可以在主机上访问, 主机上telnet 172.18.0.4可以访问到我们的服务,如下图:
eth0是ingress网络中的一块网卡, 是为了Routing Mesh而设,稍后我们会详细说明。
继续回到容器里面看我们查看一下服务情况, 执行命令:
大家会发现通过服务名或者容器ID都能找到IP地址, 区别是服务名发现了本机上所有提供服务的容器IP, 至此同时实现了服务发现和内部负载均衡。
以上就是通过DNS轮询实现的服务发现和负载均衡, 这样的负载均衡是有一些缺点的, 比如:
一些应用可能缓存DNS请求, 导致容器变化之后DNS不能实时更新;
DNS生效时间也导致不能实时反映服务变化情况;
由于以上原因导致的负载均衡不够准确。
下面我来演示一下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吐槽都可以。
(转) Docker - Docker1.12服务发现,负载均衡和Routing Mesh的更多相关文章
- .net core grpc consul 实现服务注册 服务发现 负载均衡(二)
在上一篇 .net core grpc 实现通信(一) 中,我们实现的grpc通信在.net core中的可行性,但要在微服务中真正使用,还缺少 服务注册,服务发现及负载均衡等,本篇我们将在 .net ...
- .Net Core Grpc Consul 实现服务注册 服务发现 负载均衡
本文是基于..net core grpc consul 实现服务注册 服务发现 负载均衡(二)的,很多内容是直接复制过来的,..net core grpc consul 实现服务注册 服务发现 负载均 ...
- .net core Ocelot Consul 实现API网关 服务注册 服务发现 负载均衡
大神张善友 分享过一篇 <.NET Core 在腾讯财付通的企业级应用开发实践>里面就是用.net core 和 Ocelot搭建的可扩展的高性能Api网关. Ocelot(http:// ...
- Docker(二)-在Docker中部署Nginx实现负载均衡(视频教程)
本教程介绍利用Docker部署Nginx服务实现负载均衡. (双击全屏播放)
- 关于Ocelot和Consul 实现GateWay(网关) 服务注册 负载均衡等方面
Ocelot 路由 请求聚合 服务发现 认证 鉴权 限流熔断 内置负载均衡器 Consul 自动服务发现 健康检查 通过Ocelot搭建API网关 服务注册 负载均衡 1. ...
- 解决docker中使用nginx做负载均衡时并发过高时的一些问题
# 解决docker中使用nginx做负载均衡时并发过高时的一些问题 1.问题产生原因: 由于通过nginx作为负载均衡服务,在访问并发数量达到一定量级时jmeter报错. nginx日志关键信息:a ...
- 搭建服务与负载均衡的客户端-Spring Cloud学习第二天(非原创)
文章大纲 一.Eureka中的核心概念二.Spring RestTemplate详解三.代码实战服务与负载均衡的客户端四.项目源码与参考资料下载五.参考文章 一.Eureka中的核心概念 1. 服务提 ...
- 一起来学Spring Cloud | 第三章:服务消费者 (负载均衡Ribbon)
一.负载均衡的简介: 负载均衡是高可用架构的一个关键组件,主要用来提高性能和可用性,通过负载均衡将流量分发到多个服务器,多服务器能够消除单个服务器的故障,减轻单个服务器的访问压力. 1.服务端负载均衡 ...
- RabbitMQ(四):使用Docker构建RabbitMQ高可用负载均衡集群
本文使用Docker搭建RabbitMQ集群,然后使用HAProxy做负载均衡,最后使用KeepAlived实现集群高可用,从而搭建起来一个完成了RabbitMQ高可用负载均衡集群.受限于自身条件,本 ...
随机推荐
- d2.js学习笔记(七)——动态SVG坐标空间
目标 在这一章,我们将学习如何使SVG坐标空间是动态的,这样我们的数据可视化不论数据是什么,都始终是可见的. 我们会使得SVG坐标空间尺度上调或下调来适于我们的数据. 三个SVG长方形 我们就从三个长 ...
- Div层弹出
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <hea ...
- spring mvc:复选框(多选)
以user为例,user下有 username用户,password密码, address地址, receivePaper是否订阅, favotireFramework兴趣爱好, user.java ...
- jsp:xpath - xml
.1 关于“/ ”和“// ”的使用“/”是表示当前文档的节点,类似 DOS 目录分割符,“//”则表示当前文档所有的节点.类似查看整个目录.(1)/authors/author:表示选择根目录下.父 ...
- 利用 innodb_force_recovery 解决MySQL服务器crash无法重启问题
背景 MySQL服务器因为磁盘阵列损坏机器crash,重启MySQL服务时 报如下错误: InnoDB: Reading tablespace information from the .i ...
- 猪齿鱼_01_环境搭建(二)_微服务支撑组件部署(Docker形式)
一.前言 上一节,我们以源码形式部署好了猪齿鱼微服务组件,过程繁琐,且启动后占用了服务器大量的资源,对开发极其不友好.
- LeetCode OJ:Compare Version Numbers(比较版本字符串)
Compare two version numbers version1 and version2.If version1 > version2 return 1, if version1 &l ...
- C#调用EasyPusher推送到EasyDarwin实现视频流中转
本文转自:http://www.cnblogs.com/kangkey/p/6772863.html 最近在公司项目中,遇到需要将内网的监控视频信息,在外网进行查看,最终通过查阅资料,发现EasyDa ...
- 函数及参数http://www.cnblogs.com/Eva-J/p/7125925.html
文件的修改操作.删除操作,with语句 函数: 函数的定义:def 函数名(形参1,形参2....): 函数的调用:函数名(实参1,实参2) 函数的返回值: 定义阶段:return 三种情况:没有返回 ...
- Android 蓝牙 socket通信
Android中蓝牙模块的使用 使用蓝牙API,Android应用程序能够执行以下功能: 扫描其他蓝牙设备查询本地已经配对的蓝牙适配器建立RFCOMM通道通过服务发现来连接其他设备在设备间传输数据管理 ...