kubebuilder(1)-安裝和使用

導讀: 作為云原生的從業(yè)者,多多少少也會聽說CRD(Custom Resource Definition)和operator,但是說實話開發(fā)起來挺繁瑣的,而且對初學者也不友好。還好社區(qū)目前有好使的腳手架:kubebuilderoperator-sdk,目前個人感覺大家會往前者站隊,畢竟k8s自家的,索性就學著用它來嘗試開發(fā)operator了??紤]到篇幅和觀感問題,這里就只介紹最基本的使用,像finalizerwebhook建議直接查官方文檔,code邏輯另外寫一篇心得。

1.安裝

安裝參考官方指南, 由于github下載太慢我就用碼云fork了源文件來安裝的:

git clone https://gitee.com/henrywangx/kubebuilder.git
cd kubebuilder
make build
cp bin/kubebuilder $GOPATH/bin

2.使用

kubebuilder依賴go module所以要打開go module環(huán)境變量:export GO111MODULE=on, 另外proxy或者墻的原因,先設一下go mod的proxy:export GOPROXY=https://goproxy.io, 然后就可以開始使用了??偨Y就是要:

export GO111MODULE=on
export GOPROXY=https://goproxy.io

2.1創(chuàng)建project

mkdir $GOPATH/src/demo
cd $GOPATH/src/demo
kubebuilder init --domain demo.com --license apache2 --owner "xiong"

然后呢check一下當前文件夾:

tree .
.
├── Dockerfile
├── Makefile
├── PROJECT
├── bin
│   └── manager
├── config
│   ├── certmanager
│   │   ├── certificate.yaml
│   │   ├── kustomization.yaml
│   │   └── kustomizeconfig.yaml
│   ├── default
│   │   ├── kustomization.yaml
│   │   ├── manager_auth_proxy_patch.yaml
│   │   ├── manager_webhook_patch.yaml
│   │   └── webhookcainjection_patch.yaml
│   ├── manager
│   │   ├── kustomization.yaml
│   │   └── manager.yaml
│   ├── prometheus
│   │   ├── kustomization.yaml
│   │   └── monitor.yaml
│   ├── rbac
│   │   ├── auth_proxy_role.yaml
│   │   ├── auth_proxy_role_binding.yaml
│   │   ├── auth_proxy_service.yaml
│   │   ├── kustomization.yaml
│   │   ├── leader_election_role.yaml
│   │   ├── leader_election_role_binding.yaml
│   │   └── role_binding.yaml
│   └── webhook
│       ├── kustomization.yaml
│       ├── kustomizeconfig.yaml
│       └── service.yaml
├── go.mod
├── go.sum
├── hack
│   └── boilerplate.go.txt
└── main.go

這里kubebuilder幫我們生成了一下模板文件夾,包括解決crd的rbac, cert, webhook的文件。暫時不用管他們,這時需要保證你的終端能訪問k8s的測試集群,簡單就是用kubectl cluster-info看看是否出錯,如果不出錯,就可以run起來main.go了

kubectl cluster-info
go run main.go

可以看到終端輸出的log:

2019-12-28T00:22:09.789+0800    INFO    controller-runtime.metrics  metrics server is starting to listen    {"addr": ":8080"}
2019-12-28T00:22:09.789+0800    INFO    setup   starting manager
2019-12-28T00:22:09.790+0800    INFO    controller-runtime.manager  starting metrics server {"path": "/metrics"}

main.go里面可以看出其實kubebuilder幫我們生成一個管理controller的manager的代碼,但是還沒添加controller(controller是指管理crd的控制器):

func main() {
...
    mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
        Scheme:             scheme,
        MetricsBindAddress: metricsAddr,
        LeaderElection:     enableLeaderElection,
        Port:               9443,
    })
...
    if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil {
...
    }
}

ok, 接下來我們就可以用kubebuilder幫我們創(chuàng)建一個我們想要的crd,我就叫這個crd為Object吧:

kubebuilder create api --group infra --version v1 --kind Object

這里簡單注意一下, group, version, kind這三個屬性組合起來來標識一個k8s的crd。另外就是kind要首字母大寫而且不能有特殊符號。

執(zhí)行上面的命令之后,kubebuilder就幫我們創(chuàng)建了兩個文件api/v1/object_types.gocontrollers/object_controller.go, 前者是這個crd需要定義哪些屬性,而后者是對crd的reconsile的處理邏輯(也就是增刪改crd的邏輯), 我們后面再講這兩個文件。最后呢,在main.go里面,我們定義的Object對應的controller會注冊到之前生成的manager里:

function main(){
...
// 注冊Object的controller到manager里
    if err = (&controllers.ObjectReconciler{
        Client: mgr.GetClient(),
        Log:    ctrl.Log.WithName("controllers").WithName("Object"),
        Scheme: mgr.GetScheme(),
    }).SetupWithManager(mgr); err != nil {
...
    }
...

聰明的你一定能猜到,我們反復執(zhí)行kubebuilder create api xxx這條命令就會幫我們創(chuàng)建和注冊不同的controller到manager里面。

回過頭我們再看一下api/v1/object_types.go,這里我在spec里面加一個Detail,在status里面加一個Created

// ObjectSpec defines the desired state of Object
type ObjectSpec struct {
    // INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
    // Important: Run "make" to regenerate code after modifying this file

    // Foo is an example field of Object. Edit Object_types.go to remove/update
    Foo string `json:"foo,omitempty"`
    Detail string `json:"detail,omitempty"`
}

// ObjectStatus defines the observed state of Object
type ObjectStatus struct {
    // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster
    // Important: Run "make" to regenerate code after modifying this file
    Created bool `json:"created,omitempy"`
}

實際上kubebuilder就是幫我們生成Object的spec和status的模板,從注釋就也可以看出來spec是我們期望的crd狀態(tài),而status就是觀測到的狀態(tài),具體也可以參見k8s對一個對象的定義??梢钥吹侥J定義下面,kubebuilder會為我們生成對應的yaml文件在config/samples/infra_v1_object.yaml:

---
apiVersion: infra.demo.com/v1
kind: Object
metadata:
  name: object-sample
spec:
  # Add fields here
  foo: bar
  detail: "detail for demo"

controllers/object_controller.go,也就是kubebuilder幫我們生成的Reconcile代碼里面,我添加了打印Detail的信息,并且把Created改成true:

//此method在controllers/object_controller.go
func (r *ObjectReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
    ctx := context.Background()
    _ = r.Log.WithValues("object", req.NamespacedName)
    // your logic here

    // 1. Print Spec.Detail and Status.Created in log
    obj := &infrav1.Object{}
    if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
        fmt.Errorf("couldn't find object:%s", req.String())
    } else {
    //打印Detail和Created
        r.Log.V(1).Info("Successfully get detail", "Detail", obj.Spec.Detail)
        r.Log.V(1).Info("", "Created", obj.Status.Created)
    }
    // 2. Change Created
    if !obj.Status.Created {
        obj.Status.Created = true
        r.Update(ctx, obj)
    }

    return ctrl.Result{}, nil
}

由于kubebuilder要用到kustomize,所以先確保先裝好了, mac的安裝方式:

brew install kustomize

然后就install生成的crd并且運行修改代碼后的manager:

make install
go run main.go

現(xiàn)在我們就可以用config/samples/infra_v1_object.yaml創(chuàng)建一個Object:

kubectl create -f config/samples/infra_v1_object.yaml

在運行manager的終端里面可以看到我們剛才添加的代碼打印出來的log:

2019-12-28T23:39:34.963+0800    DEBUG   controllers.Object  Successfully get detail {"Detail": "detail for demo"}
2019-12-28T23:39:34.963+0800    DEBUG   controllers.Object  {"Created": false}
2019-12-28T23:39:35.019+0800    DEBUG   controller-runtime.controller   Successfully Reconciled {"controller": "object", "request": "default/object-sample"}
2019-12-28T23:39:35.019+0800    DEBUG   controllers.Object  Successfully get detail {"Detail": "detail for demo"}
2019-12-28T23:39:35.019+0800    DEBUG   controllers.Object  {"Created": true}

再看看從k8s里面看到的這個Object的狀態(tài):

kubectl get object object-sample -o yaml
apiVersion: infra.demo.com/v1
kind: Object
metadata:
  creationTimestamp: "2019-12-28T15:39:34Z"
  generation: 2
  name: object-sample
  namespace: default
  resourceVersion: "433782"
  selfLink: /apis/infra.demo.com/v1/namespaces/default/objects/object-sample
  uid: 3f4b368d-2988-11ea-a544-080027d6a71e
spec:
  detail: detail for demo
  foo: bar
status:
  Created: true   #此處是我們修改成true的狀態(tài)

可以看到這個object-samplestatus.Created已經(jīng)被修改為true了

3.其他

關于沒有介紹的crt,webhook和finalizer,官網(wǎng)手冊有比較詳細的用法介紹。我就簡單談一下我的理解,如果有錯誤請糾正:

  1. webhook,其實就是當我們添加和修改一個Object時,我們需要對Object的合法性進行判斷,所以可以通過webhook的framework來進行合法性的判定,所以kubebuilder可以生成對應的webhook代碼;
  2. crt,用于解決webhook訪問k8s時所需要的證書問題,官網(wǎng)也建議使用crt-manager解決證書問題;
  3. finalizer,就是在刪除Object時,由于這個Object可能創(chuàng)建一些其他的resource比如pod之類的,又或者在刪除之前,我們需要做一些清理工作,finalizer就是實現(xiàn)這個清理的framework代碼;

另外kubebuilder也是支持把這個manager部署為deployment,但是調(diào)試起來比較麻煩,所以就只用go run的形式演示了。

小結

這篇blog簡單的介紹了一下kubebuilder開發(fā)crd的基本過程,沒有深入過多的代碼原理,可能也有不少錯誤地方,麻煩幫忙糾正。另外大家可能跟我剛學習kubebuilder的時候一樣,只能照著官網(wǎng)教程敲命令,kubebuilder生成的代碼就像一個黑盒一樣,接下來目標就是專門整理一下kubebuilder生成crd代碼流程和結構。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容