1创新之处在于API
这是有关 Kubernetes的两部分系列中的第一篇。第一部分是一个答案:影响Kubernetes设计的关键思想是什么?Kubernetes会将它与其他平台区分开来吗?第二部分是关于二阶效应的:行业如何响应通用控制平面?我们的工具、实践及平台将来会是什么样?
向开发人员询问Kubernetes(https://www.alauda.cn)是什么的时候,一般回答很可能会与容器编排有关。回顾Kubernetes主页上的描述,合理的答案应该是:
Kubernetes(K8s)是一个开源系统,可以用于自动化部署、扩展和管理容器化应用程序。
在过去几年激烈的竞争中,Kubernetes定位为占主导地位的容器平台。但从长远来看,我认为Kubernetes的愿景不是围绕容器,而是围绕其API,它试图成为一个在更加基本和更广泛层面上的软件管理平台。
简单说来,我认为这个目标会使Kubernetes API成为软件的通用控制平面。API旨在成为管理软件的权威接口。如果我们可以将域建模为资源,则Kubernetes应该对其进行管理。成功执行该策略将改变云计算,软件基础设施和Kubernetes本身。
2回顾:云计算原理
在进入控制平面之前,我们需要退后一步,分析云计算的兴起和快速采用。这样做的一个显而易见的原因是,Kubernetes受云计算的影响,将过程中的一些原则应用在自己的体系结构中。
下面是构建云基础设施的两个见解:
1.基础设施是可编程的:与早期的基础设施相比,云提供商需要从头开始构建完全由API调用驱动的计算/存储资源。借助可用于提升计算和存储等资源的API,提供商和用户都可以在其上构建更高级别的资源(例如,无服务器计算)。他们还可以创建基本原语,例如调度程序和控制平面,通过代码管理资源。
- 基础设施具有声明性:为了规模化交付基础设施,云提供商需要保护用户免受内部工作流故障的影响。公开声明式API意味着重点在于结果,并允许提供者将底层基础设施配置的复杂性淹没。
Kubernetes把这些想法整合到一个开放的体系结构中,为通用控制平面奠定了基础。
3基础设施是可编程的
云计算在技术方面具有吸引力的主要因素是,这些服务从头开始设计为具有弹性,自助服务和API驱动。在此模型中,用户不必提交票证或手动干预即可创建虚拟机和数据库。相反的,将数据中心中虚拟计算的复杂性封装为服务,最终用户只需要进行函数调用即可。
像所有代码一样,一旦核心服务公开为API,就可以通过重用功能来利用它们来创建更高级别的抽象。诸如容器Fargate和无服务Lambda之类的Amazon Web Services(AWS)产品是更高级别的计算服务,但最终会在EC2虚拟机上运行。对API优先计算服务的最初投资将在以后获得回报,以支持不同供应商提供不同的专业产品。云平台的用户还可以利用相同的API来构建自己的抽象。例如,Netflix建立了Titus,以EC2实例作为基础主机来调度和运行容器工作负载。
也就是说,将基础设施原语作为API提供的创新使云提供商可以构建更高级别的服务。这层抽象快速将云提供商与传统的商品托管提供商分开,因为传统托管在没有没有足够投资的情况下不能满足足够的灵活性。Kubernetes会将这些教训整合到自己的设计理念中。
4基础设施是声明性的
从历史上看,基础设施管理是当务之急。为了运行诸如安装软件之类的任务,操作员会在运行手册或自动化中对过程的每个步骤进行编码。由于每个步骤都是明确的,因此当发生故障时,工作流必须解决问题,并且能够部分恢复或至少消除故障。毫不奇怪,大多数自动化并非旨在从计算机中可能发生的各种问题中恢复,从软件依赖项不匹配到硬件问题(例如磁盘故障)。最后,操作员将通过手动干预的方式将系统恢复到良好状态,以便可以再次运行该过程。
云供应商在扩展软件方面面临着相同的挑战,但不能依靠过去的相同技术。从规模上讲,对于工作流中遇到的每个故障,手动恢复都是不切实际且不经济的。业界需要一种让用户定义软件基础结构的方法,而又不让他们暴露于内部系统内部可能发生的大量故障中。最终的解决方案是采用声明性API。使用声明性API,用户可以告诉云他们想看到什么结果,而不是如何实现。对于用户来说,他们能够通过一种与他们实际想要的方式更接近的方式与云提供商合作:描述部署的外观,而不是精确地部署它。
对于云提供商而言,他们可以灵活地将管理软件和底层硬件的复杂性推到API的背后。供应商负责复杂而繁重地创建基础设施的工作。同时,可以自由实现自己期望的目标:供应商不必受限于支持工作流中的特定步骤,例如基于命令式API构建的云。例如,云供应商可以在后台编排许多服务来提供MySQL服务(Mysql as a service)。在未来,他们可以改变实现工作流的各个部分,而保持已声明的API不变。
Kubernetes面临着与云提供商作为容器和基础架构协调者一样的挑战。毫无疑问,Kubernetes还将其设计很大程度上基于声明性API作为核心用户界面。
5一流的抽象
声明性API是为什么云提供商在可用性方面具有吸引力的决定性因素。以这种方式设计基础架构可以减少摩擦:对于提供商和用户而言,这都更容易实现。随着摩擦的减少,以更高级别的服务和诸如计算调度程序之类的原语形式出现的新抽象如今已司空见惯,以前它们仅限于复杂的软件组织。
另一方面,云计算产品(我们用来构建自己服务的核心原语)被专有API锁定。将云供应商称为专有似乎与前面描述的概念相反。即使与云进行交互的API是专有的,这也不会阻止用户以云计算/存储为基础来创建自己的抽象。声明性系统的好处之一是,基础设施配置的许多复杂性都被隐藏了。我要说的一点更加微妙。尽管用户可以在云提供商的基础上构建,但他们永远无法像云提供商一样构建一流的抽象。
为了解释什么是一流的抽象,我想对比一下AWS工程师和使用AWS的工程师构建基础设施的经验。Lambda之类的高级服务建立在为客户提供的相同EC2 API之上,但除了调用API之外,还有更多构建基础设施的内容。归根结底就是AWS随着时间的推移而构建的架构、设计和实践,以大规模地交付多租户基础设施。在无形的概念(例如shuffle sharding和静态可用性)中我们可以看到用于构建控制平面的具体内部库和工具。从外部看,我们也许可以使用相同的服务,但没有创建相同质量的基础设施所需的其他各种工具。
对Amazon和其他云提供商,我的期待是一致的,就是它们的竞争优势,而且最重要的开源工作将异常坚难。实际上,仅有可访问的API是不够的。一个新的云需要从头开始搭建,以暴露创建一流抽象所需的原语。
6一切皆在API中
当Google启动Kubernetes项目时,亚马逊在建立其云业务方面已有多年的领先优势。在没有创新和改变游戏规则的情况下,谷歌云将面临艰巨的挑战。Kubernetes应运而生,它主要是通过扮演开发人员管理基础设施的第一层和最终层,来平衡游戏环境。
以上描述并不是秘密。Kelsey Hightower经常提到这个目标,Daniel Smith也提出过未来目标的设想:Kubernetes API可以管理一切,从虚拟化(如虚拟机)到物理层面(如路由器)的所有元素。为什么Kubernetes有这个可能呢?让我们回到“一流抽象更容易创建”的想法上。
API(更好的说法是Kubernetes资源模型)提供原语,执行可对任何基础设施类型进行建模的标准。
Kubernetes API首先根据资源对所有数据进行建模,且对资源要求非常严格。资源必须全部遵循标准结构(apiVersion的顶级字段,种类,元数据和规范),并且资源(发布,放置,获取,删除等)动作都必须与API动词一致。作为各类资源的广泛标准,整个系统获得了巨大的影响。Kubernetes工具和库可以在所有类型上一致地工作,而无需为每个资源进行客户化。许多专门工作委员尽量使API系统扩大,而不是转移到其他组件上。为了进行复杂性管理,Kubernetes资源模型是一系列折衷方案。API服务器可以支持许多不同类型的资源,因为每个资源都是一致的,不需要新的特定代码即可支持。每个资源都保留一小片,保证可以从外部组件工作,这意味着Kubernetes一次可以支持多种不同的资源类型。
Kubernetes API标准化,极大地简化了定义新资源(对我们想通过Kubernetes管理的内容进行声明)。用这种方式设计的API可以做什么?可以将所有基础设施进行资源建模。Kubernetes已经提供了一组在集群内运行负载的核心资源。客户化资源定义和控制器,通过第三方将新的资源类型扩展到Kubernetes,会提升至一个新的水平。借助自定义资源,我们可以创建自己的一流抽象使Kubernetes能够理解,不管是从已有资源构建新资源类型(在Pods和ReplicaSets上部署的方式),还是定义云服务(例如AWS S3 bukets,Azure Cosmos DB等)。因为资源结构标准化,控制器也可以忽略资源之间的差异。例如,检查资源标签上的策略是否符合要求的控制器不需要知道每个资源的作用,只要结构是一致的,控制器可以去相同的位置为每个对象检查。
看到这里,读者可能会认为Kubernetes是围绕API而不是容器编排,因此容器部分没有多么重要。实际上,容器对于API可以扩展至关重要。更具体地说,正是更易运行任意计算的能力驱动了Kubernetes作为协调器而不是API资源控制器的大部分价值。控制器不仅可以处理较小的任务(通过标签注释资源,清理资源)也是管理全生命周期的成熟的应用操作员。与API资源类似,Kubernetes简化了注册新控制器的操作,使新行为能够成为在不扩展Kubernetes代码库情况下的API类型。
7定义控制平面
在这里,有一个好的idea定义什么是控制平面,尤其是在这种比较新的软件基础设施中。最初的概念来自网络路由,其中控制平面跟踪和管理网络拓扑和数据包路由规则,而数据平面则主动处理网络请求。Marc Brooker进一步概括了这一概念:
1.数据平面组件直接位于请求路径上。组件需要成功运行并可以随着系统的请求数量线性扩展。
2.控制平面组件可帮助数据平面完成其工作。职责包括:资源管理(添加和删除资源),容错(监控和纠正硬件/软件故障)和部署(随时间推移更改系统)。这些元任务需要资源拓扑的完整视图,并与在请求路径上的组件相比可以进行亚线性扩展。由于不需要控制平面来满足系统请求,因此系统可以中断一段时间而不影响数据平面。
控制平面是现代云计算设计的基础构建块,为跨虚拟机,容器,云功能,数据库,buckets,DNS等的基础架构产品奠定了基础。对于它们对云基础架构的重要性,我发现实际上它们在云从业者中并没有被经常讨论。
我认为这是因为控制平面是构建新型基础设施的实现细节。用户可以避免管理控制平面的复杂性(因使用了声明性API),但是他们也无法接触到云提供商用于构建自己的服务的原语。Kubernetes就是如此改变游戏状态的。回到较早的主题,Kubernetes提供了用于构建控制平面的原语作为一流的抽象。Kubernetes使基础架构服务管理民主化,可以将以社区驱动服务为主的第三方云资源的管理和使用。
8控制系统循环
有哪些机制保证控制平面适合基础设施管理?ColmMacCárthaigh 深入探讨了他如何通过控制理论来看待控制平面,以及AWS如何将这些原理应用到构建基础设施服务上。控制理论是一个跨越多个行业的广阔领域,以下是我们理解基础设施管理的几个关键概念:
1.声明所需状态:系统不是静态的,对外部和内部情况做出响应并反馈变化。稳定的系统需要已知状态驱动向前。
2.控制循环:绑定控制和数据平面的核心原语,循环持续观察数据平面组件,判断是否需要采取稳定措施,然后将更改应用于数据平面。就像他们观察到的系统一样,控制回路是连续的,反馈机制可以不断纠正与期望状态的偏差。
Kubernetes如何应用控制平面原理?Kubernetes API是如何管理声明性状态,如何创建/更新声明性状态,然后将系统收敛到该状态。可以在文档中发现控制循环的介绍。Kubernetes通过创建通用机制来管理所有资源作为潜在的控制平面,并进行了创新。Kubernetes在Informer和Workqueues之类的控制器中提供了一些组件,他们为控制循环的构建补充了逻辑。
如今,应用程序开发人员利用系统目录来构建自己的产品。如果应用程序需要存储二进制Blobs,他们可以将文件写入对象存储服务。如果应用程序需要管理事件流,则它们可以在应用程序流中集成消息队列服务。像一组构建块一样,应用程序构成了基础结构服务,这个服务可以管理复杂问题,简化了程序员的工作。Kubernetes提供了一组类似的构建块,适用于为其他人构建核心基础结构的开发人员。
一个说法是消除动作的摩擦会导致该动作的执行频率更高。Kubernetes在控制平面方面也朝着同样的方向前进。我们将看到控制平面用于管理更多种软件。系统是动态的,控制循环是这种管理的有力法宝。瓶颈始终是实现的复杂性,Kubernetes正在采取行动,通过与Kubernetes资源模型配对的控制和操作使这一部分易于处理。
9通用控制平面
贯穿Kubernetes架构的常见主题是标准化的思想。Kubernetes资源模型在很大程度上依赖于加强资源结构的一致性,并严格限制允许访问数据的路径。可以在许多不同的抽象中使用相同的原语,整个生态系统将在对数据模型[1]的限制中获益。这些原语还实现了云计算的核心原理:资源分层以创建更高级别的抽象(例如Deployments如何抽象Pods),并且Controller通过将底层代码实现复杂性来允许资源被声明。
因此,通用控制平面更多地取决于Kubernetes API设计,而不是容器编排。是的,没有容器,Kubernetes只是一个具有特定schema的数据库。控制器赋予各种资源不同的涵义。我们可以通过定义项目的数据进行抽象建模,然后使用一致的工具和强大的控制循环随时间管理和更改抽象,这才是使项目比容器协调器更重要的一点。
未来我们将会看到Kubernetes项目以令人惊讶的方式发展前进。我将在下一篇文章Kubernetes Unbundling中,更详细说明我对Kubernetes未来的看法。最后以一个问题供大家思考:有了通用控制平面,我们现在可以做什么?