摘要:一个容器起来,能够对外服务,这时就看下一步的负载均衡服务发现以及编排。它们有不同的应用场景,比如倾向于四层的负载均衡。不单是负载均衡,它同时解决了服务发现和负载均衡两个点。
今天是数人云容器三国演义Meetup嘉宾演讲实录第二弹。数人云工程师春明为大家奉送了一盘干货的大餐,让我们读读源码,深入了解一下SwarmKit的世界吧!
小数前方预警:有大量代码出现!
今天与大家分享一下数人云对于SwarmKit的尝试和探索。Swarm早在2014年就出来了,和Docker Compose几乎是同一时期。Docker解决的是单机上容器的问题,但如何在一个集群一组的硬件资源上去调度容器?Swarm可以解决。SwarmKit是在Swarm的基础上研发出来的,只不过Docker公司对SwarmKit联系得更紧密。SwarmKit的主要代码提交在2016年4、5月份, Docker1.12出来以后正式把它release出来。
我个人比较看好SwarmKit的原因在于它很简单。在生产环境部署Mesos或者Kubernetes,需要安装的组件非常多。Mesos为例,首先要装Zookeeper,然后装master、 slave,它们之间配置、连线都很复杂,更不用说每条连线后面大量的工作,最终cluster才能跑起来,并且有很复杂的API。相比而言,SwarmKit非常简单,一个Binary解决所有问题。
今天分享的第一部分会和大家说一下什么是SwarmKit,第二部分聊聊ServiceScheduler,从一个程序员的角度思考如何构造一个调度器。这个调度器, Service Scheduler,类似于SwarmKit、Kubernetes、Mesos加Marathon。第三部分通过几段代码片段了解SwarmKit的关键点。
SwarmKit的概念SwarmKit、Swarm、Swarm Mode这三个词,对刚开始接触的人来说可能有很多困惑。SwarmKit是Swarm这个项目的升级版。Swarm和SwarmKit最主要的区别在于Swarm是多带带运行的,它需要一个第三方的分布式存储,它支持三种存储方式,即主流的三种分布式存储——Zookeeper、ETCD和Counsul。
SwarmKit在Swarm的基础上精进了一步,不再需要有第三方存储,也不需要做Leader选举。它的发布方式,一种是独立的,另一种是直接和DockerEnginet混搭放在一起。所以大家安装新Docker1.12版本之后,实际上也拥有了SwarmKit。你有多台机器安装了Docker1.12版本,就已经拥有了一个Swarm的cluster,在上面就可以把任务负载到不同的机器上,不需要再去安装一堆组件。另外一个词叫Swarm Mode,如果你开启了Swarm模式的Docker Engine,用Docker的集群功能的时候 ,它实际上就是进入了Swarm Mode。
构造服务调度接下来聊一聊从一个程序员写代码的角度理解如何去构造一个Service Scheduler,服务调度。程序员其实不太关心底层的硬件资源或者Saas层是怎么来的,更多是考虑如何实现一个任务或者一组任务去分发、放在不同的一组机器上。如果想做好这个事情,无论是公有云、私有云或者虚拟机,首先要做的应该是把所有的资源进行抽象。如果是Mesos Framework,第一件事情是去Mesos申请一块资源,不用关心资源到底来自于哪里,你申请一个offer、要两块CPU或者200M的内存, Mesos如果满足你就会反馈OK,如果满足不了你就告诉你等一下。首先把一组资源抽象,比如池子有多少个CPU、有多少内存,把它抽象。第二步分配,如果有一个请求过来,就从池子里面分配资源,然后release。
服务可能分很多个进程,最终负载在不同的机器上。第二部分,是对服务这个概念上有一个抽象,服务应该有它的生命周期、健康检测。服务下面应该有不同的进程,这在不同的Service Scheduler有不同的叫法,比如Marathon把它叫做instance, Mesos中叫task,SwarmKit也叫task,实际上它是一个运行中的实例,包含了刚才从资源池里申请的一块资源,并且有自己的生命周期。其中最重要的应该是健康检查,不同人对一个服务的健康状态有着不同的定义。
以前我们用Docker Daemon,那现在如何判断一个服务是不是健康的?在DockerEgine加入了健康检测之前,我们主要看它的容器是否起来。一个容器起来,能够对外服务,这时就看下一步的负载均衡、服务发现以及编排。服务之间其实有一个依赖,服务A在依赖服务B的情况下,只有服务B起来,服务A才能起。所以这一步很重要,对应用具体的实例抽象,这里面其实是一个状态机,专门做了状态的切换。
第三部分,在做一个服务编排的时候,应该有一定的策略、算法去做服务的分发以及服务的编排。某些服务可能对特定资源有一些特别的需要,比如对网络的需要比较强,对存储、对运算能力可能有一些特别的需求;两个服务之间有一定的亲缘性,比如希望web服务跑在离开我更近的缓存上面;服务有几种分类,举例来说,Web的应用和数据库类型的应用其实有一些区别,数据库类型的应用对弹性的需求没有那么高,而Web服务对弹性的需求比较高。所以第三件事情应该是做好这一层面策略以及分发。
第四部分,把一堆服务都分到下面不同的机器上,有不同的分发策略以及不同的网络模型后,如何让服务真正的对外服务?即如何解决服务发现、负载均衡还有Proxy这层的问题。市面上服务发现的方案非常多。比如SwarmKit通过DNS实现,IPVS也是它的一种。新浪微博提出的NginxModule以及更早期的一个开源项目叫Bamboo,一个刷HA的工具,如果容器的状态有变化,它会通过Bamboo去刷HA的配置,最终把HA重启。还有Registratorr、confd、 Counsul Template等一些项目,其实都是着力解决服务发现、LoadBalance以及Proxy。
对于服务发现,DNS、SRV、 IPVS都是非常好的解决方案。它们有不同的应用场景,比如IPVS倾向于四层的负载均衡。DNS不单是负载均衡,它同时解决了服务发现和负载均衡两个点。
我们的场景非常需要Proxy层,对它有很多期望:比如流量分发、限制、统计以及灰度发布等。最近我做的一件事情是在所有的应用前面加一层Proxy,大家可以理解为一层Nginx或者是一层HA,但实现HA这种性能其实是很难做到的。
如何做好一个Service Scheduler,除了上述几点,接下来几个方面也很重要。第一,HA的需求,即客户对ServiceScheduler的高可用性的要求,数人云有很多金融方面的客户,他们对HA要求更高,比如提到的“两地三中心”,归根结底是HA的需求。
第二个,安全方面, SwarmKit支持分布在不同的地方,那么解决安全的问题就非常重要。Docker的安全问题很严重,因为实际上Docker给外部的人有权限去执行任何程序。
解决HA问题无非是要布多个,布单个可能有单点的问题。SwarmKit从中借鉴了很多,它把Mesos的几个部分合在一起,这就引出一个问题,比如它要记录状态,那么如何在一个分布式的环境下去记录这个状态,分布式的存储。
这是开启一个SwarmKit的管理节点的一行命令,相当于安装一个Mesosmaster和一个Zookeeper。第二个命令是把当前Docker agent加入到一个Swarm集群里面,相当于装了一个slave的节点。刚才这两条命令其实就构建了一个两节点的Swarm集群。
这张图描述了Swarm的工作模式。有三层,这是一个二进制,它们充当不同的角色。这些线彼此连接,可以看到Manager和Manager之间是可以交互的,Manager和Worker之间也可以交互。Manager和Manager节点之间交互是raft协议在做Leader的选举,和Worker之间的这条线表示把一个任务分发到不同的Worker上。在SwarmKit里面,Worker换了一个名字叫叫agent。Worker听起来像纯粹干活的东西,agent则还能做一些其它事情,比如做健康检测、做主机、主机资源的收集。
在图上大家会看到每一个Worker和三个Manager同时通信的,但事实上不是这样, SwarmKit在同一时间只和raft选举出的一个leader去交互。
SwarmKit的关键组成
接下来展示SwarmKit的代码结构,来了解它们各自的工作。第一个是agent,即刚才说的Worker,它做的事情是SwarmKit节点作为agent的时候要做的事情,代码写在agent这个地方。第二个是API,API不是通过HTTP REST Service或者通过命令行跟它交互,API实际上是Manager和Worker之间交互的那些命令,它用gRPC协议,通过protobuf协议来交互。第三个目录叫CA,CA解决安全问题。SwarmKit号称安全做得很好,它的公钥和私钥可以ratate,即它的公钥和私钥有一个过期时间,然后再不同的循环,所以私钥被compromise的时候不会影响整个系统的安全性,因为会rotate它。CLI和CMD是操作一个SwarmKit时的入口。design是设计文档。integration是集成。
下面是比较重要的两个文件夹,第一个是Manager,和上面的agent对应,一个Swarm node在充当一个Manager的时候,它的逻辑就在这里,即它分发、健康检查及其他代码都在Manager上面。另一个是node的节点,Docker Swarm init的时候就是创建一个node逻辑的概念,其主要的代码在node的下面。
这张截图是打开agent的文件夹,介绍一下每个文件分别做什么。第一个是文件夹,这里的核心逻辑,exec文件夹下核心文件是一个Docker client。大家如果用GoDocker client会发现里面就是这些——如何维护、连一个Docker的agent去update、create、destroy Docker的代码。但它使用的是docker engine-api的库,而不是Godocker client,因为engine-api那个项目是Docker公司的,agent的核心代码都在里面。
接下来比较重要的就是Task、Worker和Session这三个文件,Task是任务的一个抽象。agent下面的数据结构里面会包含一个Worker,它是task真正干活的东西,之后我们会详细的说一说Worker。刚才图中看到Worker和Manager之间那条线用的就是Session的抽象。
另一个比较重要的文件夹是Manager。它的文件夹很多,第一个allocator主要是说资源,要申请哪些资源。它里面对网络有一些抽象,从申请上看对CPU和Manager没有提到,它只是对申请allocator有一个网段。constraint是有哪些限制,大家如果用过Mesos都会知道对任务的开发需要一些label满足SSD、memory等,就是由constraint来做。controlapi是alloctator和外面交互的一个API层。下面的dispatcher和orchestrator和scheduler这三个词很难说它们本质有什么区别,只是多少会有一点。orchestrator更倾向于Swarm的任务,它分两大类, replicate和global的任务,global的任务在每个node上只部署一个节点。replicate是传一个数量,然后部署这个数量。
看了整个代码,我总结出了几点核心概念。第一个是Node的节点,更确切的说是对Dockeragent的一个抽象。然后Manager节点。Manager和Node agent是一个Node,它既可以作为Manager又可以作为agent,或者同时兼有两个。第四个是Task和Service,Service是我们更高一层对应用的抽象;Task是一个进程,更确切地说应该是一个容器。SwarmKit的Task和Service都有自己生命周期的定义。
读SwarmKit的代码比较好的一点是它入口非常简单,每一个核心的概念里面,一个new、一个run。new是初始化的数据结构,run是真正的干活。大家如果想快速的了解代码,去每一个概念里面了解这两个函数基本上就知道它们做了什么。
这是Node节点的new。Node的节点最核心的是初始化了一些channel,在上面创建了文件夹,这基本是Node节点的new,但是它的run做了很多事情。run的函数很长,里面主要做了一些文件夹初始化,以及SwarmKit用了一个在golang社区比较流行的DB叫bolt DB,这里主要初始化文件夹和bolt DB的初始化。run另外一个比较重要的是 Node的节点,Node的节点可以创造Manager的role。Node既可以充当Manager的role,又可以变为Worker的role,这两个角色可以在运行时动态变化。它们在每次变化的时候,比如变成Manager,那作为Manager身份的一些功能就开启,由Manager变成agent这些功能可能就被disable掉。
第二个关于Node的概念是Manager,这是Manager的数据结构。比较有意思的是中间这一部分它作为一个CAserver,作为一个dispatcher,作为一个replicatedOrchestrator,或者是作为一个global Orchestrator。这些是作为Manager功能的数据结构。
此图是Manager的new,这一屏核心是监听了一个端口,它和Docker Engine非常像,监听一个TCP的端口,或者监听一个unixsock的端口,都是可以的。只监听一个TCP其已经满足大部分场景,那么Docker、agent为什么监听一个unixsock的端口?大家关注过Docker Engine就会知道,有一个Docker in Docker非常适合Docker测试。如何做到Docker in Docker呢?就是把unixsock传到Docker里,相当于在一个Docker容器里控制外面的那个Docker。
这是Manager new的第二个slave,是Manager真正干活的时候,也比较简单,主要是两件事情,第一件事情是作为一个Manager节点,监听了raft的协议一些change的变化,第二是注册了一些API,这些API是Manager节点和agent的节点进行交互的一些API。
注意一下handleLeadershipEvents, Manager实际上是一个小的区别于Node的节点,这几个Manager节点参与raft的选取过程。Manager节点最终干活的只有一个,就是raft协议选出的那个leader。在这个raft协议leader变化的时候,作为Manager节点干的活就不一样了。
在LeadershipEvents发生的时候,当前的Manager就看一下自己是leader还是follower,然后根据不同的角色转换去做不同的事情。
Agent
第三个重点是agent。之前提到做一个Node的agent角色的时候,作为agent的角色它需要做哪些事情——负责Task的分发和执行。Worker这边,它作为一个interface,在agent里则作为agent。它作为interface给大家一个可能性,即SwarmKit这本身可以不只依赖于Docker Engine。我见到开源项目有人叫SwarmKit on Mesos,只要有不同的worker实现,通过Swarm底层是可以运行Mesos的。SwarmKit本身对资源和任务的抽象抽象是固定的。
作为agent,其实多了一个Start, Start的时候支撑了run的函数。核心在于让agent下面由Worker开始干活,以及维护和Manager之间的session—— agent和Worker之间,比如leader的变化、session的变化,有error都会通过session来通知agent做一些相应的事情。比如assign一个task到某个agent或者session处理一些error,大家都可以看到。
还有一个executer。executer内部是一个Docker client,操作Docker,实体化一个Docker,以及删除一个Docker。
Sessionsession是agent和Worker之间线的抽象。底层是一个gRPC的的client connection,上面有一些Mesos传递方式,有一些channel。初始化一个session,核心在于gRPC去diy一个Manager节点和建立物理上的连接。
Task
这部分代码是TaskSpec的一个描述,并不是真正运行时Task的表达方式。因为Spec其实相当于一个模板, Task第一个field是ContainerSpec,从这里可以看出Task实际上是对container的包装。下面的Resource requirements是需要什么样的资源。第三个是RestartPolicy, Task restart的时候都有哪些策略。Placement对应Manager constraint那一部分,把这个Task负载到一个什么类型的Worker上面。这是Task和Spec运行前的描述。
这是Task的一个结构,它有一个引用是到Taskspec上,上面是一些运行信息,比如Task最终在哪一个Node的ID上,Task最终属于哪一个Service,以及Task slot。我在Google Borg也见到这个slot的概念,它是一个逻辑概念,相当于对资源是一个预留。如果一个Task在slot上失败了,你会发现slot还在,这个Task历史也会在那儿, Task不断的在slot上重启、重启、重启,它实际上是对资源的一个reserve。
这是前面提到的Task life circle,Task有这么多状态,这些状态其实是对一个Task的抽象。作为Dockercontainer,大家会发现状态没有那么多,无非是running和非running。但作为一个Task,它抽象的状态就非常多,可想而知这些状态都是一个状态机,它们之间可能有各种互相的迁移,情况比较复杂。
这是一个Service,很多个stack构成Service。Service mode会分Replicated Service和Global Service,Manager下发一个Service的时候分这两种模式。下面一个字段叫EndpointSpec,是Service对外服务的时候选择哪一种服务发现的方式,目前有两个选项, DNS和VIP。DNS相当于为每一个运行时的Task生成一个DNS SRV结构;VIP的表现形式是Task,因为Docker inspect Task的时候,Task会有一个自己Task的IP,然后Task IP每次请求都打到这个Task IP上,通过IPVS负载到后面每个容器上。这是运行时Service的概念。
SwarmKit目前代码较少,是一个上升的社区,值得关注。今天的分享就到这里,谢谢大家!
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/26761.html
摘要:更多技术栈的包容数人云技术团队为了帮助广大技术爱好者对新版本有快速直观的感受,制作了一款基于最新特性的容器管理工具,具备一定容器开发经验的开发者可以通过它在第一时间体验的新特性。可以说,数人云是在技术能否持续下去的争论中发布的工具。 showImg(https://segmentfault.com/img/bVD5g2?w=900&h=500);中秋节前, 数人云技术团队推出了一...
摘要:进阶期理解中的执行上下文和执行栈进阶期深入之执行上下文栈和变量对象但是今天补充一个知识点某些情况下,调用堆栈中函数调用的数量超出了调用堆栈的实际大小,浏览器会抛出一个错误终止运行。 (关注福利,关注本公众号回复[资料]领取优质前端视频,包括Vue、React、Node源码和实战、面试指导) 本周正式开始前端进阶的第一期,本周的主题是调用堆栈,今天是第3天。 本计划一共28期,每期重点攻...
摘要:源码解读系列二启动阶段都干了些啥阅读框架源码了解启动阶段的那些事儿小伙伴刚接触的时候会感觉压力有点大更直观的说法是难开发组是不赞成难这个说法的的代码都是实现的而又是世界上最好的语言的代码阅读起来是很轻松的之后开发组会用系列源码解读文章深 date: 2018-8-01 14:22:17title: swoft| 源码解读系列二: 启动阶段, swoft 都干了些啥?descriptio...
摘要:相关基于项目和项目,并遵循应用的十二因素风格。相关在设计上,项目尽量保持驱动和模块化,以便模块支持不同的实现方案。相关不仅可以管理众多虚拟机,其计算服务还支持对的驱动,管理引擎的子项目还可用于通过模板管理容器。现已整合公司所支持的项目。 整理自《Docker技术入门与实践》 PaaS(Platform as a Service) PaaS 是希望提供一个统一的可供所有软件直接运行而无需...
摘要:终上所述这一切的一切,就是因为你技术不行但使龙城飞将在,不破楼兰终不还但使双手两眼在,不入阿里终不还是的,只要你双手还能敲代码,双眼还能看得见,对于程序员来说,阿里等这些大厂将会是你技术的必达点。 人在屋檐下,哪能不低头 (记2018年底互联网大寒潮) showImg(https://segmentfault.com/img/bVbmULW?w=240&h=240); 伴随着深冬凌冽的...
阅读 1733·2021-09-27 14:02
阅读 2948·2021-09-27 13:36
阅读 1029·2019-08-30 12:46
阅读 1819·2019-08-30 10:51
阅读 3545·2019-08-29 17:02
阅读 920·2019-08-29 16:38
阅读 1817·2019-08-29 16:37
阅读 2946·2019-08-26 10:32