新手也能看懂:如何理解 K8s 声明式 API ?

news2024/12/26 23:47:35

我们知道 Kubernetes(以下简称“K8s”)中各种资源对象的数据是通过 K8s 的 API 进行提交并持久化到存储 etcd 中的(称为K8s对象),K8s 对象是使用 K8s 的接口,kubelet 客户端通过操作这些对象来使用K8s能力。

其中 kubectl 是我们使用最多的命令行工具。K8s官方对 kubectl 管理 K8s 对象的技术做了如下表的总结:

图片

假如我们现在要在名为 test 的 namespace 下创建一个 Deployment 对象来运行 nginx 容器,接着对 nginx 的副本数量进行更改为5,三种方式流程如下:

  • 指令式命令方式

创建 deployment 对象:

 
kubectl create deployment nginx-deployment --image nginx -n test

更改副本数:

 
kubectl scale deployment nginx-deployment --replicas 5 -n test
  • 指令式对象配置方式

首先创建配置文件定义,定义如图1-1所示:

图片

图1-1 ngin.yaml配置

创建 deployment 对象:

 
kubectl create -f nginx.yaml

将配置文件中的replicas由2改成5,执行命令更改副本数:

 
kubectl replace -f nginx.yaml
  • 声明式对象配置方式

使用图1-1的配置,创建deployment对象:

 
kubectl apply -f nginx.yaml

将配置文件中的replicas由2改成5,执行命令更改副本数:

 
kubectl apply -f nginx.yaml

后两者对象配置的方式提供了用于创建新对象的模板,并且能够提供与更改关联的审核跟踪,命令除了实时内容外,不能提供记录源。所以在生产项目的情况下,我们使用 K8s 对象的方式往往是通过编写对应的.yaml文件交给 K8s(声明式API的形式),而不是直接使用指令式命令。

我们配置文件只是声明了想要创建的K8s对象的信息以及想要它们达到的期望状态,这是一种声明式API的交互方式。不同于吃饭、睡觉等明确的指令(这种方式也称为:命令式API),使用配置创建的对象的交互感觉类似顾客与实施方的交流模式,因为顾客跟实施方相比,往往不清楚为了达到目标而需要进行的操作,比如说:给我搭建一个标准的篮球场。

声明式API往往预备了合并多个操作的能力,我们在搭建球场时可以同时进行地板的铺设和大屏幕的安装,命令式API在并发访问情况下会十分复杂、低效,往往通过加锁才能保证最后结果的可预见性,孩子必须吃完了饭才能睡觉,而不是睡觉的时候吃饭。并且声明式API天然地记录了现在和最终状态,便于对结果进行检查。每天必须吃3碗饭和保持体重在50kg,不同体重的人吃三碗饭导致的体重结果是无法估计的,不同的人但却可以通过调整热量的摄入而达到50kg的目标。这也是为什么K8s中声明式API如此重要的原因,而K8s声明式API描述的主体便是K8s对象,正如开头所说它是我们操作K8s的媒介和接口。

那么K8s对象在K8s API中是如何表示的,我们怎么用.yaml文件描述它们,当把一个.yaml文件提交给 K8s后,它究竟又是如何创建出一个K8s对象的呢?

1、K8s对象

K8s对象指的是K8s系统中持久化后的实体,K8s用这些实体去表示整个集群的运行状态。它们特别描述了以下信息:

  • 哪些容器化应用在运行,以及运行在哪些节点上

  • 可以被应用使用的资源

  • 应用运行时的表现策略,如重启策略、升级策略以及容错策略。

K8s对象的操作(创建、修改、删除)都需要使用K8s API,无论是使用kubectl命令行还是程序中使用客户端,最终都会调用K8s API。

每个K8s对象都包含两个嵌套的对象字段 spec(规约)和 status(状态)。其中spec 描述的是 K8s 在创建完毕后应该达到的期望状态,如期望开启多少个副本,status 描述了对象的当前状态,它由 K8s 系统和组件进行监管设置并积极地使它与spec 相匹配。这两个字段也是对于 K8s 声明式 API 实现最为关键的一环。

2、K8s是如何描述和管理API对象的

我们在创建 K8s 对象时,必须提供对象的spec字段,告知K8s我们期望这个对象所达到状态,同时也必须提供一些关于对象的基本信息(例如名称)。不论我们是通过kubectl 命令行或者是客户端调用K8s API创建对象,API 请求必须在请求体中包含JSON 格式的信息。

大多数情况下,我们都以 .yaml 文件的形式提供这些信息。kubectl 在发起API请求时,再将这些信息转换成 JSON 格式。以图1-1举例,图中展示了使用.yaml来描述K8s对象的必需字段和对象规约,以下是其中必需字段的简要说明:

  • apiVersion - 创建该对象所使用的K8s API版本

  • kind - 想要创建的对象类别

  • metadata – 帮助唯一性表示对象的一些数据,包括一个name字符串、UID和可选的namespace

  • spec – 你期望该对象所达到的状态

其中 spec 的精确格式对于不同类别的 K8s 对象来说往往是不同的,它是对管理对象详细描述的主体,会被 K8s 持久化到 etcd 中保存。如果 spec 被删除,那么该对象也会从系统中被删除。

一个API对象在etcd里的完整资源路径是由Group(API组)、Version(API版本)、Resource(API资源类型)三个部分组成。具体案例如图1-2所示:

图片

图1-2 K8s的API结构

从图中我们可以看出,在 K8s 内 API 对象的组织方式是层层递进的,这里我们不去深究具体怎么使用这些 api 去检索需要的资源,感兴趣的读者可以参考如下链接地址,这是官方的详细说明:

https://kubernetes.io/zh/docs/reference/using-api/api-concepts/

假定现在我们要创建一个 CronJob 对象,且它的 yaml 文件开头部分如下所示:

 
apiVersion: batch/v2alpha1kind: CronJob...

其中,batch 就表示它的 API 组(Group),v2alpha1 就是它的API版本(Version),CronJob即是它所属 API 资源类型(Resource)conjobs下的一个具体类别。而其整体创建流程下图1-3所示:

图片

图1-3 持久化流程

➤ 提交阶段

当我们的 yaml 提交给 K8s 集群后(不论是通过程序客户端还是kubectl),请求会被转化成一个POST,接着交由K8s的API Server进行处理。

➤ 过滤和前置处理阶段

API Server首先会对请求进行过滤,获取其中的有效信息,再完成诸如:授权、超时处理、审计等前置性工作。

➤ 路由查找阶段

主要是借由 MUX 和 Routes 路由查找 CronJob 的定义,具体流程大致为:

  1. 匹配Group。对于 CronJob 这类非核心 API 对象,K8s 会在如图1-2所示的/apis层级内查找它的所属组(核心对象,如 Pod、Node,隶属于 /api 层级且它们的组为""),根据yaml的开头信息,查找到/apis/batch

  2. 匹配版本号。接着,根据v2alpha1这个版本号进一步匹配到/apis/batch/ v2alpha1这个路径,在 K8s 中,同种 API 对象可以有多个版本,这是 K8s 给予用户管理共存多版本 API 的手段。

  3. 匹配资源类型。最后匹配资源类型cronjobs,这时 K8s 便可明确知道自己所需要创建的具体资源类型为CronJob。

➤ 创建资源阶段

在获取到 CornJob 的类型定义后,API Server 会进行一个 Convert 工作:把用户提交的 yaml 转换成一个 Super Version 的对象,它是该 API 资源类型所有版本的字段全集,之后用户提交其他版本的 yaml,也都可以用这个 Super Version 对象来处理。

接着,再进行 Admit 处理,主要是在对象创建完成后,注入一些公共处理逻辑,例如加入一些标签 Label。最后,对这个对象里各个字段的合法性进行校验。

➤ 定义存储阶段

若通过了 Validate,会被 API Server 保存在名为 Registry 的结构中。它包含了对一个有效 K8s API 对象的定义。

➤ 持久化阶段

API Server会把通过验证的API对象由Super Version版本重新转换为最初提交的版本,再进行序列化操作,最后调用etcd的API将它们变为K8s内的实体对象。

此时,对象已经被创建持久化完成,那么它又是如何一步步达到我们所期望的状态的呢?K8s对象章节所提及到的spec和status信息正是这个解决问题的基础,K8s基于此采用了控制器模式来进行实现。

3、控制器模式实现声明式API的sepc

K8s是通过控制器模式来实现声明式API中描述的spec状态靠拢的,而控制型模式最核心的就是“控制循环“的概念。在K8s中,控制器是一个控制循环,它通过API服务器监视集群的共享状态,并进行更改,试图将当前状态(status)转移到期望状态(spec)。

实际状态的获取往往是通过K8s本身的一些组件,例如定时调用API获取资源状态信息,或kubelet通过心跳汇报的容器状态和节点状态。所需期望状态,往往由yaml文件的spec字段进行定义提交持久化到K8s的etcd中。图1-4大致表述了K8s中控制循环的过程:

图片

图1-4控制循环

  1. 比较spec和status,若相同,不进行操作,继续进行1,否则输出不同点,进入2;

  2. 控制器(Controller)根据不同点,对系统发出调控操作,系统执行操作,进入3;

  3. 系统上报当前系统状态给传感器(Sensor)或者传感器主动拉取状态,输出当前状态status,返回1。

目的是使 status 不断趋近达到 spec,从而完成 yaml 声明状态的实现。从图中也可以看出 Sensor 和 Controller 在整个循环中扮演了极其重要的角色。

在 K8s 中,Sensor 主要由ReflectorInformerIndexer三个组件构成。

Sensor 的整体工作流程如图1-5所示:

图片

图1-5 Sensor组件

  1. Reflector通过List和Watch操作从API Server 获取各个资源对象的状态。其中,List用来描述返回多个资源的集合,主要用于系统资源的全量更新;Watch用于客户端获取当前状态,然后订阅后续更改,主要用于系统资源的增量更新;

  2. Reflector在获取新的资源数据后,会往Delta队列中推入一个Delta记录,这个记录包含了资源对象本身的信息以及资源对象事件的类型。Delta队列可以保证同一个对象在队列中仅有一条记录,从而避免Reflector重新List和Watch的时候产生重复的记录。

  3. Informer组件不断地从Delta队列中弹出delta记录,然后把资源对象交给indexer。indexer把资源记录在一个默认使用命名空间做索引的缓存中,记录操作是线程安全的并且缓存是可以在Controller Manager或多个Controller间共享的。之后,informer再把这个事件交给事件回调函数。

Controller的主要流程如图1-6所示:

图片

图1-6 controller组件

控制循环中的Controller(控制器)组件主要由事件处理函数以及worker组成,事件处理函数根据控制器逻辑决定是否要进行相应的回调处理。若需要进行事件处理,它会把事件关联资源的命名空间和资源名字当成一个标识塞入工作队列中,由后续worker池中的一个worker来处理,工作队列会对存储的对象进行去重,从而避免多个woker处理同一个资源的情况。

worker 在处理资源对象时,一般需要用资源的名字来重新获得最新的资源数据,之后使用这些数据会有三种情况:

  1. 创建或者更新资源对象

  2. 调用其他的外部服务

  3. worker处理失败,把资源的名字重新加入到工作队列中进行重试

现在假如我们需要将图1-1所配置的nginx副本由2扩容为3个进行举例说明,方便读者理解,整体流程如图1-7所示:

图片

图1-7副本扩展整体流程图

首先,Reflector会watch到Deployment发生变化,在delta队列中塞入了对象是nginx-deployment并且类型是更新的记录。

Informer一方面把新的Deployment更新到缓存中,并用名为test的namespace作为索引。另外一方面,调用Update的回调函数,Deployment控制器发现Deployment发生变化后会把字符串test/nginx-deployment塞入到工作队列中,工作队列后的一个 worker从工作队列中取到了test/nginx-deployment这个字符串的key,并且从缓存中取到了最新的Deployment数据。

worker通过比较Deployment中spec和status里的数值,发现需要对这个Deployment进行扩容,因此Deployment的worker创建了一个Pod,这个pod中的Ownereference指向了nginx-deployment。

然后Reflector Watch到的Pod新增事件,在delta队列中额外加入了Add类型的deta记录。

Informer一方面把新的Pod记录通过Indexer存储到了缓存中,另一方面调用了 Deployment控制器的Add回调函数,Add回调函数通过检查pod3的ownerReferences 找到了对应的Deployment为nginx-deployment,把test/nginx-deployment字符串塞入到了工作队列中。

Deployment的woker在得到新的工作项之后,从缓存中取到新的Deployment记录,并得到了其所有的Pod信息,对比发现Deployment的状态不是最新的(关联的pod数量已经发生改变)。此时 Deployment更新 status使得spec和 status达成一致。

总结

  • 由于声明式API具有天然的记录初始和最终状态等特性,K8s采用了其作为最关键部分的API交互方式。

  • 在生产环境中,对于K8s的管理往往是通过管理器API对象,而API对象又是通过yaml进行描述的,其中的spec和status是最为关键的信息,K8s会通过定位和路由把一个yaml描述的信息持久化到etcd中成为实体。

  • K8s所采用的控制器模式,是由声明式API驱动的。它是实现K8s声明式API的关键,资源对应的控制器结合感应器通过控制循环,异步地将控制系统向设置的终态趋近。

  • 因为控制器是自主运行的,使得整体系统的自动化和无人值守成为可能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/851838.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

uniapp使用空格占位符无效

uniapp文档&#xff1a; 错误写法&#xff1a; <text>筛 选</text> 正确写法&#xff1a; <text decode>{{ 筛 选 }}</text> //要加decode属性&#xff0c;且内容必须包裹在{{}}

无人驾驶实战-第十课(决策规划)

在七月算法上报了《无人驾驶实战》课程&#xff0c;老师讲的真好。好记性不如烂笔头&#xff0c;记录一下学习内容。 课程入口&#xff0c;感兴趣的也可以跟着学一下。 ————————————————————————————————————————— Planning是目前无…

openGauss学习笔记-32 openGauss 高级数据管理-批处理模式

文章目录 openGauss学习笔记-32 openGauss 高级数据管理-批处理模式32.1 语法格式32.2 参数说明32.3 示例 openGauss学习笔记-32 openGauss 高级数据管理-批处理模式 openGauss支持从文本文件执行SQL语句。openGauss提供了gsql工具实现SQL语句的批量处理。 以下场景建议使用批…

(JS逆向专栏十二)某乐平台网站登入RSA

声明: 本文章中所有内容仅供学习交流&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff0c;若有侵权&#xff0c;请联系我立即删除&#xff01; 名称:当乐 目标:登入参数 加密类型:RSA 目标网址:https://oauth.d.cn/auth/goLogin…

【前端 | CSS】5种经典布局

页面布局是样式开发的第一步&#xff0c;也是 CSS 最重要的功能之一。 常用的页面布局&#xff0c;其实就那么几个。下面我会介绍5个经典布局&#xff0c;只要掌握了它们&#xff0c;就能应对绝大多数常规页面。 这几个布局都是自适应的&#xff0c;自动适配桌面设备和移动设备…

Linux:管道命令与文本处理三剑客(grep、sed、awk)

1 管道命令&#xff08;pipe&#xff09;介绍 众所周知&#xff0c;bash命令执行的时候会输出信息&#xff0c;但有时这些信息必须要经过几次处理之后才能得到我们想要的格式&#xff0c;此时应该如何处置&#xff1f;这就牵涉到 管道命令(pipe) 了。管道命令使用的是|这个界定…

GaussDB数据库SQL系列-表连接(JOIN)

目录 一、前言 二、GaussDB JOIN 1、LEFT JOIN 2、LEFT JOIN EXCLUDING INNER JOIN 3、RIGHT JOIN 4、LEFT JOIN EXCLUDING INNER JOIN 5、INNER JOIN 6、FULL OUTER JOIN 7、FULL OUTER JOIN EXCLUDING INNER JOIN 三、GaussDB 实验示例 1、初始化实验表 2、LEFT …

苹果正在测试新款Mac mini:搭载M3芯片 配备24GB大内存

据悉苹果目前正在测试新的Mac机型&#xff0c;亮点是采用最新的M3芯片。 据报道&#xff0c;首款搭载M3芯片的设备应该是13英寸的MacBook Pro和重新设计的MacBook Air&#xff0c;Mac mini机型并不在名单上。 M3和M2同样拥有最多8个核心&#xff0c;分别为4个性能核和4个能效核…

FPGA运算单元可以支援高运算力浮点

随着机器学习(Machine Learning)领域越来越多地使用现场可编程闸阵列(FPGA)来加速推论(inference)&#xff0c;传统FPGA只支援定点运算的瓶颈日益突显。为了解决这一困境&#xff0c;Achronix设计机器学习处理(Machine Learning Processing&#xff1b;MLP)单元&#xff0c;不仅…

GreatSQL从单机到MGR扩展纪实

一、前言 原有的业务系统跑在MySQL主从架构中&#xff0c;高可用通过脚本完成&#xff0c;但存在切换数据丢失和切换不及时风险&#xff0c;调研了高可用更稳定的MGR后&#xff0c;准备入手一试。本篇文章主要记录GreatSQL从单机扩展到MGR的详细过程&#xff0c;遇到的问题及解…

【PCIE】AER和DPC解释

AER&#xff08;Advanced Error Reporting&#xff09;和 DPC&#xff08;Downstream Port Containment&#xff09;是PCIe&#xff08;Peripheral Component Interconnect Express&#xff09;总线规范中定义的两种不同的错误处理机制&#xff0c;它们在PCIe架构中有一定的关联…

c++进阶--二叉搜索树模拟实现

目录 前言 一、二叉搜索树 1.二叉搜索树概念 2.二叉搜索树操作 二、二叉搜索树实现 0.定义一个节点 1.定义一棵树 2.增删改查 2.1.查找 2.2.插入 2.3.删除 2.3.1非递归删除法 a.只有左孩子 -- 删除14 b.只有右孩子-- 删除10 c.有左右孩子--删除8 2.3.2递归删除…

停车场收费系统ssm车辆车库管理jsp源代码mysql

本项目为前几天收费帮学妹做的一个项目&#xff0c;Java EE JSP项目&#xff0c;在工作环境中基本使用不到&#xff0c;但是很多学校把这个当作编程入门的项目来做&#xff0c;故分享出本项目供初学者参考。 一、项目描述 停车场收费系统 一个基于ssm框架的小系统 后端&…

计算机三级网络技术(持续更新)

BGP考点 A S&#xff1a;自治系统 BGP: Border Gateway Protocol&#xff08;当前使用的版本是 BGP-4&#xff09;外部网关协议 动态路由协议可以按照工作范围分为IGP以及EGP。IGP工作在同一个AS内&#xff0c;主要用来发现和计算路由&#xff0c;为AS内提供路由信息的交换&…

基于大数据为底层好用准确性高的竞彩足球比分预测进球数分析软件介绍推荐

大数据与贝叶斯理论在足球比赛分析与预测中的应用 随着科技的不断进步&#xff0c;大数据分析在各个领域的应用也越来越广泛&#xff0c;其中包括体育竞技。足球比赛作为全球最受欢迎的运动之一&#xff0c;也借助大数据和贝叶斯理论来进行模型分析和预测。本文将通过结合贝叶…

Java笔记(三十):MySQL(上)-- 数据库、MySQL常用数据类型、DDL、DML、多表设计

一、数据库 0、MySQL安装&#xff0c;IDEA配置MySQL 用MySQL installer for windows&#xff08;msi&#xff09;MySQL默认安装位置&#xff1a;C:\Program Files\MySQL\MySQL Server 8.0配置环境变量使用前先确保启动了mysql服务my.ini位置&#xff1a;C:\ProgramData\MySQL…

交替方向乘子

目录 一&#xff0c;交替方向乘子ADMM 1&#xff0c;带线性约束的分离优化模型 2&#xff0c;常见优化模型转带线性约束的分离优化模型 3&#xff0c;带线性约束的分离优化模型求解 4&#xff0c;交替方向乘子ADMM 本文部分内容来自教材 一&#xff0c;交替方向乘子ADMM …

初中信息技术考试编程题,初中信息技术python教案

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;初中信息技术python编程题库 网盘&#xff0c;初中信息技术python编程教学&#xff0c;今天让我们一起来看看吧&#xff01; ID:12450455 资源大小&#xff1a;934KB 资料简介: 2019-2020学年初中信息技术【轻松备课】P…

5基础篇:自定义日志

前言 在所有的后端服务中,日志是必不可少的一个关键环节,毕竟日常中我们不可能随时盯着控制台,问题的出现也会有随机性、不可预见性。一旦出现问题,要追踪错误以及解决,需要知道错误发生的原因、时间等细节信息。 之前的需求分析部分,在网关基础代理的服务中,网关作为…

生信豆芽菜-edgeR差异分析使用说明

网站&#xff1a;http://www.sxdyc.com/diffEdgerAnalyse 一、edgeR差异分析简介 edgeR使用经验贝叶斯估计和基于负二项模型的精确检验来确定差异基因&#xff0c;通过在基因之间来调节跨基因的过度离散程度&#xff0c;使用类似于Fisher精确检验但适应过度分散数据的精确检验用…