<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          使用kubebuilder開發(fā)簡單的Operator

          共 7965字,需瀏覽 16分鐘

           ·

          2021-05-25 21:38

          云原生技術(shù)通過方法論、工具集和最佳實踐重塑著整個軟件技術(shù)棧和生命周期,云原生對云計算服務(wù)方式與互聯(lián)網(wǎng)架構(gòu)進行整體性升級, 深刻改變著整個 IT 領(lǐng)域。云原生的核心是 kubernetes,圍繞 kubernetes 構(gòu)建滿足自身需求的 PaaS 平臺(應(yīng)用中心)是絕大數(shù)企業(yè)的訴求, 但是不同企業(yè)自身場景往往存在一定的差異,Operator 是最常見 kubernetes 拓展方式。本片博文,我將會給大家理清 Operator 的來龍去脈, 同時介紹如何通過 kubebuilder 快速開發(fā)一個簡單的 Operator。

          Operator 誕生的背景

          kubernetes 無法做到真正意義的開箱即用的,它與傳統(tǒng)的 PaaS 平臺不同,它僅僅只提供核心的基礎(chǔ)設(shè)施功能,但是還無法滿足用戶的最終需求,這里用戶主要指業(yè)務(wù)開發(fā)和業(yè)務(wù)運維, 比如說業(yè)務(wù)開發(fā)需要 CI/CD 工具實現(xiàn) Devops 的功能,原生 kubernetes 是不提供支持的,但是我們可以通過tekton這一個第三方工具實現(xiàn) DevOps 相關(guān)功能, 這也正是 kubernetes 區(qū)別傳統(tǒng)PaaS平臺的真正強大之處,其提供完善的擴展機制以及基于此而發(fā)展出來的海量的第三方工具和豐富的生態(tài)。

          Operator pattern首先由 CoreOS 提出,通過結(jié)合 CRD 和 custom controller 將特定應(yīng)用的運維知識轉(zhuǎn)換為代碼,實現(xiàn)應(yīng)用運維的自動化和智能化。Operator 允許 kubernetes 來管理復(fù)雜的,有狀態(tài)的分布式應(yīng)用程序,并由 kubernetes 對其進行自動化管理,例如,etcd operator 能夠創(chuàng)建并管理一組 etcd 集群, 定制化的 controller 組件了解這些資源,知道如何維護這些特定的應(yīng)用。

          隨著 kubernetes 的功能越來越復(fù)雜,其需要管理的資源在高速增長,對應(yīng)的 API 和 controller 的數(shù)量也愈發(fā)無法控制, kubernetes 變得很臃腫,很多不必要的 API 和功能將出現(xiàn)在每次安裝的集群中。

          為了解決這個問題,CRD 應(yīng)運而生,CRD 由 TPR(Third Part Resource v1.2 版本引入)演化而來,v1.7 進入 beta,v1.8 進入穩(wěn)定, 通過 CRD,kubernetes 可以動態(tài)的添加并管理資源。CRD 解決了結(jié)構(gòu)化數(shù)據(jù)存儲的問題,Controller 則用來跟蹤這些資源, 保證資源的狀態(tài)滿足期望值。CRD+Controller=decalartive API,聲明式 API 設(shè)計是 kubernetes 重要的設(shè)計思想, 該設(shè)計保證能夠動態(tài)擴展 kubernetes API,這種模式也正是 Operator pattern。

          kubernetes 本身也在通過 CRD 添加新功能,我們有什么理由不使用呢?

          使用場景總結(jié)及舉例

          CRD+custom controller 已經(jīng)被廣泛地使用,按使用場景可劃分為以下兩種:

          1. 通用型 controller: 這種場景和 kubernetes 內(nèi)置的apps controller類似,主要解決特定通用類型應(yīng)用的管理
          2. Operator: 該場景用于解決一個特定應(yīng)用的自動化管理

          通用型 controller 往往是 kubernetes 平臺側(cè)用戶,如各大云廠商和 kubernetes 服務(wù)提供商,Operator 則是各種軟件服務(wù)提供商, 他們設(shè)計時面向單一應(yīng)用,很多開源的應(yīng)用的 operator 可以在 operator hub 中獲取。我列舉一些示例供大家參考:

          通用型 Controller

          1. 阿里的 cafedeploymentcontroller 解決金融場景下分布式應(yīng)用特殊需求。
          2. oam-kubernetes-runtime 實現(xiàn)了 Application Model (OAM),以系統(tǒng)可持續(xù)的方式拓展 kubernetes

          Operator

          1. etcd operator
          2. Prometheus operator

          通用型Controller與kubernetes自帶的幾個controller類似,旨在解決一些通用的應(yīng)用模型,而Operator則更加面向單個特定應(yīng)用, 這兩者沒有本質(zhì)的區(qū)別。

          如何開發(fā) CRD

          作為kubernetes開發(fā)者,如何開發(fā) CRD+Custom cntroller 呢?其實官方提供示例項目sample-controller供開發(fā)者參考,開發(fā)流程大致有以下幾個過程:

          1. 初始化項目結(jié)構(gòu)(可根據(jù) sample controller 修改)
          2. 定義 CRD
          3. 生成代碼
          4. 初始化 controller
          5. 實現(xiàn) controller 具體邏輯

          其中步驟 2,5 是核心業(yè)務(wù)邏輯,其余步驟完全可以通過自動生成的方式省略,到目前,社區(qū)有兩個成熟的腳手架工具用于簡化開發(fā),一個是有 kube-sig 維護的 kubebuilder, 另一個是由 redhat 維護的 operator-sdk,這兩個工具都是基于 controller-runtime 項目而實現(xiàn),用戶可自行選擇,筆者用的是 kubebuilder。使用 kubebuilder 能夠幫助我們節(jié)省以下工作:

          如果你想要快速構(gòu)建 CRD 和 Custom controller,腳手架工具是個不錯的選擇,如果是學(xué)習(xí)目的,建議結(jié)合 sample-controller 和 kubernetes controller 相關(guān) 源碼。

          kubebuilder 詳解

          kubebuilder 是一個幫助開發(fā)者快速開發(fā) kubernetes API 的腳手架命令行工具,其依賴庫 controller-tools 和 controller-runtime, controller-runtime 簡化 kubernetes controller 的開發(fā),并且對 kubernetes 的幾個常用庫進行了二次封裝, 以簡化開發(fā)者使用。controller-tool 主要功能是代碼生成。下圖是使用 kubebuilder 的工作流程圖:

          文章后面會結(jié)合一個簡單示例來介紹開發(fā)流程。

          kubebuilder 有非常良好的文檔,包括一個從零開始的示例,您應(yīng)該以文檔為主。

          使用 kubebuilder 開發(fā)一個 CRD

          本次示例創(chuàng)建一個通用的Application資源,Application 包含一個子資源 Deployment 以及一個 Count 資源, 每當(dāng) Application 進行被重新協(xié)調(diào)Reconcil,Count 會進行自增。

          全部代碼請參考代碼倉

          前提(你需要提前了解的)

          1. Golang 開發(fā)者,kubernetes 大量使用Code Generate這一功能來自動生成重復(fù)性代碼
          2. 閱讀 kubernetes controller 的代碼
          3. 閱讀 kubebuilder 的文檔
          4. 了解 kustomize

          開發(fā)步驟及主要代碼展示

          首先,根據(jù)你的開發(fā)環(huán)境安裝 kubebuilder 工具,mac 下通過 homebrew 安裝命令如下:

          BASH
          ?  ~ brew install kubebuilder
          ?  ~ kubebuilder version
          Version: version.Version{KubeBuilderVersion:"unknown", KubernetesVendor:"unknown", GitCommit:"$Format:%H$", BuildDate:"1970-01-01T00:00:00Z", GoOs:"unknown", GoArch:"unknown"}

          安裝完畢后,首先創(chuàng)建項目目錄custom-controller并使用go mod初始化項目

          BASH
          ?  cd custom-controllers
          ?  ls
          ?  go mod init controllers.happyhack.io

          接著,使用 kubebuilder 初始化項目,生成相關(guān)文件和目錄,并創(chuàng)建 CRD 資源

          BASH
          # 使用kubebuilder初始化項目
          ?  custom-controllers kubebuilder init --domain controller.daocloud.io --license apache2 --owner "Holder"
          # 創(chuàng)建CRD資源
          ?  custom-controllers kubebuilder create api --group controller --version v1 --kind Application
          Create Resource [y/n]
          y
          Create Controller [y/n]
          y
          Writing scaffold for you to edit...
          api/v1/application_types.go
          controllers/application_controller.go
          Running make:
          $ make
          /Users/donggang/Documents/Code/golang/bin/controller-gen object:headerFile="hack/huilerplate.go.txt" paths="./..."
          go fmt ./...
          go vet ./...
          go build -o bin/manager main.go

          到目前,該項目就已經(jīng)能夠運行了,不過我們需要添加我們自己業(yè)務(wù)代碼,主要包括修改 CRD 定義和添加 controller 邏輯兩部分。首先修改 API 資源定義即 CRD 定義,Application 包含一個 Deployment,我們可以參考 kubernetes Deployment 與 Pod 這兩個類型之間的關(guān)系設(shè)計 Application 和 Deployment, Deployment 通過字段spec.template來描述如何創(chuàng)建 Pod,DeploymentTemplateSpec描述了該如何創(chuàng)建 Deployment,

          GOLANG
          // PodTemplateSpec describes the data a deployment should have when created from a template
          type DeploymentTemplateSpec struct {
           // Standard object's metadata.
           // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
           // +optional
           metav1.ObjectMeta `json:"metadata,omitempty"`

           // Specification of the desired behavior of the pod.
           // More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status
           Spec v12.DeploymentSpec `json:"spec,omitempty"`
          }

          API 描述定義完成了,接下來需要我們來進行具體業(yè)務(wù)邏輯實現(xiàn)了,編寫具體 controller 實現(xiàn),首先我們簡單梳理 controller 的主要邏輯

          • 當(dāng)一個 application 被創(chuàng)建時,需要創(chuàng)建對應(yīng)的 deployment,當(dāng) application 被刪除或更新時,對應(yīng) Deployment 也需要被刪除或更新
          • 當(dāng) application 對應(yīng)的子資源 deployment 被其他客戶端刪除或更新時,controller 需要重建或恢復(fù)它
          • 最后一步更新 application 的 status,這里即 count 加 1

          我們在方法func(r *ApplicationReconciler) Reconcile(req ctrl.Request)(ctrl.Result,error)實現(xiàn)相關(guān)邏輯, 當(dāng)然當(dāng)業(yè)務(wù)邏輯比較復(fù)雜時,可以拆分為多個方法。

          GOLANG
          func (r *ApplicationReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
           ctx := context.Background()
           log := r.Log.WithValues("application", req.NamespacedName)

           var app controllerv1.Application
           if err := r.Get(ctx, req.NamespacedName, &app); err != nil {
            log.Error(err, "unable to fetch app")
            return ctrl.Result{}, client.IgnoreNotFound(err)
           }

           selector, err := metav1.LabelSelectorAsSelector(app.Spec.Selector)
           if err != nil {
            log.Error(err, "unable to convert label selector")
            return ctrl.Result{}, err
           }

           var deploys v12.DeploymentList
           if err := r.List(ctx, &deploys, client.InNamespace(req.Namespace), client.MatchingLabelsSelector{Selector: selector}); err != nil {
            if errors.IsNotFound(err) {
             deploy, err := r.constructDeploymentForApplication(&app)
             if err != nil {
              log.Error(err, "unable to construct deployment")
              return ctrl.Result{
               RequeueAfter: time.Second * 1,
              }, err
             }
             if err = r.Create(ctx, deploy); err != nil {
              return ctrl.Result{RequeueAfter: time.Second * 1}, err
             }
            }
           }
           ...
          }

          完成Reconcile方法后,我們可以修改config目錄的示例yaml,來進行本地測試了。

          官方開發(fā)自定義 Controller 的指導(dǎo)

          kubernetes開箱自帶了多個controller,這些controller在我們開發(fā)時具有非常重要的參考價值,同時社區(qū)也總結(jié)了的 controller 開發(fā)所需要遵循十一條原則, 但是請大家結(jié)合實際場景靈活運用這些原則:

          img

          總結(jié)及展望

          本文簡單介紹了 CRD 以及如何使用腳手架工具 kubebuilder 幫助我們開發(fā)自定義 controller,當(dāng)然這個 controller 示例的邏輯比較簡單, 在實際場景中,我們會遇到很多的挑戰(zhàn),比如controller 的邏輯會比較復(fù)雜、需要通過多個controller等。作為kubernetes開發(fā)者, Controller開發(fā)是一項必不可少的技能。

          原文鏈接:https://blog.happyhack.io/2020/10/12/kubernetes-crd-day1/

          瀏覽 96
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  99精品一级毛片 | 欧美成人一区二区三区片 | 欧美一级黄视频 | 国产精品国产 | 六月丁香伊人 |