歡迎訪問網易雲社區,了解更多網易技術產品運營經驗。
前言
默認讀者有kubernetes基礎概念的背景知識,因此基礎概念例如有狀態、pod、Replica Sets、Deployments、statefulsets等不在此文詳細闡述。 可以看我之前的一些關於kubernetes的文章:
kubernetes 1.3管中窺豹- RS(Replica Sets)
kubernetes pod&container生命周期淺析
kubernetes1.6管中窺豹-StatefulSets概念、約束、原理及實例
本文主要介紹一個1.7+以后出現的新概念CRD(CustomResourceDefinition )的概念、使用場景及實例。
CRD歷史來源 | |
---|---|
k8s1.6~1.7 | TRP(CRD的前身):Third Party Resource。 |
k8s1.7+ | CRD: Custom Resource Definition。 |
CRD的概念
Custom resources:是對K8S API的擴展,代表了一個特定的kubetnetes的定制化安裝。在一個運行中的集群中,自定義資源可以動態注冊到集群中。注冊完畢以后,用戶可以通過kubelet創建和訪問這個自定義的對象,類似於操作pod一樣。
Custom controllers:Custom resources可以讓用戶簡單的存儲和獲取結構化數據。只有結合控制器才能變成一個真正的declarative API(被聲明過的API)。控制器可以把資源更新成用戶想要的狀態,並且通過一系列操作維護和變更狀態。定制化控制器是用戶可以在運行中的集群內部署和更新的一個控制器,它獨立於集群本身的生命周期。 定制化控制器可以和任何一種資源一起工作,當和定制化資源結合使用時尤其有效。
Operator模式 是一個customer controllers和Custom resources結合的例子。它可以允許開發者將特殊應用編碼至kubernetes的擴展API內。
如何添加一個Custom resources到我的kubernetes集群呢? kubernetes提供了兩種方式將Custom resources添加到集群。
1. Custom Resource Definitions (CRDs):更易用、不需要編碼。但是缺乏靈活性。
2. API Aggregation:需要編碼,允許通過聚合層的方式提供更加定制化的實現。
本文重點講解Custom Resource Definitions (CRD)的使用方法。
CRD使用場景
假設需要在原生kubernetes完成一些額外的功能開發,而且想使用restful風格的API 去調用這個功能。比如像開發容器保存鏡像或者重啟鏡像等操作(一般都通過命令發送給容器內部完成)。就可以在原生kubernetes上增加一個CRD,命名為task。通過task觸發一些邏輯。當使用apiserver下發這個task創建時,Custom controllers watch到這個task就開始處理相關業務邏輯,然后通過agent調用docker命令完成容器保存鏡像功能並且重啟容器。當Custom controllers watch到pod重新運行的時候,本次操作完成。 流程圖如下:
CRD使用示例
如果想要完成上述場景的功能,需要定義一個CRD,並且創建出來。 舉例如下,以下是一個可以在1.9集群環境中創建成功的crd yaml文件。
apiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata: # name must match the spec fields below, and be in the form: <plural>.<group> name: tasks.163yun.comspec: # group name to use for REST API: /apis/<group>/<version> group: 163yun.com # version name to use for REST API: /apis/<group>/<version> version: v1 # either Namespaced or Cluster scope: Namespaced names: # plural name to be used in the URL: /apis/<group>/<version>/<plural> plural: tasks # singular name to be used as an alias on the CLI and for display singular: task # kind is normally the CamelCased singular type. Your resource manifests use this. kind: Task # shortNames allow shorter string to match your resource on the CLI shortNames: - task
其中幾個關鍵要素是name、group、scope以及names里面的一些定義。
name:用於定義CRD的名字,后綴需要跟group一致,例如tasks.163yun.com,前綴需要跟names中的plural一致。
group以及version用於標識restAPI:即/apis//。 上文中的接口前面一部分就是/apis/163yun.com/v1
scope: 表明作用於,可以是基於namespace的,也可以是基於集群的。 如果是基於namespace的。則API格式為:/apis/{group}/v1/namespaces/{namespace}/{spec.names.plural}/… 如果是基於cluster的。則API格式為:/apis/{group}/v1/{spec.names.plural}/… 上文創建的CRD的API則為:/apis/163yun.com/v1/namespaces/{namespace}/tasks
names:描述了一些自定義資源的名字以及類型的名字(重點是plural定義以及kind定義,因為會在url或者查詢資源中用的到)。
當以上面的模板創建出來一個CRD后,可以查到crd的信息:
root@hzyq-k8s-qa-16-master:~/cxq# kubectl get CustomResourceDefinition tasks.163yun.com -o yaml apiVersion: apiextensions.k8s.io/v1beta1kind: CustomResourceDefinitionmetadata: creationTimestamp: 2018-03-16T06:17:03Z generation: 1 name: tasks.163yun.com resourceVersion: "35442027" selfLink: /apis/apiextensions.k8s.io/v1beta1/customresourcedefinitions/tasks.163yun.com uid: a538030c-28e1-11e8-b047-fa163ef9812dspec: group: 163yun.com names: kind: Task listKind: TaskList plural: tasks shortNames: - task singular: task scope: Namespaced version: v1status: acceptedNames: kind: Task listKind: TaskList plural: tasks shortNames: - task singular: task conditions: - lastTransitionTime: 2018-03-16T06:17:03Z message: no conflicts found reason: NoConflicts status: "True" type: NamesAccepted - lastTransitionTime: 2018-03-16T06:17:03Z message: the initial names have been accepted reason: InitialNamesAccepted status: "True" type: Established
這時查詢crd中定義的task類型的資源,是空的:
root@hzyq-k8s-qa-16-master:~/cxq# kubectl get task -o yaml apiVersion: v1items: []kind: Listmetadata: resourceVersion: "" selfLink: ""
這時需要自定義一個task類型的模板,創建,以使得task可以觸發自定義的一些事件
root@hzyq-k8s-qa-16-master:~/cxq# cat cxq-task.yaml apiVersion: "163yun.com/v1"kind: Taskmetadata: name: cxq-nce-taskspec: cronSpec: "* * * * /5" image: my-awesome-cron-image root@hzyq-k8s-qa-16-master:~/cxq# kubectl create -f cxq-task.yaml task "cxq-nce-task" created root@hzyq-k8s-qa-16-master:~/cxq# kubectl get task -o yamlapiVersion: v1items:- apiVersion: 163yun.com/v1 kind: Task metadata: clusterName: "" creationTimestamp: 2018-03-16T06:43:10Z labels: {} name: cxq-nce-task namespace: default resourceVersion: "35444352" selfLink: /apis/163yun.com/v1/namespaces/default/tasks/cxq-nce-task uid: 4ad237aa-28e5-11e8-b047-fa163ef9812d spec: cronSpec: '* * * * /5' image: my-awesome-cron-imagekind: Listmetadata: resourceVersion: "" selfLink: ""
注意由於CRD和自定義的Task資源本身是namespace無關的,因此對所有namespace都可見。如果指定了scope為namespace。那么創建的自定義task也需要指定namespace,如果不指定的話,系統會自動將task分配到default 的namespace下。
這時可以通過task的url去對自定義的task資源進行操作,或者watch。結合上一節的流程圖來完成實現自定義功能的目的。以下是調用watch接口對task資源進行長連接監控(變化)。
root@hzyq-k8s-qa-16-master:~/cxq# curl http://10.180.156.79:8080/apis/163yun.com/v1/namespaces/default/tasks?watch=true {"type":"ADDED","object":{"apiVersion":"163yun.com/v1","kind":"Task","metadata":{"clusterName":"","creationTimestamp":"2018-03-16T06:43:10Z","labels":{},"name":"cxq-nce-task","namespace":"default","resourceVersion":"35444352","selfLink":"/apis/163yun.com/v1/namespaces/default/tasks/cxq-nce-task","uid":"4ad237aa-28e5-11e8-b047-fa163ef9812d"},"spec":{"cronSpec":"* * * * /5","image":"my-awesome-cron-image"}}}
總結
CRD提供了一種無須編碼就可以擴展原生kubenetes API接口的方式。很適合在雲應用中擴展kubernetes的自定義接口和功能。在一些無須太多定制和靈活的開發場景下,CRD的方式已經足夠使用。如果想更為靈活的添加邏輯就需要參考API Aggregation的使用了。
網易雲容器服務為用戶提供了無服務器容器,讓企業能夠快速部署業務,輕松運維服務。容器服務支持彈性伸縮、垂直擴容、灰度升級、服務發現、服務編排、錯誤恢復及性能監測等功能。點擊免費試用
相關閱讀:淺談 kubernetes service 那些事(上篇)
淺談 kubernetes service 那些事 (下篇)
本文來自網易實踐者社區,經作者崔曉晴授權發布。
相關文章:
【推薦】 初識Continuation