-
Notifications
You must be signed in to change notification settings - Fork 3.8k
Kubernetes的设计与架构(翻译)
@[TOC] 转载请注明出处即可
文章原文
用最后提交时间为20年04月02号 85e7b63ddbb86107b2850ac4b0bacc7aed194fd5
的版本进行翻译
注意: 本文并非是直译,部分译文携带了笔者自己的理解,因为笔者水平有限,可能或曲解作者的原意。
Kubernetes的源自于Google 15 年生产环境的运维经验,同时凝聚了社区的最佳创意和实践。它是一个生产级别的开源基础设施,可以做到在跨主机集群的环境下,对应用容器进行部署、扩展、管理和组合。Kubernetes存在的意义不仅仅是提供了"容器编排"。它方便运维人员和开发者专注于以容器为中心的自助操作[1],比如帮助开发者聚焦核心应用功能,帮助运维团队获取更高的资源利用率等。它通过对开发者屏蔽了物理/虚拟计算、网络和存储,因此开发者可以专注于应用实现,而不是花费时间去思考与基础设施的集成,运维人员也不用考虑在上面部署的是什么样的应用。Kubernetes还是一个稳定的,可移植的基础平台,可以自定义的工作流和其他在更高级别的自动化,或者说Kubernetes抽象了底层的基础设施,简化了应用开发、部署等过程。
[1] (译注: 做到了关注点隔离,方便两种不同的角色专注于各自不同的领域,当某个机器出现问题时,只需要调度到其他的机器,而无需运维人员在半夜加班处理问题,可以在第二天在处理出现问题的机器。)
Kubernetes主要用于由多个容器(Docker等)组成的应用程序(或系统、服务)。为了方便管理容器和发现容器,它通过使用pods和labels(标签)来形成了一种紧耦合或松耦合的结构[2]。
[2] (译注: 这里的紧耦合和松耦合可以理解为在部署pod时,对label的使用。可以强制将pod部署到某个或者某几个节点,也可以通过对节点资源的筛选(比如需要GPU资源)等去进行选择节点(调度)部署。当然紧耦合在生产环境一般是不推荐的。)
Kubernetes是一个用于部署和管理容器的平台。Kubernetes提供了容器引擎,容器编排,以容器为中心的基础设施编排、运行时状态检查和重新调度等自我修复机制、并且还提供了服务发现和负载均衡。
Kubernetes期望能成为一个可扩展,插件化的工具集。因此,在架构上,我们希望将Kubernetes构建的组件都是可插拔的,并且可以自行选择调度器、控制器、存储系统和分发机制,我们根据这个愿景来发展这个项目。此外,我们希望大家能够扩展Kubernetes的能力,比如在无需修Kubernetes核心源代码的情况下,使用更高级的PaaS功能等,因此Kubernetes所提供的API不仅仅针对使用它的终端用户,而是针对工具和扩展Kubernetes能力的开发人员。它的API旨在作为工具、自动化系统和高级API层的开发生态系统的基础。因为,它没有“内部的”组件间的API。所有的API都是可见和可用的,包括调度器,节点控制器,复制控制器,Kubelet的API等。为了处理在不同生产环境下的独特需求,大家可以直接访问底层API。
本项目有以下的设计理论和目标:
- 方便: Kubernetes可以运行在公有云,私有云,裸机和笔记本电脑。并且无论在哪个环境下对它做的任何操作都是一致的。换句话说就是它可以到处运行,而无需考虑底层具体基础设施的差异。因此应用程序和工具可以在整个生态系统以及开发和生产环境之间进行移植。
- 通用: Kubernetes应该运行所有的系统类别。无论是有状态的、无状态的、微服务、单体应用、服务、批处理、遗留系统等,这样只需要在Kubernetes单个基础设施运行以上所有类型,来应对实际的负载。
- 满足一部分用户需求: 虽然Kubernetes不只满足于纯粹的云原生应用,但是也不会满足用户的所有需求。它主要专注于微服务和云原生应用的部署和管理,但是提供了一些机制来促进整体和遗留应用到Kubernetes的迁移。
- 灵活: Kubernetes功能可以按需使用,并且可以通过自己的解决方案来替代内置的功能。
- 可扩展的: Kubernetes通过内置功能所使用的相同公开接口来添加额外的功能。
- 易自动化: Kubernetes的目标是大幅减少手工操作。它通过声明式API指定用户期望,声明后则通过它的内部机制来进行具体的命令式的控制执行。声明式API是系统自愈等相关能力的关键。当然, 它也支持定义更高级别的编排和自动化的命令式控制。
- 推荐先进技术: 虽然Kubernetes可以支持非云原生应用,但是它也希望可以推进云原生和DevOps的技术发展,比如让应用参也参与到对自己的管理之中。但是它不会强迫程序锁死在Kubernetes API,这也是Kubernetes的API更喜欢配置而不是约定的原因。此外,Kubernetes不受它所依赖系统的限制,无论是容器引擎还是云厂商。例如,可以根据需要来选择不同的Pod的网络模型。
Kubernetes在运行时,包含节点代理(kubelet)和集群控制平面(AKA Master),集群状态存储在分布式存储系统(etcd)中。
Kubernetes的控制平面由多个组件组成,这些组件既可以单节点运行,或通过多节点来支持高可用的集群,或者将组件直接运行在Kubernetes上,进行自托管。
在Kubernetes中,资源作为控制平面的枢纽,Kubernetes提供的Rest API,主要是支持在这些资源(持久化)上进行CRUD操作。Kubernetes提供的API,比如Pods,Services和Ingress,以及生命周期的API等,都是以容器为中心的操作。通过这些API来支持业务流程(自愈、扩展、更新、终止)和常见的工作负载。比如ReplicaSet(简单的、无状态(可替换)的应用程序管理器),Deployment(部署与更新无状态应用),Job(批处理), CronJob(cron), DaemonSet(集群服务)和StateFullSet(有状态应用管理)。并且我们特意将服务注册于服务发现和负载均衡的实现分离,因为负载均衡是开放的,并且种类繁多。
用户客户端(kubectl或直接使用的k8s client)和包含异步处理的控制器(conttollers)都使用了相同的API资源、这些资源会协调中间数据状态,以及共享状态。大多数资源都包含元数据,元数据中又包含labels和annotations,资源所需的详细状态(spec),默认值和可观测到的状态。
控制器会不断检查观测状态,当期望(配置)状态与观测状态不一致时,则驱动Kubernetes达到期望的状态(自愈),同时也会为用户和其他控制器报告观测到的状态。
虽然控制器是基于声明式API已最大程序的提高容错性,但它们为了最大限度的减少延迟和冗余工作,通常会watch(监视)相关的资源更改。这样就可以在没有消息总线的情况下实现服务编排的解耦。
API Server提供Kubernetes API,它是一个相对简单的服务器,其他的组件或插件会实现大部分业务逻辑。它主要处理REST操作,并进行验证,然后更新Etcd中相应的对象(可能最终会更新其他存储)。这里请注意,Kubernetes不支持跨多个资源的原子事务。
这个基本的API机制,是Kubernetes可以运行的根本,其中包括
- REST语义,watch(监听),持久性和保证一致性, API版本控制、默认值和校验
- 内置控制语义,同步控制hooks和异步资源初始化
- API的注册和发现
此外,API服务器充当集群的网关。根据定义,Kubernetes Client能够从集群外部访问API服务器,而节点和容器则不能直接在集群外部访问。API服务器会对客户端进行验证,并且用于连接节点和Pods(Services等)的代理和通道。
所有持久化的集群状态都存储在Etcd中。通过对wahch的支持,可以非常迅速的通知和协调组件进行更改。
大多数集群级别的功能都是通过Controller-Manager来执行的。他处理生命周期的功能(例如,命名空间创建和生命周期、事件垃圾收集、终止pod垃圾收集、级联删除垃圾收集、节点垃圾收集)和API的业务逻辑(例如,由复制集控制的pod扩展)。
应用程序管理和组合层,提供自修复、伸缩、应用程序生命周期管理、服务发现、路由以及服务绑定和供应。这些功能最终可能会被分解成单独的组件,以便更容易地扩展或替换。
Kubernetes允许用户请求集群运行一组容器。调度器会为容器自动选择要运行的主机。
调度器监视未调度的Pods,并根据所请求资源的可用性、服务质量(QoS)要求、亲和性和反亲和性以及其他的约束选择节点,然后通过Binding Pod子资源API将它们绑定到节点上。
Kubernetes节点有运行应用容器所需的组件。
Kubernetes中最重要的就是Kubelet组件,它是容器执行层的Pod和Node API的主要实现者。如果没有这些API, Kubernetes就只是一个CRUD的REST应用程序框架(这些API机制可能最终会发展成为一个独立的项目)。
Kubernetes将隔离的应用容器作为默认的执行模式。应用容器不仅仅彼此隔离,而且还与它们执行的主机隔离,这对于各个应用程序管理与基础设施的管理(底层物理集群或虚拟集群)分离来说至关重要。
Kubernetes通过Pods来承载多容器和存储卷,方便每个容器只打包单个应用程序(译注: 在k8s中,一个Pod可以运行多个容器,但在实践中尽量不要在一个容器中跑多个应用)。通过Pod可以将部署和构建分离开,以及方便从物理机和虚拟机迁移。Pod的设计是现代云平台(如Kubernetes)上部署的关键。
API管理控制可能拒绝Pods或向它们添加额外的调度约束。但是Kubelet是决定Pods在指定节点(node)上是否可以运行的最终角色这,而不是调度器或其他组件。
Kubelet还链接在cAdvisor(译注: Google开源的容器资源监控项目)资源代理的监控中。
每个节点运行一个容器时,容器引擎负责下载镜像(images)和运行容器。
Kubelet没有关联任何的基础容器引擎。相反,我们定义了一个容器引擎的接口来控制底层引擎在该层的可插拔性。为了组件边界、方便测试和可插拔性,需要这种与某个具体容器引擎的解耦。目前至少支持了Docker、rkt、crio和frakti这些容器引擎。
Kubernetes中service提供了公共访问策略,可以为Pods进行分组(译注: 可以通过label来实现)后提供负载均衡。它实现了一个虚拟IP,客户端可以通过访问这个虚拟IP,来透明的代理到服务后的Pods中。每个节点都运行了一个kube-proxy进程,该进程通过改写iptables规则来捕获IP的访问,并将其重定向到具体的后端。这是一个高可用的负载均衡解决方案,通过平衡单个节点客户端流量,到相同的节点上,降低了单个节点的性能开销。
服务endpoints还可以通过DNS(内置的core-dns)来找到。
Kubernetes除了以上组件外,还依赖其他组件,通常运行在Kubernetes内部:
- DNS
- Ingress controller
- Heapster (resource monitoring)
- Dashboard (GUI)
一个Kubernetes可以跨多个可用区(Zone)部署。 但为了更高的可用性,我们建议使用集群联合。 (译注: 集群联合或者叫做集群联邦,是新版本提供的功能,可以跨集群资源同步和跨集群发现)
小傅哥(微信:fustack),公众号:bugstack虫洞栈
| bugstack.cn - 沉淀、分享、成长,让自己和他人都能有所收获!
🌏 知识星球:码农会锁
实战项目:「DDD+RPC分布式抽奖系统
」、专属小册、问题解答、简历指导、架构图稿、视频课程
🐲 头条
-
💥
🎁 Lottery 抽奖系统
- 基于领域驱动设计的四层架构的互联网分布式开发实践 -
小傅哥的《重学 Java 设计模式》
- 全书彩印、重绘类图、添加内容 -
⭐小傅哥的《Java 面经手册》
- 全书5章29节,417页11.5万字,完稿&发版 -
小傅哥的《手撸 Spring》
- 通过带着读者手写简化版 Spring 框架,了解 Spring 核心原理 -
🌈小傅哥的《SpringBoot 中间件设计和开发》
- 小册16个中间件开发30个代码库
⛳ 目录
💋 精选
🐾 友链
建立本开源项目的初衷是基于个人学习与工作中对 Java 相关技术栈的总结记录,在这里也希望能帮助一些在学习 Java 过程中遇到问题的小伙伴,如果您需要转载本仓库的一些文章到自己的博客,请按照以下格式注明出处,谢谢合作。
作者:小傅哥
链接:https://bugstack.cn
来源:bugstack虫洞栈
2021年10月24日,小傅哥
的文章全部开源到代码库 CodeGuide
中,与同好同行,一起进步,共同维护。
这里我提供 3 种方式:
-
提出
Issue
:在 Issue 中指出你觉得需要改进/完善的地方(能够独立解决的话,可以在提出 Issue 后再提交PR
)。 -
处理
Issue
: 帮忙处理一些待处理的Issue
。 -
提交
PR
: 对于错别字/笔误这类问题可以直接提交PR
,无需提交Issue
确认。
详细参考:CodeGuide 贡献指南 - 非常感谢你的支持,这里会留下你的足迹
- 加群交流 本群的宗旨是给大家提供一个良好的技术学习交流平台,所以杜绝一切广告!由于微信群人满 100 之后无法加入,请扫描下方二维码先添加作者 “小傅哥” 微信(fustack),备注:加群。
- 公众号(bugstack虫洞栈) - 沉淀、分享、成长,专注于原创专题案例,以最易学习编程的方式分享知识,让自己和他人都能有所收获。
感谢以下人员对本仓库做出的贡献或者对小傅哥的赞赏,当然不仅仅只有这些贡献者,这里就不一一列举了。如果你希望被添加到这个名单中,并且提交过 Issue 或者 PR,请与我联系。