kubebuilder4.5如何生成clientset、informer、listers代码。

背景

kubebuilder生成的代码没有clientset、informer、listers。因此无法像client-go一样可以通过代码来调用我们自己开发自定义资源。

KubeBuilderVersion: 4.5.0

code-generator

安装

创建一个go mod,然后安装code-generator到机器上

go mod init test
go get k8s.io/code-generator@v0.32.0

进入code-generator的go mod路径,然后安装

cd /root/go/pkg/mod/k8s.io/code-generator@v0.32.0
go install ./cmd/{client-gen,deepcopy-gen,informer-gen,lister-gen}

配置kubebuilder使用code-generator

进入开发好的kubebuilder项目,将code-generator拷贝的kubebuilder项目根目录下。

cd /data/codeForge
cp -r /root/go/pkg/mod/k8s.io/code-generator@v0.32.0 code-generator
可以删除code-generator中的代码,除了保留kube_codegen.sh

在kubebuilder项目中的hack目录下创建脚本,update-generator.sh

#!/usr/bin/env bash
set -o errexit
set -o nounset
set -o pipefail

SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/..
CODEGEN_PKG="/data/codeForge/code-generator"
source "${CODEGEN_PKG}/kube_codegen.sh"

THIS_PKG="github.com/hjjzs/devfroge-user" # 就是go mod init <name> 添加写的name

# Generate deepcopy, defaults, and conversion functions
kube::codegen::gen_helpers \
    --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \
    "${SCRIPT_ROOT}/pkg/apis"

# Generate clientset, informers, and listers
kube::codegen::gen_client \
    --with-watch \
    --output-dir "${SCRIPT_ROOT}/pkg/generated" \
    --output-pkg "${THIS_PKG}/pkg/generated" \
    --boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt" \
    "${SCRIPT_ROOT}/pkg/apis"

配置apis目录

新版本kubebuilder的api创建在项目的根目录下名为api。具体路径为api//。我们需要对其改造。

mkdir -p pkg/apis/<group>/<version>/  # kubebuilder项目的group、version
cp -r api/<version>/* pkg/apis/<group>/<version>

参考,下图,我开发的kubebuilder项目的group为user,version为v1alpha1。api目录改造如红框所示。

接下来所有对api types文件的操作都在pkg/apis// 下面进行

添加client-gen 注解

对所以api type进行注解,如我创建的自定义资源为user,scope为cluster。

  • crd为cluster访问而非namesapce的需要添加注解+genclient:nonNamespaced
  • 需要为自定义资源类型 和 list类型添加注解,如果图片中的 user struct 和 userlist struct 添加注解‘
  • 需要为所有<crd_name>_types.go的api添加注解。
// +genclient
// +genclient:nonNamespaced   # 如何资源为namespace范围的则不要添加该注解
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

添加doc.go文件

/*
Copyright 2025.

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

// Package user contains the user API group.
// +k8s:deepcopy-gen=package
// +groupName=user.devfroge.io    # 这里的group需要添加domain
package v1alpha1

添加Kind和Resource函数

pkg/apis/<group>/<version>路径下添加register.go文件。

package v1alpha1

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

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

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
	return SchemeGroupVersion.WithKind(kind).GroupKind()
}

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
	return SchemeGroupVersion.WithResource(resource).GroupResource()
}

添加完成后效果如下:

必须包含以下文件:

  • doc.go
  • groupversion_info.go
  • <crd_name>_types.go # 如图我的kubebuilder项目又5个crd资源因此又5个xxx_types.go文件。
  • zz_generated.deepcopy.go
  • register.go

生成clientset等代码

在项目根目录运行hack中的update-generator.sh脚本开始生成clientset等代码。

bash hack/update-generator.sh

最终效果

编程测试示例

package main

import (
	"context"
	"fmt"
	"log"
	"time"

	userv1alpha1 "github.com/hjjzs/devfroge-user/pkg/apis/user/v1alpha1"
	clientset "github.com/hjjzs/devfroge-user/pkg/generated/clientset/versioned"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/tools/clientcmd"
)

func main() {
	// 加载 kubeconfig
	config, err := clientcmd.BuildConfigFromFlags("", "/root/.kube/config")
	if err != nil {
		log.Fatalf("Error building kubeconfig: %v", err)
	}

	// 创建 clientset
	client, err := clientset.NewForConfig(config)
	if err != nil {
		log.Fatalf("Error creating clientset: %v", err)
	}

	// 创建一个 User 资源
	user := &userv1alpha1.User{
		ObjectMeta: metav1.ObjectMeta{
			Name: "example-user",
		},
		Spec: userv1alpha1.UserSpec{
			Type:        userv1alpha1.RegularUser,
			DisplayName: "lzc",
			Email:       "example@example.com",
			Description: "This is an example user",
			Enabled:     true,
			Password:    "password123",
		},
	}

	// 创建 User
	createdUser, err := client.UserV1alpha1().Users().Create(context.TODO(), user, metav1.CreateOptions{})
	if err != nil {
		log.Fatalf("Error creating user: %v", err)
	}
	fmt.Printf("Created user: %s\n", createdUser.Name)
	time.Sleep(5 * time.Second)
	// 获取 User
	getUser, err := client.UserV1alpha1().Users().Get(context.TODO(), "example-user", metav1.GetOptions{})
	if err != nil {
		log.Fatalf("Error getting user: %v", err)
	}
	fmt.Printf("Got user: %s, Email: %s\n", getUser.Name, getUser.Spec.Email)

	// 列出所有 Users
	userList, err := client.UserV1alpha1().Users().List(context.TODO(), metav1.ListOptions{})
	if err != nil {
		log.Fatalf("Error listing users: %v", err)
	}
	fmt.Printf("Found %d users\n", len(userList.Items))

	// 更新 User
	getUser.Spec.Description = "Updated description"
	updatedUser, err := client.UserV1alpha1().Users().Update(context.TODO(), getUser, metav1.UpdateOptions{})
	if err != nil {
		log.Fatalf("Error updating user: %v", err)
	}
	fmt.Printf("Updated user description: %s\n", updatedUser.Spec.Description)

	// 删除 User
	err = client.UserV1alpha1().Users().Delete(context.TODO(), "example-user", metav1.DeleteOptions{})
	if err != nil {
		log.Fatalf("Error deleting user: %v", err)
	}
	fmt.Println("User deleted successfully")
}

运行结果:

图片显示找到3个用户时因为我自己手动创建了2个用户,加上测试代码创建的一共3个。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值