CRD笔记-01

Overview

1. 前言

由于工作上需要使用自定义资源来开发新功能,这段时间入门了一下自定义资源和自定义控制器开发,这里稍作记录,下面是这次使用到相关工具和库:

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/mikumaycry/crd

4.3 添加api

使用create子命令添加api,如下:

1kubebuilder create api --group "web" --version v1 --kind Bundle

这里指定group为web,创建一个v1版本的自定义资源Bundle,创建过程中:

每次修改了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启动代码。

comments powered by Disqus