注:本文部分内容和观点来自网络。
有了Docker,为啥还需要额外容器管理工具
这一点非常容易理解。我们可以将容器与虚拟机对比来看。
首先,我们当然可以在单台ESXi主机上通过CLI命令行或者Vmware Host Client可视化工具来创建和管理虚拟机;可以在这台主机上创建多个虚拟机等。
但是如果我们需要实现ESXi群集、虚拟网络、虚拟存储、批量虚拟机管理、HA和RDS等可用性和资源调配等复杂的管理功能,上面的工具就会变得过于复杂或者力不从心,我们可能需要vSphere Client、Vmware PowerCLI等更加高级的工具。
再进一步,我们如果需要在企业环境里构建Vmware的私有云环境,并实现私有云的自动化计费、自动日志监控和管理、容量管理和环境持续优化、资源和服务的自动化交付,上面的工具又难以为继了。这个时候,我们可能需要vRealize Business for Cloud(计费)、vRealize Automation(编排与交付)、vRealize Operations(批量自动化运维)、vRealize Log Insight等云管平台工具。
所以,你看,在不同的IT运营管理需求和不同的运维场景下,需要的工具是不同的。
容器与Docker同此理。
在容器的世界里,我们经常使用“编排”这个词语。编排 (orchestration)是一个没有严格定义的概念。这个概念大概描述了自动配置、 协作和管理服务的过程。在 Docker的世界里,编排用来描述一组实践过程,这个过程会管理运行在多个Docker容器里的应用,而这些Docker容器有可能运行在多个宿主机上。
由于Docker是一个轻量级的容器管理平台,对编排的原生支持非常弱,因此整个社区围绕编排、开发和集成,建设了很多很棒的工具。
在现在的生态环境里,己经围绕Docker构建和集成了很多的工具。一些工具只是简单地将多个容器快捷地“连”在一起,使用简单的组合来构建应用程序栈。另外一些工具提供了在更大规模多个Docker宿主机上进行协作的能力,以及复杂的调度和执行能力。
下面我们一起来看下这些工具。
Docker三剑客
Docker三剑客是Docker管理中最基本的三个工具。严格意义上,这三个工具并非都是编排工具。但是由于这三个工具非常出名,因此在这里统一介绍。
Docker Machine
如果需要构建一个大的容器集群或者容器云环境,第一步需要做什么?
我们自然而然的想到的是在主机上安装Docker,但是如果需要安装Docker的主机成百上千,怎么办呢?需要一个工具来帮助实现大规模主机环境的Docker的批量、自动化安装,是吧?这个时候,Docker Machine就闪亮登场了。
Docker Machine是Docker官方三剑客项目之一,负责使用Docker的第一步,在多种平台上快速安装Docker环境。它支持多种平台,让用户可以在很短时间内搭建一套Docker主机集群。
例如,需要在本地快速创建包含100台主机的docker集群环境,总不能一台一台虚拟机去部署吧?再比如,要给100台阿里云ECS安装docker,传统方式就是一台一台ssh上去安装,听起来就很头疼,是吧?
这个时候,Docker Machine 就能帮上大忙了。Machine项目主要由Go编写,用户可以在本地任意指定被Machine管理的Docker主机,并对其进行操作。Machine定位是“在本地或者云环境中创建Docker主机(Create Docker hosts on your computer,on cloud providers,and inside your own data center.)”。
其基本功能包括:
- 在指定节点上安装Docker引擎,配置其为Docker主机;
- 集中管理所有Docker主机。
Machine连接不同类型的节点是通过不同驱动指定的,目前已经支持了以下公有和私有的云服务提供商:
- Amazon EC2
- Microsoft Azure
- Digital Ocean
- Google Compute Engine
- Rackspace
- SoftLayer
- OpenStack
- VMWare vCloud Air
- VMWare vSphere
无论是Mac,Windows或是Linux,你都可以在其上安装Docker Machine,使用docker-machine命令来创建和管理大量的Docker hosts。它会自动创建主机,在主机上安装Docker Engine,然后配置docker client。每个被管理的主机(“machine”)都是一个Docker 主机和一个配置过的client的组合。
Machine命令列表
Docker Compose
部署好了一台Docker主机之后 ,接下来我们就可以在这台主机上创建应用(进程)的容器以及业务(项目)的容器,并且最好能够实现这些容器对象的敏捷的生命周期的管理,这个时候就需要Docker Compose了。
Compose项目是Docker官方的开源项目,定位是“定义和运行多个Docker容器的应用”,其前身是开源项目Fig,目前仍然兼容Fig格式的模板文件。 通过之前的文章,我们知道使用一个Dockerfile模板文件,可以让用户很方便地定义一个单独的应用容器。然而,在日常工作中,经常会碰到需要多个容器相互配合来完成某项任务的情况。
例如要实现一个Web项目,除了Web服务容器本身,往往还需要再加上后端的数据库服务容器,甚至还包括负载均衡容器等。
Compose恰好满足了这样的需求。它允许用户通过一个单独的docker-compose.yml模板文件(YAML格式)来定义一组相关联的应用容器为一个项目(project)。
Compose中有两个重要的概念:
- 服务(service):一个应用的容器,实际上可以包括若干运行相同镜像的容器实例。
- 项目(project):由一组关联的应用容器组成的一个完整业务单元,在docker-compose.yml文件中定义。
Compose的默认管理对象是项目,通过子命令对项目中的一组容器进行便捷地生命周期管理。
Compose项目由Python编写,实现上调用了Docker服务提供的API来对容器进行管理。因此,只要所操作的平台支持Docker API,就可以在其上利用Compose来进行编排管理。
YAML 常用配置命令
Docker Compose 常用命令
Docker Swarm
1
基础架构
Docker Swarm 和 Docker Compose 一样,都是 Docker 官方容器编排工具,也能够在主机上创建容器集群服务,那么这两者的区别在哪里呢?
Docker Compose 是一个在单个服务器或主机上创建多个容器的工具,而 Docker Swarm 则可以在多个服务器或主机上创建容器集群服务,对于微服务的部署,显然 Docker Swarm 会更加适合。Docker Swarm提供Docker容器集群服务,是Docker官方对容器云生态进行支持的核心方案。使用它,用户可以将多个Docker主机封装为单个大型的虚拟Docker主机, 快速打造一套容器云平台。
Swarm的前身是Beam项目和libswarm项目,首个正式版本(Swarm V1)在2014年12月初发布。为了提高可扩展性,2016年2月对架构进行重新设计,推出了V2版本,支持超过1千个节点。最新的Docker Engine(即Docker)已经集成了Swarm Kit,加强了对Swarm的协作支持。
作为容器集群管理器,Swarm最大的优势之一就是100%支持标准的Docker API。各种基于标准API的工具,如Compose、docker-py,各种管理软件,甚至Docker本身等都可以很容易地与Swarm进行集成。这大大方便了用户将原先基于单节点的系统移植到Swarm上。同时Swarm内置了对Docker网络插件的支持,用户可以很容易地部署跨主机的容器集群服务。
Swarm V1的结构图如下图所示。可以看出,Swarm是典型的master-slave结构,通过发现服务来选举manager。manager是中心管理节点,各个node上运行agent接受manager的统一管理。
在V2中,集群会自动通过Raft协议分布式选举出manager节点,无需额外的发现服务支持,避免了单点瓶颈。同时,V2中内置了基于DNS的负载均衡和对外部负载均衡机制的集成支持。
上述架构简化之后就是下面这样的:
其中一个机器运行了一个Swarm的镜像(就像运行其他Docker镜像一样),它负责调度容器,在图片上鲸鱼代表这个机器。Swarm使用了和Docker标准API一致的API,这意味着在Swarm上运行一个容器和在单一主机上运行容器使用相同的命令。尽管有新的flags可用,但是开发者在使用Swarm的同时并不需要改变他的工作流程。
Swarm由多个代理(agent)组成,把这些代理称之为节点(node)。这些节点就是主机,这些主机在启动Docker daemon的时候就会打开相应的端口,以此支持Docker远程API。其中三个节点显示在了图上。这些机器会根据Swarm调度器分配给它们的任务,拉取和运行不同的镜像。
当启动Docker daemon时,每一个节点都能够被贴上一些标签(label),这些标签以键值对的形式存在,通过标签就能够给予每个节点对应的细节信息。当运行一个新的容器时,这些标签就能够被用来过滤集群。
2
发现服务
Docker集群管理需要使用服务发现(Service Discover)功能, Swarm支持以下几种方式:Docker Hub、本地文件、Etcd、Consul、Zookeeper和手动指定节点IP地址信息等。
除了手动指定外,这些方法原理上都是通过维护一套数据库机制来管理集群中注册节点的Docker Daemon的访问信息。
部署配置完毕后,可以看到整个Swarm集群就像一个虚拟的Docker主机一样正常工作。
由于Swarm实际上是通过agent调用了本地的Docker daemon来运行容器,当Swarm集群服务出现故障时,无法接受新的请求,但已经 运行起来的容器将不会受到影响。
3
Swarm中的调度器
调度是集群十分重要的功能,Swarm目前支持三种调度策略:spread、binpack和random。
在执行swarm manage命令启动管理服务的时候,可以通过--strategy参数指定调度策略,默认的是spread。
简单来说,这三种调度策略的优化目标如下:
- spread:如果节点配置相同,选择一个正在运行的容器数量最少的那个节点,即尽量平摊容器到各个节点;
- binpack:跟spread相反,尽可能地把所有的容器放在一台节点上运行,即尽量少用节点,避免容器碎片化。
- random:直接随机分配,不考虑集群中节点的状态,方便进行测试使用。
4
Swarm中的过滤器
Swarm的调度器可以按照指定调度策略自动分配容器到节点,但有些时候希望能对这些分配加以干预。比如,让I/O敏感的容器分配到安装了SSD的节点上;让计算敏感的容器分配到CPU核数多的机器上;让网络敏感的容器分配到高带宽的机房;让某些容器尽量放同一个节点上,等等。
这可以通过过滤器(filter)来实现,目前支持五种过滤器:Constraint、Affinity、Port、Dependency、Health。
Constraint过滤器
是绑定到节点的键值对,相当于给节点添加标签。可在启动Docker服务的时候指定,例如指定某个节点颜色为red。
当你在实际的生产环境中运行容器时,你可以指定约束来完成查找,比如说一个容器只会在red标签的节点上运行。如果没有节点满足要求,这个容器将不会运行。
Affinity过滤器
允许用户在启动一个容器的时候,让它分配到某个已有容器的节点上。
对容器来说,当你想要运行一个新的容器时,你只需要指定你想要链接的容器的名字(或者容器的ID),然后这些容器就会互相链接。如果其中一个容器停止运行了,剩下的容器都会停止运行。
镜像吸引力将会把想要运行的容器调度到已经拥有该镜像的节点上。
Dependency 过滤器
依赖过滤器能够用来运行一个依赖于其他容器的容器。依赖意味着和其他容器共享磁盘卷,或者是链接到其他容器,亦或者和其他容器在同一个网络栈上。
Port filter
如果你想要在具有特定开发端口的节点上运行容器,你就可以使用端口过滤器了。如果集群中没有任何一个节点该端口可用的话,系统就会给出一个错误的提示信息。
Health filter
健康过滤器用来防止调度不健康的节点。
5
Docker Swarm常用命令
docker swarm 常用命令
docker node 常用命令
docker service 常用命令
docker stack 常用命令
Mesos
Mesos概述
如果你仔细观察,会发现它们抽象的资源和调度的任务都发生在OS以及以上的容器层;有些场景下,例如企业需要构建容器云平台,就需要将整个数据中心的资源统筹调度进行资源抽象和任务调度,这个时候你就需要Mesos了。
Mesos最初由UC Berkeley的AMP实验室于2009年发起,遵循 Apache协议,目前已经成立了Mesosphere公司进行运营。Mesos可以将整个数据中心的资源(包括CPU、内存、存储、网络等)进行抽象和调度,使得多个应用同时运行在集群中分享资源,并无需关心资源的物理分布情况。
如果把数据中心中的集群资源看做一台服务器,那么Mesos要做的事情,其实就是今天操作系统内核的职责:“抽象资源 调度任务”。
Mesos项目主要由C 语言编写,代码仍在快速演化中,已经发布了正式版1.0.0版本。
事实上可以把Mesos理解为容器云数据中心的操作系统或者容器云的云管平台。Mesos本身提供了一个高效可扩展的系统,并且这个系统能够支持很多各种各样的框架,不管是现在的还是未来的框架,它都能支持。这也是现今一个比较大的问题:类似Hadoop和MPI这些框架都是独立开的,这导致想要在框架之间做一些细粒度的分享是不可能的。
因此Mesos的提出就是为了在底部添加一个轻量的资源共享层(resource-sharing layer),这个层使得各个框架能够适用一个统一的接口来访问集群资源。Mesos并不负责调度而是负责委派授权,毕竟很多框架都已经实现了复杂的调度。
取决于用户想要在集群上运行的作业类型,共有四种类型的框架可供使用。其中有一些支持原生的Docker,比如说Marathon。Docker容器的支持自从Mesos 0.20.0就已经被加入到Mesos中了。
值得注意的是,Mesos自身只是一个资源抽象的平台,要使用它往往需要结合运行其上的分布式应用(在Mesos中被称作框架,framework),比如Hadoop、Spark、Marathon、Elasticsecrrch等大部分时候,用户只需要跟这些框架打交道即可,完全无需关心底下的资源调度情况,因为Mesos已经自动帮你实现了。这大大方便了上层应用的开发和运维。当然,用户也可以基于Mesos打造自己的分布式应用框架。
Mesos架构
首先,需要再次强调,Mesos自身只是一个资源调度框架,并非一整套完整的应用管理平台,所以只有Mesos自己是不能干活的。但是基于Mesos,可以比较容易地为各种应用管理框架,或者为中间件平台(作为Mesos的应用)提供分布式运行能力;同时,由于多个框架也可以同时运行在一个Mesos集群中,提高了整体的资源使用效率。
Mesos对自己的定位划分清楚,使得它要完成的任务很明确,其他任务框架也可以很容易地与它进行整合。
可以看出,Mesos采用了经典的“主-从”(master-slave)架构,其中主节点(管理节点)可以使用ZooKeeper来做HA(高可靠性)。Mesos master服务将运行在主节点上,Mesos slave服务则需要运行在各个计算任务节点上。负责完成具体任务的应用框架(framwork)跟Mesos master进行交互,来申请资源。
1
基本单元
Mesos中有三个基本的组件:管理服务(master)、任务服务(slave)以及应用框架(framework)。
跟大部分分布式系统中类似,主节点(master)起到管理作用,将看到全局的信息,负责不同应用框架之间的资源调度和逻辑控制。应用框架需要注册到管理服务上才能被使用。用户和应用需要通过主节点提供的API来获取集群状态和操作集群资源。
slave负责汇报本从节点上的资源状态(空闲资源、运行状态等 等)给主节点,并负责隔离本地资源来执行主节点分配的具体任务。隔离机制目前包括各种容器机制,包括LXC、Docker等。
应用框架(framework)是实际干活的,包括两个主要组件:
- 调度器(scheduler):注册到主节点,等待分配资源;
- 执行器(executor):在从节点上执行框架指定的任务(框架也可以使用Mesos自带的执行器,包括shell脚本执行器和Docker执行器)。
应用框架可以分两种:一种是对资源的需求,是会扩展的(如Hadoop、Spark等),申请后还可能调整;另一种是对资源需求大小是固定的(如MPI等),一次申请即可。
2
调度
对于一个资源调度框架来说,最核心的就是调度机制,怎么能快速高效地完成对某个应用框架资源的分配,是核心竞争力所在。最理想情况下(大部分时候都无法实现),最好是能猜到应用的实际需求,实现最大化的资源使用率。
Mesos为了实现尽量优化的调度,采取了两层的调度算法。
算法基本过程
调度的基本思路很简单,master先全局调度一大块资源给某个 framework,framework自己再实现内部的细粒度调度,决定哪个任务用多少资源。两层调度简化了Mesos master自身的调度过程,通过将复杂的细粒度调度交由framework实现,避免了Mesos master成为性能瓶颈。
调度机制支持插件机制来实现不同的策略。默认是Dominant Resource Fairness(DRF)。
调度过程
调度通过offer发送的方式进行交互。一个offer是一组资源,例如<1 CPU,2 GB Mem>。基本调度过程如下:
- slave节点会周期性汇报自己可用的资源给master;
- 某个时候,master收到应用框架发来的资源请求,根据调度策略,计算出来一个资源offer给framework;
- framework收到offer后可以决定要不要,如果接受的话,返回一个描述,说明自己希望如何使用和分配这些资源来运行某些任务(可以说明只希望使用部分资源,则多出来的会被master收回);
- 最后,master则根据framework答复的具体分配情况发送给slave,以使用framework的executor来按照分配的资源策略执行任务。
具体给出一个例子:
某从节点向主节点汇报自己有<4 CPU,8GB Mem>的空闲资源,同时,主节点看到某个应用框架请求<3CPU,6 GB Mem>,就创建一个offer<slave#1,4 CPU,8 GB Mem>把满足的资源发给应用框架。应用框架(的调度器)收到offer后觉得可以接受,就回复主节点,并告诉主节点希望运行两个任务:一个占用<1 CPU,2 GB Mem>,另一个占用<2 CPU,4 GB Mem>。主节点收到任务信息后分配任务到从节点上进行运行(实际上是应用框架的执行器来负责执行任务)。任务运行结束后可将资源释放出来。剩余的资源还可以继续分配给其他应用框架或任务。
应用框架在收到offer后,如果offer不满足自己的偏好(例如希望继续使用上次的slave节点),则可以选择拒绝offer,等待master发送新的offer过来。另外,可以通过过滤器机制来加快资源的分配过程。
3
过滤器
framework可以通过过滤器机制告诉master它的资源偏好,比如希望分配过来的offer有哪个资源,或者至少有多少资源等。过滤器可以避免某些应用资源长期分配不到所需要的资源的情况,加速整个资源分配的交互过程。
4
回收机制
为了避免某些任务长期占用集群中资源,Mesos也支持回收机制。
主节点可以定期回收计算节点上的任务所占用的资源,可以动态调整长期任务和短期任务的分布。
5
高可用性
从架构上看,最为核心的节点是master节点。除了使用ZooKeeper来解决单点失效问题之外,Mesos的master节点自身还提供了很高的鲁棒性。
Mesos master节点在重启后,可以动态通过slave和framework发来的消息重建内部状态,虽然可能导致一定的时延,但这避免了传统控制节点对数据库的依赖。
当然,为了减少master节点的负载过大,在集群中slave节点数目较多的时候,要避免把各种通知的周期配置得过短。在实践中,可以通过部署多个Mesos集群来保持单个集群的规模不要过大。
6
常见应用框架
应用框架是实际干活的,可以理解为Mesos之上跑的“应用”。应用框架注册到Mesos master服务上即可使用。用户大部分时候,只需要跟应用框架打交道。因此,选择合适的应用框架十分关键。
Mesos目前支持的应用框架分为四大类:长期运行服务(以及 PaaS)、大数据处理、批量调度、数据存储。
随着Mesos自身的发展,越来越多的框架开始支持Mesos,下表总结了目前常用的一些框架。
小结
Mesos最初设计为资源调度器,然而其灵活的设计和对上层框架的优秀支持,使得它可以很好地支持大规模的分布式应用场景。结合Docker,Mesos可以很容易部署一套私有的容器云。
除了核心功能之外,Mesos在设计上有许多值得借鉴之处,比如它清晰的定位、简洁的架构、细致的参数、高度容错的可靠,还有对限速、监控等的支持等。
Kubernetes
概述
Mesos作为一套成熟的开源项目,可以很好地被应用和集成到生产环境中。但它的定位集中在资源调度,往往需要结合应用框架或二次开发。
但Mesos在运行集群方面不如Kubernetes,它重点放在它强大的调度功能和它被插在各种各样的调度器的性能上。Mesos并不是为容器而生的,在容器流行之前就已经被开发出来,它的一些地方被修改来支持容器。
因此在对于容器和容器集群的生命周期管理层面,Mesos还是不够开箱即用,不够强大,也不够易用。由此我们就需要另外一个在容器界大名鼎鼎,呼风唤雨的容器集群管理工具:Kubernetes。
Kubernetes是Google团队发起并维护的开源容器集群管理系统,支持如Docker等容器技术。类似Docker Swarm,使用Kubernetes,用户可以轻松搭建和管理一个私有容器云。
Kubernetes是Google公司于2014年基于内部集群管理系统Borg开源的容器集群管理项目。该项目基于Go语言实现,试图为基于容器的应用部署和管理打造一套强大并且易用的管理平台。Kubernetes自开源之日起就吸引了众多公司和容器技术爱好者的关注,是目前容器集群管理最优秀的开源项目之一。已有Microsoft、RedHat、IBM、Docker、Mesosphere、CoreOS以及SaltStack等公司加入了Kubernetes社区。
Kubernetes的前身(Borg系统)在Google内部已经应用了十几年,积累了大量来自生产环境的宝贵实践经验。在设计Kubernete的时候,团队也很好地结合了来自社区的想法。
正是因为这些积累,作为一套分布式应用容器集群系统,Kubernetes拥有鲜明的技术优势:
- 优秀的API设计,以及简洁高效的架构设计,主要组件个数很少,彼此之间通过接口调用;
- 基于微服务模式的多层资源抽象模型,兼顾灵活性与可操作性,提出的Pod模型被许多平台借鉴;
- 可拓展性好,模块化容易替换,伸缩能力极佳,1.2.0版本单集群支持1000个节点,同时运行30000个Pods;
- 自动化程度高,真正实现“所得即所需”,用户通过模板声明服务后,生命周期都是自动化管理;
- 部署支持多种环境,包括虚拟机、裸机部署,还很好地支持常见云平台,包括AWS、GCE等;
- 支持丰富的运维工具,方便用户对集群进行性能测试、问题检查和状态监控;
- 自带控制台、客户端命令等工具,允许用户通过多种方式与kubernetes集群进行交互。
基于Kubernetes,可以很容易地实现一套PaaS,比如Openshift和Deis。
2015年7月发布的1.0版本是Kubernetes的第一个正式版本,标志着核心功能已经逐渐成熟稳定,可以正式投入生产环境使用。
2016年3月发布的1.2.0版本,在性能、稳定性和可管理性上都有了重大的优化和升级,包括对多可用域的支持、监控服务增强、上千物理节点的支持等令人振奋的特性。
核心概念
要想深入理解Kubernetes的特性和工作机制,首先要掌握 Kubernete模型中的核心概念。这些核心概念反映了Kubernetes设计过程中对应用容器集群的认知模型。
首先是集群组件,从架构上看,Kubernetes集群(Cluster)也采用了典型的“主-从”架构。一个集群主要由管理组件(Master)和工作节点(Node)组件构成。
另外,Kubernetes集群的主要任务始终围绕着应用的生命周期。 通过将不同资源进行不同层次的抽象,Kubernetes提供了灵活可靠的生命周期管理。资源的核心抽象主要包括:
- 容器组(Pod):由位于同一节点上若干容器组成,彼此共享网络命名空间和存储卷(Volume)。Pod是Kubernetes中进行管理的最小资源单位,是最为基础的概念。跟容器类似,Pod是短暂的,随时可变的;
- 服务(Service):若干(往往是同类型的)Pod形成的对外提供某个功能的抽象,不随Pod改变而变化,带有唯一固定的访问路径, 如IP地址或者域名。
- 复制控制器(Replication Controller):负责启动Pod,并维护其健康运行的状态。是用户管理Pod的句柄。
- 部署(Deployment):创建Pod,并可根据参数自动创建管理 Pod的复制控制器,并且支持升级。1.2.0版本引入提供比复制控制器更方便的操作;
- 横向Pod扩展器(Horizontal Pod Autoscaler,HPA):类似云里面的自动扩展组,根据Pod的使用率(典型如CPU)自动调整一个部 署里面Pod的个数,保障服务可用性;
此外,还有一些管理资源相关的辅助概念,主要包括:
- 注解(Annotation):键值对,可以存放大量任意数据,一般用来添加对资源对象的详细说明,可供其他工具处理。
- 标签(Label):键值对,可以标记到资源对象上,用来对资源进行分类和筛选;
- 名字(Name):用户提供给资源的别名,同类资源不能重名;
- 命名空间(Namespace):这里是指资源的空间,避免不同租户的资源发生命名冲突,另外可以进行资源限额;
- 持久卷(PersistentVolume):类似于Docker中数据卷的概念,就是一个数据目录,Pod对其有访问权限。
- 秘密数据(Secret):存放敏感数据,例如用户认证的口令等;
- 选择器(Selector):基于标签概念的一个正则表达式,可通过标签来筛选出一组资源;
- Daemon集(DaemonSet):确保节点上肯定运行某个Pod,一般用来采集日志和监控节点;
- 任务(Job):确保给定数目的Pod正常退出(完成了任务);
- 入口资源(Ingress Resource):用来提供七层代理服务;
- 资源限额(Resource Quotas):用来限制某个命名空间下对资源的使用,开始逐渐提供多租户支持;
- 安全上下文(Security Context):应用到容器上的系统安全配置,包括uid、gid、capabilities、SELinux角色等;
- 服务账号(Service Accounts):操作资源的用户账号。
集群组件
集群由使用Kubernetes组件管理的一组节点组成,这些节点提供了容器资源池供用户使用。主要包括管理(Master)组件和节点(Node)组件。
Master组件
顾名思义,Master组件提供所有与管理相关的操作,例如调度、监控、支持对资源的操作等。
Master会通过Node Controller来定期检查所管理的Node资源的健康状况,完成Node的生命周期管理。
Node组件
在Kubernetes中,Node是实际工作的计算实例(在1.1之前版本中名字叫做Minion)。节点可以是虚拟机或者物理机器,在创建 Kubernetes集群过程中,都要预装一些必要的软件来响应Master的管理。目前,Node的配置还只能通过人工手动进行,未来可以支持通过Master来自动配置。
Node节点有几个重要的属性:地址信息、阶段状态、资源容量、节点信息。
地址信息包括:
- 主机名(HostName):节点所在系统的主机别名,基本不会用到;
- 外部地址(ExternalIP):集群外部客户端可以通过该地址访问到的节点;
- 内部地址(InternalIP):集群内可访问的地址,外部往往无法通过该地址访问节点。
阶段状态包括:
- 待定(Pending):新创建节点,还未就绪状态,需要进一步的配置;
- 运行中(Running):正常运行中的节点,可被分配Pod,会定期汇报运行状态消息;
- 终止(Terminated):节点已经停止,处于不可用状态,判断条件为5分钟内未收到运行状态消息。
资源容量包括常见操作系统资源,如CPU、内存、最多存放的Pod个数等。
节点信息包括操作系统内核信息、Kubernetes版本信息、Docker 引擎版本信息等,会由kubelet定期汇报。
资源抽象
Kubernetes对集群中的资源进行了不同级别的抽象,每个资源都 是一个REST对象,通过API进行操作,通过JSON/YAML格式的模板文件进行定义。
1
容器组(Pod)
在Kubernetes中,并不直接操作容器,最小的管理单位是容器组 (Pod)。容器组由一个或多个容器组成,Kubernetes围绕容器组进行创建、调度、停止等生命周期管理。
同一个容器组中,各个容器共享命名空间(包括网络、IPC、文件系统等容器支持的命名空间)、cgroups限制和存储卷。
这意味着同一容器组中,各个应用可以很方便相互进行访问,比如通过localhost地址进行网络访问,通过信号量和共享内存进行进程间通信等,类似于经典场景中运行在同一个操作系统中的一组进程。
可以简单将一个Pod当作是一个抽象的“虚拟机”,里面运行若干个不同的进程(每个进程实际上就是一个容器)。
容器组内的若干容器往往是存在共同的应用目的,彼此关联十分紧密,例如一个Web应用和对应的日志采集应用或状态监控应用。如果单纯把这些相关的应用放一个容器里面,又会造成过度耦合,管理升级都不方便。
容器组的经典应用场景包括:
- 内容管理,文件和数据加载,缓存管理等;
- 日志处理,状态快照等;
- 监控代理,消息发布等;
- 代理机制,网桥、网卡等;
- 控制器,管理器,配置以及更新等。
可以说,容器组既保持了容器轻量解耦的特性,又提供了调度操作的便利性,在实践中提供了比单个容器更为灵活和更有意义的抽象。
2
复制控制器和部署
在Kubernetes看来,Pod资源是可以随时故障的,并不非要保证 Pod的运行,而是在发生失败后重新生成。Kubernetes通过复制控制器来实现这一功能。
用户申请容器组后,复制控制器(Replication Controller)将负责调度容器组到某个节点上,并保证它的给定份数(replica)正常运行。当实际运行Pod份数超过数目,则终止某些Pod;当不足,则创建新的Pod。一般建议, 即使Pod份数是1,也要使用复制控制器来创建,而不是直接创建Pod。
可以将复制控制器类比为进程的监管者(supervisor)的角色, 只不过它不光能保持Pod的持续运行,还能保持集群中给定类型Pod 同时运行的个数为指定值。
Pod是临时性的,可以随时被复制控制器创建或者销毁,这意味着要通过Pod自身的地址访问应用是不能保证一致性的。Kubernetes 通过服务的概念来解决这个问题。
从1.2.0版本开始,Kubernetes将正式引入部署(Deployment)机制来支持更灵活的Pod管理,从而用户无需直接跟复制控制器打交道了。
3
横向Pod扩展器(Horizontal Pod Autoscaler)
横向扩展器(HPA)在复制控制器和部署的基础上增加了自动反馈机制,通过定期查询Pod的资源利用率来调整Pod的数目,确保服务的可用性。
典型的一个场景是,定期(由--horizontal-pod-autoscaler-sync-period参数指定)通过Heapster组件来检查目标部署内Pod的平均CPU使用情况,当CPU使用率高出目标值,自动增加Pod数;反之降低。 内部机制是通过scale接口来操作资源。
4
服务(Service)
Kubernetes主要面向的对象是持续运行,并且无状态(stateless)。服务的提出主要是要解决Pod地址可变的问题。由于 Pod随时可能故障,并可能在其他节点上被重启起来,它的地址是不能保持固定的。因此,用一个服务来代表提供某一类功能(可以通过标签来筛选)的一些Pod,并分配不随Pod位置变化而改变的虚拟访问地址(Cluster IP)。这也符合微服务的理念。
比如网站的后端服务可能有多个Pod都运行了后端处理程序,它们可以组成一个服务。前端只需要通过服务的唯一虚拟地址来访问即可,而无需关心具体是访问到了哪个Pod。可见,服务跟负载均衡器实现的功能很相似。
组成一个服务的Pod可能属于不同复制控制器,但服务自身是不知道复制控制器的存在的。
同样,服务也是一个REST对象,用户可以通过模板来定义一个服务资源。
服务在创建后,会被自动分配一个集群地址(Cluster IP),这个地址并不绑定到任何接口,将作为访问服务的抽象地址。访问该地址会被映射到Pod的实际地址。实现上是通过kube-proxy进程。每个节点上都会运行一个kube-proxy进程,负责将到某个Service的访问给代 理或者均衡到具体的Pod上去。同时,会为每一个服务都创建环境变量,指向集群地址;或者在DNS中注册该服务的集群地址。
也许会有用户考虑使用DNS方式来替代服务的集群IP机制,这是完全可以的,Kubernetes也提供了基于skydns的插件支持。但是要处理好DNS查找的缓存过期时间问题。当某个Pod发生变化时,要让客户端本地的DNS缓存过期。
另外,服务支持进行不同类型的健康检查(通过容器spec中的livenessProbe或ReadinessProbe字段定义),目前包括三种类型:
- 通过HTTP获取资源是否成功;
- 在容器中执行指定命令,返回值是否为0;
- 打开给定socket端口是否成功。
探测的结果可能为成功、失败或未知。其中LivenessProbe反映的是容器自身状态,如果配置了重启策略,则失败状态会触发自动重启;而ReadinessProbe字段用来反映容器内的服务是否可用。
目前,Kubenetes支持在多种环境下的安装,包括本地主机(Fedora)、云服务(Google GAE、AWS等),但最快速体验Kubernetes的方式显然是在本地通过Docker容器的方式来快速启动相关进程。
小结
容器(无论是Docker还是CoreOS的rkt)允许开发人员无缝地关注于应用程序的运行时。基础架构的问题会影响到脆弱的应用程序开发的日子一去不复返了。使用容器,开发人员仅仅需要考虑如何恰当地扩展,部署以及管理他们新开发的应用程序,但是现有的容器方案并不能在跨多节点的环境里自己管理,调度以及部署容器。
这个时候就需要Kubernetes。
在容器化的世界里,Kubernetes是环境的管理和部署引擎。使用Kubernetes的最基本功能,用户就可以轻松地在物理硬件或者虚拟机上调度并且运行应用程序。Kubernetes的更多高级用法让开发人员可以彻底摆脱主机为中心的世界,而进入容器为中心的环境里。
使用Kubernetes很容易的。
可以使用REST API来操作Kubernetes所包含的主要组件 。Kubernetes的定位是平台,但是它包含多个组件,每个都有各自的角色。Master是Kubernetes集群里的控制服务(也称为control plane),Master很重要,因为它会API调用和其交互的其他组件。集群单元管理发生在Master里,调度服务也在这里。
到这里为止,我们不妨将Docker容器以及Kubernetes结合起来,再与我们熟悉的虚拟机技术做一次全面的类比:
Kubernetes的Master和VMware的vCenter类似。Master知道集群里的所有节点,以及所有节点的容量。而且,Master对Pod的调度及放置,类似于vCenter如何在vSphere的主机上部署VM。Pod的功能和vApp很类似,因为它们都在一个网络里托管多个容器。容器类似VM,因为它们之前都是互相隔离的,除非它们被指定特定的网络路径。最后,Replication Controller类似于HA,因为RC持续监控环境,确保正确数量的Pod在运行,如果数量少于预期,就会调度一个新的实例。
Fleet——Core OS
Fleet和 etcd由 Core OS团队发布。Fleet 是一个集群管理工具,而 etcd是一个高可用性的键值数据库,用于共享配置和服务发现。Fleet与 systemd和 etcd—起,为容器提供了集群管理和调度能力。可以把Fleet看作是systemd的扩展,只是不是工作在主机层面上, 而是工作在集群这个层面上。
容器管理工具对比
总体而言,Kubernetes是一个真正的生产级容器集群平台。这也是为什么无论是开源的PaaS平台,例如OpenShift或者互联网巨头构建的PaaS平台,例如腾讯蓝鲸,都将Kubernetes作为核心的引擎进行改造和使用。
Kubernetes是一个全径且全面的容器管理平台,有动态调度、升级、自动伸缩和持续健康监测的功能。相较而言,Docker Swarm只是从单个容器引擎提供一个集群系统的视角。
Mesos和Kubernetes比较相似,因为他们都是被开发来解决在集群化环境中运行应用程序的问题。但Mesos在运行集群方面不如Kubernetes,它重点放在它强大的调度功能和它被插在各种各样的调度器的性能上。Mesos并不是为容器而生的,在容器流行之前就已经被开发出来,它的一些地方被修改来支持容器。
Fleet利用etcd,一个和Core OS一起做出来被系统化的键值对,对于Linux来说是一个系统和service管理员。系统化是为单个容器设计,但是fleet延展它的性能到一个集群的机器。Fleet通过允许你运行service的一些实例,来帮助项目应对故障。它可以部署单个的容器到任意本地,运行容器在一个或者多个机器上,并且部署一个容器的多个实例。
从另一个方面来说,Fleet并不适用于处理一些像服务注册,在调度基础上利用,服务发现或者容器间的交流这些在分布式微服务环境中发生的情况。Fleet在这四个工具中属于比较低调的引擎,所以它最好处于一个像Kubernetes或者其它解决方案可以在上面操作的层次。
以下是Kubernetes、Mesos、Swarm这三大主流容器资源编排解决方案的对比汇总。
(以下Kubernetes优势、劣势分析来自IBM,高级软件工程师,崔婧雯)
Kubernetes的优势
虽然Kubernetes并不是市场里唯一的容器管理平台(还有Docker Swarm和Mesos),但是它更受欢迎。为什么呢?从高层看,Kubernetes正获得关注,因为它提供了这样一个平台,容器化的应用程序可以只编写一次,就能够在所有类型的云供应商以及私有云上运行,无论底层使用的是哪种基础架构。而且,Kubernetes还在发展,让开发人员能够在Kubernetes上运行任意适合的应用程序。
使用Kubernetes,开发人员可以快速部署应用程序,而无需担心传统平台上的诸多风险(想想跨多OS环境的垂直扩展),可以随时扩展应用程序,并且更好地分配资源。
硬件使用量的下降是使用Kubernetes带来的另一个好处。一些公司报告由于容器的轻量天性,以及能够快速杀死不需要的实体(和传统架构相比),硬件使用量减少了40-50%。eBay是Kubernetes的支持者和用户,声称自从他们切换了平台之后,看到了服务器上overhead的急剧降低。
最后,Kubernetes最大的不同之处并非和技术相关,而是促成各种方案的社区。Google将其发布为开源项目,吸引了1000 的社区贡献者,34000次commit。它的社区比Mesos的社区(次大的竞争者社区)大5倍,比所有竞争者的社区加起来都要大。
Kubernetes的缺点
Kubernetes受到了广泛的称赞,但是它也有一些缺点。当第一次使用它做部署(大规模)时,它很复杂,并且很难搭建。它要求具有特定技能的工程师,在现在的行业里可能很难找到。
第二,Kubernetes作为容器的第三方管理系统。容器技术本身的缺陷和成长之痛会影响到Kubernetes所能够提供的服务。
Kubernetes欠缺的领域是调度器。默认的Kubernetes调度器依赖于应用程序所有者提供的分配资源的需求,而不管实时使用量。这个方案会加重每个节点上的资源分片情况。
最后,能够在容器里运行的工作负载范围将影响Kubernetes的广泛使用,但是这并非Kubernetes可以直接解决的问题。比如,很多工程师还不想把“核心”工作负载放到容器里,因为它可能会崩溃,而容器从设计上就不是为了存储数据的。常见的实践是只在容器里运行那些崩溃后也不会导致下线时间的应用程序。
即使有这些不足,也并没有阻止Goldman Sachs,Box,SAP以及The New York Times这样的公司引入Kubernetes平台作为其下一代数据中心计划的一部分。
Kubernetes的未来
应用程序是如今大多数业务的生命线。公司需要快速的部署和高质量的应用程序。这些需求正是开发人员转向容器的原因。随着容器的发展,如果还认为Kubernetes的定位有问题那就难免有些愚蠢了。Kubernetes平台有很多的可能性,但是规模大了的话它也很难管理。最初的搭建和在生产环境上大规模运行Kubernetes之间的空白是很大的。近几年里,可能会有来自于第三方的强劲挑战,来管理这些部署和工作负载。对于Kubernetes来说,不囿于已经取得的成就至关重要。如果社区能够恰当地扩展平台,那么Kubernetes的前途甚为光明。