Kubernetes - Object 与 API 规则
1 概述
1.1 组织对象的方式
Kubernetes 中组织对象的方式,就是按照 Group、Version、Resource 三个层级。
-
Group
用以来对 API 进行分组(分类); -
Version
用以对相同的 API 进行版本控制; -
Resource
代表着一个具体的资源对象的 API;
这不等同于 etcd 中组织资源对象的方式,etcd 中还是按照资源类型,以及命名来进行分类存储
|
|
这三个层次,也会体现在资源定义的 yaml 文件中:
|
|
而 Kubernetes 就是通过比较 Group Version Resource,再加上资源对象的 name 来寻找一个资源。
1.2 REST 风格
Kubernetes 系统大部分情况下,API 定义和标准都符合 HTTP REST 标准,即通过 POST、PUT、GET、DELETE 等 HTTP method 来进行对象的增删改查操作。
Kubernetes 使用 OpenAPI 文档格式生成接口文档。你可以通过 https://<master_ip>:<master_port>/openapi/v2
来访问 API 文档。
|
|
2 资源的版本控制
Kubernetes 对于资源的版本控制体现在 URL 中,每种资源请求的路径为 /apis/<group>/<version>/namespaces/<ns>/<resource>
的格式构建,其中 version
用于不同版本的资源。
Kubernetes 使用的 Semantic Version 风格的版本号。并且约定:对于一个特定的版本,包含三种级别的版本:
-
Alpha :预览版本
version 以
<v>alpha<nr>
格式,例如 v1alpha1。表明软件是不稳定,软件可能会有 Bug,某些新增特性支持可能随时被删除,某些新增 API 可能会出现不兼容性更改。
因此仅仅使用于测试集群,不适合生产环境。
-
Beta :测试版本
version 以
<v>beta<nr>
格式,例如 v2beta3。表明软件经过测试,并且特性都是安全的。如果特性与 API 发生兼容性更改,那么会提供迁移的说明。
-
GA :稳定版本
verison 以
<v>
格式,例如 v1。
3 API Groups
为了更容易扩展 API,Kubernetes 将 API 分组为多个逻辑集合,称为 API Groups
。
当前支持两类的 API Groups:
-
Core Groups(核心组)
又称为 Legacy Groups,大部分核心资源对象都在该组里,例如 Container、Pod、Service 等。
其资源的访问路径前缀为
/api/v1
。其 Group 为空,因此 spec 中使用spec.apiVersion : v1
。 -
其他 API Groups
其资源的访问路径前缀为
/apis/<Group>/<Version>
,spec 中会给出具体的 groupspec.apiVersion: <Group>/<Version>
。常见的分组包括:
apps/v1
:主要包含与用户发布、部署有关资源,包括 Deployments,RollingUpdates,ReplicaSet。extensions/<Version>
:扩展 API 组,包括 DaemonSet、ReplicaSet,Ingresses。batch/<Version>
:批处理和作业任务的对象,包括 Job。autoscaling<Version>
:HPA 相关资源对象。certificate.k8s.io/<Version>
:集群证书操作相关资源对象。rbac.authorization.k8s.io/v1
:RBAC 权限相关资源对象。policy/<Version>
:Pod 权限性相关的资源。- 其他 CRD 定义的分组
Kubernetes 内置的所有 API Group 可以见 API 参考文档。
3.1 启用或禁用 API Group
所有 API Group 默认情况都是可用的。可以通过 API Server 启动配置开启用或禁用某个 API 组。例如 --runtime-config=batch/v1=false
表明禁用 batch/v1 下的所有 API。
4 对象
Kubernetes API 所有资源类型都是以 对象 方式看待,并且以 REST 方式提供 HTTP API 接口。
每个对象的 API 以以下格式表示:
- non-namespace 资源:
GET /apis/<Group>/<Version>/<Resource>
:返回资源集合GET /apis/<Group>/<Version>/<Resource>/<Name
:操作指定 name 的资源对象
- namespace 资源:
GET /apis/<Group>/<Version>/<Resource>
:返回所有 namespace 下资源对象GET /apis/<Group>/<Version>/namespaces/<Namespace>/<Resource>
:返回指定 namespace 下的所有资源对象GET /apis/<Group>/<Version>/namespaces/<Namespace>/<Resource>/<Name>
:返回 namespace 下指定 name 的资源对象
4.1 Watch 对象
基于 etcd 的机制,每个 Kubernetes 对象都有一个 resourceVersion
字段,代表着资源在 etcd 中存储的版本。
因此,在 client 的 watch 连接断开,重新连接后,可以通过指定 resourceVersion
来得到断连期间其对象所有的更改。
|
|
当然,etcd 只会保存一定时间内的资源变更历史(默认 5min)。如果请求的历史版本不存在,那么会返回 HTTP Code 410 Gone
。因此 client 必须能够处理 410 错误,清理本地对象缓存,调用 list 操作,重新建立 watch。
为了解决历史窗口太短的问题,为 event 引入了 bookmark event 的概念。BOOKMARK
事件表明客户端请求的 resourceVersion
所有更改都已发送。
通过查询时的 Query 参数 allowWatchBookmarks=true
可以查询 BOOKMARK
事件。
|
|
4.2 分块查询
一般情况下,查询对象只需要使用 HTTP GET 请求对应的 URL 接口。
不过当查询大量的对象时,可能返回的数据很大,使得浪费网络资源。从 1.9 开始,Kubernetes 支持 分段查询对象。在进行查询请求时,可以指定 limit
和 continue
参数。
-
查询 500 个 Pod,指定 “limit=500”。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
GET /api/v1/pods?limit=500 --- 200 OK Content-Type: application/json { "kind": "PodList", "apiVersion": "v1", "metadata": { "resourceVersion":"10245", "continue": "ENCODED_CONTINUE_TOKEN", ... }, "items": [...] // returns pods 1-500 }
-
继续前面调用,查询剩余的 Pod,指定 “continue=ENCODED_CONTINUE_TOKEN” 表明继续上一次查询。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
GET /api/v1/pods?limit=500&continue=ENCODED_CONTINUE_TOKEN --- 200 OK Content-Type: application/json { "kind": "PodList", "apiVersion": "v1", "metadata": { "resourceVersion":"10245", "continue": "", // continue token is empty because we have reached the end of the list ... }, "items": [...] // returns pods 1001-1253 }
注意,当你使用 continue 继续查询时,查询的永远是同一个 resourceVersion 的对象。
4.3 编码方式
默认 Kubernetes 都是通过 JSON 格式来进行数据的传输。通过下面方式,允许 client 使用 protobuf 形式进行数据传输。
- 请求数据时,添加头部
Accept: application/vnd.kubernetes.protobuf
表明期望返回 protobuf 类型数据; - 发送数据时,通过指定
Content-Type: application/vnd.kubernetes.protobuf
表明传输的是一个 protobuf 类型数据;
部分 CRD 或者 API 扩展加入的资源不支持 Protobuf,可以使用 Accept 头部指定多种类型来允许回退。
|
|
4.4 表格查询
通过 Accept
Header 中添加 as=Table
可以让 APIServer 返回资源对应的表格输出(例如 CRD 定义的 columnDefinitions),而不是完整的资源信息。客户端有时可能更利于使用这种方式来输出。
|
|
4.5 对象的删除
资源对象删除经过两个阶段:
-
Finalization 终止:资源的
metadata.deletionTimestamp
被设置,然后等待 Finalizers 结束。该阶段体现在对象上仅仅是设置了
deletionTimestamp
字段,因此是一个 Update Event。 -
Delete 删除:当所有 Finalizers 执行结束后(
finalizer
字段为空),资源才从 etcd 中被真正删除。该阶段会真正删除对象,因此是一个 Delete Event。
5 API 访问控制
Kubernetes 对 API 有着三种访问控制方式:
-
认证 - 验证发送请求者的身份
-
授权 - 确认请求者是否有权限执行操作
-
准入控制 - 验证请求操作是否合法
更多细节见 Kubernetes 认证与鉴权机制 与 Admission。
6 扩展 API
Kubernetes 提供了很完善的 API 扩展机制,使得你不需要修改 Kubernetes 的代码,可以动态的添加你自己的资源对象。
目前主要包含两种扩展 API 的方式:
- CRD :复用 Kubernetes 的 API Server。用户只需要定义 CRD,并实现一个 CRD Controller,就能够通过 Kubernetes 管理自定义资源对象。
- API Aggregate :用户需要编写额外的 API Server,对资源进行更细粒度的控制。
更多细节见 CRD 和 Custom APIServer。
7 Dryrun
当发送修改的请求时(POST、PUT、PATCH 和 DELETE)时,可以通过 Dryrun 模式提交请求。Kubernetes 仅仅会评估请求,而不是真正的执行操作。
请求中的查询参数 dryRun=All
来触发,所有请求的阶段都会正常执行,除了最初的存储阶段。
|
|
sideEffects
来声明该 Webhook 是否要在 Dryrun 模式下运行,见 Side effects。当然,因为对象的部分属性是写入存储前自动生成的(例如 creationTimestamp
resourceVersion
等),所以这些值在 Dryrun 模式下与实际的请求执行可能不同。