kubebuilder(1)-安装和使用

导读: 作为云原生的从业者,多多少少也会听说CRD(Custom Resource Definition)和operator,但是说实话开发起来挺繁琐的,而且对初学者也不友好。还好社区目前有好使的脚手架:kubebuilderoperator-sdk,目前个人感觉大家会往前者站队,毕竟k8s自家的,索性就学着用它来尝试开发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环境变量:export GO111MODULE=on, 另外proxy或者墙的原因,先设一下go mod的proxy:export GOPROXY=https://goproxy.io, 然后就可以开始使用了。总结就是要:

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

2.1创建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帮我们创建一个我们想要的crd,我就叫这个crd为Object吧:

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

这里简单注意一下, groupversion, kind这三个属性组合起来来标识一个k8s的crd。另外就是kind要首字母大写而且不能有特殊符号。

执行上面的命令之后,kubebuilder就帮我们创建了两个文件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 {
...
    }
...

聪明的你一定能猜到,我们反复执行kubebuilder create api xxx这条命令就会帮我们创建和注册不同的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状态,而status就是观测到的状态,具体也可以参见k8s对一个对象的定义。可以看到默认定义下面,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

现在我们就可以用config/samples/infra_v1_object.yaml创建一个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的状态:

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的状态

可以看到这个object-samplestatus.Created已经被修改为true了

3.其他

关于没有介绍的crt,webhook和finalizer,官网手册有比较详细的用法介绍。我就简单谈一下我的理解,如果有错误请纠正:

  1. webhook,其实就是当我们添加和修改一个Object时,我们需要对Object的合法性进行判断,所以可以通过webhook的framework来进行合法性的判定,所以kubebuilder可以生成对应的webhook代码;
  2. crt,用于解决webhook访问k8s时所需要的证书问题,官网也建议使用crt-manager解决证书问题;
  3. finalizer,就是在删除Object时,由于这个Object可能创建一些其他的resource比如pod之类的,又或者在删除之前,我们需要做一些清理工作,finalizer就是实现这个清理的framework代码;

另外kubebuilder也是支持把这个manager部署为deployment,但是调试起来比较麻烦,所以就只用go run的形式演示了。

小结

这篇blog简单的介绍了一下kubebuilder开发crd的基本过程,没有深入过多的代码原理,可能也有不少错误地方,麻烦帮忙纠正。另外大家可能跟我刚学习kubebuilder的时候一样,只能照着官网教程敲命令,kubebuilder生成的代码就像一个黑盒一样,接下来目标就是专门整理一下kubebuilder生成crd代码流程和结构。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,126评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,254评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,445评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,185评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,178评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,970评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,276评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,927评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,400评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,883评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,997评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,646评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,213评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,204评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,423评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,423评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,722评论 2 345

推荐阅读更多精彩内容