使用kubebuilder结合code-generator开发k8s controller(2)

方浩旷
2023-12-01

前面记录了kubebuilder+code-generator的一些踩坑记录和解决方法的相关准备工作,

使用kubebuilder结合code-generator开发k8s controller(1)

使用kubebuilder结合code-generator开发k8s controller(2)

这篇文章记录kubebuilder+code-generator创建一个controller的过程

一、使用go mod管理依赖

mkdir example
go mod init gateway
kubebuilder init --domain example.com
kubebuilder edit --multigroup=true

二、创建api,这里不创建controller

kubebuilder create api --group app --version v1 --kind Gateway
Create Resource [y/n]
y
Create Controller [y/n]
n

这是会生成apis/app/v1目录,里面有{crd}_type.go和zz_generated.deepcopy.go文件,如果需要配置和修改crd字段,可以修改{crd}_type.go中的crd spec结构体

修改{crd}_type.go之后,需用重新执行make manifests重新生成crd,此时zz_generated.deepcopy.go也会同步更新。

三、添加apis/app/v1/rbac.go文件,这个文件用于生成RBAC manifests:

// +kubebuilder:rbac:groups=app.example.com,resources=gateways,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=app.example.com,resources=gateways/status,verbs=get;update;patch

package v1

生成crd manifests

make manifests

 这一步会生成config/crd/bases目录,以及该目录下的crd yaml

四、使用code-generator

1. 准备脚本

在hack目录下新增update-codegen.sh和verify-codegen.sh

其中update-codegen.sh如下

其中:

MODULE=gateway,这里和go.mod保持一致(go mod init gateway)

API_PKG=apis,目前工程的api目录,有的可能是api

OUTPUT_PKG=generated/app:输出结果的目录(generated/{group},group是之前kubebuilder create api是指定的group参数)

GROUP_VERSION=app:v1,也是跟kubebuilder create api是的group和version保持一致

#!/usr/bin/env bash

set -o errexit
set -o nounset
set -o pipefail

# corresponding to go mod init <module>
MODULE=gateway
# api package
APIS_PKG=apis
# generated output package
OUTPUT_PKG=generated/app
# group-version such as foo:v1alpha1
GROUP_VERSION=app:v1

SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
CODEGEN_PKG=${CODEGEN_PKG:-$(cd "${SCRIPT_ROOT}"; ls -d -1 ./vendor/k8s.io/code-generator 2>/dev/null || echo ../code-generator)}
 

# generate the code with:
# --output-base    because this script should also be able to run inside the vendor dir of
#                  k8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
#                  instead of the $GOPATH directly. For normal projects this can be dropped.
bash "${CODEGEN_PKG}"/generate-groups.sh "client,lister,informer" \
  ${MODULE}/${OUTPUT_PKG} ${MODULE}/${APIS_PKG} \
  ${GROUP_VERSION} \
  --go-header-file "${SCRIPT_ROOT}"/hack/boilerplate.go.txt \
  --output-base "${SCRIPT_ROOT}"
#  --output-base "${SCRIPT_ROOT}/../../.." \

其中https://github.com/kubernetes/code-generator/blob/master/hack/verify-codegen.sh 可从github上直接下载

2. 下载code-generator

go get k8s.io/code-generator@v0.20.1
go mod tidy
go mod vendor

3. 配置generate-groups.sh可执行权限

chmod +x vendor/k8s.io/code-generator/generate-groups.sh

4. 准备生成代码

在{crd}_type.go上配置tag // +genclient,由于生成clienset

// +genclient
//+kubebuilder:object:root=true
//+kubebuilder:subresource:status

// Gateway is the Schema for the gateways API
type Gateway struct {
        metav1.TypeMeta   `json:",inline"`
        metav1.ObjectMeta `json:"metadata,omitempty"`

        Spec GatewaySpec `json:"spec,omitempty"`

在apis/app/v1下新建doc.go,其中groupName要根据kubebuilder init和kubebuilder create api参数对应修改

// +groupName=app.example.com

package v1

在apis/app/v1下新建register.go,代码如下,无需修改

package v1

import (
    "k8s.io/apimachinery/pkg/runtime/schema"
)

// SchemeGroupVersion is group version used to register these objects.
var SchemeGroupVersion = GroupVersion

func Resource(resource string) schema.GroupResource {
    return SchemeGroupVersion.WithResource(resource).GroupResource()
}

此时,如果代码写的没问题,执行hack/update-codegen.sh可以得到clientset/lister/informer

./hack/update-codegen.sh

此时会得到example.com/gateway/generated/app目录,在目录下有clientset、liseters、informers

将example.com/gateway/generated移到项目根目录即可

mv example.com/gateway/generated generated

5. 编写controller

6. 运行

安装crd

make install

创建cr

kubectl apply -f config/sample/app_v1_gateway.yaml

 类似资料: