目前在容器编排领域,Kubernetes、Mesos以及Swarm呈现“三分天下”的格局,各自都有着不同的应用场景。短期内,很难看到“一统天下”的局面,本文,来自阿里云高级专家陈萌辉将带你了解阿里内部在推行容器化过程中的一些着力点,同时,他将深刻剖析Swarm的进化史以及在阿里云的大规模应用,最后,他给出三个案例,供大家参考。
阿里从前年开始就已经在集团内部大规模地推行容器化和运用Swarm来做应用的发布、集群管理等事情。特别值得注意的是去年,阿里云跟Docker达成了一项深度合作的协议,从中我们不难窥探阿里的容器战略。本文将从三个方面阐述“Swarm的进化和大规模应用”,第一,
Swarm架构;第二,Swarm Mode的编排;第三是Swarm在阿里的应用。
Swarm架构
图1 Swarm架构
我们先看一下Swarm是什么?Swarm,是Docker官方推出的,它的特点就是跟Docker本身有很好的集成,另外,它也是一个非常简单易用的工具,所以目前吸引了很多开发者在用。
Swarm是Docker公司继Docker Engine之后推出的很重要的集群管理系统和容器编排与调度系统。架构底层是集群的机器资源,可以是一些物理机也可以是一些虚拟机,上面经过Swarm这一层把容器调度和部署到这些机器上去,它对外提供跟Docker类似的API。
具体来看,Swarm的框架分成三块,第一块是Engine,第二是Manager,第三是KV store。它有几个特点,第一依赖外部存储来完成节点发现并保证一致性;第二,Manager只跟Daemon通信,不跟Agent通信;第三,Manager可以有多副本,这是为高可用设计的,采用一主多热备模式,所有manager都同时连接所有Daemon,备转发请求至主,另外,它依赖外部KV选主。
API
Swarm提供的API,主要是有这么几类:
集群类:info events
容器类:get/list、create、start/stop等
镜像类:get/list、push、pull、tag等
数据卷类:get/list、create、delete
网络类:get/list、create、delete等
调度
资源维度层面有三个: CPU 、Memory、 端口,CPU / Memory支持超卖;调度策略有两种:spread
/ binpack,另外,它不支持优先级、抢占。
它比较有特点的一些功能有两个,一个是叫节点约束,约束可以有两种类型,比如说你可以约束我这个节点是哪一个,你可以给节点去一个名字或者打一个标签什么的,另外一个可以通过打标签去选择一种机器,你在部署的时候,可以指定这些容器部署到哪些机器上去。
节点约束:
节点名:constraint:node==XXX
标签:constraint:key==value
亲和性也有两种,一种是image,一种是service,比如我有一个应用镜像很大,我不希望它在集群各个地方去部署,我希望他部署下来已经下载镜像的地方,这样的话可以减少一些启动的时间和下载的过程,你可以说我这个服务不是跟某个镜像做亲和,也可以跟某个服务做亲和。
亲和性:
镜像:affinity:image==foo
服务:affinity:service==foo
总结一下Swarm这个产品,Swarm整体来说有几个特点,第一个是部署简捷,只有三个模块,外部的依赖只有KV
Store和Docker Daemon这两个,所有组件都容器化。第二高效友好的用户交互,高度兼容Docker
Engine API,可直接使用Docker Client。第三是灵活的约束与亲和性描述,可以在一定程度上弥补调度策略的不足。
同时,我们也看到它有一些不足的地方,首先一个不足的地方就是它是容器级别的API,所有的API都是针对单个容器的,抽象层次较低。其次,响应式设计,不方便执行常驻后台的操作,它在内存中不保存任何的状态,所有的状态都是从Docker上统计过来的。有一个好处,它一旦挂掉了,能够很方便地恢复状态,但也有一些坏处,比如你要跑一个离线的任务,就不太好做。除此之外,它依赖定期同步跟Docker
Engine保持一致状态。
Swarm Mode
针对Swarm这个产品的一些不足,从1.12版本开始,Docker就提供了Swarm Mode的功能,这个功能是将Swarm的集群管理、容器调度功能集成进Docker
Engine,并且提供Service级别抽象和自带的负载均衡,它从容器级别的调度器进化到了服务级别的调度器。
架构
图2 Swarm Mode架构
它的架构比Swarm更简单一些,首先就是它没有任何的外部依赖,只要你装 Docker Engine,它就可以构成一个容器集群,DockerDaemon本身会兼Engine、Manager、Agent三职。Managers之间通过RAFT协议组成分布式强一致性KV
Store,Manager与Worker的Daemon不通信。
同时,它也是有高可用设计的,Manager数量需要大于等于3才可以实现高可用,它也是一主多热备,另外也可以动态添加/删除Manager,如果有的机器宕机或者挂掉了,你不需要把这个机器再恢复起来,很多系统对Manager控制器的机器是有依赖的。如果一旦挂掉了你只能把它修好之后再上来,但是这个是不需要的,你可以任意在里面编程。这样他会通过RAFT协议把原来集群状态信息统一到Manager上去,这样有实现了高可用。
Swarm Mode API
在刚才Swarm的API之上,多提供了两类的API:
集群管理类:
init、join、leave
token
服务类:
get/list
create、delete、update
inspect、ps
同时,Swarm的API有两个特点,它分两类,一类是像Swarm、Service、Network类,只有Manager能处理的。还有一类容器、镜像、数据卷类,所有节点都能处理。另外它的API还是高度兼容旧的API,你可以拿低版本的去访问Swarm
mode的集群。
Service
我们来看一下Swarm Service的概念,它提供了三级的概念:
Service:相同功能的一组容器
Task:任务调度单元,由Manager生成,同步至Worker
Container:Task落地
另外,还提供Rolling Update功能。
在Swarm mode里面Service分为两类,一类是有Replicated Service,一类是Global
Service。
Replicated Service:
用户指定副本数
Reconciled:自动确保副本数
constraint
node.id node.hostname:
node.role
node.labels engine.labels
Global Service:
每个节点有且仅有一个容器
添加加点时自动扩展
可附加constraint
网络模型方面,支持overlay网络,同一网络内,服务名、容器名可解析;一个服务一个网络;服务发现支持不同服务可加入同一个网络。
Routing Mesh
下面我们看一下Swarm自带的负载均衡,它取的名字叫做Routing Mesh,Service自带的负载均衡是基于LVS,主要有两种模式,
VIP模式:每个服务一个VIP,通过LVS实现;服务名解析至VIP;
DNS模式:服务名解析至容器IP,RoundRobin方式。另外,服务发生变化时,自动调整后端。
总结一下Swarm Mode的产品,第一个它是无任何依赖,可以安装Engine+一个命令,无中心架构。第二个它可以部署高可用服务,你可以在集群这边进行访问的,比如说你的容器只布在了三台机器,这个集群所有的机器都可以访问到这个服务,这样的话就很容易做成高可用的。再一个Secure
by default,自带证书颁发、更新功能,Manager与Worker之间通过SSL连接。
当然它也有一些不足的地方,第一个只有Service级抽象,Stack级抽象仍无API,另外,部署有状态服务比较复杂。第二,Service
API有很多容器特性不支持,如host network、host pid、privileged等。还有一个缺点,它无法自举,是需要手工init的。
Swarm在阿里内部的应用
上面介绍了Docker Swarm的产品相关的东西。下面我就来介绍一下Swarm在阿里内部的应用,这个也是大家更关心的一个地方,有几个方面。第一是阿里内部的容器化,可能大家都知道,阿里内部有一支非常强大的运维团队,除非查问题的时候,一般开发人员是不接触现代的机器的,所有的应用部署、升级这些都是运维人员来做的。强大的运维团队也导致了一些问题,它的应用的部署和升级往往是很个性化的,可能这个运维人员他在支持这个应用的时候,通过写一些脚本或者用一些工具,实现业务的部署的自动化,而另外的运维人员运用另外的工具和另外的脚本,导致了很多应用的升级部署不是一个标准化的方式。这样的话,比如说这个人员他转岗了,新来的人首先要去熟悉那个部署的工具,这个运维任务比较大,所以应该是从去年、前年阿里内部开始推容器化,由Swarm来统一管理我们的集群,应用的话就是容器化之后,由Swarm去统一做部署,这样的话就会形成一个跟业务无关的统一的部署平台。运维人员不再去关心应用如何地去部署,他只要关心把这个应用部署上去就可以了,所有的应用都是一样的方式,即使有新的人接替他学起来也非常地方便。
图3 阿里云容器服务整体架构
另外是阿里云的专有云输出,因为专有云这个东西一旦部署到用户的机房之后,你升级就变得非常麻烦,有了容器之后,它的镜像的管理和升级就非常方便了。还有一个优点,它可以实现管控部署的资源优化,因为原来可能所有的管控都是独占机器的,这样的话比如说你布很多服务就会占很多机器,有了容器之后管控就可以共享机器了,减少了管控所占的资源,提高了用户能使用的资源的数量。
第二是阿里云的容器服务,这是我们在阿里云公有云上推出的一款产品,作用是帮用户管理集群和部署应用,当然还提供更多高级别的服务。
第三是阿里云高性能计算 HPC也会用到容器,在高计算领域,它的安装很复杂、很麻烦,经常比如说你拿到一个带显卡的机器,你在上面部署基础的应用,可能得花掉你一周的时间,如果你的应用是容器化的,这个事情就可以放到容器里面去,你只要关心自己的应用就可以了,可以大大地提高应用部署的效率。
下面重点介绍一下阿里云容器服务的一些特性,我们先看一下整体的架构,整体来说,阿里云容器服务是一个集群托管的模式,机器是用户的,但是管控是我们提供的。现在相当于我们帮用户管理他的机器,我们通过某一些界面化、某一些API的信息让用户去管理集群以及管理他的应用。
用户的机器下面会装Engine、下面会跑容器,我们这边的管控提供一个控制台,提供集群的创建和扩容这样的功能,然后提供服务、注册和发现的功能,提供应用生命周期管理和使用调度的功能。同时我们还会把很多阿里云上的服务都集成进来,比如说我们集成了SLB、ECS等功能,达到的目标让用户只关心我的应用,而不需要关心底下的机器。
我们可以看一下我们提供的功能,从四个角度讲。
第一个是集群的管理,这是最基本的功能,我们可以帮用户一键创建出一个容器集群,同时支持公有云、专有云、混合云以及敏捷版,公有云包括GPU的机器,专有云是部署在用户机房的,混合云就是你可以一部分集群管控在我们的机房,但是真正的用户机器在你自己的机房。你可以实现应用跨云的统一部署。另外还支持bare
metal敏捷版。
第二是镜像服务,这是对容器化很重要的服务,我们支持公有和私有的仓库,你可以有自己的私有仓库,同时支持DockerHub的加速,我们提供这个加速的功能可以让你像访问国内的机器一样,另外可以连接第三方代码库,这样,其实你可以当成CICD系统的最重要的环节,你可以从代码到最终生成镜像,甚至到最后部署把它全自动打通。
第三是应用生命周期的管理,支持Swarm和Swarm Mode两种模式。
同时支持Rolling Update、蓝绿发布、离线与定时任务。
最后是微服务的支持,微服务它不是为容器而生,但是有了容器之后它的实现会变得更简单一些,为了微服务的支持,我们提供了一些很重要的基础的功能。包括服务发现、负载均衡、弹性伸缩、集成监控与日志、集成共享存储。
这是在阿里云上部署一个nginx应用的一个例子,这是用的3.0的模板,用Engine来部署,它可以通过8080端口来访问到。
图4 负载均衡案例
version: ”3.0”
#支持v1 v2 v3 compose模板
services:
nginx:
image: nginx:latest
deploy:
mode: replicated
replicas: 3
ports:
- 8080:80
labels:
aliyun.lb.port_8080`: tcp://slbtest:8080 #负载均衡
aliyun.log_store_dbstdout: stdout #日志收集
aliyun.log_store_varlog: /var/log/*.log
volumes:
- 'website:/usr/share/nginx/html'
volumes:
website:
driver: ossfs #共享存储数据卷,支持oss、nas
driver_opts:
bucket: acs-sample |
自动扩容的事例,简单来说,你只要声明一下,当CPU超过70%了就扩展出两个容器来,我们的做法是通过监控平台把数据收集上去,之后,如果当它超过了70%的时候会调用集群管理的API,给它扩出容器来,同时会把负载均衡的后端再挂到新的容器上,这样就实现了自动扩容。
图5 自动扩容案例
声明式自动扩容
aliyun.auto_scaling.max_cpu: 70
aliyun.auto_scaling.step: 2
监控插件
输入: nagios, apache, docker, UDP, ….
输出: Influxdb, prometheus, kafka
蓝绿发布的事例,如图6,蓝色的应用要进行升级,怎么做呢?首先部署一个新的应用,这两个是同时在线的,它会通过SLB给它分流量,比如80%和20%,之后做验证,验证之后,发布完成,系统就会把原来老的删掉。
图6 蓝绿发布案例
机器学习案例,假如你的集群是稳步的,有GPU机器和非GPU机器,你可以在你的Service里面注明需要两个GPU,系统会把你调度到有GPU的集群,同时把你的应用绑到GPU卡上去。
图7 机器学习案例
version: '2'
services:
inception:
image: acs_sample/inception:demo
volumes:
- inception_model/inception_model
labels:
- aliyun.gpu=2
ports:
- "9000:9000"
volumes:
inception_model:
driver: nas |
|