架构设计30-架构模式12.实践-从架构层面了解Kubernetes

架构设计系列文章,请参见连接。

因为Kubernetes字符太长本文中将Kubernetes简写为K8s。

0. 背景

0.1 为什么K8s战胜了Swarm、Mesos

从使用上来说以声明式API来降低运维的操作成本。在生态系统建设方面以极高的可扩展性来提升社区活跃度。从这两个方面既可以填充K8s的不足,也极大的简化了运维操作过程。

0.2 架构侧面

在K8s的各种文档、书籍中都没有从架构方面说明K8s的架构层面为什么是好的架构设计。

本文主要讨论K8s在架构层面上的一些内容,下面逐步的进行细化讨论。

1. K8s简述

本章通过对K8s内部原理的说明来对K8s有一个基础认知,来展示一些K8s的架构特种在后面对架构的分析与说明奠定基础。

在Ops的业务中有几项:

  1. 环境初始化:操作系统安装、运行环境安装、存储挂载、网络划分等等。
  2. 配置管理:根据运维配置,进行服务的配置。包括:副本数,可靠性保证,指标等
  3. 运行服务:选择运行环境进行服务配置与服务启动等
  4. 监控与升级:监控服务检查是否超过阈值进行相关的扩缩容,服务的升级工作等。

K8s主要解决的就是在Ops中的业务。以不可变基础设施来解决运行环境、配置管理、运行服务的问题。以声明式API来解决运维标准化的问题。

  • 不可变基础设施是结果,而不是设计
    基础设施的标准化问题在Ansible中是通过playbook来完成的,而K8s使用容器镜像做为基础设施的标准化。这其中的最大区别在于Ansible可以帮助进行标准化运行环境,而K8s中的容器镜像中包含的内容有运行环境服务配置服务监控等。这里从业务层面上来说,K8s提供了镜像的版本而Ansible提供的是基础运行环境的运行以及部署能力
    Ansible为服务配置、服务升级、运行环境的管理比K8s更为灵活,可以通过不同的playbook的配置进行处理。而K8s对于运行环境、服务配置的管理是不足的为了简化这部分的管理复杂度。这部分工作都通过容器镜像来进行管理。所以作者认为不可变基础设施是结果,而不是设计

  • 声明式API解决运维自动化、标准化问题
    面向终态的声明式API解决了运维工作中的一个重要工作:自动化、标准化。自动化、标准化、可视化、智能化是运维管理中的重要目标。使用声明式API将服务的定义都抽象出来、标准化的定义服务,就解决了运维标准化问题。

1.1 用户概念

Kubernetes用户概念

K8s的核心概念以及之间的关系。这里的概念都是给用户来操作、管理K8s中的对象所使用的。在K8s的使用过程中是理解这些概念并了解作用原理。

1.2 控制面过程

控制面包括的业务有定义转换、选择节点、部署服务、通信控制、节点管理、服务监控、权限控制等。而这些业务基本上都落在apiserver,controller,scheduler,kubelet,proxy组件之上。他们的关系如下图所示:


K8s架构

业务在组件之间的控制流的交织形成了K8s的控制面。本节主要讨论控制面中几个较为有名的过程。

1.2.1 资源过程

API Server请求处理过程

在资源过程中主要描述的是资源的下发过程。资源下发过程中以API Server为中心完整触发、转换、调度、启动等过程。从图中可以看到各个组件都以List-Watch的方式进行触发和处理过程的管理工作。

1.2.2 节点过程

这里展示的只是Kubelet中的SyncLoop过程,而Kubelet中的PLEG、自动过程、Informer、垃圾回收过程等都与syncLoop相关。Kubelet 的工作主要是围绕一个 SyncLoop 来展开,借助 go channel,各组件监听 loop 消费事件,或者往里面生产 pod 相关的事件,整个控制循环由事件驱动运行。可以用下图来表示:

Kubelet SyncLoop
  1. 用户从http,静态文件以及APIServer对pod的修改通过PodConfigchannel传递到syncLoop;
  2. 另外一方面,PLEG会周期(默认1s)通过relist从CRI获取所有pod当前状态并且跟之前状态对比产生Pod的event发送到syncLoop;
  3. syncLoop的syncLoopIteration从各种chan中取出update的内容,一方面会通过podManger里更新pod状态,另一方面会通过dispatchWork将更新内容通过PodWoker更新pod状态,调用的是syncPod这个接口(由Kubelet.syncPod实现);
  4. 而syncPod这里通过podStatusChannel 更新状态到statusManager, 再patch Status到APIServer;
  5. syncPod一方面通过containerManager更新non-runtime的信息,例如QoS,Cgroup信息;另外一方面通过CRI更新pod的状态;

1.2.3 资源调度过程

资源调度过程

k8s中的Scheduler Framework的设计。其中核心包括:Filter,Score,Bind。

1.2.4 总结

在K8s中控制面还有很多核心过程,但因为篇幅所限这里无法讨论所有的控制面板过程。

1.3 数据面过程

数据面最主要的是CNI。在CNCF中有多种类型的网络插件,都是实现了CNI的组件。在K8s中的网络也是从iptables演进到IPVS来的过程。都是由Proxy服务负责的。

1.4 总结

架构设计过程:整体架构->核心流程设计。这里整理K8s架构的时候也是以类似的方式进行。

2. K8s架构

这里的K8s架构都是从K8s中逆向工程出来的。可能很多都不能反应K8s在设计过程和设计结果中内容,不过从作者看到的内容来说已经充分的体现了K8s架构的优点。按照作者总结的K8s架构:以控制环路的风格构建起来的C/S形式的微服务。从总结出的K8s架构就可以看出K8s使用了多种架构风格与模式处理在K8s不同的功能点的设计。架构风格的使用是对于架构结构(参照:《软件架构:架构模式、特征及实践指南》)的定义,而架构结构背后的对于架构模式的选择的原则以及决策过程才是支撑K8s的架构好坏的原因。所以下面会以架构风格的讨论引出架构原则与决策的讨论

2.1 架构风格与模式

这里以抽象的方式总结出K8s中的涉及到的架构风格、架构模式和设计模式的内容。

  • 微内核架构风格
    微内核架构风格最大的特点就是插件。一般的微内核模式都会以定义接口的形式来进行扩展点、扩展方式、扩展点结果形式等的定义来描述一个扩展点,但是K8s不同之处在于Watch的方式进行扩展,这样就可以以最少接口定义的方式支持最多的扩展点。
    这样做即提高了系统的整体可扩展性,又提高了系统的性能与稳定性。因为以事件驱动的方式来处理业务比顺序执行的方式肯定要快,并Watch在不同的进程中执行就算客户端进程退出也不会影响API Server的正常运行。从设计模式的开闭原则来看Informer即实现了对扩展的开发,有实现了对修改的关闭。可以通过实现Controller Manager的方式对业务进行扩展,又不允许对数据的存储以及Watch机制进行修改。
    Scheduler Framework(以下简称SF)的扩展方式与Controller的扩展方式不一致,也与上面描述的微内核架构的扩展方式也不同。SF是提供了扩展点,但是扩展内容必须和Scheduler编译在一起。而作者认为使用dlopen去做标准的微内核方式也不失为一种更好的扩展方式。

  • 事件驱动风格(brokers)
    ListAndWatch机制和Informer机制是K8s中的事件驱动风格的一种体现。这两种机制为事件驱动的一个长期争论的问题:事件中应该带多少信息?给出一种解决方案:边沿触发,水平驱动。触发事件带索引性信息,在事件处理中去根据索引查询完整信息。以这样的方式解决并发与实践传输信息量之间的关系。
    另外,在K8s中Event也可以认为是一种记录型的事件驱动机制。不过在K8s中主要以日志的方式使用Event概念。

  • 控制环路架构风格
    控制环路一般在IoT系统中较为常见,因为在IoT系统中需要不断的采集设备运行数据并根据设备运行数据进行相应的以命令的形式控制设备的行为。在K8是中的Controller Manager就是通过这种机制来控制Pod的状态的。
    资源的状态发生变更之后,由Controller进行相关的状态变更动作。

  • 黑板架构风格
    API Server和Etcd即是黑板架构风格中的中心节点。Controller、Schedule、Kubelet、Proxy等都是通过API Server的Informer进行数据的访问与操作的,所以API Server是K8s其他组件的知识源,数据结构就是K8s中定义的各种资源对象。由API Server负责维护K8s中的数据,并以事件的方式通知各组件数据状态的变更。

  • 管道过滤器风格
    虽然不明显但是有很多内容。像Scheduler Framework就是一个典型的管道过滤器风格的。但在作者去查看Scheduler Framework的代码时发现不是这么实现的。

  • 微服务架构风格
    微服务四原则:RESTFull,无状态服务,前后端分离,AKF。K8s中的微服务拆分风格不是DDD或者分层的方式进行的,它是以事件驱动为核心拆分的微服务。所以,K8s中的微服务的划分规则与平常业务中的微服务划分规则有明显的区别。例如:api server即使BFF也是数据存储控制,还负责事件的转发。而其他的组件基本上都是以事件机制作为业务出发条件进行业务的处理工作。

  • CQRS架构风格
    Informer和Queue机制代表着读和写的过程。虽然是小范围的命令查询职责分离模式。

  • 解释器设计模式
    使用编译原理,将操作解析为原子操作,并进行执行动作。原子操作执行队列进行命令执行。

2.2 架构原则与ARD

上一节中说到K8s的架构与很多先行的微服务架构不一样的特点,也说明了这些特点的原因以及考虑点。这里就说明K8s中一些实现过程中的原则。但是K8s现在由CNCF社区进行维护,能不能遵循一些既定的原则是不被保证的。所以,这里只能说是K8s在实现之初遵循的一些架构原则。

2.2.1 架构原则

以DDD中的战略设计的统一语言来定义原则。例如:Event和ListAndWatch的区别。顶层Event对象是一种资源,Event对象时一种用户可见的日志机制。Watch事件在API服务器与控制器之间通过HTTP流的方式发送用于驱动Informer。

2.2.2 架构决策(ARD)

架构决策定义一组关于如何构建系统的规则。这里只记录Kubernetes架构中的少数几个决策:事件处理事务模型数据操作

  • 事件处理

事件处理机制决策:边沿触发、水平驱动+重新同步

备选方案:

  1. 在仅仅依赖边沿驱动的场景下,有可能会丢失一个后续事件。
  2. 在边沿触发的场景下,处理事件时总是重新获取最新的状态(即水平)。也可以说业务逻辑是边沿触发、水平驱动的。
  3. 边沿触发加上水平驱动的逻辑,同时服务已额外的重新同步逻辑。

决策:
边沿触发、水平驱动+重新同步

  • 事务模型

事务模型机制决策:乐观并发

备选方案:

  1. 无锁
  2. 乐观
  3. 悲观

决策:

  1. 为了实现无锁的并发操作,Kubernetes API服务器使用乐观并发模型。
  2. 在内嵌的ObjectMeta结构中包含了一个资源版本

关联决策:

  1. 水平驱动的逻辑,可以使用水平驱动逻辑进行进行乐观重试
  • 数据操作

数据操作机制决策:只有API Server操作

备选方案:

  1. API Server,Controller可以直接操作数据
  2. Controller可以操作数据
  3. API Server可以操作数据

2.3 设计结果

设计结果以4+1视图的方式进行说明。Kubernetes在每个视图中都有它独有的特点。

3. 总结

K8s是由开源社区维护的,那随着不断的演进肯定会朝着好的方向前进。但在发展过程中,代码的水平设计的水平都会出现参差不齐的情况。在K8s中有好的有不好的,我们只需要取其精华,去其糟粕即可。

3.1 优缺点

  • K8s的对象描述不能满足架构即代码的要求
    没有描述组件之间的关系,没有描述组件边界。
  • 调用链的管理是不完善的
    因为使用的并非分层微服务的模式对服务进行管理,所以在服务的管理如调用链的管理工作就不是很完善。
  • 故障的隔离方式值得借鉴
    K8s的核心过程是List-Watch的,所以,服务之间的关系都是间接的,没有任何一个服务是直接关系。这样就不会形成惊群或雪崩问题。
  • Yaml Schema和XML Schema
    为了规范yaml配置中的输入值,引入的Yaml Schema机制。其实也带来的一定的复杂度,不过有代码生成器可以生成Yaml Schema的内容。

5. 参考

Kubernetes 编程基础知识
一文梳理REST API的设计原则
在 Kubernetes 上开发
最新、最全、最详细的 K8S 学习笔记总结(2021最新版)!建议收藏
一文看懂 Kubelet
调度框架

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容