基本概述
不管IT领域如何的分层抽象,应用的开发者始终是面向终端用户提供真正业务服务的主体,尽管现阶段云计算的进步是希望通过分层抽象的能力,尽量转移和减少开发者聚焦点,让其专注到提供业务服务上来,但是任何技术的演变进步,最先感受到的其实还是应用的开发者们。
在容器技术普及之前,应用的开发者们一直是基于物理机或虚拟机的开发运维环境的,而物理机和虚拟机给开发者提供的抽象服务就是操作系统,而操作系统为应用开发者提供了“进程”这个管理应用运行全部资源的抽象服务。
物理机-->虚拟机-->操作系统-->进程
容器技术在paas平台化时期就存在,本质上也是基于Linux系统提供的资源管理的能力来提供的封装。只不过在Docker没有出现之前,容器这项技术因为太涉及操作系统层面提供的能力只被小规模的运用。
传统应用开发运行环境
开发者大概都有普遍的经历,就是开发和部署的应用在服务器上运行的时候,因为操作系统的cpu的竞争分片的运作机制,经常会面临着应用在不同服务器上部署规划和运行时启动应用进程的数量的问题。
传统情况下,开发者发布生产应用通常通过一个公共的部署发布的机器来与生产域服务器交互,部署和启动应用程序。
此时的开发者需要关注如下方面(有专业运维团队的,在运维团队考虑,大多数情况下都是开发者的事情):
1)应用在一群服务器中的部署规划,也就是哪些应用应该怎样的划分部署在哪些服务器上;
2)应用启动进程,因为是竞争销毁计算、存储等能力的,所以需要凭借经验预估计算资源占比,甚至还要考虑业务一定的冗余量;
3)为了服务器的稳定,同时也为了应用能够在服务器出现宕机的时候进行备用切换,所以一般需要将生产使用的服务器负载的占比控制在50%以内,极大的浪费了资源。
直到今天,很多领域仍然在应用部署上线之前,会做一系列的人工的部署规划和资源预估,这些基本上是凭借着经验或者一些历史的运行数据来参考完成的。
Paas模式下应用开发运行环境
容器技术在PaaS平台推出时期阶段就已经存在了,PaaS平台模式早期在一些大的应用体的公司落地,主要解决的也就是传统应用部署和分发存在的一系列的问题。
PaaS平台在原先开发环境中部署了一套应用的打包和分发机制的服务,这套服务主要围绕“应用”构建一套管控的体系。
1.在这套体系里面,开发者关注点发生转移:
1)过去大部分管理应用的手工过程,都被PaaS平台中构建的应用打包和分发机制所取代;
2)开发者只需要在PaaS平台中通过发布命令或者对用的可视化操作来发布应用,并不需要具体知道应用运行的服务器上面都部署了哪些具体的应用;
3)开发者需要重点关注的是应用打包时候的程序和配置的启停脚本的环境,这是需要重点关注的。
PaaS平台为了实现这套能力,内置了一套典型的前面文章介绍的任务调度机制的服务,结合了容器技术(linux上的cgroups和namespace技术,具体这部分在Docker小节理解)来为每类在上面发布的应用创建一个盒子的运行环境。
2.这时候应用的发布流程如下:
1)开发者提前在PaaS平台中构建好需要运行的程序包,程序包中包括了应用程序和相应的启动脚本;
2)开发者在PaaS平台操作相应的应用定义和发布启动的命令;
3)PaaS平台的调度器接受相关应用发布命令,通过调度器选择某台服务器节点将启动应用命令下发给该服务的agent;
4)服务器上agent接受启动命令后,将连接并下载指定的程序包到本地,控制程序包中的脚本,启动相应的应用程序。
3.开发者关注的问题被解决:
1)应为调度器的存在,应用进程出现故障可以被确保在其它的服务器中启动起来,因此故障互备不再需要专门的服务器资源空运行;
2)应用进程在哪些服务器启动多少进程,通过一套调度器结合调度算法来自动化的完成。
4.带来哪些新问题
1)PaaS环境中应用是多种多样的,不同的应用在服务器上依赖的环境是不一样的,比如java要依赖相应的jdk等环境,c++应用会依赖相应的gcc等工具,而且不同的服务器的linux对应的环境操作的命令都不一样;
2)开发者需要维护好应用的程序包和运行服务器对应的环境,而且开发、测试、生产环境中部署的服务器的环境版本等可能不一致。
最大的困难还是不同环境之间不同类型应用之间的统一管理问题,经常会出现应用在某个环境下调度启动运行正常,但在另外的环境里运行出错。
Docker带来的改变
在没有Docker出现以及普及之前,容器核心技术已经存在了,只不过由于涉及linux较为底层的实现,所以在商用的应用领域并没有被太多的普及。
容器技术的核心有两个方面:
1)容器在逻辑隔离资源的技术cgroups;
2)容器在逻辑视图方面技术namespace;
1.资源隔离cgroups
容器技术在PaaS平台时期就被应用,之前的应用通常大家启动实例化进程都很少会利用到linux提供的这两个技术,所以进程启动后是以竞争的方式来轮询使用cpu的分片的。
容器技术应用之后,cgroups技术相当于给运行中的进程提供一个边界限制,利用了linux在管理进程资源方面的技术,通过配置可以限制一个应用进程所使用的资源的上限(包括cpu、内存、磁盘、网络带宽等)
在linux系统的/sys/fs/cgroup目录下,有一系列的cpuset、cpu、 memory资源配置子目录,这个目录可以理解为一个Control Group控制组。
容器启动后,会为每个容器创建这么一套资源的限制文件,用于控制每个容器的资源上限。PaaS中就是通过管理和配置这些进程的资源限制文件,在控制着应用分发和资源的限制,以防止应用进程竞争造成资源不可控的局面。
2.容器逻辑视图namespace
linux中为启动的进程也可以模拟一个类似操作系统的全局视图,简单的说:
一个应用在容器中启动之后,容器会模拟操作系统的启动运行视图,将当前应用进程视为1号进程,尽管该进程在linux系统中被分配的是真实的进程号,比如10000.
这是一种逻辑的抽象,namespace其实就是为容器提供了这种逻辑上的假象,让操作者以为他是在一个操作系统中操作应用进程。不仅仅是进程方式的管理逻辑视图,linux这项技术还为整体的进程涉及的网络、存储等方方面面都提供这样的逻辑视图。
容器方面技术在云原生实践中会深入剖析,这里暂时先介绍到这里。
3.Docker出现改变了什么
Docker出现以及普及最主要的原因应该还是在容器的技术易用性方面做了改进,让容器技术在开发者中普及开来。
前面说到应用在PaaS平台这套打包和分发的机制中,开发者再也不用关注服务器部分手工部署策略了,但是同样带来了不同环境应用的打包以及环境差异带来的管理上的困难。
Docker解决了这个问题!
1)Docker针对应用打包,在服务器linux环境中,不同的应用、不同的环境可能造成的不一致的困境,首先提出了“镜像”,这项改变容器技术使用复杂性的技术,让Docker迅速获得开发者的青睐,毕竟解决了困扰已久的问题。
2)Docker封装了服务器上面容器更好的使用体系,取代了过去PaaS平台的调度器/执行器中的agent,通过一整套客户端、守护Daemon、容器的友好性封装,更容易使用,屏蔽了容器技术的细节。
镜像机制:
操作系统linux文件系统和内核是分开的,文件系统就是我们经常操作linux的各种目录,内核就是linux的核心一系列模块。
Docker将其中的文件系统这个壳子进行了整理,镜像的核心就是类似一套rootfs的文件系统壳子,它构成了一个操作系统的一系列的依赖目录,这样应用的程序包和其运行的环境就可以打包进这个镜像的文件系统。
对于所有的Docker,操作系统的内核是共用的,镜像技术利用了操作系统的文件系统和内核分离的机制,模拟出了一套在容器里面运行的操作系统的环境,确保了应用程序包镜像制作后,可以在不同的环境中一致性的运行,只要共用的内核没有差异,具体的依赖环境差异都被放入了制作的镜像。
镜像详细的实现机制在云原生实践的系列中详细说明,这里就不再深入。
kubernetes带来什么改变
到Docker出现后,容器技术得到开发者的青睐,这个时候传统的PaaS平台面临着从最底层的单个运行环境方面的竞争,毕竟Docker是一家公司的产品,虽然开源了,但是后来也推出了自己的容器编排系统,简述起来就是容器环境的PaaS。
在这个体系演变中,谷歌等公司加入了,发起了一个叫CNCF的云原生基金会,这个基金会有几家掌控行业生态的大企业把持,吸引越来越多的企业加入。
云原生的CNCF推出了kubernetes,简单讲就是为容器环境而生的更好的编排调度系统。加上全开源的生态,发展的相当快(传统的PaaS平台虽然有的也开源,但大多是带着商业版本策略的)。谷歌主导的这套容器编排调度系统,参考了其内部庞大集群的管理思路,同时解决了使用Docker在单机扩展到集群下的容器管理问题。
kubernetes是一套容器的编排系统,借助Docker,但又摆脱对Docker的依赖(IT界很有意思,假如你希望在这个体系里面分一杯羹,最好的办法的就是不断的抽象,利用并且同时摆脱依赖)
kubernetes的体系中,类似PaaS机制,采用了一系列的调度器和执行器的模式,以更友好的API的编程模式,面向开发者开放其生态,任何开发者都可以基于其API机制方式去扩展它的实现。
一套正常可运行的kubernetes的集群主要包括如下可独立运行的模块:
1.Master
Master主要由三个核心模块组成:
1)kube-apiserver,是整个集群对外提供控制、配置等唯一入口,该服务主要提供rest风格的API服务能力。如果在kubernetes基础上构建自有的paas平台的话,通常在应用的配置管理、应用的发布调度等上面需要与该模块交互完成控制。
2)kube-scheduler,负责资源的调度,按照预定的调度策略将Pod调度到相应的机器上。
3)kube-controller-manager,负责维护集群的状态,包括故障检测、自动扩展、滚动更新等。
2.Slave
Slave集群的节点主要由两个核心模块组成:
1)kubelet,负责维护计算节点的生命周期的模块,总得来讲主要是维护容器资源的生命周期,包括容器、网络、存储的管理。
2)kube-proxy,负责为Service提供cluster内部的服务发现和负载均衡,这个可以理解为计算节点上的负载均衡服务,因为一个计算节点可以运行多个容器,kube-proxy将为这些容器实例提供负载能力。
kubernetes如何摆脱对Docker的依赖的
kubernetes是容器的编排系统,提出了一系列的封装的概念将Docker变成了这套编排系统中的一种容器实现方式。
kubernetes中,相当于重新启用了PaaS中的agent,kubelet就是个独立运行的agent进程,该进程在具体创建容器的时候,通过Docker的客户端与Docker连接,创建实际容器。
kubernetes为了摆脱对Docker的依赖,通过一系列的标准定义和抽象来实现解耦。
1)首先,容器实例基础上提供了pod的概念,pod是一组容器的抽象,是一个逻辑的管理概念,可以确保多个容器实例被纳管在一个pod中,而这个pod内的容器都是可以本地通信的。这样一来容器实例的概念被屏蔽,在kubernetes只看到pod。
2)计算节点中的agent的模块kubelet在和Docker的环境对接的时候,不是简单的集成客户端对接,而是抽象并且制定了一系列的对接规范,这些规范涵盖了对接容器的runtime、对容器网络、存储等配置管理方面。这样一来就将Docker作为了其中编排调度的一个实现。
应用开发者在容器阶段关注点
回顾下容器技术这个领域的进程:
1)容器技术出现,让PaaS平台有了为应用构建打包、分发机制的体系下还能解决应用的资源限制的问题。
2)Docker技术出现,让容器技术变得更好用,尤其其镜像技术解决了PaaS平台应用部署多环境不一致的问题。
3)kubernetes的出现,有了对容器更好的编排和调度的工具,其可扩展性,让更多的企业在这个生态上面去扩展的定义属于自己的paas平台。
开发者在容器普及下关注点:
1)从过去关注应用的打包上转移到镜像机制上来,通过一系列的PaaS平台的镜像构建工具在线去构建运行环境的应用镜像,可以通过简单的修改在不同环境的linux系统上运行,只要内核满足运行要求即可。
2)应用的编排和定义变得简单,通过封装kubernetes之上的应用模板,比如自定义的、helm等这类模板便捷的定义应用,然后一切就交给PaaS平台去与kubernetes的API Server交互,完成应用的调度运行。