什么是kubernetes?
官方说明:
Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.It groups containers that make up an application into logical units for easy management and discovery.
说简单点,Kubernetes 就是自动化容器管理平台,它跟一般的 PaaS 平台一样,也都支持比如服务部署、自动运维、资源调度、扩缩容、自我修复、负载均衡,服务发现
等功能。
讲点不一样的,Kubernets 到底有什么特别的地方?以我的理解还是在于能力抽象
,抽象可以分为两大块:基础设施
和 API
。
1.基础设施的抽象
基础设施包括很多,比如runtime(docker、rkt、pouch),存储,网络等。还有不同的云服务提供商,集群环境的差异都会很大。
像存储、网络这类都是难啃的骨头,如果 Kubernetes 想吃,那就会出现大量的 PR,这些代码量甚至会比主体代码倍上好几倍,不仅会提升代码的复杂度,还会影响系统的稳定性。
所以 Kubernetes 根本不想吃,但是又想做云无关
,便开始实现各类 interface,做各种抽象。比如容器运行时接口(CRI)、容器网络接口(CNI)、容器存储接口(CSI)。这些接口让 Kubernetes 变得无比开放,而其本身则可以专注于内部部署及容器调度。
Kubernetes 生态中也会有很多通用的功能,比如服务发现、负载均衡、日志系统、监控系统等,这些都有提供默认方案,且这些方案都是可选、可插拔的。这些也都可以看作是 PaaS 平台的基础设施,在 Kubernetes 上也没有强绑强销的买卖,给用户提供了高度的灵活性。
2. API 的抽象
Kubernetes 的各种功能都离不开它定义的资源对象,这些对象都可以通过 API 被提交到集群的 Etcd 中。API 的定义和实现都符合 HTTP REST 的格式,用户可以通过标准的 HTTP 动词(POST、PUT、GET、DELETE)来完成对相关资源对象的增删改查。
常用的资源对象,比如 Deployment、DaemonSet、Job、PV 等。API 的抽象也意在这部分资源对象的定义。Kubernetes 有新的功能实现,一般会创建新的资源对象,而功能也依托于该对象进行实现。
我觉得这两部分的抽象,才是极大的成就了当前的 Kubernetes,使其成为业界标准的关键之一。
设计
Kubernetes 已经是一个非常庞大的分布式系统了,在深入各类源码实现之前,值得先了解下 Kubernetes 的设计理念。
这里先学习下 Kubernetes 的声明式设计及控制闭环。
1. 声明式
Kubernetes 采用了声明式(Declarative)的资源管理模式,该模式会有如下几个步骤:
- 声明:用户通过声明式的配置文件(json/yaml等)向 Kubernetes 告诉所期望达到的应用状态。(比如:运行 2 个副本的 nginx 服务)
- 观测:Kubernetes 会观测到用户的声明,并自动分析出需要执行的操作及用户所期望达到的应用状态。(比如选取合适的节点,配置相应的负载均衡策略等)
- 行动:Kubernetes 控制器会负责具体的工作执行,以达到用户声明的应用状态,该过程是全自动化。
- 持续观测与收敛:大型分布式系统必然会存在各种异常,比如系统崩溃、容器退出等。Kubernetes 自然会持续关注系统的实时状态,当遇到异常时能够及时的进行自我修复。比如用户声明了 2 个 nginx 服务,当其中有个 nginx 挂了,或者所在的宿主机挂了,kubernetes 会自动发现,并寻找合适的节点,再运行一个新的 nginx 服务,以维持用户所期望达到的应用状态。
在命令式(Imperative)设计模式中,用户需要指明一步一步的具体流程和指令,而并非像声明式模式一样直接指明最终想要达到的状态。
可以简单假想下,如果用命令式来实现 Kubernetes集群,会如何实现?
必然 scheduler 模块自身不仅需要完成原本的调度工作,还携带了 apiserver & controller等功能;scheduler 不仅需要执行命令,还需要关心命令执行的结果;很多复杂的概念都会堆积在 scheduler 模块上,导致该模块越来越重,越来越复杂。
相对于命令式操作,声明式操作会更稳定且更容易被用户接受,因为该API中隐含了用户想要操作的目标对象,而这些对象刚好都是名词性质的,比如Service、Deployment、PV等;且声明式的配置文件更贴近“人类语言”,比如YAML、JSON。
所以相比较,命令式思想在分布式系统和微服务架构中会存在各种困境。
2. 控制闭环
Kubernetes 使用了声明式设计模式,这里控制闭环又起到了什么作用呢?
我们可以从该系统的需求入手分析:
- 持续观测、校正,最终将运行状态达到用户期望的状态。
- 感知用户的行为并执行。比如修改 Pod 数量,应用升级/回滚等等。
声明仅仅只是声明,用户丢过来一个 yaml 文件后,该如何智能的转化为一系列可执行操作,且达到上面所描述的需求?
调度器是核心,但它只是负责从集群节点中选择合适的 node 来运行 pods,显然让调度器来实现上诉的功能不太合适,而需要有专门的控制器组件来实现。
Kubernetes 实现了大量的 controllers,它们通过 list-watch etcd 来感知集群数据的更新,然后 24 小时不间断的工作以达到期待的状态,在该过程中它们也会把创建的各类数据反馈回 kube-apiserver & etcd,从而形成了数据流的闭环。
Kube-controller-manager 不仅完成了 Kubernetes 集群功能的半片天,还提供很强大的扩展能力,可以让用户轻松的实现自己的 controllers。
架构
Kubernetes 架构是借鉴了 Borg 的设计理念,如下图:
Kubernetes 主要由以下几个核心组件组成:
- Etcd:是高可用的key/value存储系统,用于持久化存储集群中的所有资源对象,比如:Node,Pod,Serivce,RC,namespace等。API server提供了操作etcd的封装接口API,以Rest的方式提供,这些API基本上都是集群中资源对象的增删改查及监听资源变化的接口,比如创建Pod、RC,监听Pod的变化等接口。API server是连接其他所有服务组件的中间枢纽。
- API Server:提供了资源对象的唯一操作入口,其他组件都必须通过它提供的 API 来操作资源数据,通过对相关的资源数据"全量查询" + "变化监听",这些组件可以很"实时"的完成相关的业务功能。比如提交一个新的 Pod 到 API server 中,Controller Manger 可以立即就发现并开始作用。它还有一套完备的安全机制,包括认证、授权及准入控制等相关模块。
- Controller Manger:集群内部的管理控制中心,主要完成了集群的故障检测和恢复的自动化工作。比如对 RC 定义的 Pod 进行维护;根据 service 和 Pod的关系,完成服务的 Endpoints 对象的创建和更新;还有 Node 的发现、管理和状态监控,死亡容器所占资源及本地缓存的镜像文件的清理等工作。
- Scheduler: 集群的调度器,负责 Pod 在集群节点中的调度分配。
- Kubelet:负责本地节点上 Pod 的创建、修改、监控、删除等生命周期管理,同时会上报本 Node 的状态信息到 API server。
- Kube-proxy:实现 Service 的代理及软件模式的负载均衡器。
- Kubectl:集群内部的客户端可以直接使用 kubectl 命令管理集群;集群外的客户端需要使用 kubectl Porxy 进行反向代理来访问 API server。
- cAdvisor: 在 Node 节点运行的 Kubelet 服务中内嵌了一个 cAdvisor 服务,cAdvisor 是谷歌的开源项目,用于实时监控 Docker 上运行的容器的性能指标。
除了这些核心组件,还有一些推荐的服务:
- Kube-DNS:负责为整个集群提供 DNS 服务。
- Heapster:提供资源监控服务。
- Dashboard:提供 GUI。
- Fluentd-ES:提供集群日志系统。
- ….
分层架构
Kubernetes 有类似于 Linux 的分层架构,如下图所示:
- 基础设施层:runtime、网络、存储等
- 核心层:Kubernetes 最核心的功能,对外提供 API 构建高层的应用,对内提供插件式应用执行环境。
- 应用层:部署(无状态、有状态应用、Job等)和路由(服务发现、负载均衡等)
- 管理层:系统度量(如基础设施、容器和网络的度量),自动化(如自动扩展、动态 Provision 等)以及策略管理(RBAC、Quota、PSP、NetworkPolicy 等)
- 接口层:kubectl 命令行工具、客户端 SDK 以及集群联邦
-
生态系统:在接口层之上的庞大容器集群管理调度的生态系统,可以划分为两个范畴。
- Kubernetes 外部:日志、监控、配置管理、CI、CD、Workflow、FaaS、OTS应用、ChatOps 等
- Kubernetes 内部:CRI、CNI、CSI、镜像仓库、Cloud Provider、集群自身的配置和管理等。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。