👻

kubebuilderで作成したCRDのclientsetをcode-generatorで生成する方法

2022/10/28に公開

概要

kubebuilderで作成したCRDのclientsetをcode-generatorで生成しようとしたときに、ちょっとはまったのでメモ。

https://github.com/sosomasox/example-controller

環境

goとkubebuilderのバージョンは以下の通り。

$ go version
go version go1.19.2 linux/amd64
$ kubebuilder version
Version: main.version{KubeBuilderVersion:"3.7.0", KubernetesVendor:"1.24.1", GitCommit:"3bfc84ec8767fa760d1771ce7a0cb05a9a8f6286", BuildDate:"2022-09-20T17:21:57Z", GoOs:"linux", GoArch:"amd64"}

方法

プロジェクト作成

どうもcode-generatorはプロジェクトのディレクトリ構成に要件があるっぽくて、kubebuilderの方でMulti-Group対応が必要っぽい。

したがって、下記手順でプロジェクトの作成を行う必要がある。

  1. プロジェクトの初期化
$ kubebuilder init --domain sosomasox.com --repo github.com/sosomasox/example-controller
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
Get controller runtime:
$ go get sigs.k8s.io/controller-runtime@v0.13.0
go: downloading sigs.k8s.io/controller-runtime v0.13.0
go: downloading k8s.io/apimachinery v0.25.0
go: downloading k8s.io/client-go v0.25.0
go: downloading k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
go: downloading k8s.io/klog/v2 v2.70.1
go: downloading sigs.k8s.io/structured-merge-diff/v4 v4.2.3
go: downloading k8s.io/component-base v0.25.0
go: downloading golang.org/x/net v0.0.0-20220722155237-a158d28d115b
go: downloading github.com/evanphx/json-patch/v5 v5.6.0
go: downloading golang.org/x/time v0.0.0-20220609170525-579cf78fd858
go: downloading k8s.io/api v0.25.0
go: downloading k8s.io/apiextensions-apiserver v0.25.0
go: downloading sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2
go: downloading golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f
go: downloading k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1
go: downloading github.com/emicklei/go-restful/v3 v3.8.0
Update dependencies:
$ go mod tidy
go: downloading github.com/go-logr/zapr v1.2.3
go: downloading go.uber.org/zap v1.21.0
go: downloading github.com/Azure/go-autorest/autorest v0.11.27
go: downloading cloud.google.com/go v0.97.0
go: downloading github.com/golang-jwt/jwt/v4 v4.2.0
go: downloading golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
go: downloading github.com/onsi/ginkgo/v2 v2.1.4
go: downloading github.com/Azure/go-autorest/autorest/mocks v0.4.2
Next: define a resource with:
$ kubebuilder create api
  1. Multi-Group対応
$ kubebuilder edit --multigroup=true
  1. APIの作成
$ kubebuilder create api --group example --version v1alpha1 --kind Hoge
Create Resource [y/n]
y
Create Controller [y/n]
y
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
apis/hoge/v1alpha1/hoge_types.go
controllers/hoge/hoge_controller.go
Update dependencies:
$ go mod tidy
Running make:
$ make generate
mkdir -p /home/taichi/Workspace/example-controller/bin
test -s /home/taichi/Workspace/example-controller/bin/controller-gen || GOBIN=/home/taichi/Workspace/example-controller/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.9.2
go: downloading sigs.k8s.io/controller-tools v0.9.2
go: downloading github.com/gobuffalo/flect v0.2.5
go: downloading k8s.io/apiextensions-apiserver v0.24.0
go: downloading golang.org/x/tools v0.1.10-0.20220218145154-897bd77cd717
go: downloading golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3
/home/taichi/Workspace/example-controller/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
Next: implement your new API and generate the manifests (e.g. CRDs,CRs) with:
$ make manifests

code-generatorに必要なファイルの作成と変更

プロジェクト作成が終わったらcode-generatorに必要なファイルを作成していく。

まず、下記内容のファイルを apis/<group名>/v1alpha1/doc.go として作成する。
groupName<group名>.<domain名> にする。

$ cat apis/example/v1alpha1/doc.go
// +groupName=example.sosomasox.com

package v1alpha1

さらに、下記内容のファイルを apis/<group名>/v1alpha1/register.go として作成する。

$ cat apis/example/v1alpha1/register.go
package v1alpha1

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()
}

次に、クライアントを作成したいカスタムリソースを定義づけているファイル内の構造体付近に //+genclient をつける。


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

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

	Spec   HogeSpec   `json:"spec,omitempty"`
	Status HogeStatus `json:"status,omitempty"`
}

スクリプトの作成

hack ディレクトリ配下に下記内容のファイルを作成します。

$ cat hack/tools.go
// +build tools

package tools

import _ "k8s.io/code-generator"

code-generatorを実行するスクリプトを作成します。

$ cat hack/update-codegen.sh
#!/bin/bash -x

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

# corresponding to go mod init <module>
MODULE=github.com/sosomasox/example-controller
# api package
APIS_PKG=apis
# group-version such as foo:v1alpha1
GROUP=example
VERSION=v1alpha1
GROUP_VERSION=${GROUP}:${VERSION}
# generated output package
OUTPUT_PKG=generated/${GROUP}


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.

rm -rf generated

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}"

mv ${MODULE}/generated generated
rm -rf `echo ${MODULE} | cut -d '/' -f 1`
rm -rf generated/${GROUP}/clientset/versioned/fake
rm -rf generated/${GROUP}/clientset/versioned/typed/${GROUP}/v1alpha1/fake

exit 0

hack/update-codegen.sh に実行権限を付与します。

$ chmod +x hack/update-codegen.sh

code-generatorのインストール

依存関係を更新します。

$ go mod tidy
go: downloading k8s.io/code-generator v0.25.0
go: downloading golang.org/x/tools v0.1.12

ベンダーを更新し、generate-groups.sh に実行権限を付与します。

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

clientsetの生成

hack/update-codegen.sh を実行し、code-generatorでclientsetを生成します。

$ ./hack/update-codegen.sh
+ set -o errexit
+ set -o nounset
+ set -o pipefail
+ MODULE=github.com/sosomasox/example-controller
+ APIS_PKG=apis
+ GROUP=example
+ VERSION=v1alpha1
+ GROUP_VERSION=example:v1alpha1
+ OUTPUT_PKG=generated/example
++ dirname ./hack/update-codegen.sh
+ SCRIPT_ROOT=./hack/..
++ cd ./hack/..
++ ls -d -1 ./vendor/k8s.io/code-generator
+ CODEGEN_PKG=./vendor/k8s.io/code-generator
+ rm -rf generated
+ bash ./vendor/k8s.io/code-generator/generate-groups.sh client,lister,informer github.com/sosomasox/example-controller/generated/example github.com/sosomasox/example-controller/apis example:v1alpha1 --go-header-file ./hack/../hack/boilerplate.go.txt --output-base ./hack/..
Generating clientset for example:v1alpha1 at github.com/sosomasox/example-controller/generated/example/clientset
Generating listers for example:v1alpha1 at github.com/sosomasox/example-controller/generated/example/listers
Generating informers for example:v1alpha1 at github.com/sosomasox/example-controller/generated/example/informers
+ mv github.com/sosomasox/example-controller/generated generated
++ echo github.com/sosomasox/example-controller
++ cut -d / -f 1
+ rm -rf github.com
+ rm -rf generated/example/clientset/versioned/fake
+ rm -rf generated/example/clientset/versioned/typed/example/v1alpha1/fake
+ exit 0

generated ディレクトリ配下にclientsetが生成されていることが確認できます。

$ ls generated/example/
clientset  informers  listers

中身はこんな感じ。

https://github.com/sosomasox/example-controller/blob/main/generated/example/clientset/versioned/clientset.go

https://github.com/sosomasox/example-controller/blob/main/generated/example/clientset/versioned/typed/example/v1alpha1/example_client.go

https://github.com/sosomasox/example-controller/blob/main/generated/example/clientset/versioned/typed/example/v1alpha1/hoge.go

参考

https://juejin.cn/post/6943182462813995044

Discussion