Kubernetes CustomResourceDefinition的版本

2022-06-17 09:04 更新

CustomResourceDefinition 的版本

本頁介紹如何添加版本信息到 CustomResourceDefinitions。 目的是標(biāo)明 CustomResourceDefinitions 的穩(wěn)定級(jí)別或者服務(wù)于 API 升級(jí)。 API 升級(jí)時(shí)需要在不同 API 表示形式之間進(jìn)行轉(zhuǎn)換。 本頁還描述如何將對(duì)象從一個(gè)版本升級(jí)到另一個(gè)版本。

在開始之前

你必須擁有一個(gè) Kubernetes 的集群,同時(shí)你的 Kubernetes 集群必須帶有 kubectl 命令行工具。 建議在至少有兩個(gè)節(jié)點(diǎn)的集群上運(yùn)行本教程,且這些節(jié)點(diǎn)不作為控制平面主機(jī)。 如果你還沒有集群,你可以通過 Minikube 構(gòu)建一個(gè)你自己的集群,或者你可以使用下面任意一個(gè) Kubernetes 工具構(gòu)建:

你應(yīng)該對(duì)定制資源 有一些初步了解。

您的 Kubernetes 服務(wù)器版本必須不低于版本 v1.16. 要獲知版本信息,請(qǐng)輸入 ?kubectl version?。

概覽

CustomResourceDefinition API 提供了用于引入和升級(jí)的工作流程到 CustomResourceDefinition 的新版本。

創(chuàng)建 CustomResourceDefinition 時(shí),會(huì)在 CustomResourceDefinition ?spec.versions? 列表設(shè)置適當(dāng)?shù)姆€(wěn)定級(jí)別和版本號(hào)。例如,?v1beta1? 表示第一個(gè)版本尚未穩(wěn)定。 所有定制資源對(duì)象將首先用這個(gè)版本保存。

創(chuàng)建 CustomResourceDefinition 后,客戶端可以開始使用 ?v1beta1? API。

稍后可能需要添加新版本,例如 ?v1?。

添加新版本:

  1. 選擇一種轉(zhuǎn)化策略。由于定制資源對(duì)象需要能夠兩種版本都可用, 這意味著它們有時(shí)會(huì)以與存儲(chǔ)版本不同的版本來提供服務(wù)。為了能夠做到這一點(diǎn), 有時(shí)必須在它們存儲(chǔ)的版本和提供的版本之間進(jìn)行轉(zhuǎn)換。如果轉(zhuǎn)換涉及模式變更, 并且需要自定義邏輯,則應(yīng)該使用 Webhook 來完成。如果沒有模式變更, 則可使用默認(rèn)的 ?None ?轉(zhuǎn)換策略,為不同版本提供服務(wù)時(shí)只有 apiVersion 字段 會(huì)被改變。
  2. 如果使用轉(zhuǎn)換 Webhook,請(qǐng)創(chuàng)建并部署轉(zhuǎn)換 Webhook。
  3. 更新 CustomResourceDefinition,將新版本設(shè)置為 ?served:true?,加入到 ?spec.versions? 列表。另外,還要設(shè)置 ?spec.conversion? 字段 為所選的轉(zhuǎn)換策略。如果使用轉(zhuǎn)換 Webhook,請(qǐng)配置 ?spec.conversion.webhookClientConfig? 來調(diào)用 Webhook。

添加新版本后,客戶端可以逐步遷移到新版本。讓某些客戶使用舊版本的同時(shí) 支持其他人使用新版本是相當(dāng)安全的。

將存儲(chǔ)的對(duì)象遷移到新版本:

  • 請(qǐng)參閱下文-將現(xiàn)有對(duì)象升級(jí)到新的存儲(chǔ)版本節(jié)

對(duì)于客戶來說,在將對(duì)象升級(jí)到新的存儲(chǔ)版本之前、期間和之后使用舊版本和新版本都是安全的。

刪除舊版本:

  1. 確保所有客戶端都已完全遷移到新版本。 可以查看 kube-apiserver 的日志以識(shí)別仍通過舊版本進(jìn)行訪問的所有客戶端。
  2. 在 ?spec.versions? 列表中將舊版本的 ?served ?設(shè)置為 ?false?。 如果仍有客戶端意外地使用舊版本,他們可能開始會(huì)報(bào)告采用舊版本嘗試訪 定制資源的錯(cuò)誤消息。 如果發(fā)生這種情況,請(qǐng)將舊版本的?served:true? 恢復(fù),然后遷移余下的客戶端 使用新版本,然后重復(fù)此步驟。
  3. 確保已完成將現(xiàn)有對(duì)象升級(jí)到新存儲(chǔ)版本 的步驟。
    1. 在 CustomResourceDefinition 的 ?spec.versions? 列表中,確認(rèn)新版本的 ?storage ?已被設(shè)置為 ?true?。
    2. 確認(rèn)舊版本不在 CustomResourceDefinition ?status.storedVersions? 中。
  4. 從 CustomResourceDefinition ?spec.versions? 列表中刪除舊版本。
  5. 在轉(zhuǎn)換 Webhooks 中放棄對(duì)舊版本的轉(zhuǎn)換支持。

指定多個(gè)版本 

CustomResourceDefinition API 的 ?versions ?字段可用于支持你所開發(fā)的 定制資源的多個(gè)版本。版本可以具有不同的模式,并且轉(zhuǎn)換 Webhooks 可以在多個(gè)版本之間轉(zhuǎn)換定制資源。 在適當(dāng)?shù)那闆r下,Webhook 轉(zhuǎn)換應(yīng)遵循 Kubernetes API 約定。 尤其是,請(qǐng)查閱 API 變更文檔 以了解一些有用的常見錯(cuò)誤和建議。

說明: 在 ?apiextensions.k8s.io/v1beta1? 版本中曾經(jīng)有一個(gè) ?version ?字段, 名字不叫做 ?versions?。該 ?version ?字段已經(jīng)被廢棄,成為可選項(xiàng)。 不過如果該字段不是空,則必須與 ?versions ?字段中的第一個(gè)條目匹配。

下面的示例顯示了兩個(gè)版本的 CustomResourceDefinition。 第一個(gè)例子中假設(shè)所有的版本使用相同的模式而它們之間沒有轉(zhuǎn)換。 YAML 中的注釋提供了更多背景信息。

  • apiextensions.k8s.io/v1
  • apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      # name 必須匹配后面 spec 中的字段,且使用格式 <plural>.<group>
      name: crontabs.example.com
    spec:
      # 組名,用于 REST API: /apis/<group>/<version>
      group: example.com
      # 此 CustomResourceDefinition 所支持的版本列表
      versions:
      - name: v1beta1
        # 每個(gè) version 可以通過 served 標(biāo)志啟用或禁止
        served: true
        # 有且只能有一個(gè) version 必須被標(biāo)記為存儲(chǔ)版本
        storage: true
        # schema 是必需字段
        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
      # conversion 節(jié)是 Kubernetes 1.13+ 版本引入的,其默認(rèn)值為無轉(zhuǎn)換,即
      # strategy 子字段設(shè)置為 None。
      conversion:
        # None 轉(zhuǎn)換假定所有版本采用相同的模式定義,僅僅將定制資源的 apiVersion
        # 設(shè)置為合適的值.
        strategy: None
      # 可以是 Namespaced 或 Cluster
      scope: Namespaced
      names:
        # 名稱的復(fù)數(shù)形式,用于 URL: /apis/<group>/<version>/<plural>
        plural: crontabs
        # 名稱的單數(shù)形式,用于在命令行接口和顯示時(shí)作為其別名
        singular: crontab
        # kind 通常是駝峰編碼(CamelCased)的單數(shù)形式,用于資源清單中
        kind: CronTab
        # shortNames 允許你在命令行接口中使用更短的字符串來匹配你的資源
        shortNames:
        - ct
  • apiextensions.k8s.io/v1beta1
  • # 在 v1.16 中被棄用以推薦使用 apiextensions.k8s.io/v1
    apiVersion: apiextensions.k8s.io/v1beta1
    kind: CustomResourceDefinition
    metadata:
      # name 必須匹配后面 spec 中的字段,且使用格式 <plural>.<group>
      name: crontabs.example.com
    spec:
      # 組名,用于 REST API: /apis/<group>/<version>
      group: example.com
      # 此 CustomResourceDefinition 所支持的版本列表
      versions:
      - name: v1beta1
        # 每個(gè) version 可以通過 served 標(biāo)志啟用或禁止
        served: true
        # 有且只能有一個(gè) version 必須被標(biāo)記為存儲(chǔ)版本
        storage: true
      - name: v1
        served: true
        storage: false
      validation:
        openAPIV3Schema:
          type: object
          properties:
            host:
              type: string
            port:
              type: string
      # conversion 節(jié)是 Kubernetes 1.13+ 版本引入的,其默認(rèn)值為無轉(zhuǎn)換,即
      # strategy 子字段設(shè)置為 None。
      conversion:
        # None 轉(zhuǎn)換假定所有版本采用相同的模式定義,僅僅將定制資源的 apiVersion
        # 設(shè)置為合適的值.
        strategy: None
      # 可以是 Namespaced 或 Cluster
      scope: Namespaced
      names:
        # 名稱的復(fù)數(shù)形式,用于 URL: /apis/<group>/<version>/<plural>
        plural: crontabs
        # 名稱的單數(shù)形式,用于在命令行接口和顯示時(shí)作為其別名
        singular: crontab
        # kind 通常是大駝峰編碼(PascalCased)的單數(shù)形式,用于資源清單中
        kind: CronTab
        # shortNames 允許你在命令行接口中使用更短的字符串來匹配你的資源
        shortNames:
        - ct

你可以將 CustomResourceDefinition 存儲(chǔ)在 YAML 文件中,然后使用 ?kubectl apply? 來創(chuàng)建它。

kubectl apply -f my-versioned-crontab.yaml

在創(chuàng)建之后,API 服務(wù)器開始在 HTTP REST 端點(diǎn)上為每個(gè)已啟用的版本提供服務(wù)。 在上面的示例中,API 版本可以在 ?/apis/example.com/v1beta1? 和 ?/apis/example.com/v1? 處獲得。

版本優(yōu)先級(jí)

不考慮 CustomResourceDefinition 中版本被定義的順序,kubectl 使用 具有最高優(yōu)先級(jí)的版本作為訪問對(duì)象的默認(rèn)版本。 通過解析 name 字段確定優(yōu)先級(jí)來決定版本號(hào),穩(wěn)定性(GA、Beta 或 Alpha) 級(jí)別及該穩(wěn)定性級(jí)別內(nèi)的序列。

用于對(duì)版本進(jìn)行排序的算法在設(shè)計(jì)上與 Kubernetes 項(xiàng)目對(duì) Kubernetes 版本進(jìn)行排序的方式相同。 版本以 ?v? 開頭跟一個(gè)數(shù)字,一個(gè)可選的 ?beta ?或者 ?alpha ?和一個(gè)可選的附加數(shù)字 作為版本信息。 從廣義上講,版本字符串可能看起來像 ?v2? 或者 ?v2beta1?。 使用以下算法對(duì)版本進(jìn)行排序:

  • 遵循 Kubernetes 版本模式的條目在不符合條件的條目之前進(jìn)行排序。
  • 對(duì)于遵循 Kubernetes 版本模式的條目,版本字符串的數(shù)字部分從最大到最小排序。
  • 如果第一個(gè)數(shù)字后面有字符串 ?beta ?或 ?alpha?,它們首先按去掉 ?beta ?或 ?alpha ?之后的版本號(hào)排序(相當(dāng)于 GA 版本),之后按 ?beta ?先、?alpha ?后的順序排序,
  • 如果 ?beta ?或 ?alpha ?之后還有另一個(gè)數(shù)字,那么也會(huì)針對(duì)這些數(shù)字 從大到小排序。
  • 不符合上述格式的字符串按字母順序排序,數(shù)字部分不經(jīng)過特殊處理。 請(qǐng)注意,在下面的示例中,?foo1 ?排在 ?foo10 ?之前。 這與遵循 Kubernetes 版本模式的條目的數(shù)字部分排序不同。

如果查看以下版本排序列表,這些規(guī)則就容易懂了:

- v10
- v2
- v1
- v11beta2
- v10beta3
- v3beta1
- v12alpha1
- v11alpha2
- foo1
- foo10

版本廢棄

特性狀態(tài): Kubernetes v1.19 [stable]

從 v1.19 開始,CustomResourceDefinition 可用來標(biāo)明所定義的資源的特定版本 被廢棄。當(dāng)發(fā)起對(duì)已廢棄的版本的 API 請(qǐng)求時(shí),會(huì)在 API 響應(yīng)中以 HTTP 頭部 的形式返回警告消息。 如果需要,可以對(duì)資源的每個(gè)廢棄版本定制該警告消息。

定制的警告消息應(yīng)該標(biāo)明廢棄的 API 組、版本和類別(kind),并且應(yīng)該標(biāo)明 應(yīng)該使用(如果有的話)哪個(gè) API 組、版本和類別作為替代。

  • apiextensions.k8s.io/v1
  • 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
        # 此屬性標(biāo)明此定制資源的 v1alpha1 版本已被棄用。
        # 發(fā)給此版本的 API 請(qǐng)求會(huì)在服務(wù)器響應(yīng)中收到警告消息頭。
        deprecated: true
        # 此屬性設(shè)置用來覆蓋返回給發(fā)送 v1alpha1 API 請(qǐng)求的客戶端的默認(rèn)警告信息。
        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
        # 此屬性標(biāo)明該定制資源的 v1beta1 版本已被棄用。
        # 發(fā)給此版本的 API 請(qǐng)求會(huì)在服務(wù)器響應(yīng)中收到警告消息頭。
        # 針對(duì)此版本的請(qǐng)求所返回的是默認(rèn)的警告消息。
        deprecated: true
        schema: ...
      - name: v1
        served: true
        storage: true
        schema: ...
  • apiextensions.k8s.io/v1beta1
  • # 在 v1.16 中棄用以推薦使用  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
        # 此屬性標(biāo)明此定制資源的 v1alpha1 版本已被棄用。
        # 發(fā)給此版本的 API 請(qǐng)求會(huì)在服務(wù)器響應(yīng)中收到警告消息頭。
        deprecated: true
        # 此屬性設(shè)置用來覆蓋返回給發(fā)送 v1alpha1 API 請(qǐng)求的客戶端的默認(rèn)警告信息。
        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
        # 此屬性標(biāo)明該定制資源的 v1beta1 版本已被棄用。
        # 發(fā)給此版本的 API 請(qǐng)求會(huì)在服務(wù)器響應(yīng)中收到警告消息頭。
        # 針對(duì)此版本的請(qǐng)求所返回的是默認(rèn)的警告消息。
        deprecated: true
      - name: v1
        served: true
        storage: true

Webhook 轉(zhuǎn)換 

特性狀態(tài): Kubernetes v1.16 [stable]

說明: Webhook 轉(zhuǎn)換在 Kubernetes 1.13 版本引入,在 Kubernetes 1.15 中成為 Beta 功能。 要使用此功能,應(yīng)啟用 ?CustomResourceWebhookConversion ?特性。 在大多數(shù)集群上,這類 Beta 特性應(yīng)該是自動(dòng)啟用的。

上面的例子在版本之間有一個(gè) None 轉(zhuǎn)換,它只在轉(zhuǎn)換時(shí)設(shè)置 ?apiVersion ?字段 而不改變對(duì)象的其余部分。API 服務(wù)器還支持在需要轉(zhuǎn)換時(shí)調(diào)用外部服務(wù)的 webhook 轉(zhuǎn)換。 例如:

  • 定制資源的請(qǐng)求版本與其存儲(chǔ)版本不同。
  • 使用某版本創(chuàng)建了 Watch 請(qǐng)求,但所更改對(duì)象以另一版本存儲(chǔ)。
  • 定制資源的 PUT 請(qǐng)求所針對(duì)版本與存儲(chǔ)版本不同。

為了涵蓋所有這些情況并優(yōu)化 API 服務(wù)器所作的轉(zhuǎn)換,轉(zhuǎn)換請(qǐng)求可以包含多個(gè)對(duì)象, 以便減少外部調(diào)用。Webhook 應(yīng)該獨(dú)立執(zhí)行各個(gè)轉(zhuǎn)換。

編寫一個(gè)轉(zhuǎn)換 Webhook 服務(wù)器

請(qǐng)參考定制資源轉(zhuǎn)換 Webhook 服務(wù)器 的實(shí)現(xiàn);該實(shí)現(xiàn)在 Kubernetes e2e 測(cè)試中得到驗(yàn)證。 Webhook 處理由 API 服務(wù)器發(fā)送的 ?ConversionReview ?請(qǐng)求,并在 ?ConversionResponse ?中封裝發(fā)回轉(zhuǎn)換結(jié)果。 請(qǐng)注意,請(qǐng)求包含需要獨(dú)立轉(zhuǎn)換的定制資源列表,這些對(duì)象在被轉(zhuǎn)換之后不能改變其 在列表中的順序。該示例服務(wù)器的組織方式使其可以復(fù)用于其他轉(zhuǎn)換。 大多數(shù)常見代碼都位于  framework 文件 中,只留下 一個(gè)函數(shù) 用于實(shí)現(xiàn)不同的轉(zhuǎn)換。

說明: 轉(zhuǎn)換 Webhook 服務(wù)器示例中將 ?ClientAuth ?字段設(shè)置為 , 默認(rèn)為 ?NoClientCert?。 這意味著 webhook 服務(wù)器沒有驗(yàn)證客戶端(也就是 API 服務(wù)器)的身份。

被允許的變更

轉(zhuǎn)換 Webhook 不可以更改被轉(zhuǎn)換對(duì)象的 ?metadata ?中除 ?labels ?和 ?annotations ?之外的任何屬性。 嘗試更改 ?name?、?UID ?和 ?namespace ?時(shí)都會(huì)導(dǎo)致引起轉(zhuǎn)換的請(qǐng)求失敗。 所有其他變更都被忽略。

部署轉(zhuǎn)換 Webhook 服務(wù)

這里的假設(shè)是轉(zhuǎn)換 Webhook 服務(wù)器被部署為 ?default ?名字空間中名為 ?example-conversion-webhook-server? 的服務(wù),并在路徑 ?/crdconvert? 上處理請(qǐng)求。

說明: 當(dāng) Webhook 服務(wù)器作為一個(gè)服務(wù)被部署到 Kubernetes 集群中時(shí),它必須 通過端口 443 公開其服務(wù)(服務(wù)器本身可以使用任意端口,但是服務(wù)對(duì)象 應(yīng)該將它映射到端口 443)。 如果為服務(wù)器使用不同的端口,則 API 服務(wù)器和 Webhook 服務(wù)器之間的通信 可能會(huì)失敗。

配置 CustomResourceDefinition 以使用轉(zhuǎn)換 Webhook 

通過修改 ?spec ?中的 ?conversion ?部分,可以擴(kuò)展 ?None ?轉(zhuǎn)換示例來 使用轉(zhuǎn)換 Webhook。

  • apiextensions.k8s.io/v1
  • apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    metadata:
      # name 必須匹配后面 spec 中的字段,且使用格式 <plural>.<group>
      name: crontabs.example.com
    spec:
      # 組名,用于 REST API: /apis/<group>/<version>
      group: example.com
      # 此 CustomResourceDefinition 所支持的版本列表
      versions:
      - name: v1beta1
        # 每個(gè) version 可以通過 served 標(biāo)志啟用或禁止
        served: true
        # 有且只能有一個(gè) version 必須被標(biāo)記為存儲(chǔ)版本
        storage: true
        # 當(dāng)不存在頂級(jí)模式定義時(shí),每個(gè)版本(version)可以定義其自身的模式
        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:
        # Webhook strategy 告訴 API 服務(wù)器調(diào)用外部 Webhook 來完成定制資源
        # 之間的轉(zhuǎn)換
        strategy: Webhook
        # 當(dāng) strategy 為 "Webhook" 時(shí),webhook 屬性是必需的
        # 該屬性配置將被 API 服務(wù)器調(diào)用的 Webhook 端點(diǎn)
        webhook:
          # conversionReviewVersions 標(biāo)明 Webhook 所能理解或偏好使用的
          # ConversionReview 對(duì)象版本。
          # API 服務(wù)器所能理解的列表中的第一個(gè)版本會(huì)被發(fā)送到 Webhook
          # Webhook 必須按所接收到的版本響應(yīng)一個(gè) ConversionReview 對(duì)象
          conversionReviewVersions: ["v1","v1beta1"]
          clientConfig:
            service:
              namespace: default
              name: example-conversion-webhook-server
              path: /crdconvert
            caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
      # 可以是 Namespaced 或 Cluster
      scope: Namespaced
      names:
        # 名稱的復(fù)數(shù)形式,用于 URL: /apis/<group>/<version>/<plural>
        plural: crontabs
        # 名稱的單數(shù)形式,用于在命令行接口和顯示時(shí)作為其別名
        singular: crontab
        # kind 通常是駝峰編碼(CamelCased)的單數(shù)形式,用于資源清單中
        kind: CronTab
        # shortNames 允許你在命令行接口中使用更短的字符串來匹配你的資源
        shortNames:
        - ct
  • apiextensions.k8s.io/v1beta1
  • # 在 v1.16 中被棄用以推薦使用 apiextensions.k8s.io/v1
    apiVersion: apiextensions.k8s.io/v1beta1
    kind: CustomResourceDefinition
    metadata:
      # name 必須匹配后面 spec 中的字段,且使用格式 <plural>.<group>
      name: crontabs.example.com
    spec:
      # 組名,用于 REST API: /apis/<group>/<version>
      group: example.com
      # 裁剪掉下面的 OpenAPI 模式中未曾定義的對(duì)象字段
      preserveUnknownFields: false
      # 此 CustomResourceDefinition 所支持的版本列表
      versions:
      - name: v1beta1
        # 每個(gè) version 可以通過 served 標(biāo)志啟用或禁止
        served: true
        # 有且只能有一個(gè) version 必須被標(biāo)記為存儲(chǔ)版本
        storage: true
        # 當(dāng)不存在頂級(jí)模式定義時(shí),每個(gè)版本(version)可以定義其自身的模式
        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:
        # Webhook strategy 告訴 API 服務(wù)器調(diào)用外部 Webhook 來完成定制資源
        strategy: Webhook
        # 當(dāng) strategy 為 "Webhook" 時(shí),webhookClientConfig 屬性是必需的
        # 該屬性配置將被 API 服務(wù)器調(diào)用的 Webhook 端點(diǎn)
        webhookClientConfig:
          service:
            namespace: default
            name: example-conversion-webhook-server
            path: /crdconvert
          caBundle: "Ci0tLS0tQk...<base64-encoded PEM bundle>...tLS0K"
      # 可以是 Namespaced 或 Cluster
      scope: Namespaced
      names:
        # 名稱的復(fù)數(shù)形式,用于 URL: /apis/<group>/<version>/<plural>
        plural: crontabs
        # 名稱的單數(shù)形式,用于在命令行接口和顯示時(shí)作為其別名
        singular: crontab
        # kind 通常是駝峰編碼(CamelCased)的單數(shù)形式,用于資源清單中
        kind: CronTab
        # shortNames 允許你在命令行接口中使用更短的字符串來匹配你的資源
        shortNames:
        - ct

你可以將 CustomResourceDefinition 保存在 YAML 文件中,然后使用 ?kubectl apply? 來應(yīng)用它。

kubectl apply -f my-versioned-crontab-with-conversion.yaml

在應(yīng)用新更改之前,請(qǐng)確保轉(zhuǎn)換服務(wù)器已啟動(dòng)并正在運(yùn)行。

調(diào)用 Webhook

API 服務(wù)器一旦確定請(qǐng)求應(yīng)發(fā)送到轉(zhuǎn)換 Webhook,它需要知道如何調(diào)用 Webhook。 這是在 ?webhookClientConfig ?中指定的 Webhook 配置。

轉(zhuǎn)換 Webhook 可以通過 URL 或服務(wù)引用來調(diào)用,并且可以選擇包含自定義 CA 包, 以用于驗(yàn)證 TLS 連接。

URL

url 以標(biāo)準(zhǔn) URL 形式給出 Webhook 的位置(?scheme://host:port/path?)。 ?host ?不應(yīng)引用集群中運(yùn)行的服務(wù),而應(yīng)通過指定 ?service ?字段來提供 服務(wù)引用。 在某些 API 服務(wù)器中,?host ?可以通過外部 DNS 進(jìn)行解析(即 ?kube-apiserver? 無法解析集群內(nèi) DNS,那樣會(huì)違反分層規(guī)則)。 ?host ?也可以是 IP 地址。

請(qǐng)注意,除非你非常小心地在所有運(yùn)行著可能調(diào)用 Webhook 的 API 服務(wù)器的 主機(jī)上運(yùn)行此 Webhook,否則將 ?localhost ?或 ?127.0.0.1? 用作 ?host ?是風(fēng)險(xiǎn)很大的。這樣的安裝可能是不可移植的,或者不容易在一個(gè)新的集群中運(yùn)行。

HTTP 協(xié)議必須為 ?https?;URL 必須以 ?https://? 開頭。

嘗試使用用戶或基本身份驗(yàn)證(例如,使用?user:password@?)是不允許的。 URL 片段(?#...?)和查詢參數(shù)(??...?)也是不允許的。

下面是為調(diào)用 URL 來執(zhí)行轉(zhuǎn)換 Webhook 的示例,其中期望使用系統(tǒng)信任根 來驗(yàn)證 TLS 證書,因此未指定 caBundle:

  • apiextensions.k8s.io/v1
  • apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    ...
    spec:
      ...
      conversion:
        strategy: Webhook
        webhook:
          clientConfig:
            url: "https://my-webhook.example.com:9443/my-webhook-path"
    ...
  • apiextensions.k8s.io/v1beta1
  • # 在 v1.16 中已棄用以推薦使用 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"
    ...

服務(wù)引用

?webhookClientConfig ?內(nèi)部的 ?service ?段是對(duì)轉(zhuǎn)換 Webhook 服務(wù)的引用。 如果 Webhook 在集群中運(yùn)行,則應(yīng)使用 ?service ?而不是 ?url?。 服務(wù)的名字空間和名稱是必需的。端口是可選的,默認(rèn)為 443。 路徑是可選的,默認(rèn)為?/?。

下面配置中,服務(wù)配置為在端口 ?1234?、子路徑 ?/my-path? 上被調(diào)用。 例子中針對(duì) ServerName ?my-service-name.my-service-namespace.svc?, 使用自定義 CA 包驗(yàn)證 TLS 連接。

  • apiextensions.k8s.io/v1
  • 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"
    ...
  • apiextensions.k8s.io/v1beta1
  • #  v1.16 中被棄用以推薦使用 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 請(qǐng)求和響應(yīng) 

請(qǐng)求

向 Webhooks 發(fā)起請(qǐng)求的動(dòng)詞是 POST,請(qǐng)求的 ?Content-Type? 為 ?application/json?。 請(qǐng)求的主題為 JSON 序列化形式的 apiextensions.k8s.io API 組的 ConversionReview API 對(duì)象。

Webhooks 可以在其 CustomResourceDefinition 中使用?conversionReviewVersions ?字段 設(shè)置它們接受的 ?ConversionReview ?對(duì)象的版本:

  • apiextensions.k8s.io/v1
  • apiVersion: apiextensions.k8s.io/v1
    kind: CustomResourceDefinition
    ...
    spec:
      ...
      conversion:
        strategy: Webhook
        webhook:
          conversionReviewVersions: ["v1", "v1beta1"]
          ...

    創(chuàng)建 ?apiextensions.k8s.io/v1? 版本的自定義資源定義時(shí), ?conversionReviewVersions?是必填字段。 Webhooks 要求支持至少一個(gè) ?ConversionReview ?當(dāng)前和以前的 API 服務(wù)器 可以理解的版本。

  • apiextensions.k8s.io/v1beta1
  • # v1.16 已棄用以推薦使用 apiextensions.k8s.io/v1
    apiVersion: apiextensions.k8s.io/v1beta1
    kind: CustomResourceDefinition
    ...
    spec:
      ...
      conversion:
        strategy: Webhook
        conversionReviewVersions: ["v1", "v1beta1"]
        ...

    創(chuàng)建 apiextensions.k8s.io/v1beta1 定制資源定義時(shí)若未指定 ?conversionReviewVersions?,則默認(rèn)值為 v1beta1。

API 服務(wù)器將 ?conversionReviewVersions ?列表中他們所支持的第一個(gè) ?ConversionReview ?資源版本發(fā)送給 Webhook。 如果列表中的版本都不被 API 服務(wù)器支持,則無法創(chuàng)建自定義資源定義。 如果某 API 服務(wù)器遇到之前創(chuàng)建的轉(zhuǎn)換 Webhook 配置,并且該配置不支持 API 服務(wù)器知道如何發(fā)送的任何 ?ConversionReview ?版本,調(diào)用 Webhook 的嘗試會(huì)失敗。

下面的示例顯示了包含在 ?ConversionReview ?對(duì)象中的數(shù)據(jù), 該請(qǐng)求意在將 ?CronTab ?對(duì)象轉(zhuǎn)換為 ?example.com/v1?:

  • apiextensions.k8s.io/v1
  • apiVersion: apiextensions.k8s.io/v1
    kind: ConversionReview
    request:
      # 用來唯一標(biāo)識(shí)此轉(zhuǎn)換調(diào)用的隨機(jī) UID
      uid: 705ab4f5-6393-11e8-b7cc-42010a800002
      
      # 對(duì)象要轉(zhuǎn)換到的目標(biāo) API 組和版本
      desiredAPIVersion: example.com/v1
      
      # 要轉(zhuǎn)換的對(duì)象列表
      # 其中可能包含一個(gè)或多個(gè)對(duì)象,版本可能相同也可能不同
      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
  • apiextensions.k8s.io/v1beta1
  • # v1.16 中已廢棄以推薦使用 apiextensions.k8s.io/v1
    apiVersion: apiextensions.k8s.io/v1beta1
    kind: ConversionReview
    request:
      # 用來唯一標(biāo)識(shí)此轉(zhuǎn)換調(diào)用的隨機(jī) UID
      uid: 705ab4f5-6393-11e8-b7cc-42010a800002
      
      # 對(duì)象要轉(zhuǎn)換到的目標(biāo) API 組和版本
      desiredAPIVersion: example.com/v1
      
      # 要轉(zhuǎn)換的對(duì)象列表
      # 其中可能包含一個(gè)或多個(gè)對(duì)象,版本可能相同也可能不同
      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

響應(yīng)

Webhooks 響應(yīng)包含 200 HTTP 狀態(tài)代碼、?Content-Type: application/json?, 在主體中包含 JSON 序列化形式的數(shù)據(jù),在 ?response ?節(jié)中給出 ConversionReview 對(duì)象(與發(fā)送的版本相同)。

如果轉(zhuǎn)換成功,則 Webhook 應(yīng)該返回包含以下字段的 ?response ?節(jié):

  • ?uid?,從發(fā)送到 webhook 的 ?request.uid? 復(fù)制而來
  • ?result?,設(shè)置為 ?{"status":"Success"}} ?
  • ?convertedObjects?,包含來自 ?request.objects? 的所有對(duì)象,均已轉(zhuǎn)換為 ?request.desiredVersion ?

Webhook 的最簡(jiǎn)單成功響應(yīng)示例:

  • apiextensions.k8s.io/v1
  • apiVersion: apiextensions.k8s.io/v1
    kind: ConversionReview
    response:
      # 必須與 <request.uid> 匹配
      uid: "705ab4f5-6393-11e8-b7cc-42010a800002"
      result:
        status: Success
      # 這里的對(duì)象必須與 request.objects 中的對(duì)象順序相同并且其 apiVersion
      # 被設(shè)置為 <request.desiredAPIVersion>。
      # kind、metadata.uid、metadata.name 和 metadata.namespace 等字段都不可
      # 被 Webhook 修改。
      # Webhook 可以更改 metadata.labels 和 metadata.annotations 字段值
      # Webhook 對(duì) metadata 中其他字段的更改都會(huì)被忽略
      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"
  • apiextensions.k8s.io/v1beta1
  • # v1.16 中已棄用以推薦使用  apiextensions.k8s.io/v1
    apiVersion: apiextensions.k8s.io/v1beta1
    kind: ConversionReview
    response:
      # 必須與 <request.uid> 匹配
      uid: "705ab4f5-6393-11e8-b7cc-42010a800002"
      result:
        status: Failed
      # 這里的對(duì)象必須與 request.objects 中的對(duì)象順序相同并且其 apiVersion
      # 被設(shè)置為 <request.desiredAPIVersion>。
      # kind、metadata.uid、metadata.name 和 metadata.namespace 等字段都不可
      # 被 Webhook 修改。
      # Webhook 可以更改 metadata.labels 和 metadata.annotations 字段值
      # Webhook 對(duì) metadata 中其他字段的更改都會(huì)被忽略
      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"

如果轉(zhuǎn)換失敗,則 Webhook 應(yīng)該返回包含以下字段的 ?response ?節(jié):

  • ?uid?,從發(fā)送到 Webhook 的 ?request.uid? 復(fù)制而來
  • ?result?,設(shè)置為 ?{"status": "Failed"}?
警告:
轉(zhuǎn)換失敗會(huì)破壞對(duì)定制資源的讀寫訪問,包括更新或刪除資源的能力。 轉(zhuǎn)換失敗應(yīng)盡可能避免,并且不可用于實(shí)施合法性檢查約束 (應(yīng)改用驗(yàn)證模式或 Webhook 準(zhǔn)入插件)。

來自 Webhook 的響應(yīng)示例,指示轉(zhuǎn)換請(qǐng)求失敗,并帶有可選消息:

  • apiextensions.k8s.io/v1
  •   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
  • apiextensions.k8s.io/v1beta1
  •   # v1.16 中棄用以推薦使用 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 對(duì)象

寫入對(duì)象時(shí),將使用寫入時(shí)指定的存儲(chǔ)版本來存儲(chǔ)。如果存儲(chǔ)版本發(fā)生變化, 現(xiàn)有對(duì)象永遠(yuǎn)不會(huì)被自動(dòng)轉(zhuǎn)換。然而,新創(chuàng)建或被更新的對(duì)象將以新的存儲(chǔ)版本寫入。 對(duì)象寫入的版本不再被支持是有可能的。

當(dāng)讀取對(duì)象時(shí),作為路徑的一部分,你需要指定版本。 如果所指定的版本與對(duì)象的持久版本不同,Kubernetes 會(huì)按所請(qǐng)求的版本將對(duì)象返回, 但是在滿足服務(wù)請(qǐng)求時(shí),被持久化的對(duì)象既不會(huì)在磁盤上更改,也不會(huì)以任何方式進(jìn)行 轉(zhuǎn)換(除了 ?apiVersion ?字符串被更改之外)。你可以以當(dāng)前提供的任何版本 來請(qǐng)求對(duì)象。

如果你更新一個(gè)現(xiàn)有對(duì)象,它將以當(dāng)前的存儲(chǔ)版本被重寫。 這是可以將對(duì)象從一個(gè)版本改到另一個(gè)版本的唯一辦法。

為了說明這一點(diǎn),請(qǐng)考慮以下假設(shè)的一系列事件:

  1. 存儲(chǔ)版本是 ?v1beta1?。你創(chuàng)建一個(gè)對(duì)象。該對(duì)象以版本 ?v1beta1 ?存儲(chǔ)。
  2. 你將為 CustomResourceDefinition 添加版本 ?v1?,并將其指定為存儲(chǔ)版本。
  3. 你使用版本 ?v1beta1 ?來讀取你的對(duì)象,然后你再次用版本 ?v1 ?讀取對(duì)象。 除了 apiVersion 字段之外,返回的兩個(gè)對(duì)象是完全相同的。
  4. 你創(chuàng)建一個(gè)新對(duì)象。對(duì)象以版本 ?v1 ?保存在存儲(chǔ)中。 你現(xiàn)在有兩個(gè)對(duì)象,其中一個(gè)是 ?v1beta1?,另一個(gè)是 ?v1?。
  5. 你更新第一個(gè)對(duì)象。該對(duì)象現(xiàn)在以版本 ?v1 ?保存,因?yàn)?nbsp;?v1 ?是當(dāng)前的存儲(chǔ)版本。

以前的存儲(chǔ)版本 

API 服務(wù)器在狀態(tài)字段 ?storedVersions ?中記錄曾被標(biāo)記為存儲(chǔ)版本的每個(gè)版本。 對(duì)象可能以任何曾被指定為存儲(chǔ)版本的版本保存。 存儲(chǔ)中不會(huì)出現(xiàn)從未成為存儲(chǔ)版本的版本的對(duì)象。

將現(xiàn)有對(duì)象升級(jí)到新的存儲(chǔ)版本 

棄用版本并刪除其支持時(shí),請(qǐng)?jiān)O(shè)計(jì)存儲(chǔ)升級(jí)過程。

選項(xiàng) 1: 使用存儲(chǔ)版本遷移程序(Storage Version Migrator)

  1. 運(yùn)行存儲(chǔ)版本遷移程序
  2. 從 CustomResourceDefinition 的 ?status.storedVersions? 字段中去掉 老的版本。

選項(xiàng) 2: 手動(dòng)將現(xiàn)有對(duì)象升級(jí)到新的存儲(chǔ)版本

以下是從 ?v1beta1 ?升級(jí)到 ?v1 ?的示例過程。

  1. 在 CustomResourceDefinition 文件中將 ?v1 ?設(shè)置為存儲(chǔ)版本,并使用 kubectl 應(yīng)用它。 ?storedVersions?現(xiàn)在是?v1beta1, v1?。
  2. 編寫升級(jí)過程以列出所有現(xiàn)有對(duì)象并使用相同內(nèi)容將其寫回存儲(chǔ)。 這會(huì)強(qiáng)制后端使用當(dāng)前存儲(chǔ)版本(即 ?v1?)寫入對(duì)象。
  3. 從 CustomResourceDefinition 的 ?status.storedVersions? 字段中刪除 ?v1beta1?。

說明:
?kubectl ?工具目前不能用于編輯或修補(bǔ) CRD 上的 ?status ?子資源:請(qǐng)參閱 kubectl Subresource Support KEP 了解更多細(xì)節(jié)。
從 CLI 給 ?status ?子資源打補(bǔ)丁的更簡(jiǎn)單的方法是使用 ?curl ?工具直接與 API 服務(wù)器交互,示例:
kubectl proxy &
curl --header "Content-Type: application/json-patch+json" \
  --request PATCH http://localhost:8001/apis/apiextensions.k8s.io/v1/customresourcedefinitions/<your CRD name here>/status \
  --data '[{"op": "replace", "path": "/status/storedVersions", "value":["v1"]}]'


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)