本文介绍使用kubebuilder搭建一个kubernetes CRD crontroller框架,并使用code generator生产对应的clientset/informers/listers.
https://book.kubebuilder.io/introduction.html
bashcurl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)"
bashmkdir -p ${GOPATH}/guestbook/src/example
cd ${GOPATH}/guestbook/src/example
kubebuilder init --domain my.domain
如果项目路径没有按照gopath的格式,则需要加上--repo
参数:
bashkubebuilder init --domain my.domain --repo my.domain/guestbook
bashkubebuilder create api --group webapp --version v1 --kind Guestbook
INFO Create Resource [y/n]
选y会创建api/v1/guestbook_types.go
INFO Create Controller [y/n]
选y会创建internal/controllers/guestbook_controller.go
使用make manifests
更新CRD
如果要创建已有资源的controller,需要指定group为core,参考https://github.com/kubernetes-sigs/kubebuilder/issues/1270
官方参考代码:https://github.com/kubernetes-sigs/controller-runtime/tree/master/examples/builtins
bashkubebuilder create api --group core --version v1 --kind Node
# Create Resource [y/n] 选n
# Create Controller [y/n] 选y
Kubebuilder不会生成informers、listers、clientsets,而code-generator会。
Kubebuilder会生成Controller、Admission Webhooks,而code-generator不会。
Kubebuilder会生成manifests yaml,而code-generator不会。
Kubebuilder还带有一些其他便利性设施。
ref: https://cloud.tencent.com/developer/article/1656317
注意K8S_VERSION必须和go.mod里面的一致
bashK8S_VERSION=v0.29.0
go get k8s.io/code-generator@$K8S_VERSION
hack/update-codegen.sh
参考:https://github.com/kubernetes/code-generator/raw/v0.29.0/examples/hack/update-codegen.sh
最终修改的版本:
bash#!/usr/bin/env bash
# Copyright 2017 The Kubernetes Authors.
#
# 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.
set -x
set -o errexit
set -o nounset
set -o pipefail
SCRIPT_DIR="$(dirname "${BASH_SOURCE[0]}")"
SCRIPT_ROOT="${SCRIPT_DIR}/.."
CODEGEN_PKG="${CODEGEN_PKG:-"${SCRIPT_ROOT}/.."}"
source "${CODEGEN_PKG}/kube_codegen.sh"
# 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.
kube::codegen::gen_helpers \
--input-pkg-root . \
--output-base ${SCRIPT_ROOT} \
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt"
if [[ -n "${API_KNOWN_VIOLATIONS_DIR:-}" ]]; then
report_filename="${API_KNOWN_VIOLATIONS_DIR}/codegen_violation_exceptions.list"
if [[ "${UPDATE_API_KNOWN_VIOLATIONS:-}" == "true" ]]; then
update_report="--update-report"
fi
fi
kube::codegen::gen_openapi \
--input-pkg-root . \
--output-pkg-root . \
--output-base ${SCRIPT_ROOT} \
--report-filename "${report_filename:-"/dev/null"}" \
${update_report:+"${update_report}"} \
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt"
kube::codegen::gen_client \
--with-watch \
--input-pkg-root . \
--output-pkg-root . \
--output-base ${SCRIPT_ROOT} \
--boilerplate "${SCRIPT_ROOT}/hack/boilerplate.go.txt"
hack/verify-codegen.sh
https://github.com/kubernetes/code-generator/raw/v0.29.0/examples/hack/verify-codegen.sh
hack/kube_codegen.sh
https://github.com/kubernetes/code-generator/raw/v0.29.0/kube_codegen.sh
修改一个地方:
bash done < <(
( kube::codegen::internal::git_grep -l \
-e '+genclient' \
":(glob)${in_root}"/'**/*types.go' \ //这里types.go前面加上星号
|| true \
) | LC_ALL=C sort -u
)
修改api/v1/guestbook_types.go
,在type Guestbook struct
上面添加:
go//+genclient
如果要全局生效,可以创建一个doc.go文件,把注释写在里面:
go// +groupName=my.domain/guestbook
// +genclient
package v1
各种注释的作用(来自chatgpt):
genclient
注释 +genclient
用于指示 Kubernetes 的代码生成工具 client-gen 为特定的 API 类型生成客户端代码。这个客户端代码包含了与 Kubernetes API 交互所需的方法,例如创建、获取、更新和删除资源对象。
当你在 API 类型定义文件中添加了 +genclient 注释时,client-gen 工具会为该类型生成一个客户端接口,这个接口包含了一系列标准的客户端操作方法。这些方法对应于 Kubernetes API 的操作,使得开发者可以在他们的应用程序中方便地管理 Kubernetes 资源。
此外,+genclient
注释还可以与其他选项一起使用,以定制生成的客户端代码的行为。例如:
+genclient:noStatus
:即使 .Status 字段存在,也不生成 updateStatus 方法。
+genclient:nonNamespaced
:为集群范围的资源(不属于任何命名空间的资源)生成客户端代码。
+genclient:onlyVerbs=create,get
:只为指定的动作生成客户端方法。
+genclient:skipVerbs=watch
:生成除 watch 之外的所有客户端方法。
deecopy-gen
注释 +k8s:deepcopy-gen
用于指示 Kubernetes 的代码生成工具为特定的 Go 包中的类型生成 DeepCopy 方法。这是 Kubernetes 自定义资源定义(CRD)开发过程中的一个重要步骤,因为它确保了类型的每个实例都可以被安全地复制,这对于 Kubernetes 的许多操作来说是必需的。
由于kubebuilder已经为crd生成了deepcopy函数,所以这个注释可以不用
defaulter-gen
注释 +k8s:defaulter-gen
是 Kubernetes 代码生成工具中使用的一个标记,它用于为特定的 Go 包中的类型生成默认值设置函数。这些函数通常在 API 对象被创建或更新时调用,以确保所有未设置的字段都有合适的默认值。当你在包的 doc.go 文件或类型定义文件中添加了 +k8s:defaulter-gen=TypeMeta
注释时,code-generator 工具会为该包中的所有公开类型生成默认值设置函数。如果你想为特定的类型生成默认值设置函数,可以在类型定义上使用 +k8s:defaulter-gen=true
注释。
conversion-gen
注释 +k8s:conversion-gen
用于指导 Kubernetes 的代码生成工具 conversion-gen 自动生成在内部和外部类型之间转换的函数。这些转换函数对于 Kubernetes API 中的多版本支持非常重要,因为它们允许不同版本的 API 对象之间进行转换。
具体来说,conversion-gen 工具会生成函数,这些函数能够高效地在具有相同名称的类型之间进行转换,无论这些类型是定义在内部包还是外部包中。生成的函数包括 autoConvert_<pkg1>_<type>_To_<pkg2>_<type>
,这些函数会递归地处理数据类型的结构。对于结构体,它会根据名称匹配源字段和目标字段;如果源字段没有对应的目标字段,或者字段类型存在根本的不匹配,那么生成的 autoConvert_...
函数将只包含一个关于该字段的警告注释。
openapi-gen
注释 +k8s:openapi-gen
用于指导 Kubernetes 代码生成工具 openapi-gen 为 Go 包中的类型生成 OpenAPI 规范。这个规范定义了 RESTful API 的接口,使得人类和计算机都能理解服务的功能,而无需接触源代码或监控网络通信。
当你在包的 doc.go 文件或类型定义文件中添加了 +k8s:openapi-gen
注释时,openapi-gen 工具会扫描该包下的所有类型,并为它们生成 OpenAPI 定义。这样,Kubernetes 就可以使用文档生成工具来展示其 API,使用代码生成工具来自动生成服务器端和客户端的代码,以及使用自动测试工具进行测试。
bashexport CODEGEN_PKG=./hack/
./hack/update-codegen.sh
如果报错:
/data/go/pkg/mod/k8s.io/code-generator@v0.29.0/cmd/openapi-gen/main.go:37:43: undefined: generatorargs.NewDefaults
需要更新kube-openapi
bashgo get k8s.io/kube-openapi@v0.0.0-20231010175941-2dd684a91f00
版本是从code-generator的go.mod拿到的
执行完,会得到clientset
informers
listers
三个目录
本文作者:renbear
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC 2.0 许可协议。转载请注明出处!