本文转自 ArthurChiao's Blog,原文:https://arthurchiao.art/blog/k8s-is-about-apis-zh/,版权归原作者所有。欢迎投稿,投稿请添加微信好友:cloud-native-yang

本文串联了以下几篇文章的核心部分:

  1. Kubernetes isn’t about containers[1],2021

  2. Kubernetes is a Database[2], 2019

  3. CRD is just a table in Kubernetes[3], 2020

论述了 K8s 的核心价值是其通用、跨厂商和平台、可灵活扩展的声明式 API 框架, 而不是容器(虽然容器是它成功的基础);然后手动创建一个 API extension(CRD), 通过测试和类比来对这一论述有一个更直观的理解。

例子及测试基于 K8s v1.21.0,感谢原作者们的精彩文章。

K8s 的核心是其 API 框架而非容器

容器是基础

时间回到 2013 年。当一条简单的 docker run postgre 命令就能运行起 postgre 这样 复杂的传统服务时,开发者在震惊之余犹如受到天启;以 docker 为代表的实用容器技术的横空出世,也预示着一扇通往敏捷基础设施的大门即将打开。此后,一切都在往好的方向迅速发展:

  • 越来越多的开发者开始采用容器作为一种标准构建和运行方式

  • 业界也意识到,很容易将这种封装方式引入计算集群,通过 Kubernetes 或 Mesos 这样的编排器来调度计算任务 —— 自此,容器便成为这些调度器最重要的 workload 类型

但本文将要说明,容器并非 Kubernetes 最重要、最有价值的地方,Kubernetes 也并非 仅仅是一个更广泛意义上的 workload 调度器 —— 高效地调度不同类型的 workload 只是 Kubernetes 提供的一种重要价值,但并不是它成功的原因。

API 才是核心

“等等 —— K8s 只是一堆 API?

“不好意思,一直都是!”

K8s 的成功和价值在于,提供了一种标准的编程接口(API),可以用来编写和使用 软件定义的基础设施服务(本文所说的“基础设施”,范围要大于 IAAS):

  • Specification + Implementation 构成一个完整的 API 框架 —— 用于设计、实现和使用各种类型和规模的基础设施服务

  • 这些 API 都基于相同的核心结构和语义:typed resources watched and reconciled by controllers (资源按类型划分,控制器监听相应类型的资源,并将其实际 status 校准到 spec 里期望的状态)。

为了进一步解释这一点,考虑下 Kubernetes 出现之前的场景。

K8s 之前:各自造轮子,封装厂商 API 差异

K8s 之前,基础设施基本上是各种不同 API、格式和语义的“云”服务组成的大杂烩:

  1. 云厂商只提供了计算实例、块存储、虚拟网络和对象存储等基础构建模块,开发者需要像拼图一样将它们拼出一个相对完整的基础设施方案;

  2. 对于其他云厂商,重复过程 1,因为各家的 API、结构和语义并不相同,甚至差异很大。

虽然 Terraform 等工具的出现,提供了一种跨厂商的通用格式,但原始的结构和语义仍然 是五花八门的,—— 针对 AWS 编写的 Terraform descriptor 是无法用到 Azure 的。

K8s 面世:标准化、跨厂商的 API、结构和语义

现在再来看 Kubernetes 从一开始就提供的东西:描述各种资源需求的标准 API。例如,

  • 描述 pod、container 等计算需求 的 API;

  • 描述 service、ingress 等虚拟网络功能 的 API;

  • 描述 volumes 之类的持久存储 的 API;

  • 甚至还包括 service account 之类的服务身份 的 API 等等。

这些 API 是跨公有云/私有云和各家云厂商的,各云厂商会将 Kubernetes 结构和语义 对接到它们各自的原生 API。 因此我们可以说,Kubernetes 提供了一种管理软件定义基础设施(也就是云)的标准接口。 或者说,Kubernetes 是一个针对云服务(cloud services)的标准 API 框架。

K8s API 扩展:CRD

提供一套跨厂商的标准结构和语义来声明核心基础设施(pod/service/volume/serviceaccount/…), 是 Kubernetes 成功的基础。在此基础上,它又通过 CRD(Custom Resource Definition), 将这个结构扩展到任何/所有基础设施资源

  • CRD 在 1.7 引入,允许云厂商和开发者自己的服务复用 K8s 的 spec/impl 编程框架。

    有了 CRD,用户不仅能声明 Kubernetes API 预定义的计算、存储、网络服务,  还能声明数据库、task runner、消息总线、数字证书 … 任何云厂商能想到的东西!

  • Operator Framework[4] 以及 SIG API Machinery[5] 等项目的出现,提供了方便地创建和管理这些 CRD 的工具,最小化用户工作量,最大程度实现标准化。

例如,Crossplane 之类的项目,将厂商资源 RDS 数据库、SQS queue 资源映射到 Kubernetes API,就像核心 K8s controller 一样用自己的 controller 来管理网卡、磁盘等自定义资源。 Google、RedHat 等 Kubernetes 发行商也在它们的基础 Kubernetes 发行版中包含越来越多的自定义资源类型。

小结

我们说 Kubernetes 的核心是其 API 框架,但并不是说这套 API 框架就是完美的。 事实上,后一点并不是(非常)重要,因为 Kubernetes 模型已经成为一个事实标准: 开发者理解它、大量工具主动与它对接、主流厂商也都已经原生支持它。用户认可度、互操作性 经常比其他方面更能决定一个产品能否成功。

随着 Kubernetes 资源模型越来越广泛的传播,现在已经能够 用一组 Kubernetes 资源来描述一整个软件定义计算环境。 就像用 docker run 可以启动单个程序一样,用 kubectl apply -f 就能部署和运行一个分布式应用, 而无需关心是在私有云还是公有云以及具体哪家云厂商上,Kubernetes 的 API 框架已经屏蔽了这些细节。

因此,Kubernetes 并不是关于容器的,而是关于 API。

K8s 的 API 类型

可以通过 GET/LIST/PUT/POST/DELETE 等 API 操作,来创建、查询、修改或删除集群中的资源。 各 controller 监听到资源变化时,就会执行相应的 reconcile 逻辑,来使 status 与 spec 描述相符。

标准 API(针对内置资源类型)

Namespaced 类型

这种类型的资源是区分 namespace,也就是可以用 namespace 来隔离。 大部分内置资源都是这种类型,包括:

  • pods

  • services

  • networkpolicies

API 格式:

  • 格式:/api/{version}/namespaces/{namespace}/{resource}

  • 举例:/api/v1/namespaces/default/pods

Un-namespaced 类型

这种类型的资源是全局的,不能用 namespace 隔离,例如:

  • nodes

  • clusterroles (clusterxxx 一般都是,表示它是 cluster-scoped 的资源)

API 格式:

  • 格式:/api/{version}/{resource}

  • 举例:/api/v1/nodes

扩展 API(apiextension

Namespaced 类型

API 格式:

  • 格式:/apis/{apiGroup}/{apiVersion}/namespaces/{namespace}/{resource}

  • 举例:/apis/cilium.io/v2/namespaces/kube-system/ciliumnetworkpolicies

Un-namespaced 类型

略。

CRD

用户发现了 k8s 的强大之后,希望将越来越多的东西(数据)放到 k8s 里面, 像内置的 Pod、Service、NetworkPolicy 一样来管理,因此出现了两个东西:

  1. CRD:用来声明用户的自定义资源,例如它是 namespace-scope 还是 cluster-scope  的资源、有哪些字段等等,K8s 会自动根据这个定义生成相应的 API

    官方文档的例子[6], 后文也将给出一个更简单和具体的例子。

    CRD 是资源类型定义,具体的资源叫 CR。

  2. Operator 框架:“operator” 在这里的字面意思是“承担运维任务的程序”,  它们的基本逻辑都是一样的:时刻盯着资源状态,一有变化马上作出反应(也就是 reconcile 逻辑)。

这就是扩展 API 的(最主要)声明和使用方式。

至此,我们讨论的都是一些比较抽象的东西,接下来通过一些例子和类比来更直观地理解一下。

直观类比:K8s 是个数据库,CRD 是一张表,API 是 SQL

在本节中,我们将创建一个名为 fruit 的 CRD,它有 name/sweet/weight 三个字段, 完整 CRD 如下,

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:name: fruits.example.org        ## CRD 名字
spec:conversion:strategy: Nonegroup: example.org              ## REST API: /apis/<group>/<version>names:kind: FruitlistKind: FruitListplural: fruitssingular: fruitscope: Namespaced               ## Fruit 资源是区分 namespace 的versions:- name: v1                      ## REST API: /apis/<group>/<version>schema:openAPIV3Schema:properties:spec:properties:comment:            ## 字段 1,表示备注type: stringsweet:              ## 字段 2,表示甜否type: booleanweight:             ## 字段 3,表示重量type: integertype: objecttype: objectserved: true                  ## 启用这个版本的 API(v1)storage: trueadditionalPrinterColumns:     ## 可选项,配置了这些 printer columns 之后,- jsonPath: .spec.sweet       ## 命令行 k get <crd> <cr> 时,能够打印出下面这些字段,name: sweet                 ## 否则,k8s 默认只打印 CRD 的 NAME 和 AGEtype: boolean- jsonPath: .spec.weightname: weighttype: integer- jsonPath: .spec.commentname: commenttype: string

后面会解释每个 section 都是什么意思。在此之前,先来做几个(直观而粗糙的)类比。

K8s 是个数据库

像其他数据库技术一样,它有自己的持久存储引擎(etcd),以及构建在存储引擎之上的 一套 API 和语义。这些语义允许用户创建、读取、更新和删除(CURD)数据库中的数据。 下面是一些概念对应关系

关系型数据库 Kubernetes (as a database) 说明
DATABASE cluster 一套 K8s 集群就是一个 database 【注 1】
TABLE Kind 每种资源类型对应一个表;分为内置类型和扩展类型 【注 2】
COLUMN property 表里面的列,可以是 string、boolean 等类型
rows resources 表中的一个具体 record

【注 1】 如果只考虑 namespaced 资源的话,也可以说一个 namespace 对应一个 database。

【注 2】 前面已经介绍过,

  • 内置 Kind:Job、Service、Deployment、Event、NetworkPolicy、Secret、ConfigMap 等等;

  • 扩展 Kind:各种 CRD,例如 CiliumNetworkPolicy。

所以,和其他数据库一样,本质上 Kubernetes 所做的不过是以 schema 规定的格式来处理 records。

另外,Kubernetes 的表都有自带文档

$ kubectl explain fruits
KIND:     Fruit
VERSION:  example.org/v1DESCRIPTION:<empty>FIELDS:apiVersion   <string>APIVersion defines the versioned schema of this representation of anobject. Servers should convert recognized schemas to the latest internalvalue, and may reject unrecognized values. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resourceskind <string>Kind is a string value representing the REST resource this objectrepresents. Servers may infer this from the endpoint the client submitsrequests to. Cannot be updated. In CamelCase. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kindsmetadata     <Object>Standard object's metadata. More info:https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadataspec <Object>

另外,Kubernetes API 还有两大特色

  1. 极其可扩展:声明 CRD 就会自动创建 API;

  2. 支持事件驱动。

CRD 是一张表

CRD 和内置的 Pod、Service、NetworkPolicy 一样,不过是数据库的一张表。 例如,前面给出的 fruit CRD,有 name/sweet/weight 列,以及 “apple”, “banana” 等 entry,

用户发现了 k8s 的强大,希望将越来越多的东西(数据)放到 k8s 里面来管理。数据类 型显然多种多样的,不可能全部内置到 k8s 里。因此,一种方式就是允许用户创建自己的 “表”,设置自己的“列” —— 这正是 CRD 的由来。

定义表结构(CRD spec)

CRD(及 CR)描述格式可以是 YAML 或 JSON。CRD 的内容可以简单分为三部分:

  1. 常规 k8s metadata:每种 K8s 资源都需要声明的字段,包括 apiVersionkindmetadata.name 等。

    apiVersion: apiextensions.k8s.io/v1kind: CustomResourceDefinitionmetadata:name: fruits.example.org        ## CRD 名字
  2. Table-level 信息:例如表的名字,最好用小写,方便以后命令行操作;

    spec:conversion:strategy: Nonegroup: example.org              ## REST API: /apis/<group>/<version>names:kind: FruitlistKind: FruitListplural: fruitssingular: fruitscope: Namespaced               ## Fruit 资源是区分 namespace 的
  3. Column-level 信息:列名及类型等等,遵循 OpenAPISpecification v3 规范。

    versions:- name: v1                      ## REST API: /apis/<group>/<version>schema:openAPIV3Schema:properties:spec:properties:comment:            ## 字段 1,表示备注type: stringsweet:              ## 字段 2,表示甜否type: booleanweight:             ## 字段 3,表示重量type: integertype: objecttype: objectserved: true                  ## 启用这个版本的 API(v1)storage: trueadditionalPrinterColumns:     ## 可选项,配置了这些 printer columns 之后,- jsonPath: .spec.sweet       ## 命令行 k get <crd> <cr> 时,能够打印出下面这些字段,name: sweet                 ## 否则,k8s 默认只打印 CRD 的 NAME 和 AGEtype: boolean- jsonPath: .spec.weightname: weighttype: integer- jsonPath: .spec.commentname: commenttype: string

测试:CR 增删查改 vs. 数据库 SQL

  1. 创建 CRD:这一步相当于 CREATE TABLE fruits ...;

$ kubectl create -f fruits-crd.yamlcustomresourcedefinition.apiextensions.k8s.io/fruits.example.org created
  1. 创建 CR:相当于 INSERT INTO fruits values(...);

apple-cr.yaml

apiVersion: example.org/v1kind: Fruitmetadata:name: applespec:sweet: falseweight: 100comment: little bit rotten

banana-cr.yaml

apiVersion: example.org/v1kind: Fruitmetadata:name: bananaspec:sweet: trueweight: 80comment: just bought

创建:

$ kubectl create -f apple-cr.yamlfruit.example.org/apple created$ kubectl create -f banana-cr.yamlfruit.example.org/banana created
  1. 查询 CR:相当于 SELECT \* FROM fruits ... ;SELECT \* FROM fruits WHERE name='apple';

$ k get fruits.example.org ## or kubectl get fruitsNAME     SWEET   WEIGHT   COMMENTapple    false   100      little bit rottenbanana   true    80       just bought$ kubectl get fruits appleNAME    SWEET   WEIGHT   COMMENTapple   false   100      little bit rotten
  1. 删除 CR:相当于 DELETE FROM fruits WHERE name='apple';

$ kubectl delete fruit apple

可以看到,CRD/CR 的操作都能对应到常规的数据库操作。

API 是 SQL

上一节我们是通过 kubectl 命令行来执行 CR 的增删查改,它其实只是一个外壳,内部 调用的是 Kubernetes 为这个 CRD 自动生成的 API —— 所以 又回到了本文第一节论述的内容:K8s 的核心是其 API 框架

只要在执行 kubectl 命令时指定一个足够大的 loglevel,就能看到 背后的具体 API 请求。例如,

$ kubectl create -v 10 -f apple-cr.yaml...Request Body: {"apiVersion":"example.org/v1","kind":"Fruit",\"spec\":{\"comment\":\"little bit rotten\",\"sweet\":false,\"weight\":100}}\n"},"name":"apple","namespace":"default"},"spec":{"comment":"little bit rotten","sweet":false,"weight":100}}curl -k -v -XPOST 'https://127.0.0.1:6443/apis/example.org/v1/namespaces/default/fruits?fieldManager=kubectl-client-side-apply'POST https://127.0.0.1:6443/apis/example.org/v1/namespaces/default/fruits?fieldManager=kubectl-client-side-apply 201 Created in 25 milliseconds...

其他

给 CR 打标签(label),根据 label 过滤

和内置资源类型一样,K8s 支持对 CR 打标签,然后根据标签做过滤:

## 查看所有 frutis
$ k get fruits
NAME     SWEET   WEIGHT   COMMENT
apple    false   100      little bit rotten
banana   true    80       just bought## 给 banana 打上一个特殊新标签
$ k label fruits banana tastes-good=true
fruit.example.org/banana labeled## 按标签筛选 CR
$ k get fruits -l tastes-good=true
NAME     SWEET   WEIGHT   COMMENT
banana   true    80       just bought## 删除 label
$ k label fruits banana tastes-good-
fruit.example.org/banana labeled

K8s API 与鉴权控制(RBAC)

不管是内置 API,还是扩展 API,都能用 K8s 强大的 RBAC 来做鉴权控制。

关于如何使用 RBAC 网上已经有大量文档;但如果想了解其设计,可参考 Cracking Kubernetes RBAC Authorization Model[7], 它展示了如何从零开始设计出一个 RBAC 鉴权模型(假设 K8s 里还没有)。

参考资料

  1. Kubernetes isn’t about containers[8],2021

  2. Kubernetes is a Database[9], 2019

  3. CRD is just a table in Kubernetes[10], 2020

  4. Cracking Kubernetes RBAC Authorization Model[11], 2022

引用链接

[1]

Kubernetes isn’t about containers: https://blog.joshgav.com/2021/12/16/kubernetes-isnt-about-containers.html

[2]

Kubernetes is a Database: https://github.com/gotopple/k8s-for-users-intro/blob/master/database.md

[3]

CRD is just a table in Kubernetes: https://itnext.io/crd-is-just-a-table-in-kubernetes-13e15367bbe4

[4]

Operator Framework: https://operatorframework.io/

[5]

SIG API Machinery: https://github.com/kubernetes/community/tree/master/sig-api-machinery

[6]

例子: https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#create-a-customresourcedefinition

[7]

Cracking Kubernetes RBAC Authorization Model: https://arthurchiao.art/blog/cracking-k8s-authz-rbac/

[8]

Kubernetes isn’t about containers: https://blog.joshgav.com/2021/12/16/kubernetes-isnt-about-containers.html

[9]

Kubernetes is a Database: https://github.com/gotopple/k8s-for-users-intro/blob/master/database.md

[10]

CRD is just a table in Kubernetes: https://itnext.io/crd-is-just-a-table-in-kubernetes-13e15367bbe4

[11]

Cracking Kubernetes RBAC Authorization Model: https://arthurchiao.art/blog/cracking-k8s-authz-rbac/

你可能还喜欢

点击下方图片即可阅读

使用自动化工作流聚合信息,实现个人数字生活的信息聚合

2022-06-01

使用 Packer 构建虚拟机镜像踩的坑

2022-05-30

使用 Finalizers 来删除那些死活删除不掉的 K8s资源

2022-05-29

K3s 工具进阶完全指南

2022-05-25

云原生是一种信仰 

K8s 的核心是 API 而非容器:从理论到 CRD 实践相关推荐

  1. 你被骗了!Kubernetes 的核心是 API 而非容器

    本文论述了 Kubernetes 的核心价值是其通用.跨厂商和平台.可灵活扩展的声明式 API 框架, 而不是容器(虽然容器是它成功的基础):然后手动创建一个 API Extension(CRD), ...

  2. K8S中的pod、services、容器的概念和区别

    K8S中的pod.services.容器的概念和区别 k8s的部署架构 kubernetes中有两类资源,分别是master和nodes,master和nodes上跑的服务如下图: 1 kube-ap ...

  3. kubeadm部署K8S集群并使用containerd做容器运行时

    kubeadm部署K8S集群并使用containerd做容器运行时(内容全部实战验证有任何问题欢迎留言咨询讨论) 前言 去年12月份,当Kubernetes社区宣布1.20版本之后会逐步弃用docke ...

  4. SQLite3中核心C API

    核心C API SQLite3 有八个函数用于实际处理连接.处理查询以及断开数据库连接的.其余都是为了完成特定的任务 一.查询封装 通过封装查询对数据库进行连接.断开.以及查询. 1.连接和断开 执行 ...

  5. hibernate框架(二)核心配置API

    一:核心配置分为三大部分  必须的配置 .可选的配置和引入映射文件. 1.必须的配置 连接数据库的参数:驱动类  url路径  用户名  密码  方言 <property name=" ...

  6. java中组件与容器_java中的容器组件和非容器组件

    1.java使用到的图形类主要在java.awt 与javax.swing包中. 2.java.awt 与 javax.swing包的区别: ① java.awt中使用的图形类都是依赖于系统的图形库的 ...

  7. nsga2多目标优化之核心知识点(快速非支配排序、拥挤距离、精英选择策略)详解(python实现)

    文章目录 一.多目标优化算法简介 1.基本知识 二.NSGA2算法 1.基本原理 2.快速非支配排序 2.1快速非支配排序 python实现 3.拥挤距离 3.1 拥挤距离python 实现 4.精英 ...

  8. Windows核心编程 - API HOOK应用

    #Windows核心编程 - API HOOK应用 如需转载请标明出处:http://blog.csdn.net/itas109 QQ技术交流群:129518033 目录 文章目录 #Windows核 ...

  9. 【Android P】非公开API(非 SDK 接口)相关知识总结

    关于P-OSV中非公开API(非 SDK 接口)的限制及搜索方式,做了以下整理. 1.背景 Android 9(API 级别 28)引入了针对非 SDK 接口的使用限制,无论是直接使用还是通过反射或 ...

最新文章

  1. 深圳大学计算机暑期学校,The First Day-深度学习暑期学校
  2. 获得诺贝尔奖的底层小职员 | 从来没有一个高手,是在一夜之间强大起来的
  3. 《突破C#编程实例五十讲》源文件下载(2)
  4. javascript基础 (2)
  5. java yii_构建 Java 应用程序
  6. LINUX文件系统介绍
  7. 力扣合并两个有序数组
  8. mysql注入技巧原理_MySQL注入技巧总结
  9. Docker 使用Dockerfile构建自己的docker服务(三)
  10. 如果测试没有梦想,那跟咸鱼有什么区别?
  11. openstack 安装windows系统
  12. python-列表演练-根据学生id获取学生数据-获取学生数据中得分较高的前N条数据
  13. mysql 表中中文不显示
  14. linux怎么修改内存缓存,Linux内存、缓存、Swap等修改
  15. 安装mysql5.7,如何将之前mysql的数据库导入
  16. 【Qt Quick】零基础入门系列之安装与卸载(一)
  17. 为什么低代码治好了CIO们的 “精神内耗” ?
  18. C语言数据结构代码——有向图
  19. 网站日志分析(二)——利用Quick BI制作企业化报表分析
  20. 分布式事务2PC论文翻译(Concurrency Control and Recovery in Database Systems )

热门文章

  1. 《从实践中学嵌入式Linux应用程序开发》pdf完整版资源分享
  2. !important的理解
  3. java核心技术总结
  4. c语言程序设计钟志水答案,c语言程序设计答案钟志水周鸣争
  5. CSDN平台比赛第五期第四题:三而竭
  6. Python中text文件操作
  7. 平面图的判定定理:Kuratowski定理(库拉托夫斯基定理)
  8. io类游戏快速开发 1
  9. vscode 快速生成html模板
  10. 如何组建和激励工程师团队