一. 简介

Kubernetes 的能力都是通过各种 API 对象来提供,API 对象正是我们使用 Kubernetes 的接口,我们正是通过操作这些提供的 API 对象来使用 Kubernetes 能力的。最常见的就是 kubectl apply 命令。

二. 声明式

对于我们使用 Kubernetes API 对象的方式,一般会编写对应 API 对象的 YAML 文件交给 Kubernetes(而不是使用一些命令来直接操作 API)。所谓“声明式”,指的就是只需要提交一个定义好的 API 对象来“声明”(这个 YAML 文件其实就是一种“声明”),表示所期望的最终状态是什么样子就可以了。而如果提交的是一个个命令,去指导怎么一步一步达到期望状态,这就是“命令式”了。

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

三. “声明式”与“命令式”区别

  1. 在“声明式API“中,通常具有如下特点:
  • API包含相对少量的相对较小的对象(资源)
  • 这些对象定义应用程序或基础结构的配置
  • 对象相对不频繁地更新
  • 通常需要读取和写入对象
  • 对象的主要操作是 CRUD-y (creating, reading, updating and deleting)
  • 不需要跨对象进行事务处理:API 代表期望的状态,而不是当前的状态
  1. “命令式API”中,通常具有如下特点:
  • 客户端说“执行此操作”,然后在完成后返回一个同步响应
  • 客户端说“执行此操作”,然后取回操作ID,并且必须检查单独的 Operation 对象以确定请求是否完成
  • 使用远程过程调用(RPCs)
  • 直接存储大量数据,例如,每个对象大于几kB,或者大于1000个对象。
  • 需要高带宽访问(持续每秒10s的请求)
  • 存储最终用户数据(例如图像,PII 等)或应用程序处理的其他大规模数据
  • 对象上的操作不是 CRUD-y 操作
  • 该 API 很难建模为对象
  • 选择了用“操作ID”或“操作对象”表示待处理的操作

四. API 对象

4.1 组成结构

一个 API 对象在 Etcd 里的完整资源路径,是由:Group(API组)、Version(API版本)和 Resource(API资源类型)三个部分组成的。

具体案例如下图:
Api architecture
可以看出,Kubernetes 里 API 对象的组织方式,其实是层层递进的。

4.2 YAML结构

借助之前的yaml文件,参考如下的一个结构:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: demo-statefulset
spec:
  serviceName: "demo-service"
  replicas: 3
  selector:
    matchLabels:
      app: demo-nginx
  template:
  ........

在这个 YAML 文件中,StatefulSet就是这个 API 对象的资源类型(Resource),apps 就是它的组(Group),v1 就是它的版本(Version)。

4.3 API 检索流程

对 Resource、Group 和 Version 进行检索,最终定位到API对象的流程如下:

  1. 匹配 Group
    在陪陪Group时,一般分俩类。
  • 核心 API 对象
    对于 Kubernetes 里的核心 API 对象,比如:Pod、Node 等,是不需要 Group 的,因为它们的 Group 是“”。对于这些 API 对象来说,Kubernetes 会直接在 /api 这个层级进行下一步的匹配过程。
  • 非核心 API 对象
    对于 StatefulSet 等非核心 API 对象来说,Kubernetes 就必须在 /apis 这个层级里查找它对应的 Group,进而根据“apps”这个 Group 的名字,找到 /apis/apps
    这些 API Group 的分类是以对象功能为依据的,比如 DeploymentStatefulSet 就都属于“apps” 这个 Group。

具体可查看如下这张图:
Group

  1. 匹配 Version
    对于 StatefulSet 这个 API 对象来说,Kubernetes 在 apps 这个 Group 下,匹配到的版本号就是 v1。在 Kubernetes 中,同一种 API 对象可以有多个版本,这正是 Kubernetes 进行 API 版本化管理的重要手段。这样,比如在 StatefulSet 的开发过程中,对于会影响到用户的变更就可以通过升级新版本来处理,从而保证了向后兼容。

  2. 匹配 Resource
    在前面匹配到正确的版本之后,Kubernetes 就知道,要创建的原来是一个 /apis/apps/v1 下的 StatefulSet 对象。

五. 概念拓展

5.1 CRD

CRD 的全称是 Custom Resource Definition。它指的就是,允许用户在 Kubernetes 中添加一个跟 Pod、Node 类似的、新的 API 资源类型,即:自定义 API 资源。

5.2 ListAndWatch

在 ListAndWatch 机制下,一旦 APIServer 端有新的实例被创建、删除或者更新,Reflector 都会收到“事件通知”。
ListAndWatch 方法的含义是:

  • 首先,通过 APIServer 的 LIST API“获取”所有最新版本的 API 对象。
  • 然后,再通过 WATCH API 来“监听”所有这些 API 对象的变化。

六. 总结

综上,Kubernetes“声明式 API”的独特之处:

  • 首先,所谓“声明式”,指的就是只需要提交一个定义好的 API 对象来“声明”所期望的状态。
  • 其次,“声明式 API”允许有多个 API 写端,以 PATCH 的方式对 API 对象进行修改,而无需关心本地原始 YAML 文件的内容。
  • 最后,基于上面俩种能力,Kubernetes 才可以基于对 API 对象的增、删、改、查,在完全无需外界干预的情况下,完成对“实际状态”和“期望状态”的调谐(Reconcile)过程。

所以“声明式 API“ 才是 Kubernetes 项目编排能力“赖以生存”的核心所在,PaaS平台与这完全没有可比性。

欢迎收藏个人博客: Wyatt's Blog ,非常感谢~

个人博客: Wyatt's Blog个人公众号:Wyatt的成长之路
微信号公众号

Reference

https://docs.openshift.com/container-platform/4.5/rest_api/workloads_apis/workloads-apis-index.html
https://time.geekbang.org/column/article/42493?utm_campaign=guanwang&utm_source=baidu-ad&utm_medium=ppzq-pc&utm_content=title&utm_term=baidu-ad-ppzq-title
https://blog.csdn.net/KevinBetterQ/article/details/104012293
https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/