声明式API vs 命令时API

计算机系统是分层的,也就是下层做一些支持的工作,暴露接口给上层用。注意:语言的本质是一种接口。

计算机的最下层是CPU指令,其本质就是用“变量定义+顺序执行+分支判断+循环”所表达的逻辑过程。计算机应用的最上层是实现人类社会的某种功能。所以所有计算机编码的过程,就是用逻辑表达现实的过程。层与层之间定义的借口,越接近现实的表达就叫越“声明式”(declarative),越接近计算机的执行过程就叫越“命令式”(imperative)。注意这不是绝对的概念,而是相对的概念。

当接口越是在表达“要什么”,就是越声明式;越是在表达“要怎样”,就是越命令式。SQL就是在表达要什么(数据),而不是表达怎么弄出我要的数据,所以它就很“声明式”。C++就比C更声明式,因为面向对象本身就是一种声明式的体现。HTML也很声明式,它只描述我要一张什么样的表,并不表达怎么弄出一张表。

越是声明式,意味着下层要做更多的东西,或者说能力越强。也意味着效率的损失。越是命令式,意味着上层对下层有更多的操作空间,可以按照自己特定的需求要求下层按照某种方式来处理。

Kubernetes声明式API

想要使用Kubernetes 的 API 对象,需要编写一个对应的 YAML 文件交给 Kubernetes,而声明式API,则为kubectl apply 命令。而先 kubectl create,再 replace 的操作,称为命令式配置文件操作,并不是声明式API。

kube-apiserver 在响应命令式请求(如kubectl replace)的时候, 一次只能处理一个写请求,否则会有产生冲突的可能;而对于声明式请求(如kubectl apply),一次能处理多个写操作,并且具备 Merge 能力。

声明式 API是 Kubernetes 项目编排能力“赖以生存”的核心所在:

  • 首先,“声明式”就是提交一个定义好的API对象来声明所期望的状态是什么

  • 其次,声明式API允许有多个API写端,以PATCH的方式对API对象进行修改,而无需关心本地原始YAML文件的内容

    RESTful 使用POST来创建一个资源,使用PUT或者PATCH来更新一个资源
    
    区别是:
    – PUT用来整体更新一个资源,所以请求中必须包含完整的资源信息。如果缺少部分信息,会导致这部分数据被更新为NULL。
    – PATCH则是部分更新。仅更新提供的字段,请求中缺少的字段仍保持不变
  • 最后,也是最重要的,有了上述两个能力,Kubernetees项目才可以基于对API对象的增、删、改、查在完全无需外界干预的情况下,完成对“实际状态”和“期望状态”的调谐(Reconcile)过程。

工作原理

首先知道一下一个 API 对象在 Etcd 里的完整资源路径,是由:Group(API 组)、 Version(API 版本)和 Resource(API 资源类型)三个部分组成的,可以用如下图的树形结构表示出来:

API对象的组织方式是层层递进的,Kubernetes会对Group、Version和Resource进行解析,也就是层层匹配,得到相应的对象定义,如Cronjob(Pod、Node 等核心API对象不需要Group,直接匹配Version)。

把YAML 文件提交给 Kubernetes 之后,创建出 API 对象的流程:以创建 CronJob为例

  1. 发起创建CronJob的POST请求后,编写的YAML的信息就被提交给api-server

  2. Api-server过滤这个请求,完成一些前置性的工作,比如授权、超时处理、审计等

  3. 请求进入mux和routes流程,mux和routees是api-server完成url和handler绑定的场所,api-server的Handler要做的事情就是按照层层匹配的过程,找到对应的CronJob类型定义

  4. Api-server根据crontJob类型定义,使用用户提交的YAML文件里的字段,创建一个CrontJob对象

    Api-server会进行一个convert工作,即把用户提交的YAML文件转换成一个叫做Super Version的对象,它正是该API资源类型所有版本的字段全集,这样用户提交的不同版本的YAML就都可以用这个Super Version对象来进行处理了

  5. 先后进行admission()和validation()操作

    Admission Controller和Initializer都属于Admission的内容,Validation负责验证这个对象里的各个字段是否合法,这个被验证过的API对象,都保存在来api-server里一个叫做Registry的数据结构中,也就是说只要一个API对象的定义能在Registry里查到,他就是一个有效的Kubernetes API对象

  6. 把验证过的API对象转换成用户最初提交的版本,进行序列化操作,并调用Etcd的API把它保存起来

自定义API对象

如果想要添加自定义API资源类型,建议使用CRD( Custom Resource Definition),它允许用户在 Kubernetes 中添加一个跟 Pod、Node 类似的、新的 API 资源类型,即:自定义 API 资源。

使用CRD创建出自定义API对象后,就是为这个 API 对象编写一个自定义控制器(Custom Controller),这样, Kubernetes 才能根据 自定义 API 对象的“增、删、改”操作,在真实环境中做出相应的响应。

编写自定义控制器分为三个过程:编写 main 函数、编写自定义控制器的定义,以编写控制器里的业务逻辑。

自定义控制器工作流程

  1. 首先从 Kubernetes 的 APIServer 里获取它所关心的对象,也就是自定义的控制器对象。这个操作,依靠的是一个叫作 Informer(通知器)的代码库完成的;Informer 与 API 对象是一一对应的,所以需要传递给自定义控制器一个Informer;

    Informer是一个带有本地缓存和索引机制的、可以注册EventHandler 的 client。它是自定义控制器跟 APIServer 进行数据同步的重要组件。

    创建Informer的时候需要传一个Client,Informer 正是使用Client,跟 APIServer 建立了连接;真正负责维护这个连接的是 Informer 所使用的 Reflector 包。

    Reflector 使用的是一种叫作ListAndWatch的方法,来“获取”并“监听”这些API对象实例的变化(Informer通过 ListAndWatch,把 APIServer 中的 API 对象缓存在了本地,并负责更新和维护这个缓存。)在 ListAndWatch 机制下,一旦 APIServer 端有新的API对象实例被创建、删除或者更新, Reflector 都会收到“事件通知”;这时,该事件及它对应的 API 对象这个组合,就被称为增量 (Delta),它会被放进一个 Delta FIFO Queue(即:增量先进先出队列)中;Informe 会不断地从 Delta FIFO Queue 里读取(Pop)增量。每拿到一个增量,Informer 就会判断这个增量里的事件类型,然后创建或者更新本地对象的缓存;这个缓存,在 Kubernetes 里一般被叫作 Store

    Informer 的第二个职责,则是根据这些事件的类型,触发事先注册好的 ResourceEventHandler;

    这些 Handler,需要在创建控制器的时候注册给它对应的 Informer。

  2. Informer 与要编写的控制循环之间,则使用了一个工作队列来进行协同,防止控制循环执行过慢把Informer拖死。

  3. 接下来就是熟悉的控制循环的逻辑了

参考链接:

https://www.zhihu.com/question/22285830/answer/469177185

https://www.pianshen.com/article/40791568713/

最新文章

  1. JS eval()函数的一些见解
  2. PHP数组操作汇总 php数组的使用技巧
  3. u11-nav02
  4. Jquery EasyUI的添加,修改,删除,查询等基本操作介绍
  5. sbit命令行中运行scala脚本
  6. zoj 3841 Cards
  7. $_SERVER变量 以及 PHP 使用 $_SERVER['PHP_SELF'] 获取当前页面地址及其安全性问题
  8. xssless - 自动化的XSS payload攻击器
  9. attr(),addClass()使用方法练习
  10. 来自projecteuler.net网站的练习题2
  11. iOS 如何优化 App 的启动时间
  12. Linux Centos7配置防火墙开启端口
  13. VS WebDev.WebServer40
  14. Python直接控制鼠标键盘
  15. web driver下载地址(selenium-3.141_浏览器版本对应)
  16. DataGridView控件用法一:数据绑定
  17. python常用模块-01
  18. 【iOS地图开发】巧妙打造中英文全球地图
  19. C#方法参数--值参数,引用参数,输出参数
  20. 【vue】this与that 一个坑

热门文章

  1. 动态规划算法 All In One
  2. MacBook Pro 2019 13 inch & screen blink
  3. Inspect Network Activity In Chrome DevTools
  4. windows driver 简单的驱动和通信
  5. 为什么说USDN是一种应用型稳定币?
  6. Zookeeper从入门到删库跑路
  7. linux文件权限的查看和修改(转)
  8. The last packet successfully received from the server was 49,061,696 millise
  9. Vue学习笔记-Vue.js-2.X 学习(三)===>组件化高级
  10. 微信小程序:删除时提示是否删除