CRD笔记-01
文章目录
1. 前言
由于工作上需要使用自定义资源来开发新功能,这段时间入门了一下自定义资源和自定义控制器开发,这里稍作记录,下面是这次使用到相关工具和库:
- kubebuilder:脚手架工具,用于创建项目,添加自定义资源、控制器和Webhook
- github:kubebuilder
- doc:book.kubebuilder.io
- controller-runtime:controller运行时,封装了实现controller所需的大部分代码,用户只要实现Reconcile接口即可处理关注的资源
- github:controller-runtime
- doc:designs
- controller-gen:DeepCopy及manifests生成工具
- github:controller-tools
- controller-manager:k8s标准controller实现代码,可供参考
2. 初始化集群
笔者在一台2C4G的轻量应用服务器上部署了一个v1.22.5+k3s1版本的单节点k3s集群,启用了内嵌的etcd,并设置了cluster-cidr与service-cidr避免和VPC网段冲突。
1➜ ~ curl -sfL https://get.k3s.io | INSTALL_K3S_EXEC="server" sh -s - --cluster-init --cluster-cidr 10.16.0.0/16 --service-cidr 10.32.0.0/16
2➜ ~ kubectl get node
3NAME STATUS ROLES AGE VERSION
4lighthouse Ready control-plane,etcd,master 47d v1.22.5+k3s1
3. 使用自定义资源拓展k8s
部署完成后可以看到k3s集群已经创建了许多crd和cr,如下:
1➜ ~ kubectl -n kube-system get crd
2NAME CREATED AT
3addons.k3s.cattle.io 2022-01-14T15:05:46Z
4...
5traefikservices.traefik.containo.us 2022-01-14T15:06:36Z
6➜ ~ kubectl -n kube-system get addons.k3s.cattle.io
7NAME AGE
8aggregated-metrics-reader 47d
9...
10traefik 47d
k3s的内置控制器会监控类型为 addons.k3s.cattle.io 的自定义资源,并完成同步操作:github.com/k3s-io/k3s/pkg/deploy
再回顾下我们平时如何使用的标准资源,例如deployment:
- k8s提供了deployment的定义
- 用户根据资源定义创建所需的deployment资源
- deployment控制器监控资源变动,将资源同步到期望的状态
k8s中对资源的处理流程大抵如此,Operator模式就是将自定义资源与自定义控制器相结合的,允许用户在不修改k8s自身代码的情况下,来扩展集群的能力。
可用于构建自定义控制器和operator的工具有kubebuilder与operator-sdk,两功能大致相似,从当前的文档看,operator-sdk底层已经用上了kubebuilder:
What are the the differences between Kubebuilder and Operator-SDK?。
而kubebuilder则是基于controller-runtime和controller-tools开发,这里直接使用kubebuilder来测试。
4. 使用kubebuilder
4.1 安装
1curl -L -o kubebuilder https://go.kubebuilder.io/dl/latest/linux/amd64
2chmod +x kubebuilder && mv kubebuilder /usr/local/bin/
4.2 初始化
使用init初始化项目,domain参数设置groups,repo参数设置go module
1mkdir -p ~/github/crd && cd ~/github/crd
2kubebuilder init --domain app.wbuntu.com --repo github.com/wbuntu/crd
4.3 添加api
使用create子命令添加api,如下:
1kubebuilder create api --group "web" --version v1 --kind Bundle
这里指定group为web,创建一个v1版本的自定义资源Bundle,创建过程中:
- 自动创建一个Bundle类型的自定义资源,完整api版本为 web.app.wbuntu.com/v1:api/v1/bundle_types.go
- 自动创建一个监听Bundle资源的控制器:controllers/bundle_controller.go
每次修改了bundle_types.go,为Bundle类型添加自定义字段或引用标准资源后,需执行以下命令生成相关代码和yaml:
- make generate:生成Bundle类型的DeepCopy、DeepCopyInto、DeepCopyObject等方法
- make manifests:生成WebhookConfiguration、ClusterRole、CustomResourceDefinition等yaml定义文件
注意:若自定义资源内嵌了标准组件(例如Pod),且需要使用到ObjectMeta字段,则需要在Makefile的manifests构建指令中添加一个参数:crd:generateEmbeddedObjectMeta=true
,如下:
1➜ crd git:(master) cat Makefile
2...
3.PHONY: manifests
4manifests: controller-gen ## Generate WebhookConfiguration, ClusterRole and CustomResourceDefinition objects.
5 $(CONTROLLER_GEN) rbac:roleName=manager-role crd:generateEmbeddedObjectMeta=true webhook paths="./..." output:crd:artifacts:config=config/crd/bases
6...
4.4 添加webhook
使用create子命令添加webhook,如下:
1kubebuilder create webhook --group "web" --version v1 --kind Bundle --defaulting --programmatic-validation
该命令自动生成文件:api/v1/bundle_webhook.go,包含一个Default方法用于设置Bundle资源默认值,三个ValidateCreate/Update/Delete方法用于验证Bundle资源。
4.5 部署CRD
如下所示:
1➜ crd git:(master) cat Makefile
2...
3install: manifests kustomize ## Install CRDs into the K8s cluster specified in ~/.kube/config.
4 $(KUSTOMIZE) build config/crd | kubectl apply -f -
5...
执行make install指令会先执行manifests生成yaml,再利用kustomize构建config/crd目录下的yaml,然后执行kubectl apply命令,在集群中创建CRD。
1➜ crd git:(master) kubectl get crd|grep app
2...
3bundles.web.app.wbuntu.com 2022-01-22T09:15:58Z
4...
config/samples/web_v1_bundle.yaml 保存着一个yaml,可用于创建示例:
1➜ crd git:(master) kubectl apply -f config/samples/web_v1_bundle.yaml
2bundle.web.app.wbuntu.com/bundle-sample created
3➜ crd git:(master) kubectl get bundles.web.app.wbuntu.com
4NAME AGE
5bundle-sample 15s
4.6 运行Controller
执行make run运行Controller:
1➜ crd git:(master) ✗ make run
2/root/github/crd/bin/controller-gen rbac:roleName=manager-role crd:generateEmbeddedObjectMeta=true webhook paths="./..." output:crd:artifacts:config=config/crd/bases
3/root/github/crd/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
4go fmt ./...
5go vet ./...
6go run ./main.go
71.6463015152880957e+09 INFO controller-runtime.metrics Metrics server is starting to listen {"addr": ":8080"}
81.6463015152883682e+09 INFO setup starting manager
91.646301515288627e+09 INFO Starting server {"path": "/metrics", "kind": "metrics", "addr": "[::]:8080"}
101.6463015152887075e+09 INFO Starting server {"kind": "health probe", "addr": "[::]:8081"}
111.6463015152888494e+09 INFO controller.bundle Starting EventSource {"reconciler group": "web.app.wbuntu.com", "reconciler kind": "Bundle", "source": "kind source: *v1.Bundle"}
121.6463015152888756e+09 INFO controller.bundle Starting Controller {"reconciler group": "web.app.wbuntu.com", "reconciler kind": "Bundle"}
131.646301515389471e+09 INFO controller.bundle Starting workers {"reconciler group": "web.app.wbuntu.com", "reconciler kind": "Bundle", "worker count": 1}
BundleReconciler在Bundle资源Add、Update、Delete时都会收到通知,自动Reconcile方法。
注意:本地运行时,会出现由于webhooks找不到证书导致crash的问题,可以暂时注释掉main.go中的webhook启动代码。