Kubernetes API 概念
Kubernetes API 是一个基于资源(RESTful)的程序化接口,通过 HTTP 提供。它支持通过标准的 HTTP 动词(POST、PUT、PATCH、DELETE、GET)检索、创建、更新和删除主要资源。
对于某些资源,API 包括额外的子资源,这些子资源允许细粒度的授权(例如,Pod 详情和日志检索的单独视图),并且可以为了方便或效率而接受并以不同的表示形式提供这些资源。
Kubernetes 通过监听支持资源上的高效变更通知
在 Kubernetes API 中,监听是一个动词,用于以流的形式跟踪 Kubernetes 中对象的更改。它用于高效检测更改。
Kubernetes 还提供一致的列表操作,以便 API 客户端可以有效地缓存、跟踪和同步资源的状态。你可以在线查看API 参考,或继续阅读以了解有关 API 的一般信息。
Kubernetes API 术语
Kubernetes 通常利用通用的 RESTful 术语来描述 API 概念
- 资源类型是在 URL 中使用的名称(
pods
、namespaces
、services
) - 所有资源类型都有一个具体的表示形式(其对象模式),称为种类
- 资源类型的实例列表称为集合
- 资源类型的单个实例称为资源,并且通常也表示一个对象
- 对于某些资源类型,API 包括一个或多个子资源,这些子资源表示为资源下的 URI 路径
大多数 Kubernetes API 资源类型是对象 – 它们表示集群上概念的具体实例,例如 Pod 或命名空间。较少数量的 API 资源类型是虚拟的,因为它们通常表示对对象的操作,而不是对象,例如权限检查(使用带有 JSON 编码的 SubjectAccessReview
主体的 POST 到 subjectaccessreviews
资源),或 Pod 的 eviction
子资源(用于触发 API 发起的驱逐)。
对象名称
你通过 API 创建的所有对象都有一个唯一的对象名称,以允许幂等的创建和检索,除非虚拟资源类型在不可检索或不依赖于幂等性的情况下可能没有唯一的名称。在命名空间中,给定种类的对象在同一时间只能有一个给定名称。但是,如果你删除该对象,你可以创建一个具有相同名称的新对象。某些对象不是命名空间的(例如:节点),因此它们的名称在整个集群中必须是唯一的。
API 动词
几乎所有对象资源类型都支持标准的 HTTP 动词 - GET、POST、PUT、PATCH 和 DELETE。Kubernetes 还使用自己的动词,这些动词通常以小写形式书写,以将其与 HTTP 动词区分开来。
Kubernetes 使用术语 list 来描述返回资源集合,以区别于检索单个资源,后者通常称为 get。如果你发送带有 ?watch
查询参数的 HTTP GET 请求,Kubernetes 将其称为 watch 而不是 get(有关更多详细信息,请参阅高效检测更改)。
对于 PUT 请求,Kubernetes 会根据现有对象的状态在内部将其分类为 create 或 update。update 与 patch 不同;patch 的 HTTP 动词是 PATCH。
资源 URI
所有资源类型要么由集群范围限定(/apis/GROUP/VERSION/*
),要么由命名空间范围限定(/apis/GROUP/VERSION/namespaces/NAMESPACE/*
)。命名空间范围的资源类型将在其命名空间被删除时删除,并且对该资源类型的访问由命名空间范围的授权检查控制。
注意:核心资源使用 /api
而不是 /apis
,并省略 GROUP 路径段。
示例
/api/v1/namespaces
/api/v1/pods
/api/v1/namespaces/my-namespace/pods
/apis/apps/v1/deployments
/apis/apps/v1/namespaces/my-namespace/deployments
/apis/apps/v1/namespaces/my-namespace/deployments/my-deployment
你还可以访问资源集合(例如:列出所有节点)。以下路径用于检索集合和资源
集群范围的资源
GET /apis/GROUP/VERSION/RESOURCETYPE
- 返回资源类型的资源集合GET /apis/GROUP/VERSION/RESOURCETYPE/NAME
- 返回资源类型下具有 NAME 的资源
命名空间范围的资源
GET /apis/GROUP/VERSION/RESOURCETYPE
- 返回所有命名空间中资源类型的所有实例的集合GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE
- 返回 NAMESPACE 中资源类型的所有实例的集合GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME
- 返回 NAMESPACE 中具有 NAME 的资源类型实例
由于命名空间是集群范围的资源类型,你可以使用 GET /api/v1/namespaces
检索所有命名空间的列表(“集合”),并使用 GET /api/v1/namespaces/NAME
检索有关特定命名空间的详细信息。
- 集群范围的子资源:
GET /apis/GROUP/VERSION/RESOURCETYPE/NAME/SUBRESOURCE
- 命名空间范围的子资源:
GET /apis/GROUP/VERSION/namespaces/NAMESPACE/RESOURCETYPE/NAME/SUBRESOURCE
每个子资源支持的动词将因对象而异 - 有关更多信息,请参阅API 参考。不可能跨多个资源访问子资源 - 如果需要,通常会使用新的虚拟资源类型。
HTTP 媒体类型
通过 HTTP,Kubernetes 支持 JSON 和 Protobuf 线编码。
默认情况下,Kubernetes 使用 application/json
媒体类型以JSON 序列化返回对象。尽管 JSON 是默认值,但客户端可以请求 YAML 格式的响应,或者使用更高效的二进制 Protobuf 表示形式以获得更好的规模性能。
Kubernetes API 实现了标准的 HTTP 内容类型协商:使用 GET
调用传递 Accept
标头将请求服务器尝试以你首选的媒体类型返回响应。如果你想为 PUT
或 POST
请求将 Protobuf 中的对象发送到服务器,你必须适当地设置 Content-Type
请求标头。
如果你请求可用的媒体类型,API 服务器将返回带有合适的 Content-Type
的响应;如果你请求的媒体类型都不支持,API 服务器将返回 406 Not acceptable
错误消息。所有内置资源类型都支持 application/json
媒体类型。
JSON 资源编码
Kubernetes API 默认使用JSON 来编码 HTTP 消息体。
例如
列出集群上的所有 Pod,而不指定首选格式
GET /api/v1/pods
200 OK Content-Type: application/json … JSON encoded collection of Pods (PodList object)
通过将 JSON 发送到服务器来创建一个 Pod,请求 JSON 响应。
POST /api/v1/namespaces/test/pods Content-Type: application/json Accept: application/json … JSON encoded Pod object
200 OK Content-Type: application/json { "kind": "Pod", "apiVersion": "v1", … }
YAML 资源编码
Kubernetes 还支持 application/yaml
媒体类型进行请求和响应。 YAML
可用于定义 Kubernetes 清单和 API 交互。
例如
以 YAML 格式列出集群上的所有 Pod
GET /api/v1/pods Accept: application/yaml
200 OK Content-Type: application/yaml … YAML encoded collection of Pods (PodList object)
通过将 YAML 编码的数据发送到服务器来创建一个 Pod,请求 YAML 响应
POST /api/v1/namespaces/test/pods Content-Type: application/yaml Accept: application/yaml … YAML encoded Pod object
200 OK Content-Type: application/yaml apiVersion: v1 kind: Pod metadata: name: my-pod …
Kubernetes Protobuf 编码
Kubernetes 使用一个信封包装器来编码 Protobuf 响应。该包装器以 4 字节的幻数开头,以帮助识别磁盘或 etcd 中的内容为 Protobuf(而不是 JSON)。这 4 字节的幻数数据后面跟着一个 Protobuf 编码的包装器消息,该消息描述了底层对象的编码和类型。在 Protobuf 包装器消息中,内部对象数据使用 Unknown 的 raw
字段记录(有关更多详细信息,请参阅 IDL)。
例如
以 Protobuf 格式列出集群上的所有 Pod。
GET /api/v1/pods Accept: application/vnd.kubernetes.protobuf
200 OK Content-Type: application/vnd.kubernetes.protobuf … JSON encoded collection of Pods (PodList object)
通过向服务器发送 Protobuf 编码的数据来创建一个 Pod,但请求以 JSON 格式响应。
POST /api/v1/namespaces/test/pods Content-Type: application/vnd.kubernetes.protobuf Accept: application/json … binary encoded Pod object
200 OK Content-Type: application/json { "kind": "Pod", "apiVersion": "v1", ... }
你可以将这两种技术结合使用,并使用 Kubernetes 的 Protobuf 编码与任何支持它的 API 进行交互,无论是读取还是写入。只有一些 API 资源类型与 Protobuf 兼容。
包装器格式为
A four byte magic number prefix:
Bytes 0-3: "k8s\x00" [0x6b, 0x38, 0x73, 0x00]
An encoded Protobuf message with the following IDL:
message Unknown {
// typeMeta should have the string values for "kind" and "apiVersion" as set on the JSON object
optional TypeMeta typeMeta = 1;
// raw will hold the complete serialized object in protobuf. See the protobuf definitions in the client libraries for a given kind.
optional bytes raw = 2;
// contentEncoding is encoding used for the raw data. Unspecified means no encoding.
optional string contentEncoding = 3;
// contentType is the serialization method used to serialize 'raw'. Unspecified means application/vnd.kubernetes.protobuf and is usually
// omitted.
optional string contentType = 4;
}
message TypeMeta {
// apiVersion is the group/version for this type
optional string apiVersion = 1;
// kind is the name of the object schema. A protobuf definition should exist for this object.
optional string kind = 2;
}
注意
接收到application/vnd.kubernetes.protobuf
格式的响应但不匹配预期前缀的客户端应拒绝该响应,因为未来的版本可能需要以不兼容的方式更改序列化格式,并且会通过更改前缀来实现。与 Kubernetes Protobuf 的兼容性
并非所有 API 资源类型都支持 Kubernetes 的 Protobuf 编码;具体来说,Protobuf 不适用于定义为 CustomResourceDefinitions 或通过 聚合层 提供的资源。
作为客户端,如果可能需要使用扩展类型,则应在请求的 Accept
标头中指定多种内容类型,以支持回退到 JSON。例如
Accept: application/vnd.kubernetes.protobuf, application/json
CBOR 资源编码
Kubernetes v1.32 [alpha]
(默认禁用:false)启用 CBORServingAndStorage
功能门 后,所有内置资源类型和 CustomResourceDefinition 定义的所有资源的请求和响应主体都可以编码为 CBOR 二进制数据格式。如果 CBOR 在各个聚合 API 服务器中启用,则它也支持 聚合层。
当请求正文包含单个 CBOR 编码的数据项时,客户端应在 Content-Type
HTTP 请求标头中指示 IANA 媒体类型 application/cbor
,并在准备接受响应中 CBOR 编码的数据项时,在 Accept
HTTP 请求标头中指示。当响应正文包含 CBOR 编码的对象时,API 服务器将在 Content-Type
HTTP 响应标头中使用 application/cbor
。
如果 API 服务器使用 CBOR 将其响应编码为 watch 请求,则响应正文将是一个 CBOR 序列,并且 Content-Type
HTTP 响应标头将使用 IANA 媒体类型 application/cbor-seq
。序列的每个条目(如果有)都是一个单独的 CBOR 编码的 watch 事件。
除了现有的 application/apply-patch+yaml
媒体类型用于 YAML 编码的 服务器端应用配置之外,启用 CBOR 的 API 服务器将接受 application/apply-patch+cbor
媒体类型用于 CBOR 编码的服务器端应用配置。application/json-patch+json
、application/merge-patch+json
或 application/strategic-merge-patch+json
没有支持的 CBOR 等效项。
高效检测更改
Kubernetes API 允许客户端对对象或集合进行初始请求,然后跟踪自初始请求以来的更改:一个 watch。客户端可以发送一个 list 或一个 get,然后发出后续的 watch 请求。
为了使此更改跟踪成为可能,每个 Kubernetes 对象都有一个 resourceVersion
字段,表示该资源在底层持久层中存储的版本。当检索资源集合(无论是命名空间还是集群范围)时,API 服务器的响应包含一个 resourceVersion
值。客户端可以使用该 resourceVersion
来启动对 API 服务器的 watch。
当你发送一个 watch 请求时,API 服务器会响应一个更改流。这些更改列出了在您指定为 watch 请求参数的 resourceVersion
之后发生的(例如 create、delete 和 update)操作的结果。整个 watch 机制允许客户端获取当前状态,然后订阅后续更改,而不会遗漏任何事件。
如果客户端 watch 断开连接,则该客户端可以从上次返回的 resourceVersion
启动新的 watch;客户端也可以执行新的 get / list 请求并重新开始。有关更多详细信息,请参阅资源版本语义。
例如
列出给定命名空间中的所有 Pod。
GET /api/v1/namespaces/test/pods --- 200 OK Content-Type: application/json { "kind": "PodList", "apiVersion": "v1", "metadata": {"resourceVersion":"10245"}, "items": [...] }
从资源版本 10245 开始,接收影响 test 命名空间中 Pod 的任何 API 操作(如 create、delete、patch 或 update)的通知。每个更改通知都是一个 JSON 文档。HTTP 响应主体(以
application/json
提供)由一系列 JSON 文档组成。GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245 --- 200 OK Transfer-Encoding: chunked Content-Type: application/json { "type": "ADDED", "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10596", ...}, ...} } { "type": "MODIFIED", "object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "11020", ...}, ...} } ...
给定的 Kubernetes 服务器只会保留有限时间的更改历史记录。默认情况下,使用 etcd 3 的集群会保留最近 5 分钟内的更改。当请求的 watch 操作因该资源的历史版本不可用而失败时,客户端必须通过识别状态代码 410 Gone
、清除其本地缓存、执行新的 get 或 list 操作,并从返回的 resourceVersion
开始 watch 来处理这种情况。
对于订阅集合,Kubernetes 客户端库通常为此 list-then-watch 逻辑提供某种形式的标准工具。(在 Go 客户端库中,这称为 Reflector
,位于 k8s.io/client-go/tools/cache
包中。)
Watch 书签
为了减轻短历史窗口的影响,Kubernetes API 提供了一个名为 BOOKMARK
的 watch 事件。这是一种特殊类型的事件,用于标记客户端请求的给定 resourceVersion
之前的所有更改已发送。表示 BOOKMARK
事件的文档类型是请求所请求的类型,但仅包含 .metadata.resourceVersion
字段。例如
GET /api/v1/namespaces/test/pods?watch=1&resourceVersion=10245&allowWatchBookmarks=true
---
200 OK
Transfer-Encoding: chunked
Content-Type: application/json
{
"type": "ADDED",
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10596", ...}, ...}
}
...
{
"type": "BOOKMARK",
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "12746"} }
}
作为客户端,你可以通过将 allowWatchBookmarks=true
查询参数设置为 watch 请求来请求 BOOKMARK
事件,但不应假设书签以任何特定的间隔返回,客户端也不能假设 API 服务器即使在请求时也会发送任何 BOOKMARK
事件。
流式列表
Kubernetes v1.32 [beta]
(默认启用:true)在大型集群上,检索某些资源类型的集合可能会导致控制平面上资源使用量(主要是 RAM)的显著增加。为了减轻影响并简化 list + watch 模式的用户体验,Kubernetes v1.32 将允许请求初始状态(之前通过 list 请求请求)作为 watch 请求的一部分的功能提升为 beta 版。
在客户端,可以通过在 watch 请求中将 sendInitialEvents=true
指定为查询字符串参数来请求初始状态。如果设置,API 服务器将使用合成的 init 事件(类型为 ADDED
)启动 watch 流,以构建所有现有对象的整个状态,后跟一个 BOOKMARK
事件(如果通过 allowWatchBookmarks=true
选项请求)。书签事件包括同步到的资源版本。发送书签事件后,API 服务器将像任何其他 watch 请求一样继续运行。
当你在查询字符串中设置 sendInitialEvents=true
时,Kubernetes 还要求你将 resourceVersionMatch
设置为 NotOlderThan
值。如果你在查询字符串中提供了 resourceVersion
但未提供值或根本没有提供,则这被解释为 一致读取 的请求;当状态至少同步到从请求开始处理时一致读取的时刻时,会发送书签事件。如果你指定 resourceVersion
(在查询字符串中),则当状态至少同步到提供的资源版本时,会发送书签事件。
示例
一个示例:你想监视一个 Pod 集合。对于该集合,当前资源版本为 10245,并且有两个 pod:foo
和 bar
。然后发送以下请求(通过使用 resourceVersion=
设置空资源版本来显式请求 一致读取)可能会导致以下事件序列
GET /api/v1/namespaces/test/pods?watch=1&sendInitialEvents=true&allowWatchBookmarks=true&resourceVersion=&resourceVersionMatch=NotOlderThan
---
200 OK
Transfer-Encoding: chunked
Content-Type: application/json
{
"type": "ADDED",
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "8467", "name": "foo"}, ...}
}
{
"type": "ADDED",
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "5726", "name": "bar"}, ...}
}
{
"type": "BOOKMARK",
"object": {"kind": "Pod", "apiVersion": "v1", "metadata": {"resourceVersion": "10245"} }
}
...
<followed by regular watch stream starting from resourceVersion="10245">
响应压缩
Kubernetes v1.16 [beta]
(默认启用:true)APIResponseCompression
是一个选项,允许 API 服务器压缩 get 和 list 请求的响应,从而减少网络带宽并提高大型集群的性能。它自 Kubernetes 1.16 起默认启用,可以通过在 API 服务器上的 --feature-gates
标志中包含 APIResponseCompression=false
来禁用。
API 响应压缩可以显著减小响应的大小,尤其是对于大型资源或集合。例如,对 Pod 的 list 请求可能会返回数百 KB 甚至 MB 的数据,具体取决于 Pod 的数量及其属性。通过压缩响应,可以节省网络带宽并减少延迟。
要验证 APIResponseCompression
是否正在工作,你可以向 API 服务器发送带有 Accept-Encoding
标头的 get 或 list 请求,并检查响应大小和标头。例如
GET /api/v1/pods
Accept-Encoding: gzip
---
200 OK
Content-Type: application/json
content-encoding: gzip
...
content-encoding
标头指示响应已使用 gzip
压缩。
分块检索大型结果集
Kubernetes v1.29 [stable]
(默认启用:true)在大型集群上,检索某些资源类型的集合可能会导致非常大的响应,从而影响服务器和客户端。例如,一个集群可能拥有数万个 Pod,每个 Pod 大约相当于 2 KiB 的编码 JSON。跨所有命名空间检索所有 Pod 可能会导致非常大的响应(10-20MB)并消耗大量服务器资源。
Kubernetes API 服务器支持将单个大型集合请求分解为许多较小的块,同时保持整个请求的一致性。可以按顺序返回每个块,这既减少了请求的总大小,又允许面向用户的客户端增量显示结果以提高响应速度。
你可以请求 API 服务器通过使用页面(Kubernetes 称为 块)来处理单个集合的 list。为了分块检索单个集合,在对集合的请求中支持两个查询参数 limit
和 continue
,并且在集合的 metadata
字段中,所有 list 操作都返回一个响应字段 continue
。客户端应使用 limit
指定他们希望在每个块中接收的最大结果数,并且如果集合中有更多资源,服务器将在结果中最多返回 limit
个资源,并包含一个 continue
值。
作为 API 客户端,您可以将此 continue
值传递给 API 服务器,以便在下次请求时指示服务器返回下一页(块)结果。 通过不断地继续,直到服务器返回空的 continue
值,您可以检索整个集合。
与 watch 操作类似,continue
令牌会在短时间后过期(默认为 5 分钟),如果无法返回更多结果,则返回 410 Gone
。 在这种情况下,客户端需要从头开始或省略 limit
参数。
例如,如果集群上有 1,253 个 Pod,并且您希望一次接收 500 个 Pod 的块,请按如下方式请求这些块
列出集群上的所有 Pod,每次最多检索 500 个 Pod。
GET /api/v1/pods?limit=500 --- 200 OK Content-Type: application/json { "kind": "PodList", "apiVersion": "v1", "metadata": { "resourceVersion":"10245", "continue": "ENCODED_CONTINUE_TOKEN", "remainingItemCount": 753, ... }, "items": [...] // returns pods 1-500 }
继续上一次调用,检索下一组 500 个 Pod。
GET /api/v1/pods?limit=500&continue=ENCODED_CONTINUE_TOKEN --- 200 OK Content-Type: application/json { "kind": "PodList", "apiVersion": "v1", "metadata": { "resourceVersion":"10245", "continue": "ENCODED_CONTINUE_TOKEN_2", "remainingItemCount": 253, ... }, "items": [...] // returns pods 501-1000 }
继续上一次调用,检索最后 253 个 Pod。
GET /api/v1/pods?limit=500&continue=ENCODED_CONTINUE_TOKEN_2 --- 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 }
请注意,集合的 resourceVersion
在每次请求中保持不变,这表明服务器正在向您展示 Pod 的一致快照。除非您在不使用 continue
令牌的情况下发出单独的 list 请求,否则不会显示在版本 10245
之后创建、更新或删除的 Pod。这允许您将大型请求分成较小的块,然后对整个集合执行 watch 操作,而不会遗漏任何更新。
remainingItemCount
是集合中未包含在此响应中的后续项的数量。如果 list 请求包含标签或字段选择器,则剩余项的数量未知,并且 API 服务器不会在其响应中包含 remainingItemCount
字段。如果 list 完成(要么是因为它没有分块,要么是因为这是最后一个块),则没有更多剩余项,并且 API 服务器不会在其响应中包含 remainingItemCount
字段。remainingItemCount
的预期用途是估计集合的大小。
集合
在 Kubernetes 术语中,您从 list 获取的响应是一个集合。 但是,Kubernetes 为不同类型的资源集合定义了具体的种类。集合的种类名称以资源种类命名,并附加 List
。
当您查询 API 获取特定类型时,该查询返回的所有项都属于该类型。例如,当您 list 服务时,集合响应的 kind
设置为 ServiceList
;该集合中的每个项代表一个服务。例如
GET /api/v1/services
{
"kind": "ServiceList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "2947301"
},
"items": [
{
"metadata": {
"name": "kubernetes",
"namespace": "default",
...
"metadata": {
"name": "kube-dns",
"namespace": "kube-system",
...
Kubernetes API 中定义了数十种集合类型(例如 PodList
、ServiceList
和 NodeList
)。您可以从 Kubernetes API 文档中获取有关每种集合类型的更多信息。
某些工具(例如 kubectl
)对 Kubernetes 集合机制的表示与 Kubernetes API 本身略有不同。由于 kubectl
的输出可能包括来自 API 级别的多个 list 操作的响应,因此 kubectl
使用 kind: List
表示项列表。例如
kubectl get services -A -o yaml
apiVersion: v1
kind: List
metadata:
resourceVersion: ""
selfLink: ""
items:
- apiVersion: v1
kind: Service
metadata:
creationTimestamp: "2021-06-03T14:54:12Z"
labels:
component: apiserver
provider: kubernetes
name: kubernetes
namespace: default
...
- apiVersion: v1
kind: Service
metadata:
annotations:
prometheus.io/port: "9153"
prometheus.io/scrape: "true"
creationTimestamp: "2021-06-03T14:54:14Z"
labels:
k8s-app: kube-dns
kubernetes.io/cluster-service: "true"
kubernetes.io/name: CoreDNS
name: kube-dns
namespace: kube-system
注意
请记住,Kubernetes API 没有名为 List
的 kind
。
kind: List
是一个客户端内部实现细节,用于处理可能属于不同对象种类的集合。避免在自动化或其他代码中依赖 kind: List
。
以表格形式接收资源
当您运行 kubectl get
时,默认输出格式是特定资源类型的一个或多个实例的简单表格表示形式。过去,客户端需要重现 kubectl
中实现的表格和描述输出,以执行简单的对象列表。这种方法的一些限制包括在处理某些对象时需要复杂的逻辑。此外,API 聚合或第三方资源提供的类型在编译时是未知的。这意味着必须为客户端无法识别的类型提供通用实现。
为了避免如上所述的潜在限制,客户端可以请求对象的表格表示形式,将打印的特定细节委派给服务器。Kubernetes API 实现了标准的 HTTP 内容类型协商:传递一个包含 application/json;as=Table;g=meta.k8s.io;v=v1
值的 Accept
标头和 GET
调用,将请求服务器以表格内容类型返回对象。
例如,以表格格式列出集群上的所有 Pod。
GET /api/v1/pods
Accept: application/json;as=Table;g=meta.k8s.io;v=v1
---
200 OK
Content-Type: application/json
{
"kind": "Table",
"apiVersion": "meta.k8s.io/v1",
...
"columnDefinitions": [
...
]
}
对于控制平面不知道自定义表格定义的 API 资源类型,API 服务器会返回一个默认的表格响应,其中包含资源的 name
和 creationTimestamp
字段。
GET /apis/crd.example.com/v1alpha1/namespaces/default/resources
---
200 OK
Content-Type: application/json
...
{
"kind": "Table",
"apiVersion": "meta.k8s.io/v1",
...
"columnDefinitions": [
{
"name": "Name",
"type": "string",
...
},
{
"name": "Created At",
"type": "date",
...
}
]
}
并非所有 API 资源类型都支持表格响应;例如,CustomResourceDefinitions 可能没有定义字段到表格的映射,并且扩展核心 Kubernetes API 的 APIService 可能根本不提供表格响应。如果您正在实现使用表格信息并必须针对所有资源类型(包括扩展)工作的客户端,则应在 Accept
标头中指定多种内容类型的请求。例如
Accept: application/json;as=Table;g=meta.k8s.io;v=v1, application/json
资源删除
当您 delete 资源时,它会分两个阶段进行。
- 最终确定
- 删除
{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": {
"finalizers": ["url.io/neat-finalization", "other-url.io/my-finalizer"],
"deletionTimestamp": nil,
}
}
当客户端首次发送 delete 请求删除资源时,.metadata.deletionTimestamp
会设置为当前时间。一旦设置了 .metadata.deletionTimestamp
,作用于终结器的外部控制器可以随时以任何顺序开始执行其清理工作。
终结器之间不强制执行顺序,因为它会引入 .metadata.finalizers
卡住的重大风险。
.metadata.finalizers
字段是共享的:任何有权限的参与者都可以重新排序它。如果按顺序处理终结器列表,则可能会导致这种情况:列表中第一个终结器的组件正在等待由列表中稍后终结器的组件产生的某个信号(字段值、外部系统或其他),从而导致死锁。
在没有强制排序的情况下,终结器可以自由地在彼此之间排序,并且不会受到列表中排序更改的影响。
一旦删除了最后一个终结器,该资源实际上会从 etcd 中删除。
强制删除
Kubernetes v1.32 [alpha]
(默认禁用:false)注意
如果强制删除的资源依赖于正常的删除流程,这可能会破坏与该资源相关联的工作负载,因此可能会产生集群破坏的后果。通过启用删除选项 ignoreStoreReadErrorWithClusterBreakingPotential
,用户可以对不可解密/损坏的资源执行不安全的强制 delete 操作。此选项位于 ALPHA 功能门之后,默认情况下处于禁用状态。为了使用此选项,集群操作员必须通过设置命令行选项 --feature-gates=AllowUnsafeMalformedObjectDeletion=true
来启用该功能。
注意
执行强制 delete 操作的用户必须具有对给定资源执行 delete 和 unsafe-delete-ignore-read-errors 动词的权限。如果由于 a) 转换错误(例如:解密失败)或 b) 对象无法解码而无法从存储中成功检索资源,则该资源被认为是损坏的。API 服务器首先尝试正常删除,如果删除失败并出现*损坏的资源*错误,则会触发强制删除。强制 delete 操作是不安全的,因为它会忽略终结器约束并跳过前提条件检查。
此选项的默认值为 false
,这保持了向后兼容性。对于将 ignoreStoreReadErrorWithClusterBreakingPotential
设置为 true
的 delete 请求,必须将字段 dryRun
、gracePeriodSeconds
、orphanDependents
、preconditions
和 propagationPolicy
保持未设置状态。
注意
如果用户在其他可读资源上发出将ignoreStoreReadErrorWithClusterBreakingPotential
设置为 true
的 delete 请求,则 API 服务器将中止该请求并返回错误。单个资源 API
Kubernetes API 动词 get、create、update、patch、delete 和 proxy 仅支持单个资源。这些支持单个资源的动词不支持在有序或无序列表或事务中一起提交多个资源。
当客户端(包括 kubectl)作用于一组资源时,客户端会发出一系列单资源 API 请求,然后根据需要聚合响应。
相比之下,Kubernetes API 动词 list 和 watch 允许获取多个资源,而 deletecollection 允许删除多个资源。
字段验证
Kubernetes 始终验证字段的类型。例如,如果 API 中的字段定义为数字,则不能将该字段设置为文本值。如果一个字段定义为字符串数组,则只能提供一个数组。某些字段允许您省略它们,其他字段是必需的。从 API 请求中省略必需的字段是错误的。
如果您发出包含额外字段的请求,即集群的控制平面无法识别的字段,则 API 服务器的行为会更加复杂。
默认情况下,API 服务器会删除它从接收到的输入中无法识别的字段(例如,PUT
请求的 JSON 正文)。
在两种情况下,API 服务器会删除您在 HTTP 请求中提供的字段。
这两种情况是
- 该字段无法识别,因为它不在资源的 OpenAPI 模式中。(一个例外是 CRD,它们明确选择不通过
x-kubernetes-preserve-unknown-fields
修剪未知字段)。 - 该字段在对象中重复。
对无法识别或重复字段的验证
Kubernetes v1.27 [稳定]
(默认启用:true)从 1.25 开始,当您使用可以提交数据的 HTTP 动词(POST
、PUT
和 PATCH
)时,服务器上的验证会检测对象中无法识别或重复的字段。可能的验证级别为 Ignore
、Warn
(默认)和 Strict
。
Ignore
- API 服务器成功处理该请求,就像没有设置错误字段一样,删除所有未知和重复的字段,并且不给出它已这样做的任何指示。
Warn
- (默认)API 服务器成功处理请求,并向客户端报告警告。警告通过
Warning:
响应头发送,为每个未知或重复的字段添加一个警告项。有关警告和 Kubernetes API 的更多信息,请参阅博客文章警告:前方有帮助性的警告。 严格
- 当 API 服务器检测到任何未知或重复字段时,它会拒绝请求并返回 400 Bad Request 错误。来自 API 服务器的响应消息会指定 API 服务器检测到的所有未知或重复字段。
字段验证级别由 fieldValidation
查询参数设置。
注意
如果您提交的请求指定了无法识别的字段,并且由于其他原因也无效(例如,请求为已知字段提供了字符串值,而 API 期望的是整数值),则 API 服务器会响应 400 Bad Request 错误,但不会提供有关未知或重复字段的任何信息(仅提供首先遇到的致命错误)。
在这种情况下,无论您请求的字段验证级别是什么,您始终会收到错误响应。
向服务器提交请求的工具(例如 kubectl
)可能会设置与 API 服务器默认使用的 Warn
验证级别不同的默认值。
kubectl
工具使用 --validate
标志来设置字段验证级别。它接受值 ignore
、warn
和 strict
,同时也接受值 true
(等同于 strict
)和 false
(等同于 ignore
)。kubectl 的默认验证设置为 --validate=true
,这意味着严格的服务器端字段验证。
当 kubectl 无法连接到具有字段验证的 API 服务器(Kubernetes 1.27 之前的 API 服务器)时,它将回退到使用客户端验证。客户端验证将在未来版本的 kubectl 中完全删除。
注意
在 Kubernetes 1.25 之前,kubectl --validate
用作布尔标志来切换客户端验证的开或关。模拟运行
Kubernetes v1.19 [稳定]
(默认启用:true)当您使用可以修改资源的 HTTP 动词(POST
、PUT
、PATCH
和 DELETE
)时,您可以在模拟运行模式下提交请求。模拟运行模式有助于通过典型的请求阶段(准入链、验证、合并冲突)评估请求,直到将对象持久化到存储。请求的响应正文尽可能接近非模拟运行的响应。Kubernetes 保证模拟运行请求不会持久化到存储中或产生任何其他副作用。
发出模拟运行请求
通过设置 dryRun
查询参数触发模拟运行。此参数是一个字符串,用作枚举,唯一接受的值是
- [未设置值]
- 允许副作用。您可以使用查询字符串(如
?dryRun
或?dryRun&pretty=true
)请求此操作。响应是最终将要持久化的对象,如果请求无法完成,则返回错误。 全部
- 每个阶段都正常运行,除了最后一个存储阶段,在该阶段会阻止副作用。
当您设置 ?dryRun=All
时,任何相关的准入控制器都会运行,验证准入控制器会在突变后检查请求,对 PATCH
执行合并,字段会设置为默认值,并进行模式验证。更改不会持久化到基础存储中,但最终将要持久化的对象仍然会返回给用户,同时也会返回正常的状态代码。
如果请求的非模拟运行版本会触发具有副作用的准入控制器,则请求将失败,而不是冒险产生不必要的副作用。所有内置的准入控制插件都支持模拟运行。此外,准入 Webhook 可以在其配置对象中声明它们没有副作用,方法是将它们的 sideEffects
字段设置为 None
。
注意
如果 Webhook 实际上确实有副作用,那么sideEffects
字段应设置为 "NoneOnDryRun"。只要 Webhook 也被修改为理解 AdmissionReview 中的 DryRun
字段,并防止对任何标记为模拟运行的请求产生副作用,该更改就是适当的。这是一个使用 ?dryRun=All
的模拟运行请求示例
POST /api/v1/namespaces/test/pods?dryRun=All
Content-Type: application/json
Accept: application/json
响应看起来与非模拟运行请求相同,但某些生成的字段的值可能不同。
生成的值
对象的某些值通常在对象持久化之前生成。重要的是不要依赖模拟运行请求设置的这些字段的值,因为这些值在模拟运行模式下可能与发出真实请求时不同。其中一些字段是
name
:如果设置了generateName
,则name
将具有唯一的随机名称creationTimestamp
/deletionTimestamp
:记录创建/删除的时间UID
:唯一标识对象并随机生成(不确定性)resourceVersion
:跟踪对象的持久化版本- 任何由突变准入控制器设置的字段
- 对于
Service
资源:kube-apiserver 分配给 Service 对象的端口或 IP 地址
模拟运行授权
模拟运行和非模拟运行请求的授权是相同的。因此,要发出模拟运行请求,您必须获得执行非模拟运行请求的授权。
例如,要为 Deployment 运行模拟运行 patch,您必须获得执行该 patch 的授权。这是一个 Kubernetes RBAC 规则的示例,该规则允许修补 Deployment
rules:
- apiGroups: ["apps"]
resources: ["deployments"]
verbs: ["patch"]
请参阅授权概述。
更新现有资源
Kubernetes 提供了几种更新现有对象的方法。您可以阅读选择更新机制,了解哪种方法最适合您的用例。
您可以使用 HTTP PUT 覆盖(更新)现有资源(例如 ConfigMap)。对于 PUT 请求,客户端有责任指定 resourceVersion
(从正在更新的对象中获取)。Kubernetes 使用该 resourceVersion
信息,以便 API 服务器可以检测到丢失的更新,并拒绝由与集群不同步的客户端发出的请求。如果资源已更改(客户端提供的 resourceVersion
已过时),则 API 服务器会返回 409 Conflict
错误响应。
客户端可以发送指令到 API 服务器来 patch 现有资源,而不是发送 PUT 请求。如果客户端想要进行的更改不是以现有数据为条件,则 patch 通常是合适的。需要有效检测丢失更新的客户端应考虑使其请求以现有 resourceVersion
为条件(HTTP PUT 或 HTTP PATCH),然后处理在发生冲突时需要的任何重试。
Kubernetes API 支持四种不同的 PATCH 操作,由它们相应的 HTTP Content-Type
标头确定
application/apply-patch+yaml
- 服务器端应用 YAML(一种基于 YAML 的 Kubernetes 特定扩展)。所有 JSON 文档都是有效的 YAML,因此您也可以使用此媒体类型提交 JSON。有关更多详细信息,请参阅服务器端应用序列化。
对于 Kubernetes,如果对象不存在,这是一个 create 操作;如果对象已存在,这是一个 patch 操作。 application/json-patch+json
- JSON Patch,在 RFC6902 中定义。JSON patch 是在资源上执行的操作序列;例如
{"op": "add", "path": "/a/b/c", "value": [ "foo", "bar" ]}
。
对于 Kubernetes,这是一个 patch 操作。使用
application/json-patch+json
的 patch 可以包括验证一致性的条件,如果未满足这些条件,则操作将失败(例如,避免丢失更新)。 application/merge-patch+json
- JSON Merge Patch,在 RFC7386 中定义。JSON Merge Patch 本质上是资源的局部表示。提交的 JSON 与当前资源组合以创建一个新资源,然后保存新资源。
对于 Kubernetes,这是一个 patch 操作。 application/strategic-merge-patch+json
- 策略性合并补丁(一种基于 JSON 的 Kubernetes 特定扩展)。策略性合并补丁是 JSON 合并补丁的自定义实现。您只能将策略性合并补丁用于内置 API,或具有特殊支持它的聚合 API 服务器。您不能将
application/strategic-merge-patch+json
与使用 CustomResourceDefinition 定义的任何 API 一起使用。注意
Kubernetes 的服务器端应用机制已取代策略性合并补丁。
Kubernetes 的服务器端应用功能允许控制平面跟踪新创建对象的托管字段。服务器端应用为管理字段冲突提供了一个清晰的模式,提供了服务器端 apply 和 update 操作,并取代了 kubectl apply
的客户端功能。
对于服务器端应用,如果对象尚不存在,则 Kubernetes 将请求视为 create,否则视为 patch。对于其他在 HTTP 级别使用 PATCH 的请求,逻辑 Kubernetes 操作始终是 patch。
有关更多详细信息,请参阅服务器端应用。
选择更新机制
HTTP PUT 替换现有资源
更新 (HTTP PUT
) 操作易于实现且灵活,但也有缺点
- 您需要处理对象在客户端读取它和尝试将其写回之间
resourceVersion
发生更改时出现的冲突。Kubernetes 始终会检测到冲突,但作为客户端作者,您需要实现重试。 - 如果您在本地解码对象(例如,使用 client-go,您可能会收到客户端不知道如何处理的字段 - 然后在更新过程中删除它们),您可能会意外地删除字段。
- 如果对象上有很多争用(即使在您不尝试编辑的字段或字段集上),您可能难以发送更新。对于较大的对象和具有许多字段的对象,问题会更严重。
HTTP PATCH 使用 JSON Patch
patch 更新很有帮助,因为
- 由于您只发送差异,因此在
PATCH
请求中发送的数据更少。 - 您可以进行依赖现有值的更改,例如将特定字段的值复制到注释中。
- 与更新(HTTP
PUT
)不同,即使不相关的字段频繁更改,你的更改也可以立即生效:你通常不需要重试。- 如果你想格外小心以避免更新丢失,你可能仍然需要指定
resourceVersion
(以匹配现有对象) - 为了防止出错,编写一些重试逻辑仍然是一个好习惯。
- 如果你想格外小心以避免更新丢失,你可能仍然需要指定
- 你可以使用测试条件来精心设计特定的更新条件。例如,如果现有值与你期望的值匹配,你可以在不读取它的情况下递增一个计数器。即使自你上次写入以来对象以其他方式发生了更改,你也可以这样做,而不会有更新丢失的风险。(如果测试条件失败,你可以回退到读取当前值,然后再写回更改后的数字)。
然而
- 你需要更多的本地(客户端)逻辑来构建补丁;如果你有一个 JSON Patch 的库实现,甚至专门针对 Kubernetes 创建 JSON Patch,这将有很大的帮助。
- 作为客户端软件的作者,你在构建补丁(HTTP 请求体)时需要小心,不要丢弃字段(操作顺序很重要)。
使用服务器端应用的 HTTP PATCH
服务器端应用有一些明显的优势
- 一次往返:它很少需要先发出
GET
请求。- 你仍然可以检测到意外更改的冲突
- 如果合适,你可以选择强制覆盖冲突
- 客户端实现很容易创建。
- 你可以获得一个原子创建或更新操作,而无需额外的努力(类似于某些 SQL 方言中的
UPSERT
)。
然而
- 服务器端应用完全不适用于依赖于对象当前值的字段更改。
- 你只能对对象应用更新。Kubernetes HTTP API 中的某些资源不是对象(它们没有
.metadata
字段),服务器端应用仅与 Kubernetes 对象相关。
资源版本
资源版本是标识服务器内部对象版本的字符串。客户端可以使用资源版本来确定对象何时发生了更改,或者在获取、列出和监视资源时表达数据一致性要求。客户端必须将资源版本视为不透明的,并将它们原封不动地传递回服务器。
你不能假设资源版本是数字或可排序的。API 客户端只能比较两个资源版本是否相等(这意味着你不能比较资源版本的大小关系)。
metadata 中的 resourceVersion
字段
客户端可以在资源中找到资源版本,包括来自watch的响应流中的资源,或者在使用list枚举资源时找到。
v1.meta/ObjectMeta - 资源实例的 metadata.resourceVersion
标识该实例上次修改时的资源版本。
v1.meta/ListMeta - 资源集合(对 list 的响应)的 metadata.resourceVersion
标识构造该集合时的资源版本。
查询字符串中的 resourceVersion
参数
get、list 和 watch 操作都支持 resourceVersion
参数。从 v1.19 版本开始,Kubernetes API 服务器还支持 list 请求中的 resourceVersionMatch
参数。
API 服务器根据你请求的操作以及 resourceVersion
的值以不同的方式解释 resourceVersion
参数。如果你设置了 resourceVersionMatch
,那么这也会影响匹配的发生方式。
get 和 list 的语义
对于 get 和 list,resourceVersion
的语义是
get
resourceVersion 未设置 | resourceVersion="0" | resourceVersion="{0 以外的值}" |
---|---|---|
最新 | 任意 | 不早于 |
list
从 v1.19 版本开始,Kubernetes API 服务器支持 list 请求中的 resourceVersionMatch
参数。如果同时设置了 resourceVersion
和 resourceVersionMatch
,则 resourceVersionMatch
参数将确定 API 服务器如何解释 resourceVersion
。
在 list 请求中设置 resourceVersion
时,你应始终设置 resourceVersionMatch
参数。但是,请准备好处理响应的 API 服务器不知道 resourceVersionMatch
并忽略它的情况。
除非你具有强一致性要求,否则使用 resourceVersionMatch=NotOlderThan
和已知的 resourceVersion
是首选,因为它可以比不设置 resourceVersion
和 resourceVersionMatch
更好地实现群集的性能和可伸缩性,后者需要提供仲裁读取。
在不设置 resourceVersion
的情况下设置 resourceVersionMatch
参数是无效的。
下表说明了具有各种 resourceVersion
和 resourceVersionMatch
组合的 list 请求的行为
resourceVersionMatch 参数 | 分页参数 | resourceVersion 未设置 | resourceVersion="0" | resourceVersion="{0 以外的值}" |
---|---|---|---|---|
未设置 | limit 未设置 | 最新 | 任意 | 不早于 |
未设置 | limit=<n>,continue 未设置 | 最新 | 任意 | 精确 |
未设置 | limit=<n>,continue=<token> | 继续令牌,精确 | 无效,视为继续令牌,精确 | 无效,HTTP 400 Bad Request |
resourceVersionMatch=Exact | limit 未设置 | 无效 | 无效 | 精确 |
resourceVersionMatch=Exact | limit=<n>,continue 未设置 | 无效 | 无效 | 精确 |
resourceVersionMatch=NotOlderThan | limit 未设置 | 无效 | 任意 | 不早于 |
resourceVersionMatch=NotOlderThan | limit=<n>,continue 未设置 | 无效 | 任意 | 不早于 |
注意
如果你的群集的 API 服务器不遵守resourceVersionMatch
参数,则其行为与你未设置该参数时的行为相同。get 和 list 语义的含义是
- 任意
- 返回任何资源版本的数据。首选最新的可用资源版本,但不需要强一致性;可以提供任何资源版本的数据。由于分区或过时的缓存,请求可能会返回比客户端先前观察到的旧得多的资源版本的数据,尤其是在高可用性配置中。无法容忍这种情况的客户端不应使用此语义。
- 最新
- 返回最新资源版本的数据。返回的数据必须是一致的(详细地说:通过仲裁读取从 etcd 提供)。对于 etcd v3.4.31+ 和 v3.5.13+,Kubernetes 1.32 从观察缓存提供“最新”读取:API 服务器内部的内存存储,用于缓存和镜像持久化到 etcd 中的数据状态。Kubernetes 请求进度通知以维持缓存与 etcd 持久化层的一致性。Kubernetes 版本 v1.28 到 v1.30 也支持此功能,尽管作为 Alpha 版,不建议用于生产,直到 v1.31 版本才默认启用。
- 不早于
- 返回至少与提供的
resourceVersion
一样新的数据。首选最新的可用数据,但可以提供不早于提供的resourceVersion
的任何数据。对于向遵守resourceVersionMatch
参数的服务器发出的 list 请求,这保证了集合的.metadata.resourceVersion
不早于请求的resourceVersion
,但不保证该集合中任何项的.metadata.resourceVersion
。 - 精确
- 返回提供的确切资源版本的数据。如果提供的
resourceVersion
不可用,则服务器会以 HTTP 410 "Gone" 响应。对于向遵守resourceVersionMatch
参数的服务器发出的 list 请求,这保证了集合的.metadata.resourceVersion
与你在查询字符串中请求的resourceVersion
相同。该保证不适用于该集合中任何项的.metadata.resourceVersion
。 - 继续令牌,精确
- 返回初始分页 list 调用的资源版本的数据。返回的继续令牌负责跟踪所有分页 list 调用在初始分页 list 之后最初提供的资源版本。
注意
当你 list 资源并接收到集合响应时,响应包括集合的列表元数据以及该集合中每个项的对象元数据。对于在集合响应中找到的单个对象,.metadata.resourceVersion
跟踪该对象上次更新的时间,而不是该对象在提供服务时的最新程度。当使用 resourceVersionMatch=NotOlderThan
并且设置了 limit 时,客户端必须处理 HTTP 410 "Gone" 响应。例如,客户端可能会使用较新的 resourceVersion
重试,或者回退到 resourceVersion=""
。
当使用 resourceVersionMatch=Exact
并且 limit
未设置时,客户端必须验证集合的 .metadata.resourceVersion
是否与请求的 resourceVersion
匹配,并处理不匹配的情况。例如,客户端可能会回退到设置了 limit
的请求。
watch 的语义
对于 watch,资源版本的语义是
watch
resourceVersion 未设置 | resourceVersion="0" | resourceVersion="{0 以外的值}" |
---|---|---|
获取状态并从最新开始 | 获取状态并从任意开始 | 从精确开始 |
这些 watch 语义的含义是
- 获取状态并从任意开始
- 在任何资源版本开始 watch;首选最新的可用资源版本,但不是必需的。允许任何起始资源版本。由于分区或过时的缓存,watch 可能会从客户端先前观察到的旧得多的资源版本开始,尤其是在高可用性配置中。无法容忍这种明显回溯的客户端不应使用此语义启动 watch。要建立初始状态,watch 从在起始资源版本处存在的所有资源实例的合成“已添加”事件开始。所有后续的观察事件都是在 watch 开始的资源版本之后发生的所有更改。
注意
以此方式初始化的观察可能会返回任意过时的数据。请在使用前检查此语义,并尽可能支持其他语义。 - 获取状态并从最新开始
- 在最新的资源版本开始 watch,该版本必须是一致的(详细地说:通过仲裁读取从 etcd 提供)。要建立初始状态,watch 从在起始资源版本处存在的所有资源实例的合成“已添加”事件开始。所有后续的观察事件都是在 watch 开始的资源版本之后发生的所有更改。
- 从精确开始
- 在确切的资源版本开始 watch。观察事件是在提供的资源版本之后发生的所有更改。与“获取状态并从最新开始”和“获取状态并从任意开始”不同,watch 不会从提供的资源版本的合成“已添加”事件开始。假设客户端已具有起始资源版本的初始状态,因为客户端提供了该资源版本。
"410 Gone" 响应
服务器不需要提供所有较旧的资源版本,如果客户端请求的 resourceVersion
比服务器保留的旧,则可能会返回 HTTP 410 (Gone)
状态代码。客户端必须能够容忍 410 (Gone)
响应。有关在监视资源时如何处理 410 (Gone)
响应的详细信息,请参阅高效检测更改。
如果请求超出适用限制的 resourceVersion
,那么根据请求是否从缓存提供,API 服务器可能会回复 410 Gone
HTTP 响应。
不可用的资源版本
服务器不需要提供无法识别的资源版本。如果请求 list 或 get 的资源版本是 API 服务器无法识别的,那么 API 服务器可能会
- 短暂等待资源版本变为可用,如果提供的资源版本在合理的时间内未变为可用,则超时并返回
504 (Gateway Timeout)
; - 使用
Retry-After
响应头进行响应,指示客户端在重试请求之前应等待多少秒。
如果您请求的资源版本 API 服务器无法识别,kube-apiserver 还会使用“资源版本过大”的消息来标识其错误响应。
如果您对无法识别的资源版本发出 watch 请求,API 服务器可能会无限期地等待(直到请求超时)该资源版本变为可用。