Kubernetes设计与架构 中文翻译
更多细节请参见:Architectural Roadmap(架构演进路线)
概述
Kubernetes是由谷歌开发的,为了在主机集群间的应用容器可以进行部署、动态伸缩、管理的一个生产级别的、开源的基础设施。Kubernetes不仅想要做一个容器编排者,它的目的在于减轻各种资源(包括虚拟/物理计算资源、网络资源、存储资源等)的编排负担,让应用的维护和开发者能够更专注于容器原生的服务构建。Kubernetes也为构建定制工作流和更高等级的自动操作提供了稳定的、轻便的基础设施(一个平台)。
作用域
Kubernetes是一个用于部署和管理容器的平台。Kubernetes提供了容器运行时间管理、容器编排、容器原生基建编排、自愈的机制,例如:健康状态监测、重调度、服务发现、负载均衡等。
Kubernetes希望成为一个可扩展、插件化的平台和工具集。因此,架构上,我们希望Kubernetes成为一个可插拔组件/平面的集合,如此就有能力在调度器、控制器、存储系统、分布式组件等方面做灵活的选择,我们也正在令它的代码往这个方向去演进。此外,我们也希望开发者能够不必修改其源代码就能实现功能的扩展,例如更高层次的PaaS支持,或者多集群架构。因此,它的API不仅面向终端使用者,更面向工具和扩展功能的开发者。它的API是有意地被设计作为开源生态系统、自动化系统和更高级别的API的基础。总而言之,没有任何所谓的“内部”API。所有的API,包括那些被调度器、节点控制器、复制管理器、Kubelet等等使用的API,都是可见的和可用的。这么设计是为了能够兼容更多的复杂使用场景,比如说,在某些完全透明的组合操作中,一些操作需要访问到底层的API。
目标
这个项目承诺遵循以下的设计原则:
- 轻便的。Kubernetes可以在任何地方运行——公有云、私有云、裸机、手提电脑等——因其具有一致的行为,应用程序和工具就可以在整个生态系统以及任何开发环境或生产环境中随意移植。
- 通用性强的。Kubernetes应该运行所有主要类别的工作,以便用户可以在一个单一的基础平台上运行自己的所有服务,无论基础平台是有状态还是无状态的,微服务隔离的还是整体控制的,服务型还是批处理型,新建环境还是遗留环境。
- 某种程度上适配用户。Kubernetes并不仅仅适配全新的云原生应用,也不能支持所有的应用架构。它专注于微服务和云原生应用的部署和管理,也提供一些机制来帮助传统应用向微服务的方向迁移。
- 灵活的。Kubernetes的功能能够被定制,并且在大多数情况下,也并不组织用户用自己的解决方案代替内置功能。
- 可拓展的。Kubernetes通过暴露内部接口,使用户能够将Kubernetes集成到自己的平台上,或者额外增加一些功能。
- 自动化的。Kubernetes的目标是显著降低运维操作。它既支持声明式控制,即用户通过API指定所需意图,也支持命令式控制以支持更高级别的编制和自动化。声明式方法是系统自修复和自管理的关键。
- 驱动当前技术发展。Kubernetes打算支持非云原生应用,也渴望驱动云原生和DevOps的技术发展,例如在participation of applications in their own management(参与应用自己的管理)。但是,与此同时,我们也严格要求自己不要把应用绑定在Kubernetes的生态上,这也是为什么我们在南向API中,更喜欢配置而非约定。同时,Kubernetes也不受其运行平台的最低水平限制,例如容器运行时间和云服务提供商,举个例子,我们在IP per Pod networking model(每Pod一个IP的网络模型中),突破了可实现的极限。
架构
一个运行中的Kubernetes包括节点代理(kubelet)和一个集群控制平面(也称为master),集群状态存储在一个分布式存储系统(etcd)中。
集群控制平面(也称为master)
Kubernetes的集群控制平面(control plane)被切分为一堆的组件,能运行于单个master节点,也能多副本地运行于一个高可用集群中,甚至能运行在Kubernetes自身(self-hosted)。
Kubernetes提供REST规范的API支持主流的CURD操作用于持久化资源,这也是其控制平面的中心。Kubernetes的API提供了IaaS一般的容器中心基元例如Pods, Services, Ingress,也提供了生命周期API,来支持编排常见的特性(如自修复,动态伸缩,更新,终止),例如ReplicaSet (简易可替换/无状态应用程序管理器), Deployment (编排无状态的应用更新), Job (批处理), CronJob (定时任务), DaemonSet(集群服务), and StatefulSet (有状态应用)。我们故意地将服务发现和负载均衡从应用实现中解耦了出来,因为应用实现是开放且差异非常大的。
用户的客户端和组件都包含了异步控制器来和相同的API资源交互,API资源作为了调和点、中间件、状态共享而存在。大部分资源包含元数据,包括labels(标签)和annotations(注释),非常详尽的目标状态,包括默认值和观测到的当前状态。
控制器持续地工作,驱动从当前状态向目标状态转变,与此同时也不断地向用户和其他控制器上报当前观测到的状态。
假如控制器是设置成水平触发的,以此来增大容错率,它通常会监控相关资源的变化,以此来减少反应延迟和重复工作。这使得无需消息总线就可以实现分散和解耦的类似于编排的协调。
API服务
API server(API服务)提供了Kubernetes API,它被设计成一个相当简单的服务,其大部分业务逻辑在分散的组件和插件中实现。它主要处理REST请求,并更新etcd(或其他存储)中的相应对象。值得注意的是,因为某些原因Kubernetes不支持跨资源的原子性事务。
Kubernetes必须在以下API机制帮助下运行:
- REST原则、监听、持久性和一致性保证、API的版本控制、默认设置、鉴权
- 内置的接入控制机制,同步的接入控制钩子,和异步资源初始化
- API注册和发现
此外,API服务也作为集群对外的接口。从定义上讲,API服务必须暴露给集群以外的客户端,然而集群内的节点和容器可能是不暴露的。客户端通过API服务进行鉴权,也以API服务作为堡垒机访问集群中的节点和服务。
集群状态存储
所有持久化的集群状态存储在etcd的一个实例中,这也提供了一个可靠的方法来存储配置数据。通过监控的支持,协调组件能够很快地感知集群的变化。
控制管理服务
大部分其他的集群层面上的功能由一个分布式服务实现,称作Controller Manager(控制管理服务)。它既执行生命周期函数(命名空间的创建和生命周期管理、事件垃圾回收、终端Pod垃圾回收、级联删除垃圾回收、节点垃圾回收),也实现API业务逻辑(Pod的动态伸缩)。
应用管理和组合面提供了自修复、动态伸缩、应用生命周期管理、服务发现、路由、服务绑定和发放功能。
这些功能可能最后被拆分到多个组件中去以使其更加易于扩展和可替代。
调度器
Kubernetes允许用户在一个集群中运行多个容器。调度器组件能够自动地选择哪个物理/虚拟机来运行这些容器。
调度器监控那些未经调度的Pod,并使用“/binding”API来将它们绑定到节点上。调度依据Pods请求的资源的可用性、服务的质量、亲和性和反亲和性以及其他的一些限制。
Kubernetes支持用户自行提供调度器和多并发的调度器(使用由Omega首创的共享状态方法)。除了Omega的论文中提到的悲观的并发状况之外,two-level scheduling models(二级调度模型)中,高层调度器和低层调度器均需实现相同的调度需求以保证供调度的资源能满足它们的需求。
Kubernetes节点
Kubernetes节点有运行应用容器以及接受管理所需的必要服务。
Kubelet
Kubernetes体系中,最重要也最突出的控制器就是Kubelet,它是Pod和节点API的主要实现者,驱动了容器执行面。没有了这些API,Kubernetes可能就只是一个应用的CURD操作的框架,背后有一个存储系统而已。
Kubernetes使用独立的应用容器作为其默认的本机执行模式,而非进程或传统的操作系统包。不仅应用容器间相互独立,并且应用容器也和运行它们的物理节点相互独立,这也是解耦不同应用的管控和基础设施的管控的关键点。
Kubernetes提供了Pods这样的能够同时运行数个容器并共享存储的管理基元,以便为每个容器打包单个应用程序,将部署和构建解耦,在不同的(物理/虚拟)节点间进行迁移。以Pod作为管理基元是部署在现代云平台上,如Kubernetes,的主要好处。
API准入控制也许会拒绝Pods或向它们添加额外的调度约束,但是Kubelet最终决定Pods能否在给定节点上运行,而不是调度程序或守护进程集。
Kubelet目前也会受到cAdvisor资源监控代理的监控。
容器运行时间
每个节点都维护一个容器运行时间,在下载镜像和运行容器时起作用。
Kubelet并不链接到基础的容器运行时间。相反,我们定义了一个Container Runtime Interface(容器运行时间接入面)来管控下层的运行时间,这种机制也促进了这个层面的可插拔性。为了维护组件间的边界,促进可调试性和可插拔性,这种解耦是很有必要的。今天的运行时间支持,不管是上游的还是分叉的,都至少支持docker, rkt, cri-o, frakti。
Kube Proxy
服务的抽象提供了一种划分Pods的公开原则(例如,负载均衡)。这种实现创建了一个虚拟IP给客户端访问,并且这个IP被透明代理给一个服务中的Pods。每个节点都运行了一个kube-proxy,其通过规划防火墙规则来将不同的访问重定向到正确的后端。这提供了一个高可用的负载均衡解决方案,通过平衡同一节点的流量来实现低性能消耗。
服务端点主要通过DNS创建
附加组件和其他依赖
非常多的组件作为附加组件运行在Kubernetes上:
- DNS
- Ingress controller
- Heapster (resource monitoring)
- Dashboard (GUI)
集群联邦
单一的Kubernetes集群可能跨越多个可用区域。
然而,为了更高的可用性,我们推荐cluster federation(集群联邦)。