Go 1.18でKubebuilder を使うとbin/controller-gen: No such file or directoryが出る (暫定解決策: v3.4.0以降にする)

# 実行環境

```
kubebuilder version
Version: main.version{KubeBuilderVersion:"3.3.0", KubernetesVendor:"1.23.1", GitCommit:"47859bf2ebf96a64db69a2f7074ffdec7f15c1ec", BuildDate:"2022-01-18T17:03:29Z", GoOs:"darwin", GoArch:"amd64"}
```

# エラー


`kubebuilder create api --group webapp --version v1 --kind Guestbook`を実行すると

```
bash: /Users/nakamasato/projects/guestbook/bin/controller-gen: No such file or directory
make: *** [generate] Error 127
```

`bin/controller-gen`が存在しないというので落ちてる

<details><summary>詳細</summary>

```
kubebuilder create api --group webapp --version v1 --kind Guestbook

Create Resource [y/n]
y
Create Controller [y/n]
y
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
api/v1/guestbook_types.go
controllers/guestbook_controller.go
Update dependencies:
$ go mod tidy
Running make:
$ make generate
go: creating new go.mod: module tmp
Downloading sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0
go: downloading sigs.k8s.io/controller-tools v0.8.0
go: downloading golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff
go: added github.com/fatih/color v1.12.0
go: added github.com/go-logr/logr v1.2.0
go: added github.com/gobuffalo/flect v0.2.3
go: added github.com/gogo/protobuf v1.3.2
go: added github.com/google/go-cmp v0.5.6
go: added github.com/google/gofuzz v1.1.0
go: added github.com/inconshreveable/mousetrap v1.0.0
go: added github.com/json-iterator/go v1.1.12
go: added github.com/mattn/go-colorable v0.1.8
go: added github.com/mattn/go-isatty v0.0.12
go: added github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd
go: added github.com/modern-go/reflect2 v1.0.2
go: added github.com/spf13/cobra v1.2.1
go: added github.com/spf13/pflag v1.0.5
go: added golang.org/x/mod v0.4.2
go: added golang.org/x/net v0.0.0-20210825183410-e898025ed96a
go: added golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e
go: added golang.org/x/text v0.3.7
go: added golang.org/x/tools v0.1.6-0.20210820212750-d4cc65f0b2ff
go: added golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
go: added gopkg.in/inf.v0 v0.9.1
go: added gopkg.in/yaml.v2 v2.4.0
go: added gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
go: added k8s.io/api v0.23.0
go: added k8s.io/apiextensions-apiserver v0.23.0
go: added k8s.io/apimachinery v0.23.0
go: added k8s.io/klog/v2 v2.30.0
go: added k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b
go: added sigs.k8s.io/controller-tools v0.8.0
go: added sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6
go: added sigs.k8s.io/structured-merge-diff/v4 v4.1.2
go: added sigs.k8s.io/yaml v1.3.0
/Users/nakamasato/projects/guestbook/bin/controller-gen object:headerFile="hack/boilerplate.go.txt" paths="./..."
bash: /Users/nakamasato/projects/guestbook/bin/controller-gen: No such file or directory
make: *** [generate] Error 127
Error: failed to create API: unable to run post-scaffold tasks of "base.go.kubebuilder.io/v3": exit status 2
Usage:
  kubebuilder create api [flags]

Examples:
  # Create a frigates API with Group: ship, Version: v1beta1 and Kind: Frigate
  kubebuilder create api --group ship --version v1beta1 --kind Frigate

  # Edit the API Scheme
  nano api/v1beta1/frigate_types.go

  # Edit the Controller
  nano controllers/frigate/frigate_controller.go

  # Edit the Controller Test
  nano controllers/frigate/frigate_controller_test.go

  # Generate the manifests
  make manifests

  # Install CRDs into the Kubernetes cluster using kubectl apply
  make install

  # Regenerate code and run against the Kubernetes cluster configured by ~/.kube/config
  make run


Flags:
      --controller           if set, generate the controller without prompting the user (default true)
      --force                attempt to create resource even if it already exists
      --group string         resource Group
  -h, --help                 help for api
      --kind string          resource Kind
      --make make generate   if true, run make generate after generating files (default true)
      --namespaced           resource is namespaced (default true)
      --plural string        resource irregular plural form
      --resource             if set, generate the resource without prompting the user (default true)
      --version string       resource Version

Global Flags:
      --plugins strings   plugin keys to be used for this subcommand execution

2022/04/27 05:56:30 failed to create API: unable to run post-scaffold tasks of "base.go.kubebuilder.io/v3": exit status 2
```

</details>

# 暫定解決策

[v3.4.0](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v3.4.0)以降に上げれば良い

v3.4.0では公式にはまだgo1.18はサポートされていない。今回の問題だけに関してであれば、v3.4.0で大丈夫だったが、本質的にはgo1.18のサポートを待つのが安全。

> Kubebuilder does not support the go 1.18 version. You should still be using go versions 1.17+ < 1.18 with this release. For further information see: [#2559 (comment)](https://github.com/kubernetes-sigs/kubebuilder/issues/2559#issuecomment-1106200994)


# Issue & PR
https://github.com/operator-framework/operator-sdk/issues/5481

operator-sdkのIssueで報告されていた

> HI @ghostsquad SDK and KB will not work with 1.18 yet.
We need to update its dependencies first. However, some changes to support 1.18 began to be addressed already such as replacing the go get with go install. See: kubernetes-sigs/kubebuilder#2486
https://github.com/operator-framework/operator-sdk/issues/5481#issuecomment-1073048271

kubebuilder側で直しているということ。

https://github.com/kubernetes-sigs/kubebuilder/pull/2486

すでにインストール方法が変更されたPRがマージされている。

~~が！まだ、リリースがされていない。
書いてる時点では、最新版は2022年1月22日にリリースされた[v3.3.0](https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v3.3.0)~~

https://github.com/kubernetes-sigs/kubebuilder/releases/tag/v3.4.0
がリリースされた！


operator-sdk側もKubebuilder側でのMakefileの変更が影響しないか確認するIssue:

https://github.com/operator-framework/operator-sdk/issues/5564



# 暫定解決策 (v3.4.0リリース前まで)

MakefileをPR通りに更新.


```diff
- CONTROLLER_GEN = $(shell pwd)/bin/controller-gen
- .PHONY: controller-gen
- controller-gen: ## Download controller-gen locally if necessary.
- 	$(call go-get-tool,$(CONTROLLER_GEN),sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0)
- 
- KUSTOMIZE = $(shell pwd)/bin/kustomize
- .PHONY: kustomize
- kustomize: ## Download kustomize locally if necessary.
- 	$(call go-get-tool,$(KUSTOMIZE),sigs.k8s.io/kustomize/kustomize/v3@v3.8.7)
- 
- ENVTEST = $(shell pwd)/bin/setup-envtest
- .PHONY: envtest
- envtest: ## Download envtest-setup locally if necessary.
- 	$(call go-get-tool,$(ENVTEST),sigs.k8s.io/controller-runtime/tools/setup-envtest@latest)
- 
- # go-get-tool will 'go get' any package $2 and install it to $1.
- PROJECT_DIR := $(shell dirname $(abspath $(lastword $(MAKEFILE_LIST))))
- define go-get-tool
- @[ -f $(1) ] || { \
- set -e ;\
- TMP_DIR=$$(mktemp -d) ;\
- cd $$TMP_DIR ;\
- go mod init tmp ;\
- echo "Downloading $(2)" ;\
- GOBIN=$(PROJECT_DIR)/bin go get $(2) ;\
- rm -rf $$TMP_DIR ;\
- }
- endef
+ ##@ Build Dependencies
+ 
+ ## Location to install dependencies to
+ LOCALBIN ?= $(shell pwd)/bin
+ $(LOCALBIN): ## Ensure that the directory exists
+ 	mkdir -p $(LOCALBIN)
+ 
+ ## Tool Binaries
+ KUSTOMIZE ?= $(LOCALBIN)/kustomize
+ CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
+ ENVTEST ?= $(LOCALBIN)/setup-envtest
+ 
+ ## Tool Versions
+ KUSTOMIZE_VERSION ?= v3.8.7
+ CONTROLLER_TOOLS_VERSION ?= v0.8.0
+ ENVTEST_VERSION ?= latest
+ 
+ KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
+ .PHONY: kustomize
+ kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
+ $(KUSTOMIZE):
+ 	curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN)
+ 
+ .PHONY: controller-gen
+ controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
+ $(CONTROLLER_GEN):
+ 	GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
+ 
+ .PHONY: envtest
+ envtest: ## Download envtest-setup locally if necessary.
+ 	GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@$(ENVTEST_VERSION)
```

<details><summary>コピー用</summary>

```Makefile
##@ Build Dependencies

## Location to install dependencies to
LOCALBIN ?= $(shell pwd)/bin
$(LOCALBIN): ## Ensure that the directory exists
	mkdir -p $(LOCALBIN)

## Tool Binaries
KUSTOMIZE ?= $(LOCALBIN)/kustomize
CONTROLLER_GEN ?= $(LOCALBIN)/controller-gen
ENVTEST ?= $(LOCALBIN)/setup-envtest

## Tool Versions
KUSTOMIZE_VERSION ?= v3.8.7
CONTROLLER_TOOLS_VERSION ?= v0.8.0
ENVTEST_VERSION ?= latest

.PHONY: envtest
envtest: ## Download envtest-setup locally if necessary.
	GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-runtime/tools/setup-envtest@$(ENVTEST_VERSION)

KUSTOMIZE_INSTALL_SCRIPT ?= "https://raw.githubusercontent.com/kubernetes-sigs/kustomize/master/hack/install_kustomize.sh"
.PHONY: kustomize
kustomize: $(KUSTOMIZE) ## Download kustomize locally if necessary.
$(KUSTOMIZE):
	curl -s $(KUSTOMIZE_INSTALL_SCRIPT) | bash -s -- $(subst v,,$(KUSTOMIZE_VERSION)) $(LOCALBIN)

.PHONY: controller-gen
controller-gen: $(CONTROLLER_GEN) ## Download controller-gen locally if necessary.
$(CONTROLLER_GEN):
	GOBIN=$(LOCALBIN) go install sigs.k8s.io/controller-tools/cmd/controller-gen@$(CONTROLLER_TOOLS_VERSION)
```

</details>

# 確認

コマンドが途中まで作成してErrorで止まっていたので、一回変更を消してから再度以下を実行

```
kubebuilder create api --group webapp --version v1 --kind Guestbook
```

結果
```
kubebuilder create api --group webapp --version v1 --kind Guestbook

Create Resource [y/n]
y
Create Controller [y/n]
y
Writing kustomize manifests for you to edit...
Writing scaffold for you to edit...
api/v1/guestbook_types.go
controllers/guestbook_controller.go
Update dependencies:
$ go mod tidy
Running make:
$ make generate
GOBIN=/Users/nakamasato/projects/guestbook/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.8.0
/Users/nakamasato/projects/guestbook/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
```

エラーなく作成できた!