上篇讲到Docker容器技术在快速部署、环境标准化、隔离性方面的优势得到了开发人员普遍认可,但是如果以一个完整PaaS平台为标准来衡量这些还不够。首先,Docker提供了名为“容器”的隔离环境,但是面对多容器间有拓扑有关联的场景,Docker还难以应对;其次,虽然容器解决了应用交付规范问题,但难以实现完全应用托管;另外,随着基础设施规模的扩大,开发中心必将分布式化,调度问题就需要解决。从其近年来的产品研发和市场行为可以看出,Docker并不甘于只专注容器的开源生态,而是继续向容器平台的能力拓展,在收购了Fig等一系列容器周边产品后,开始打造自己的容器平台生态。
2014年7月Docker宣布收购单机容器编排软件Fig(后来命名为Docker Compose),并在同年12月推出了自己的容器集群编排项目Docker Swarm。Docker Swarm成功打造了两方面能力:1. 多容器编排能力,支持通过YAML文件声明多容器应用,并定义容器之间的关系;2. 分布式调度能力,允许跨集群节点调度容器。Docker Compose和Dockers Swarm可以基本满足开发人员对于PaaS平台的需求,对于Docker向平台化发展的规划具有基石一般的意义。至此,Docker未来的发展似乎很乐观,但是随着Google加入,容器市场的局面发生了重大改变。 — Google容器编排工具K8S的诞生 —
2014年同年,Google开源了名为Kubernetes(简称K8S)的项目,它是由Google内部Borg项目而开源出来的容器集群管理系统。Kubernetes继承了Google丰富的大规模集群运维的经验和基因,能够提供复杂的、大规模的容器编排管理服务。2015年Google发布了Kubernetes第一个商业版本,代表Kubernetes进军生产级容器规模管理,也意味着开始与Docker竞争PaaS平台的未来版图。Kubernetes集群由两类节点构成:Master Node和Worker Node。Kubernetes采用声明式的设计,任何操作指令都通过声明式API与Master通信。Master Node可响应API声明,进行集群管理和容器调度。容器则运行在Worker Node,Worker负责响应Master指令,执行容器启停等维护操作。Kubernetes中最基础的调度单元是Pod(而不是容器)。Pod内可以封装多个容器,以及这些容器共享的各种资源,包括存储、独立网络IP等。那么为什么不直接以容器为最小调度单位,而是以Pod呢?在上一篇文章中介绍过容器封装了不同组进程,但如果两个模块关系很紧密,例如通过共享存储通信,那分割为两个容器就比较困难了。为此Kubernetes提出把具有这种紧密关系的容器封装在一个Pod对象中调度,可以近似理解Pod就是轻量的虚拟机,每个容器是运行在虚拟机的应用。
除了紧密的容器关系,一个面向生产的编排系统必然应当支持更多的容器关系,所以Kubernetes还提供了Deployment无状态多副本关系、StatefulSet有状态多副本关系、Job一次性长任务等许多对象以满足多样的编排需求。这些对象的基础调度单元还是Pod,由控制器Controller控制Pod对象的状态来实现声明的编排关系。 — 启动一个容器应用 —
下面以Deployment为例,大致介绍K8S容器编排是如何实现的:Kubernetes需要声明一个Deployment的运行规格,就是声明一个对象运行所希望保持的状态。譬如我们需要部署一个Web Server组件,为了负载均衡和高可用,准备运行三个副本,此时就需要通过YAML声明一个Deployment对象,指定Replicas为3。
通过API提交创建Deployment对象请求后,Master Node开始根据声明进行处理。首先Master的调度器(kube-scheduler)会把Pod规划到合适的Worker,并将指令下发给对应Worker。假设三个Pod分别调度到三个Worker,每个Worker的容器生命周期管理组件(kubelet)都接收到Master节点的指令,然后启动Pod。
如果系统运行一段时间后,访问流量变大,需要扩容以提升响应能力,通过声明扩容后副本数就可以实现。命令形如:kubectl scale deployment nginx-deployment--replicas 4命令执行后,Master便会进行扩容操作,把Web Server的第四个Pod副本,调度到某个Worker Node上。
对于正常运行的集群,Kubernetes会不断的收集容器和节点状态,并维护开发者声明的规格。如果某个Worker Node突然宕机,Kubernetes会根据资源和节点工作情况把该Worker上原有Pod重新安排到健康的节点,保证系统正常提供服务。
图5 工作节点宕机后的Kubernetes自我调节
Kubernetes使开发人员和工程师拥有了快速处理大型项目所需的管理工具和基础架构。从负载测试或创建过渡环境,到将业务和在线应用程序移至生产环境,Kubernetes集群都可以对其进行管理。 — Kubernetes VS Docker Swarm —
正如现状,Kubernetes势如破竹的占领了容器编排的霸主地位,那么Docker Swarm早期积累的优势为什么没有帮助Docker创造最主流的编排调度工具呢?我们认为有以下几点原因:与Docker不断并购的运营策略不同,Google提出围绕Kubernetes构建容器生态的理念,通过与Red Hat等公司建立CNCF云开源社区,鼓励各大厂和社区的普通开发人员贡献容器项目,孵化出很多世界级的成功项目,如指标监控工具Prometheus、容器网络接口CNI、高性能RPC框架gRPC,大幅完善了周边配套,影响力逐渐攀升。
Kubernetes获得国外亚马逊、微软、IBM以及国内华为、京东各大公司的大规模应用。各大厂商支持和背书无疑是对一个产品发展强有力的催化剂,这一点对Kubernetes地位的树立有重要作用。Swarm偏重容器部署,是Docker针对自身容器的原生集群解决方案,它的优点是紧密集成到Docker的生态系统,依赖于Docker的API,是创建集群Docker应用程序的最方便的方法,但是对于容器运行时的扩展性会差一些。
而Kubernetes通过CRI(Container Runtime Interface)不仅支持Docker容器运行时,还支持其他如rkt、runV等容器项目,甚至支持客户自定义容器。CRI抽象层使得Kubernetes的运行不依赖于底层某一种具体的容器,这样的管理模式和多类型容器支持使得Kubernetes相比Docker Swarm有更好的可扩展性。Kubernetes与Docker Swarm相比对复杂场景更加友好,更适合应用到生产环境,优势主要体现在以下方面。
1. 存储。Swarm仅提供临时存储,如果进行容器节点迁移,先前节点的数据将丢失。而K8S提供可持久化存储,独立于Pod生命周期,在迁移节点和Pod时依旧可以保证数据完整,直到用户删除为止。 2. 可扩展性。K8S在网络、存储、容器、调度框架等方面的可扩展性都强于Swarm,有更高的可定制度。 3. 集群可维护性。Kubernetes是一种分布式系统的多合一框架,该框架虽然一定程度上会减慢容器的部署和扩展速度,但提供了一套统一的API,结合监控和告警实现了对集群状态的有力保证。 4. 容错性。如果容器宕机,Swarm并不会追踪状态,自动创建新的容器。而Kubernetes则会通过Controller维护规格定义的多副本,确保期望的Pod以维持正常的应用活动,来减少运维人员在故障恢复的时间投入。 — 总 结 —
Docker自2013年发布之后早已成为了首屈一指的容器平台,它能提供轻量的虚拟化和一致性环境,可广泛应用于:将开发环境贴近生产环境,提高开发效率;简化代码流水线;整合服务器提高利用率;多租户场景。未来,从容器应用的角度,Docker仍有广阔的发展空间,在容器主导地位并不断发挥其价值。
而容器编排也已经脱离概念普及阶段,获得广泛落地。目前很多国内外厂商都提供了基于Kubernetes的产品化的解决方案,如亚马逊 EKS、微软AKS、阿里云ACK等。除此之外还有很多厂商基于自身既有特点,发展着自己的容器编排项目,例如亚马逊 ECS、星环TCOS等,提供了丰富的附加能力。
可以说容器技术发展为多种类、增速高的业务发展带来了颠覆性的技术开发方案。未来,随着容器技术的不断深化,以下几方面或将成为关注焦点:有状态应用的支持,无状态应用的可移植性,在物联网中的应用,容器平台的可维护性,以及容器安全问题。
大数据开放实验室由星环信息科技(上海)有限公司运营,专门致力于大数据技术的研究和传播。若转载请在文章开头明显注明“文章来源于微信订阅号——大数据开放实验室”,并保留作者和账号介绍。