前面记录了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