天天看點

「雲原生」Kubernetes CRD 實戰講解(Custom Resource Definition)

作者:大資料老司機

一、概述

CRD(Custom Resource Definition) 本身是一種 Kubernetes 内置的資源類型,即自定義資源的定義,用于描述使用者定義的資源是什麼樣子。CRD 的相關概念:
  • CRD 是 v1.7 +新增的無需改變代碼 就可以擴充 Kubernetes API 的機制,用來管理自定義對象。它實際上是ThirdPartyResources(TPR) 的更新版本,而 TPR 已經在 v1.8 中删除。
  • 從 Kubernetes 的使用者角度來看,所有東西都叫資源 Resource,就是 Yaml 裡的字段 Kind 的内容,例如 Service、Deployment 等。
  • 除了常見内置資源之外,Kubernetes 允許使用者自定義資源 Custom Resource,而 CRD 表示自定義資源的定義。
  • 當你建立新的 CustomResourceDefinition(CRD)時,Kubernetes API 伺服器會為你所指定的每個版本生成一個新的 RESTful 資源路徑。
  • 基于 CRD 對象所建立的自定義資源可以是名字空間作用域的,也可以是叢集作用域的, 取決于 CRD 對象 spec.scope 字段的設定。
  • 定義 CRD 對象的操作會使用你所設定的名字和模式定義(Schema)建立一個新的定制資源, Kubernetes API 負責為你的定制資源提供存儲和通路服務。 CRD 對象的名稱必須是合法的 DNS 子域名。

DNS 子域名

很多資源類型需要可以用作 DNS 子域名的名稱。名稱必須滿足如下規則:
  • 不能超過 253 個字元
  • 隻能包含小寫字母、數字,以及 '-' 和 '.'
  • 必須以字母數字開頭
  • 必須以字母數字結尾

CRD 官方文檔:https://kubernetes.io/zh-cn/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/

「雲原生」Kubernetes CRD 實戰講解(Custom Resource Definition)

二、定制資源

定制資源(Custom Resource) 是對 Kubernetes API 的擴充。
「雲原生」Kubernetes CRD 實戰講解(Custom Resource Definition)

1)定制資源 和 定制控制器

  • 資源(Resource) 是 Kubernetes API 中的一個端點, 其中存儲的是某個類别的 API 對象的一個集合。 例如内置的 Pod 資源包含一組 Pod 對象。
  • 定制資源(Custom Resource) 是對 Kubernetes API 的擴充, 定制資源所代表的是對特定 Kubernetes 安裝的一種定制。 不過,很多 Kubernetes 核心功能現在都用定制資源來實作,這使得 Kubernetes 更加子產品化。
  • 定制資源可以通過動态注冊的方式在運作中的叢集内或出現或消失,叢集管理者可以獨立于叢集更新定制資源。
  • 一旦某定制資源被安裝,使用者可以使用 kubectl 來建立和通路其中的對象, 就像他們為 Pod 這種内置資源所做的一樣。

2)定制控制器

  • 就定制資源本身而言,它隻能用來存取結構化的資料。 當你将定制資源與定制控制器(Custom Controller) 結合時, 定制資源就能夠提供真正的聲明式 API(Declarative API)。
  • Operator 模式就是将定制資源與定制控制器相結合的。

3)Operator 介紹

Kubernetes CRD Operator = kubernetes CRD + custom controller
  • Operator 是由 CoreOS 開發的,用來擴充 Kubernetes API,特定的應用程式控制器,它用來建立、配置和管理複雜的有狀态應用,如資料庫、緩存和監控系統。
  • Operator 基于 Kubernetes 的資源和控制器概念之上建構,但同時又包含了應用程式特定的領域知識。建立Operator 的關鍵是CRD(自定義資源)的設計。
  • Operator是 Kubernetes 的擴充軟體, 它利用定制資源管理應用及其元件。 Operator 遵循 Kubernetes 的理念,特别是在控制器方面。
  • Operator 模式會封裝你編寫的(Kubernetes 本身提供功能以外的)任務自動化代碼。
  • Kubernetes 的 Operator 模式概念允許你在不修改 Kubernetes 自身代碼的情況下, 通過為一個或多個自定義資源關聯控制器來擴充叢集的能力。
  • Operator 是 Kubernetes API 的用戶端。Operator 旨在為其管理的資源提供強大的自動化功能,是以它還需要一些額外的支援性代碼。

1、Operator Framework

Operator Framework 同樣也是 CoreOS 開源的一個用于快速開發 Operator 的工具包,該架構包含兩個主要的部分:
  • Operator SDK——無需了解複雜的 Kubernetes API 特性,即可讓你根據你自己的專業知識建構一個 Operator 應用。
  • Operator Lifecycle Manager——監督跨 Kubernetes 叢集運作的所有 Operator(及其相關服務)的生命周期的安裝、更新和管理。
「雲原生」Kubernetes CRD 實戰講解(Custom Resource Definition)

2、Operator 安裝

Operator SDK 提供以下工作流來開發一個新的 Operator:

  • 使用 SDK 建立一個新的 Operator 項目
  • 通過添加自定義資源(CRD)定義新的資源 API
  • 指定使用 SDK API 來 watch 的資源
  • 定義 Operator 的協調(reconcile)邏輯
  • 使用 Operator SDK 建構并生成 Operator 部署清單檔案

3、安裝 Operator SDK

下載下傳位址:https://github.com/operator-framework/operator-sdk/releases

operator sdk 官方文檔:https://sdk.operatorframework.io/docs/installation/

wget https://github.com/operator-framework/operator-sdk/releases/download/v1.23.0/operator-sdk_linux_amd64

# 添加可執行權限
 
chmod +x operator-sdk_linux_amd64
 
# 添加軟鍊
ln -s /opt/k8s/crd/Operator/operator-sdk_linux_amd64 /usr/local/bin/operator-sdk           

4、Operator 簡單使用

【示例1】快速簡單使用

operator-sdk init --domain=example.com --repo=github.com/example-inc/memcached-operator
# 步驟二: 建立 API(operator-sdk create api --group cache --version v1 --kind Memcached --resource=true --controller=true)
operator-sdk create api --group cache --version v1 --kind Memcached --resource=true --controller=true
# 步驟三: 建構鏡像-需要本地存在 docker 環境(make docker-build IMG=liumiaocn/memcache:v1)
make docker-build IMG=liumiaocn/memcache:v1
# 步驟四: 運作Operator-需要環境具備 K8s/K3s(make install && make deploy IMG=liumiaocn/memcache:v1)
make install && make deploy IMG=liumiaocn/memcache:v1
# 步驟五:建立自定義資源
kubectl apply -f config/samples/cache_v1_memcached.yaml
# 步驟六:删除CR和相關資源(kubectl delete -f config/samples/cache_v1_memcached.yaml)
kubectl delete -f config/samples/cache_v1_memcached.yaml           

這裡隻是簡單的安裝部署使用,後面會單獨拿一篇文章來詳細介紹Operator 。

4)Kubernetes API 聚合層

  • 使用聚合層(Aggregation Layer),使用者可以通過附加的 API 擴充 Kubernetes, 而不局限于 Kubernetes 核心 API 提供的功能。 這裡的附加 API 可以是現成的解決方案,比如 metrics server, 或者你自己開發的 API。
  • 聚合層不同于 定制資源(Custom Resources)。 後者的目的是讓 kube-apiserver 能夠識别新的對象類别(Kind)。
  • 聚合層在 kube-apiserver 程序内運作。在擴充資源注冊之前,聚合層不做任何事情。
  • 要注冊 API,你可以添加一個 APIService 對象,用它來 “申領” Kubernetes API 中的 URL 路徑。 自此以後,聚合層将把發給該 API 路徑的所有内容(例如 /apis/myextension.mycompany.io/v1/…) 轉發到已注冊的 APIService。

5)聲明式 APIs

典型地,在聲明式 API 中:

  • 你的 API 包含相對而言為數不多的、尺寸較小的對象(資源)。
  • 對象定義了應用或者基礎設施的配置資訊。
  • 對象更新操作頻率較低。
  • 通常需要人來讀取或寫入對象。
  • 對象的主要操作是 CRUD 風格的(建立、讀取、更新和删除)。
  • 不需要跨對象的事務支援:API 對象代表的是期望狀态而非确切實際狀态。

指令式 API(Imperative API)與聲明式有所不同。 以下迹象表明你的 API 可能不是聲明式的:

  • 用戶端發出“做這個操作”的指令,之後在該操作結束時獲得同步響應。
  • 用戶端發出“做這個操作”的指令,并獲得一個操作 ID,之後需要檢查一個 Operation(操作) 對象來判斷請求是否成功完成。
  • 你會将你的 API 類比為遠端過程調用(Remote Procedure Call,RPCs)。
  • 直接存儲大量資料;例如每個對象幾 kB,或者存儲上千個對象。
  • 需要較高的通路帶寬(長期保持每秒數十個請求)。
  • 存儲有應用來處理的最終使用者資料(如圖檔、個人辨別資訊(PII)等)或者其他大規模資料。
  • 在對象上執行的正常操作并非 CRUD 風格。

6)添加定制資源

Kubernetes 提供了兩種方式供你向叢集中添加定制資源:

  • CRD 相對簡單,建立 CRD 可以不必程式設計。
  • API 聚合 需要程式設計,但支援對 API 行為進行更多的控制,例如資料如何存儲以及在不同 API 版本間如何轉換等。

Kubernetes 提供這兩種選項以滿足不同使用者的需求,這樣就既不會犧牲易用性也不會犧牲靈活性。

  • 聚合 API指的是一些下位的 API 伺服器,運作在主 API 伺服器後面;主 API 伺服器以代理的方式工作。這種組織形式稱作 API 聚合(API Aggregation,AA) 。 對使用者而言,看起來僅僅是 Kubernetes API 被擴充了。
  • CRD 允許使用者建立新的資源類别同時又不必添加新的 API 伺服器。 使用 CRD 時,你并不需要了解 API 聚合。
CRD 聚合 API
無需程式設計。使用者可選擇任何語言來實作 CRD 控制器。 需要程式設計,并建構可執行檔案和鏡像。
無需額外運作服務;CRD 由 API 伺服器處理。 需要額外建立服務,且該服務可能失效。
一旦 CRD 被建立,不需要持續提供支援。Kubernetes 主要節點更新過程中自動會帶入缺陷修複。 可能需要周期性地從上遊提取缺陷修複并更新聚合 API 伺服器。
無需處理 API 的多個版本;例如,當你控制資源的用戶端時,你可以更新它使之與 API 同步。 你需要處理 API 的多個版本;例如,在開發打算與很多人共享的擴充時。
僅支援 CRUD 操作,例如 "logs" 或 "exec"的操作是不支援的。 支援 CRUD 之外的操作。

7)通路定制資源

Kubernetes 用戶端庫可用來通路定制資源。 并非所有用戶端庫都支援定制資源。Go 和 Python 用戶端庫是支援的。

當你添加了新的定制資源後,可以用如下方式之一通路它們:

  • kubectl
  • Kubernetes 動态用戶端(DynamicClient),可以對任意Kubernetes資源進行RESTFful操作,包括CRD自定義資源。
  • 你所編寫的 REST 用戶端
  • 使用 Kubernetes 用戶端生成工具 所生成的用戶端。生成用戶端的工作有些難度,不過某些項目可能會随着 CRD 或 聚合 API 一起提供一個用戶端

三、CRD 示例示範

1)建立 CRD (定制資源)

當你建立新的 CustomResourceDefinition(CRD)時,Kubernetes API 伺服器會為你所指定的每個版本生成一個新的 RESTful 資源路徑。 基于 CRD 對象所建立的自定義資源可以是名字空間作用域的,也可以是叢集作用域的, 取決于 CRD 對象 spec.scope 字段的設定。
cat > resourcedefinition.yaml << EOF
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  # 名字必需與下面的 spec 字段比對,并且格式為 '<名稱的複數形式>.<組名>'
  name: crontabs.stable.example.com
spec:
  # 組名稱,用于 REST API: /apis/<組>/<版本>
  group: stable.example.com
  # 列舉此 CustomResourceDefinition 所支援的版本
  versions:
    - name: v1
      # 每個版本都可以通過 served 标志來獨立啟用或禁止
      served: true
      # 其中一個且隻有一個版本必需被标記為存儲版本
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                cronSpec:
                  type: string
                image:
                  type: string
                replicas:
                  type: integer
  # 可以是 Namespaced 或 Cluster
  scope: Namespaced
  names:
    # 名稱的複數形式,用于 URL:/apis/<組>/<版本>/<名稱的複數形式>
    plural: crontabs
    # 名稱的單數形式,作為指令行使用時和顯示時的别名
    singular: crontab
    # kind 通常是單數形式的駝峰命名(CamelCased)形式。你的資源清單會使用這一形式。
    kind: CronTab
    # shortNames 允許你在指令行使用較短的字元串來比對資源
    shortNames:
    - ct
EOF           

執行建立

kubectl apply -f resourcedefinition.yaml
           

這樣一個新的受名字空間限制的 RESTful API 端點會被建立在:

/apis/stable.example.com/v1/namespaces/
           

對象的 kind 将是來自你上面建立時 所用的 spec 中指定的 CronTab。

Kubernetes(k8s)API 的 操作可以參考我之前的文章:Kubernetes(k8s)API Server詳解

kubectl get --raw /apis/stable.example.com/v1/
kubectl get --raw /apis/stable.example.com/v1/|python -m json.tool           
「雲原生」Kubernetes CRD 實戰講解(Custom Resource Definition)
「雲原生」Kubernetes CRD 實戰講解(Custom Resource Definition)

2)建立定制對象(定制控制器)

在建立了 CustomResourceDefinition 對象之後,你可以建立定制對象(Custom Objects)。定制對象可以包含定制字段。這些字段可以包含任意的 JSON 資料。 在下面的例子中,在類别為 CronTab 的定制對象中,設定了cronSpec 和 image 定制字段。類别 CronTab 來自你在上面所建立的 CRD 的規約。
cat >my-crontab.yaml<<EOF
apiVersion: "stable.example.com/v1"
kind: CronTab
metadata:
  name: my-new-cron-object
spec:
  cronSpec: "* * * * */5"
  image: my-awesome-cron-image
EOF           

并執行建立指令:

kubectl apply -f my-crontab.yaml           

你就可以使用 kubectl 來管理你的 CronTab 對象了。例如:

kubectl get crontab
kubectl get ct -o yaml           
「雲原生」Kubernetes CRD 實戰講解(Custom Resource Definition)

3)删除 CustomResourceDefinition

當你删除某 CustomResourceDefinition 時,伺服器會解除安裝其 RESTful API 端點,并删除伺服器上存儲的所有定制對象。

kubectl delete -f resourcedefinition.yaml
kubectl get crontabs           

Kubernetes CRD 和 控制器的講解就先到這裡,關于更多的CRD 介紹,可以參考官方文檔,有任何疑問,也可以歡迎給我留言哦,後續持續更新【雲原生和大資料】相關的文章,請小夥伴耐心等待~

繼續閱讀