CustomResourceDefinition 中的版本
本頁說明如何將版本資訊新增至 CustomResourceDefinitions,以指出 CustomResourceDefinitions 的穩定性層級,或使用 API 表示之間的轉換將您的 API 進階到新版本。它也說明如何將物件從一個版本升級到另一個版本。
開始之前
您需要有一個 Kubernetes 叢集,並且必須設定 kubectl 命令列工具以與您的叢集通訊。建議在至少有兩個節點且未充當控制平面主機的叢集上執行本教學課程。如果您還沒有叢集,可以使用 minikube 建立一個,或者您可以使用這些 Kubernetes playground 之一
您應該初步了解自訂資源。
您的 Kubernetes 伺服器必須是 v1.16 或更新版本。若要檢查版本,請輸入kubectl version
。概觀
CustomResourceDefinition API 提供了一個工作流程,用於引入和升級到 CustomResourceDefinition 的新版本。
建立 CustomResourceDefinition 時,第一個版本會在 CustomResourceDefinition spec.versions
清單中設定為適當的穩定性層級和版本號碼。例如,v1beta1
表示第一個版本尚未穩定。所有自訂資源物件最初都會儲存在此版本。
建立 CustomResourceDefinition 後,用戶端可以開始使用 v1beta1
API。
稍後可能需要新增新版本,例如 v1
。
新增新版本
- 選擇轉換策略。由於自訂資源物件需要能夠在兩個版本中提供服務,這表示它們有時會以與儲存版本不同的版本提供服務。為了實現這一點,自訂資源物件有時必須在它們儲存的版本和它們服務的版本之間進行轉換。如果轉換涉及結構描述變更並需要自訂邏輯,則應使用轉換 Webhook。如果沒有結構描述變更,則可以使用預設的
None
轉換策略,並且在服務不同版本時只會修改apiVersion
欄位。 - 如果使用轉換 Webhook,請建立和部署轉換 Webhook。請參閱 Webhook 轉換 以取得更多詳細資訊。
- 更新 CustomResourceDefinition 以在
spec.versions
清單中包含新版本,並設定served:true
。此外,將spec.conversion
欄位設定為選定的轉換策略。如果使用轉換 Webhook,請設定spec.conversion.webhookClientConfig
欄位以呼叫 Webhook。
新增新版本後,用戶端可以逐步遷移到新版本。某些用戶端使用舊版本,而其他用戶端使用新版本是完全安全的。
將儲存的物件遷移到新版本
- 請參閱將現有物件升級到新的儲存版本章節。
在將物件升級到新的儲存版本之前、期間和之後,用戶端使用舊版本和新版本都是安全的。
移除舊版本
- 確保所有用戶端都已完全遷移到新版本。可以審閱 kube-apiserver 日誌,以協助識別任何仍透過舊版本存取的用戶端。
- 在
spec.versions
清單中,將舊版本的served
設定為false
。如果任何用戶端仍意外地使用舊版本,它們可能會開始報告嘗試以舊版本存取自訂資源物件的錯誤。如果發生這種情況,請切換回在舊版本上使用served:true
,將剩餘的用戶端遷移到新版本,然後重複此步驟。 - 確保已完成將現有物件升級到新的儲存版本步驟。
- 驗證在 CustomResourceDefinition 中,新版本的
storage
是否已設定為true
。 - 驗證舊版本不再列在 CustomResourceDefinition
status.storedVersions
中。
- 驗證在 CustomResourceDefinition 中,新版本的
- 從 CustomResourceDefinition
spec.versions
清單中移除舊版本。 - 在轉換 Webhook 中刪除對舊版本的轉換支援。
指定多個版本
CustomResourceDefinition API versions
欄位可用於支援您開發的自訂資源的多個版本。版本可以具有不同的結構描述,而轉換 Webhook 可以在版本之間轉換自訂資源。Webhook 轉換應儘可能遵循 Kubernetes API 慣例。具體來說,請參閱 API 變更文件,以取得一組有用的陷阱和建議。
注意
在apiextensions.k8s.io/v1beta1
中,有一個 version
欄位而不是 versions
。version
欄位已棄用且為可選,但如果它不是空的,則必須與 versions
欄位中的第一個項目相符。此範例顯示具有兩個版本的 CustomResourceDefinition。對於第一個範例,假設所有版本共用相同的結構描述,且它們之間沒有轉換。YAML 中的註解提供更多上下文。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
# A schema is required
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
# The conversion section is introduced in Kubernetes 1.13+ with a default value of
# None conversion (strategy sub-field set to None).
conversion:
# None conversion assumes the same schema for all versions and only sets the apiVersion
# field of custom resources to the proper value
strategy: None
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular name to be used as an alias on the CLI and for display
singular: crontab
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: CronTab
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- ct
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
- name: v1
served: true
storage: false
validation:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
# The conversion section is introduced in Kubernetes 1.13+ with a default value of
# None conversion (strategy sub-field set to None).
conversion:
# None conversion assumes the same schema for all versions and only sets the apiVersion
# field of custom resources to the proper value
strategy: None
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular name to be used as an alias on the CLI and for display
singular: crontab
# kind is normally the PascalCased singular type. Your resource manifests use this.
kind: CronTab
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- ct
您可以將 CustomResourceDefinition 儲存在 YAML 檔案中,然後使用 kubectl apply
建立它。
kubectl apply -f my-versioned-crontab.yaml
建立後,API 伺服器開始在 HTTP REST 端點提供每個已啟用的版本。在上述範例中,API 版本在 /apis/example.com/v1beta1
和 /apis/example.com/v1
中可用。
版本優先順序
無論在 CustomResourceDefinition 中定義版本的順序為何,kubectl 始終會使用優先順序最高的版本,作為存取物件的預設版本。優先順序取決於剖析 name 欄位,以判斷版本號碼、穩定性(GA、Beta 或 Alpha),以及在該穩定性層級內的順序。
用於排序版本的演算法,其設計目的在於以 Kubernetes 專案排序 Kubernetes 版本的方式進行排序。版本開頭為 v
,後接數字、可選的 beta
或 alpha
指定,以及可選的其他數字版本資訊。廣義而言,版本字串可能看起來像 v2
或 v2beta1
。版本使用以下演算法排序:
- 符合 Kubernetes 版本模式的條目會優先於不符合的條目進行排序。
- 對於符合 Kubernetes 版本模式的條目,版本字串的數字部分會從大到小排序。
- 如果字串
beta
或alpha
出現在第一個數字部分之後,它們會依該順序排序,在沒有beta
或alpha
後綴的對等字串之後(預計為 GA 版本)。 - 如果另一個數字跟在
beta
或alpha
之後,這些數字也會從大到小排序。 - 不符合上述格式的字串會依字母順序排序,且數字部分不會被特殊處理。請注意,在以下範例中,
foo1
排序在foo10
之前。這與符合 Kubernetes 版本模式的條目的數字部分排序方式不同。
如果您查看以下排序後的版本列表,可能會更清楚理解
- v10
- v2
- v1
- v11beta2
- v10beta3
- v3beta1
- v12alpha1
- v11alpha2
- foo1
- foo10
對於指定多個版本中的範例,版本排序順序為 v1
,接著是 v1beta1
。這會導致 kubectl 指令使用 v1
作為預設版本,除非提供的物件指定了版本。
版本棄用
Kubernetes v1.19 [stable]
從 v1.19 開始,CustomResourceDefinition 可以指示其定義的資源的特定版本已被棄用。當對該資源的已棄用版本發出 API 請求時,API 回應中會以標頭形式傳回警告訊息。如果需要,可以自訂每個資源已棄用版本的警告訊息。
自訂的警告訊息應指出已棄用的 API 群組、版本和種類,並應指出應改用哪個 API 群組、版本和種類(如果適用)。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
name: crontabs.example.com
spec:
group: example.com
names:
plural: crontabs
singular: crontab
kind: CronTab
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: false
# This indicates the v1alpha1 version of the custom resource is deprecated.
# API requests to this version receive a warning header in the server response.
deprecated: true
# This overrides the default warning returned to API clients making v1alpha1 API requests.
deprecationWarning: "example.com/v1alpha1 CronTab is deprecated; see http://example.com/v1alpha1-v1 for instructions to migrate to example.com/v1 CronTab"
schema: ...
- name: v1beta1
served: true
# This indicates the v1beta1 version of the custom resource is deprecated.
# API requests to this version receive a warning header in the server response.
# A default warning message is returned for this version.
deprecated: true
schema: ...
- name: v1
served: true
storage: true
schema: ...
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: crontabs.example.com
spec:
group: example.com
names:
plural: crontabs
singular: crontab
kind: CronTab
scope: Namespaced
validation: ...
versions:
- name: v1alpha1
served: true
storage: false
# This indicates the v1alpha1 version of the custom resource is deprecated.
# API requests to this version receive a warning header in the server response.
deprecated: true
# This overrides the default warning returned to API clients making v1alpha1 API requests.
deprecationWarning: "example.com/v1alpha1 CronTab is deprecated; see http://example.com/v1alpha1-v1 for instructions to migrate to example.com/v1 CronTab"
- name: v1beta1
served: true
# This indicates the v1beta1 version of the custom resource is deprecated.
# API requests to this version receive a warning header in the server response.
# A default warning message is returned for this version.
deprecated: true
- name: v1
served: true
storage: true
版本移除
在現有的已儲存資料已遷移到更新的 API 版本,以適用於所有服務舊版本自訂資源的叢集,且舊版本已從 CustomResourceDefinition 的 status.storedVersions
中移除之前,較舊的 API 版本無法從 CustomResourceDefinition 資訊清單中移除。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
name: crontabs.example.com
spec:
group: example.com
names:
plural: crontabs
singular: crontab
kind: CronTab
scope: Namespaced
versions:
- name: v1beta1
# This indicates the v1beta1 version of the custom resource is no longer served.
# API requests to this version receive a not found error in the server response.
served: false
schema: ...
- name: v1
served: true
# The new served version should be set as the storage version
storage: true
schema: ...
Webhook 轉換
Kubernetes v1.16 [stable]
注意
Webhook 轉換自 1.15 版起以 Beta 版提供,自 Kubernetes 1.13 版起以 Alpha 版提供。必須啟用CustomResourceWebhookConversion
功能,對於 Beta 功能而言,許多叢集會自動啟用此功能。請參閱功能閘道文件以取得更多資訊。上述範例在版本之間具有 None 轉換,這只會在轉換時設定 apiVersion
欄位,而不會變更物件的其餘部分。API 伺服器也支援 Webhook 轉換,在需要轉換的情況下,可以呼叫外部服務。例如,當
- 以與儲存版本不同的版本請求自訂資源時。
- 在一個版本中建立 Watch,但變更後的物件儲存在另一個版本中時。
- 自訂資源 PUT 請求的版本與儲存版本不同時。
為了涵蓋所有這些情況,並最佳化 API 伺服器的轉換,轉換請求可能包含多個物件,以盡量減少外部呼叫。Webhook 應獨立執行這些轉換。
撰寫轉換 Webhook 伺服器
請參閱 自訂資源轉換 Webhook 伺服器的實作,該伺服器在 Kubernetes e2e 測試中經過驗證。Webhook 處理 API 伺服器傳送的 ConversionReview
請求,並將轉換結果包裝在 ConversionResponse
中傳回。請注意,請求包含需要獨立轉換的自訂資源列表,且不變更物件的順序。範例伺服器的組織方式使其可以重複用於其他轉換。大多數常見程式碼都位於 framework 檔案中,僅留下 一個函數需要針對不同的轉換進行實作。
注意
範例轉換 Webhook 伺服器將ClientAuth
欄位留空,預設為 NoClientCert
。這表示 Webhook 伺服器不會驗證用戶端(據推測為 API 伺服器)的身分。如果您需要相互 TLS 或其他方式來驗證用戶端,請參閱如何驗證 API 伺服器。允許的變更
轉換 Webhook 不得變更轉換後物件的 metadata
內部的任何內容,labels
和 annotations
除外。嘗試變更 name
、UID
和 namespace
將會遭到拒絕,並導致導致轉換的請求失敗。所有其他變更都會被忽略。
部署轉換 Webhook 服務
部署轉換 Webhook 的文件與 准入 Webhook 範例服務的文件相同。以下各節的假設是,轉換 Webhook 伺服器已部署到 default
命名空間中名為 example-conversion-webhook-server
的服務,並在路徑 /crdconvert
上服務流量。
注意
當 Webhook 伺服器以服務形式部署到 Kubernetes 叢集中時,必須透過連接埠 443 上的服務公開(伺服器本身可以具有任意連接埠,但服務物件應將其對應到連接埠 443)。如果服務使用不同的連接埠,API 伺服器與 Webhook 服務之間的通訊可能會失敗。設定 CustomResourceDefinition 以使用轉換 Webhook
可以擴充 None
轉換範例,透過修改 spec
的 conversion
區段來使用轉換 Webhook。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
# Each version can define its own schema when there is no top-level
# schema is defined.
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
conversion:
# the Webhook strategy instructs the API server to call an external webhook for any conversion between custom resources.
strategy: Webhook
# webhook is required when strategy is `Webhook` and it configures the webhook endpoint to be called by API server.
webhook:
# conversionReviewVersions indicates what ConversionReview versions are understood/preferred by the webhook.
# The first version in the list understood by the API server is sent to the webhook.
# The webhook must respond with a ConversionReview object in the same version it received.
conversionReviewVersions: ["v1","v1beta1"]
clientConfig:
service:
namespace: default
name: example-conversion-webhook-server
path: /crdconvert
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular name to be used as an alias on the CLI and for display
singular: crontab
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: CronTab
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- ct
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
# name must match the spec fields below, and be in the form: <plural>.<group>
name: crontabs.example.com
spec:
# group name to use for REST API: /apis/<group>/<version>
group: example.com
# prunes object fields that are not specified in OpenAPI schemas below.
preserveUnknownFields: false
# list of versions supported by this CustomResourceDefinition
versions:
- name: v1beta1
# Each version can be enabled/disabled by Served flag.
served: true
# One and only one version must be marked as the storage version.
storage: true
# Each version can define its own schema when there is no top-level
# schema is defined.
schema:
openAPIV3Schema:
type: object
properties:
hostPort:
type: string
- name: v1
served: true
storage: false
schema:
openAPIV3Schema:
type: object
properties:
host:
type: string
port:
type: string
conversion:
# the Webhook strategy instructs the API server to call an external webhook for any conversion between custom resources.
strategy: Webhook
# webhookClientConfig is required when strategy is `Webhook` and it configures the webhook endpoint to be called by API server.
webhookClientConfig:
service:
namespace: default
name: example-conversion-webhook-server
path: /crdconvert
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
# either Namespaced or Cluster
scope: Namespaced
names:
# plural name to be used in the URL: /apis/<group>/<version>/<plural>
plural: crontabs
# singular name to be used as an alias on the CLI and for display
singular: crontab
# kind is normally the CamelCased singular type. Your resource manifests use this.
kind: CronTab
# shortNames allow shorter string to match your resource on the CLI
shortNames:
- ct
您可以將 CustomResourceDefinition 儲存到 YAML 檔案中,然後使用 kubectl apply
來套用它。
kubectl apply -f my-versioned-crontab-with-conversion.yaml
在套用新變更之前,請確保轉換服務已啟動並執行。
聯絡 Webhook
一旦 API 伺服器確定應將請求傳送到轉換 Webhook,它就需要知道如何聯絡 Webhook。這在 Webhook 設定的 webhookClientConfig
節中指定。
轉換 Webhook 可以透過 URL 或服務參考呼叫,並且可以選擇性地包含自訂 CA 憑證套件,以用於驗證 TLS 連線。
URL
url
以標準 URL 格式(scheme://host:port/path
)提供 Webhook 的位置。
host
不應參考在叢集中執行的服務;請改為指定 service
欄位來使用服務參考。在某些 API 伺服器中,主機可能會透過外部 DNS 解析(即,kube-apiserver
無法解析叢集內 DNS,因為這會違反分層)。host
也可能是 IP 位址。
請注意,除非您非常小心地在所有執行可能需要呼叫此 Webhook 的 API 伺服器的主機上執行此 Webhook,否則使用 localhost
或 127.0.0.1
作為 host
是有風險的。此類安裝可能不具可攜性,或不容易在新叢集中執行。
scheme 必須為 "https";URL 必須以 "https://" 開頭。
不允許嘗試使用使用者或基本驗證(例如 "user:password@")。也不允許片段 ("#...") 和查詢參數 ("?...")。
以下是一個設定為呼叫 URL 的轉換 Webhook 範例(並預期使用系統信任根驗證 TLS 憑證,因此未指定 caBundle)
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
clientConfig:
url: "https://my-webhook.example.com:9443/my-webhook-path"
...
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhookClientConfig:
url: "https://my-webhook.example.com:9443/my-webhook-path"
...
服務參考
webhookClientConfig
內的 service
節是對轉換 Webhook 服務的參考。如果 Webhook 在叢集中執行,則應使用 service
而不是 url
。服務命名空間和名稱是必要的。連接埠是選用的,預設為 443。路徑是選用的,預設為 "/"。
以下是一個 Webhook 的範例,該 Webhook 設定為呼叫連接埠 "1234" 上子路徑 "/my-path" 的服務,並使用自訂 CA 套件針對 ServerName my-service-name.my-service-namespace.svc
驗證 TLS 連線。
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
clientConfig:
service:
namespace: my-service-namespace
name: my-service-name
path: /my-path
port: 1234
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhookClientConfig:
service:
namespace: my-service-namespace
name: my-service-name
path: /my-path
port: 1234
caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
...
Webhook 請求和回應
請求
Webhook 會收到 POST 請求,Content-Type: application/json
,其中 ConversionReview
API 物件位於 apiextensions.k8s.io
API 群組中,序列化為 JSON 作為主體。
Webhook 可以使用 CustomResourceDefinition 中的 conversionReviewVersions
欄位,指定它們接受的 ConversionReview
物件版本
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
webhook:
conversionReviewVersions: ["v1", "v1beta1"]
...
建立 apiextensions.k8s.io/v1
自訂資源定義時,conversionReviewVersions
是必要欄位。Webhook 必須至少支援目前和先前的 API 伺服器理解的一個 ConversionReview
版本。
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
...
spec:
...
conversion:
strategy: Webhook
conversionReviewVersions: ["v1", "v1beta1"]
...
如果未指定 conversionReviewVersions
,則建立 apiextensions.k8s.io/v1beta1
自訂資源定義時的預設值為 v1beta1
。
API 伺服器會傳送它們支援的 conversionReviewVersions
列表中的第一個版本。如果列表中沒有任何版本受到 API 伺服器支援,則不允許建立自訂資源定義。如果 API 伺服器遇到先前建立的轉換 Webhook 設定,且不支援 API 伺服器知道如何傳送的任何 ConversionReview
版本,則嘗試呼叫 Webhook 將會失敗。
此範例顯示 ConversionReview
物件中包含的資料,用於將 CronTab
物件轉換為 example.com/v1
的請求
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"request": {
# Random uid uniquely identifying this conversion call
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
# The API group and version the objects should be converted to
"desiredAPIVersion": "example.com/v1",
# The list of objects to convert.
# May contain one or more objects, in one or more versions.
"objects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"hostPort": "localhost:1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"hostPort": "example.com:2345"
}
]
}
}
{
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"request": {
# Random uid uniquely identifying this conversion call
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
# The API group and version the objects should be converted to
"desiredAPIVersion": "example.com/v1",
# The list of objects to convert.
# May contain one or more objects, in one or more versions.
"objects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"hostPort": "localhost:1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1beta1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"hostPort": "example.com:2345"
}
]
}
}
回應
Webhook 會以 200 HTTP 狀態碼、Content-Type: application/json
和包含 ConversionReview
物件(與傳送的版本相同)的主體回應,其中 response
節已填入,並序列化為 JSON。
如果轉換成功,Webhook 應傳回包含以下欄位的 response
節
uid
,從傳送到 Webhook 的request.uid
複製result
,設定為{"status":"Success"}
convertedObjects
,包含來自request.objects
的所有物件,轉換為request.desiredAPIVersion
Webhook 的最小成功回應範例
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"response": {
# must match <request.uid>
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
"result": {
"status": "Success"
},
# Objects must match the order of request.objects, and have apiVersion set to <request.desiredAPIVersion>.
# kind, metadata.uid, metadata.name, and metadata.namespace fields must not be changed by the webhook.
# metadata.labels and metadata.annotations fields may be changed by the webhook.
# All other changes to metadata fields by the webhook are ignored.
"convertedObjects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"host": "localhost",
"port": "1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"host": "example.com",
"port": "2345"
}
]
}
}
{
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"response": {
# must match <request.uid>
"uid": "705ab4f5-6393-11e8-b7cc-42010a800002",
"result": {
"status": "Failed"
},
# Objects must match the order of request.objects, and have apiVersion set to <request.desiredAPIVersion>.
# kind, metadata.uid, metadata.name, and metadata.namespace fields must not be changed by the webhook.
# metadata.labels and metadata.annotations fields may be changed by the webhook.
# All other changes to metadata fields by the webhook are ignored.
"convertedObjects": [
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-04T14:03:02Z",
"name": "local-crontab",
"namespace": "default",
"resourceVersion": "143",
"uid": "3415a7fc-162b-4300-b5da-fd6083580d66"
},
"host": "localhost",
"port": "1234"
},
{
"kind": "CronTab",
"apiVersion": "example.com/v1",
"metadata": {
"creationTimestamp": "2019-09-03T13:02:01Z",
"name": "remote-crontab",
"resourceVersion": "12893",
"uid": "359a83ec-b575-460d-b553-d859cedde8a0"
},
"host": "example.com",
"port": "2345"
}
]
}
}
如果轉換失敗,Webhook 應傳回包含以下欄位的 response
節
uid
,從傳送到 Webhook 的request.uid
複製result
,設定為{"status":"Failed"}
警告
轉換失敗可能會中斷對自訂資源的讀取和寫入存取,包括更新或刪除資源的能力。應盡可能避免轉換失敗,且不應用於強制執行驗證約束(改用驗證架構或 Webhook 准入)。以下是 Webhook 回應的範例,指示轉換請求失敗,並帶有選用的訊息
{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "ConversionReview",
"response": {
"uid": "<value from request.uid>",
"result": {
"status": "Failed",
"message": "hostPort could not be parsed into a separate host and port"
}
}
}
{
# Deprecated in v1.16 in favor of apiextensions.k8s.io/v1
"apiVersion": "apiextensions.k8s.io/v1beta1",
"kind": "ConversionReview",
"response": {
"uid": "<value from request.uid>",
"result": {
"status": "Failed",
"message": "hostPort could not be parsed into a separate host and port"
}
}
}
寫入、讀取和更新版本化的 CustomResourceDefinition 物件
寫入物件時,它會以寫入時指定為儲存版本的版本儲存。如果儲存版本變更,現有的物件永遠不會自動轉換。但是,新建立或更新的物件會以新的儲存版本寫入。物件有可能以不再服務的版本寫入。
當您讀取物件時,會在路徑中指定版本。您可以請求目前服務中任何版本的物件。如果您指定的版本與物件的儲存版本不同,Kubernetes 會以您請求的版本將物件傳回給您,但儲存的物件在磁碟上不會變更。
在服務讀取請求時傳回的物件會發生什麼情況,取決於 CRD 的 spec.conversion
中指定了什麼
- 如果指定了預設的
strategy
值None
,則對物件的唯一修改是變更apiVersion
字串,以及可能的修剪未知的欄位(取決於設定)。請注意,如果儲存版本和請求版本之間的架構不同,這不太可能產生良好的結果。特別是,如果相同資料在不同版本之間以不同的欄位表示,則不應使用此策略。 - 如果指定了Webhook 轉換,則此機制會控制轉換。
如果您更新現有的物件,它會以目前為儲存版本的版本重新寫入。這是物件可以從一個版本變更為另一個版本的唯一方式。
為了說明這一點,請考慮以下假設的事件序列
- 儲存版本為
v1beta1
。您建立一個物件。它以版本v1beta1
儲存 - 您將版本
v1
新增至 CustomResourceDefinition,並將其指定為儲存版本。此處v1
和v1beta1
的架構相同,這通常是在 Kubernetes 生態系統中將 API 升級到穩定版時的情況。 - 您以版本
v1beta1
讀取您的物件,然後您再次以版本v1
讀取該物件。除了 apiVersion 欄位之外,兩個傳回的物件都相同。 - 您建立一個新物件。它以版本
v1
儲存。您現在有兩個物件,其中一個物件位於v1beta1
,另一個物件位於v1
。 - 您更新第一個物件。由於
v1
是目前的儲存版本,因此現在以版本v1
儲存。
先前的儲存版本
API 伺服器會在狀態欄位 storedVersions
中記錄每個曾經標記為儲存版本的版本。物件可能已儲存在任何曾經指定為儲存版本的版本中。在從未作為儲存版本的版本中,可能不存在任何物件。
將現有物件升級到新的儲存版本
在棄用版本並停止支援時,請選擇儲存升級程序。
選項 1: 使用儲存版本遷移程式
- 執行儲存版本遷移程式
- 從 CustomResourceDefinition
status.storedVersions
欄位中移除舊版本。
選項 2: 手動將現有物件升級到新的儲存版本
以下是從 v1beta1
升級到 v1
的範例程序。
- 在 CustomResourceDefinition 檔案中將
v1
設定為儲存版本,並使用 kubectl 套用它。storedVersions
現在為v1beta1, v1
。 - 撰寫升級程序以列出所有現有物件,並以相同的內容寫入它們。這會強制後端以目前的儲存版本(即
v1
)寫入物件。 - 從 CustomResourceDefinition
status.storedVersions
欄位中移除v1beta1
。
注意
--subresource
旗標與 kubectl get、patch、edit 和 replace 指令搭配使用,以擷取和更新所有支援它們的 API 資源的子資源 status
和 scale
。此旗標從 kubectl 版本 v1.24 開始提供。先前,透過 kubectl 讀取子資源(如 status
)涉及使用 kubectl --raw
,而完全無法使用 kubectl 更新子資源。從 v1.24 開始,kubectl
工具可用於編輯或修補 CRD 物件上的 status
子資源。請參閱如何使用子資源旗標修補 Deployment。
本頁是 Kubernetes v1.32 文件的其中一部分。如果您執行的是不同版本的 Kubernetes,請參閱該版本的說明文件。
以下是如何使用 kubectl
修補 CRD 物件的 status
子資源的範例
kubectl patch customresourcedefinitions <CRD_Name> --subresource='status' --type='merge' -p '{"status":{"storedVersions":["v1"]}}'