Kubernetes API 概念
Kubernetes API 是一種透過 HTTP 提供的基於資源的(RESTful)程式設計介面。它支援透過標準的 HTTP 動詞(POST、PUT、PATCH、DELETE、GET)來檢索、建立、更新和刪除主要資源。
對於某些資源,API 包含額外的子資源,允許細粒度的授權(例如,Pod 詳情和日誌檢索的單獨檢視),並且可以接受和提供不同表示形式的這些資源,以方便或提高效率。
Kubernetes 透過 _watch_ 支援對資源進行高效的變更通知。
在 Kubernetes API 中,watch 是一個動詞,用於以流的形式跟蹤 Kubernetes 中物件的變更。它用於高效地檢測變更。
Kubernetes 還提供一致的列表操作,以便 API 客戶端可以有效地快取、跟蹤和同步資源的狀態。你可以線上檢視API 參考,或者繼續閱讀以瞭解 API 的一般資訊。
Kubernetes API 術語
Kubernetes 通常利用常見的 RESTful 術語來描述 API 概念。
- _資源型別_ 是 URL 中使用的名稱(`pods`、`namespaces`、`services`)。
- 所有資源型別都有一個具體的表示(它們的物件模式),稱為 _kind_。
- 資源型別的例項列表稱為 _集合_。
- 資源型別的單個例項稱為 _資源_,通常也表示一個 _物件_。
- 對於某些資源型別,API 包含一個或多個 _子資源_,它們表示為資源下的 URI 路徑。
大多數 Kubernetes API 資源型別都是物件——它們表示叢集上概念的具體例項,如 Pod 或 Namespace。少數 API 資源型別是_虛擬的_,因為它們通常表示對物件的操作,而不是物件本身,例如許可權檢查(使用 POST 和 JSON 編碼的 `SubjectAccessReview` 主體到 `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、YAML、CBOR 和 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 和 Protobuf 編碼,Kubernetes 實現了自定義編碼器,逐項寫入。此功能不會改變輸出,但允許 API 伺服器避免將整個 LIST 響應載入到記憶體中。對於大型資源集合(>100MB),應避免使用其他型別的編碼(包括 JSON 的美觀表示),因為它可能對效能產生負面影響。
JSON 資源編碼
Kubernetes API 預設使用 JSON 對 HTTP 訊息體進行編碼。
例如
列出叢集上的所有 Pod,不指定首選格式。
GET /api/v1/pods200 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 object200 OK Content-Type: application/json { "kind": "Pod", "apiVersion": "v1", … }
YAML 資源編碼
Kubernetes 還支援 `application/yaml` 媒體型別,用於請求和響應。`YAML` 可用於定義 Kubernetes 清單和 API 互動。
例如
以 YAML 格式列出叢集上的所有 Pod。
GET /api/v1/pods Accept: application/yaml200 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 object200 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.protobuf200 OK Content-Type: application/vnd.kubernetes.protobuf … binary 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 object200 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] (預設停用)啟用 `CBORServingAndStorage` 功能門後,所有內建資源型別以及透過CustomResourceDefinition 定義的所有資源的請求和響應主體都可以編碼為 CBOR 二進位制資料格式。如果在各個聚合 API 伺服器中啟用了 CBOR,聚合層也支援 CBOR。
當請求體包含單個 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 事件。
除了用於 YAML 編碼的伺服器端應用配置的現有 `application/apply-patch+yaml` 媒體型別外,啟用 CBOR 的 API 伺服器還將接受用於 CBOR 編碼的伺服器端應用配置的 `application/apply-patch+cbor` 媒體型別。沒有支援的 CBOR 等效項用於 `application/json-patch+json` 或 `application/merge-patch+json`,或 `application/strategic-merge-patch+json`。
高效的變更檢測
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**-然後-**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.34 [beta] (預設啟用:true)在大型叢集上,檢索某些資源型別的集合可能會導致控制平面上的資源使用量(主要是 RAM)顯著增加。為了減輕這種影響並簡化 **list** + **watch** 模式的使用者體驗,Kubernetes v1.32 將允許請求初始狀態(以前透過 **list** 請求請求)作為 **watch** 請求的一部分的功能提升為 beta 版。
在客戶端,可以透過在 **watch** 請求中將 `sendInitialEvents=true` 指定為查詢字串引數來請求初始狀態。如果設定,API 伺服器將啟動 watch 流,其中包含合成的初始事件(型別為 `ADDED`),以構建所有現有物件的完整狀態,然後是`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 伺服器傳送 **get** 或 **list** 請求,並帶上 `Accept-Encoding` 頭,然後檢查響應大小和頭。例如:
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` 引數。
例如,如果叢集上有 1253 個 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 的一致快照。版本 `10245` 之後建立、更新或刪除的 Pod 將不會顯示,除非你發出不帶 `continue` 令牌的單獨 **list** 請求。這允許你將大型請求分解為較小的塊,然後對完整集合執行 **watch** 操作而不會錯過任何更新。
remainingItemCount 是此響應中未包含的集合中後續專案的數量。如果 **list** 請求包含標籤或欄位選擇器,則剩餘專案的數量未知,API 伺服器不會在其響應中包含 `remainingItemCount` 欄位。如果 **list** 完成(無論是由於未分塊,還是因為這是最後一個塊),則沒有更多剩餘專案,API 伺服器不會在其響應中包含 `remainingItemCount` 欄位。`remainingItemCount` 的預期用途是估計集合的大小。
集合
在 Kubernetes 術語中,你從 **list** 得到的響應是一個_集合_。然而,Kubernetes 為不同型別資源的集合定義了具體的 kind。集合的 kind 名稱是資源 kind,後跟 `List`。
當你查詢 API 某個特定型別時,該查詢返回的所有項都屬於該型別。例如,當你 **list** Services 時,集合響應的 `kind` 設定為 `ServiceList`;該集合中的每個項都代表一個 Service。例如:
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 內容型別協商:在 `GET` 呼叫中傳遞包含 `application/json;as=Table;g=meta.k8s.io;v=v1` 值的 `Accept` 頭將請求伺服器以 Table 內容型別返回物件。
例如,以表格格式列出叢集上的所有 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": [
...
]
}
對於控制平面未知的沒有自定義 Table 定義的 API 資源型別,API 伺服器會返回一個預設的 Table 響應,其中包含資源的 `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 資源型別都支援 Table 響應;例如,CustomResourceDefinitions 可能沒有定義欄位到表格的對映,並且擴充套件核心 Kubernetes API 的 APIService 可能根本不提供 Table 響應。如果你正在實現一個使用 Table 資訊並必須處理所有資源型別(包括擴充套件)的客戶端,你應發出在 `Accept` 頭中指定多種內容型別的請求。例如:
Accept: application/json;as=Table;g=meta.k8s.io;v=v1, application/json
資源刪除
當你**刪除**資源時,這會分兩個階段進行。
- 終結化
- 刪除
{
"kind": "ConfigMap",
"apiVersion": "v1",
"metadata": {
"finalizers": ["url.io/neat-finalization", "other-url.io/my-finalizer"],
"deletionTimestamp": nil,
}
}
當客戶端首次傳送 **delete** 請求刪除資源時,`.metadata.deletionTimestamp` 被設定為當前時間。一旦 `.metadata.deletionTimestamp` 被設定,作用於 Finalizer 的外部控制器就可以隨時以任何順序開始執行它們的清理工作。
Finalizer 之間不強制執行順序,因為這會帶來 `.metadata.finalizers` 陷入停滯的重大風險。
`.metadata.finalizers` 欄位是共享的:任何有許可權的參與者都可以對其重新排序。如果 Finalizer 列表按順序處理,那麼這可能導致以下情況:列表中第一個 Finalizer 負責的元件正在等待由列表中較晚 Finalizer 負責的元件產生的一些訊號(欄位值、外部系統或其他),從而導致死鎖。
在不強制排序的情況下,Finalizer 可以自由地自行排序,並且不受列表中排序變更的影響。
一旦最後一個 Finalizer 被移除,資源實際上就會從 etcd 中移除。
強制刪除
Kubernetes v1.32 [alpha] (預設停用)注意
如果被強制刪除的資源依賴於正常的刪除流程,這可能會破壞與之關聯的工作負載,因此可能會產生破壞叢集的後果。透過啟用刪除選項 `ignoreStoreReadErrorWithClusterBreakingPotential`,使用者可以對不可解密/損壞的資源執行不安全的強制 **delete** 操作。此選項在 ALPHA 功能門後,預設停用。為了使用此選項,叢集操作員必須透過設定命令列選項 `--feature-gates=AllowUnsafeMalformedObjectDeletion=true` 來啟用該功能。
注意
執行強制 **delete** 操作的使用者必須具有對給定資源執行 **delete** 和 **unsafe-delete-ignore-read-errors** 動詞的許可權。如果資源因以下原因無法從儲存中成功檢索,則被視為損壞:
- 轉換錯誤(例如:解密失敗),或
- 物件解碼失敗。
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 [stable](預設啟用:true)從 1.25 版本開始,當您使用可以提交資料的 HTTP 動詞(`POST`、`PUT` 和 `PATCH`)時,伺服器透過驗證檢測物件中無法識別或重複的欄位。驗證級別可能為 `Ignore`、`Warn`(預設)和 `Strict`。
忽略- API 伺服器成功處理請求,就像沒有設定錯誤欄位一樣,刪除所有未知和重複欄位,並且不給出任何指示。
警告- (預設)API 伺服器成功處理請求,並向客戶端報告警告。警告透過 `Warning:` 響應頭髮送,每個未知或重複欄位新增一個警告項。有關警告和 Kubernetes API 的更多資訊,請參閱部落格文章警告:前方有用警告。
嚴格- 當 API 伺服器檢測到任何未知或重複欄位時,它會以 400 Bad Request 錯誤拒絕請求。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` 用作布林標誌來開啟或關閉客戶端驗證。從 v1.33 開始,Kubernetes(包括 v1.34)提供了一種使用_宣告式標籤_定義欄位驗證的方法。這對於 Kubernetes 本身的貢獻者很有用,如果你正在使用 Kubernetes 庫編寫自己的 API,這也相關。要了解更多資訊,請參閱宣告式 API 驗證。
試執行
Kubernetes v1.19 [stable](預設啟用: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 伺服器來**修補**現有資源,而不是傳送 PUT 請求。如果客戶端想要進行的更改不依賴於現有資料,則**修補**通常是合適的。需要有效檢測丟失更新的客戶端應考慮使其請求以現有 `resourceVersion` 為條件(無論是 HTTP PUT 還是 HTTP PATCH),然後處理在發生衝突時所需的任何重試。
Kubernetes API 支援四種不同的 PATCH 操作,由其相應的 HTTP `Content-Type` 標頭決定:
application/apply-patch+yaml- 伺服器端應用 YAML(Kubernetes 特定的擴充套件,基於 YAML)。所有 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 合併補丁,定義在 RFC7386 中。JSON 合併補丁本質上是資源的部分表示。提交的 JSON 與當前資源合併以建立一個新資源,然後儲存新資源。對於 Kubernetes,這是一個 **patch** 操作。
application/strategic-merge-patch+json- 戰略合併補丁(Kubernetes 特定的基於 JSON 的擴充套件)。戰略合併補丁是 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,你可能會收到客戶端不知道如何處理的欄位,然後在更新時將其丟棄)。
- 如果物件上存在大量爭用(即使在您未嘗試編輯的欄位或一組欄位上),您可能會難以傳送更新。對於更大的物件和具有許多欄位的物件,問題會更嚴重。
使用 JSON Patch 的 HTTP PATCH
**補丁**更新很有幫助,因為:
- 由於你只發送差異,因此 `PATCH` 請求中要傳送的資料量更少。
- 你可以進行依賴現有值的更改,例如將特定欄位的值複製到註解中。
- 與 **更新** (HTTP `PUT`) 不同,即使無關欄位頻繁更改,你的更改也可以立即發生:你通常不需要重試。
- 如果你想額外小心以避免丟失更新,你可能仍然需要指定 `resourceVersion`(以匹配現有物件)。
- 在出現錯誤時編寫一些重試邏輯仍然是良好的實踐。
- 你可以使用測試條件精心設計特定的更新條件。例如,如果現有值與你期望的匹配,你可以在不讀取它的情況下遞增計數器。即使物件自上次寫入以來已以其他方式更改,你也可以這樣做,而不會丟失更新風險。(如果測試條件失敗,你可以回退到讀取當前值,然後寫回更改後的數字)。
然而,
- 你需要更多的本地(客戶端)邏輯來構建補丁;如果你有 JSON Patch 的庫實現,甚至專門針對 Kubernetes 製作 JSON Patch 的庫,將大有幫助。
- 作為客戶端軟體的作者,在構建補丁(HTTP 請求體)時,你需要小心不要丟失欄位(操作順序很重要)。
使用伺服器端應用的 HTTP PATCH
伺服器端應用有一些明顯的優勢:
- 單次往返:很少需要先發出 `GET` 請求。
- 你仍然可以檢測意外更改的衝突。
- 如果合適,你可以選擇強制覆蓋衝突。
- 客戶端實現很容易。
- 您可以輕鬆獲得原子性的建立或更新操作(類似於某些 SQL 方言中的
UPSERT)。
然而,
- Server-Side Apply 完全不適用於依賴物件當前值的欄位更改。
- 您只能對物件應用更新。Kubernetes HTTP API 中的某些資源不是物件(它們沒有
.metadata欄位),Server-Side Apply 僅與 Kubernetes 物件相關。
資源版本
資源版本是標識伺服器內部物件版本的字串。客戶端可以使用資源版本來確定物件何時發生更改,或者在獲取、列出和監視資源時表達資料一致性要求。客戶端必須將資源版本視為不透明,並將其未修改地傳回伺服器。
您不得假定資源版本是數字或可排序的。API 客戶端只能比較兩個資源版本的相等性(這意味著您不得比較資源版本的“大於”或“小於”關係)。
元資料中的 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 引數是無效的。
此表解釋了 list 請求在 resourceVersion 和 resourceVersionMatch 各種組合下的行為
| 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 語義的含義是
- 任意
- 返回任意資源版本的資料。首選最新的可用資源版本,但不需要強一致性;可以提供任意資源版本的資料。請求可能會返回比客戶端之前觀察到的舊得多的資源版本的資料,特別是在高可用性配置中,由於分割槽或陳舊快取。不能容忍這種情況的客戶端不應使用此語義。始終從 watch cache 提供服務,提高效能並減少 etcd 負載。
- 最新
- 返回最新資源版本的資料。返回的資料必須一致(具體來說:透過仲裁讀取從 etcd 提供)。對於 etcd v3.4.31+ 和 v3.5.13+,Kubernetes 1.34 從 watch cache 提供“最新”讀取服務:API 伺服器內部的記憶體儲存,用於快取和映象持久化到 etcd 中的資料狀態。Kubernetes 請求進度通知以維護快取與 etcd 持久層的最新一致性。Kubernetes v1.28 到 v1.30 也支援此功能,儘管作為 Alpha 版不建議用於生產環境,直到 v1.31 版本才預設啟用。
- 不早於
- 返回至少與提供的
resourceVersion一樣新的資料。首選最新的可用資料,但可以提供不早於提供的resourceVersion的任何資料。對於遵守resourceVersionMatch引數的伺服器的 list 請求,這保證了集合的.metadata.resourceVersion不早於請求的resourceVersion,但不對該集合中任何專案的.metadata.resourceVersion做任何保證。始終從 watch cache 提供服務,提高效能並減少 etcd 負載。 - 精確
- 返回提供的精確資源版本的資料。如果提供的
resourceVersion不可用,伺服器將響應 HTTP410 Gone。對於遵守resourceVersionMatch引數的伺服器的 list 請求,這保證了集合的.metadata.resourceVersion與您在查詢字串中請求的resourceVersion相同。該保證不適用於該集合中任何專案的.metadata.resourceVersion。在預設啟用ListFromCacheSnapshot功能門的情況下,API 伺服器將嘗試從快照提供響應,如果有一個resourceVersion早於請求的快照可用。這提高了效能並減少了 etcd 負載。API 伺服器開始時沒有快照,在每次 watch 事件時建立新快照,並保留它們直到檢測到 etcd 已壓縮或快取已滿(事件早於 75 秒)。如果提供的resourceVersion不可用,伺服器將回退到 etcd。 - 繼續
- 返回分頁列表請求的下一頁資料,確保與序列中初始請求建立的精確
resourceVersion一致。對帶有 limit 的 list 請求的響應包括 continue token,它編碼了resourceVersion和上次觀察到的位置,以便從中恢復列表。如果提供的 continue token 中的resourceVersion不可用,伺服器將響應 HTTP410 Gone。在預設啟用ListFromCacheSnapshot功能門的情況下,API 伺服器將嘗試從快照提供響應,如果有一個resourceVersion早於請求的快照可用。這提高了效能並減少了 etcd 負載。API 伺服器開始時沒有快照,在每次 watch 事件時建立新快照,並保留它們直到檢測到 etcd 已壓縮或快取已滿(事件早於 75 秒)。如果提供的 continue token 中的resourceVersion不可用,伺服器將回退到 etcd。
注意
當您 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 以起始資源版本存在的所有資源例項的合成“Added”事件開始。所有後續的 watch 事件都是在 watch 開始的資源版本之後發生的所有更改。
注意
以這種方式初始化的 watches 可能會返回任意陳舊的資料。在使用它之前請仔細審查此語義,並儘可能優先使用其他語義。 - 獲取狀態並從最新開始
- 從最新資源版本開始 watch,該版本必須一致(具體來說:透過仲裁讀取從 etcd 提供)。為了建立初始狀態,watch 以起始資源版本存在的所有資源例項的合成“Added”事件開始。所有後續的 watch 事件都是在 watch 開始的資源版本之後發生的所有更改。
- 從精確版本開始
- 從精確資源版本開始 watch。watch 事件是提供的資源版本之後的所有更改。與“獲取狀態並從最新開始”和“獲取狀態並從任意開始”不同,watch 不會以提供的資源版本的合成“Added”事件開始。假定客戶端已經具有起始資源版本的初始狀態,因為客戶端提供了資源版本。
“410 Gone”響應
伺服器不需要提供所有較舊的資源版本,如果客戶端請求的 resourceVersion 比伺服器保留的舊,則可能會返回 HTTP 410 (Gone) 狀態碼。客戶端必須能夠容忍 410 (Gone) 響應。有關在監視資源時如何處理 410 (Gone) 響應的詳細資訊,請參閱高效檢測更改。
如果您請求超出適用限制的 resourceVersion,那麼根據請求是否從快取提供,API 伺服器可能會回覆 410 Gone HTTP 響應。
不可用的資源版本
伺服器不需要提供無法識別的資源版本。如果您請求 list 或 get 無法識別的資源版本,則 API 伺服器可能會
- 短暫等待資源版本變得可用,如果提供的資源版本在合理的時間內未變得可用,則超時並返回
504 (Gateway Timeout); - 使用
Retry-After響應頭回復,指示客戶端在重試請求之前應等待多少秒。
如果您請求 API 伺服器無法識別的資源版本,kube-apiserver 還會用訊息 Too large resource version 標識其錯誤響應。
如果您請求無法識別的資源版本的 watch 請求,API 伺服器可能會無限期地等待(直到請求超時)資源版本變得可用。