지난 글에선 kubebuilder 공식 docs에 가이드에 따라 프로젝트와 API를 생성해 보았다.
이번에는 직접 Reconcile 로직을 사용해서 동작을 테스트 해보자
프로젝트 세팅
아래 명령어를 통해 원하는 CRD의 주소와 프로젝트를 생성
작성 후에 이전글에서 설명했듯이
아래의 파일들이 설치된다.
API 생성
resource와 Controller 생성 여부를 입력하고 API를 생성하는데
에러가 발생했다.
kind 명은 대문자로 시작해야 한다는 에러였다. 소문자는 안됨
❯ kubebuilder create api --group test --version v1 --kind jsTest
INFO Create Resource [y/n]
y
INFO Create Controller [y/n]
y
Error: failed to create API: unable to inject the resource to "base.go.kubebuilder.io/v4": invalid Kind: must start with an uppercase character
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 internal/controller/frigate/frigate_controller.go
# Edit the Controller Test
nano internal/controller/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
FATA failed to create API: unable to inject the resource to "base.go.kubebuilder.io/v4": invalid Kind: must start with an uppercase character
--kind의 첫 시작을 대문자로 하니 설치가 완료되었다.
❯ kubebuilder create api --group test --version v1 --kind JsTest
INFO Create Resource [y/n]
y
INFO Create Controller [y/n]
y
INFO Writing kustomize manifests for you to edit...
INFO Writing scaffold for you to edit...
INFO api/v1/jstest_types.go
INFO api/v1/groupversion_info.go
INFO internal/controller/suite_test.go
INFO internal/controller/jstest_controller.go
INFO Update dependencies:
$ go mod tidy
INFO Running make:
$ make generate
mkdir -p /Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin
test -s /Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin/controller-gen && /Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin/controller-gen --version | grep -q v0.13.0 || \\
GOBIN=/Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin go install sigs.k8s.io/controller-tools/cmd/controller-gen@v0.13.0
/Users/kb01-junskee/Desktop/go_test/operator-test/untitled/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
API를 추가한 모습
보다시피 api/v1, controller dir가 생겼다.
생성된 디렉터리의 api의 version에서 입력한 옵션인 v1이 kind 이름으로 생성되었고,
Create Resource를 y로 입력해야 생성된다.
아래의 Controller 디렉토리도 마찬가지로 동일한 이름으로 생성된 걸 볼 수 있다.
아래의 코드는 jstest_controller.go 파일에 작성한 코드이다.
pod를 Get 해서 찾아온 파드의 로그를 출력하는 코드이다.
func (r *JsTestReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
l := log.FromContext(ctx)
pod := &v1.Pod{}
if err := r.Get(ctx, req.NamespacedName, pod); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
# 아래의 코드는 잘못된 로그 설정 예시 아래를 참조
l.Info("Pod", "name", pod.Name, pod.Namespace, "podSpec", pod.Spec)
return ctrl.Result{}, nil
}
아래의 에러는 manifests 파일을 생성하지 않아서 발생한 에러였다.
> make run
2023-11-17T16:26:56+09:00 ERROR controller-runtime.source.EventHandler failed to get informer from cache {"error": "failed to get API group resources: unable to retrieve the complete list of server APIs: test.js.test.io/v1: the server could not find the requested resource"}
sigs.k8s.io/controller-runtime/pkg/internal/source.(*Kind).Start.func1.1
/Users/kb01-junskee/go/pkg/mod/sigs.k8s.io/controller-runtime@v0.16.3/pkg/internal/source/kind.go:68
k8s.io/apimachinery/pkg/util/wait.loopConditionUntilContext.func2
/Users/kb01-junskee/go/pkg/mod/k8s.io/apimachinery@v0.28.3/pkg/util/wait/loop.go:73
k8s.io/apimachinery/pkg/util/wait.loopConditionUntilContext
/Users/kb01-junskee/go/pkg/mod/k8s.io/apimachinery@v0.28.3/pkg/util/wait/loop.go:74
k8s.io/apimachinery/pkg/util/wait.PollUntilContextCancel
/Users/kb01-junskee/go/pkg/mod/k8s.io/apimachinery@v0.28.3/pkg/util/wait/poll.go:33
sigs.k8s.io/controller-runtime/pkg/internal/source.(*Kind).Start.func1
make manifests를 통해 controller-gen 변경된 컨트롤러를 새로 생성해줘야 한다.
make install 명령어를 통해서도 가능
❯ make manifests
/Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
make install
/Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin/controller-gen rbac:roleName=manager-role crd webhook paths="./..." output:crd:artifacts:config=config/crd/bases
test -s /Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin/kustomize || GOBIN=/Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin GO111MODULE=on go install sigs.k8s.io/kustomize/kustomize/v5@v5.2.1
go: downloading sigs.k8s.io/kustomize/kustomize/v5 v5.2.1
go: downloading sigs.k8s.io/kustomize/cmd/config v0.12.0
go: downloading sigs.k8s.io/kustomize/api v0.15.0
go: downloading sigs.k8s.io/kustomize/kyaml v0.15.0
go: downloading golang.org/x/text v0.8.0
go: downloading gopkg.in/evanphx/json-patch.v5 v5.6.0
go: downloading github.com/imdario/mergo v0.3.13
go: downloading k8s.io/kube-openapi v0.0.0-20230601164746-7562a1006961
go: downloading go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5
/Users/kb01-junskee/Desktop/go_test/operator-test/untitled/bin/kustomize build config/crd | kubectl apply -f -
customresourcedefinition.apiextensions.k8s.io/jstests.test.js.test.io created
Get Pod
log.Info를 사용할 때에도
string과 찾아올 값을 key value 형태로 선언해야 올바른 로그가 나온다. (아니면 에러가 발생)
func (r *AllResourceReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
l := log.FromContext(ctx)
pod := &corev1.Pod{}
if err := r.Get(ctx, req.NamespacedName, pod); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
l.Info("pod", "name", pod.Name, "namespace", pod.Namespace)
return ctrl.Result{}, nil
}
그리고 실행을 해보면 아래의 결과가 나온다.
설정한대로 pod의 정보를 잘 가져오고 있다.
끝으로 kubebuilder가 거의 정석적인 Kubernetes Operator 툴이라고 하는데
docs가 핸즈온 형식으로만 제공되고 세부적으로 api가 제공되지 않고, 관련 자료가 많은 편이 아니라
학습하기가 꽤 까다로운 것 같다.
혹시 kubebuild 관련해서 괜찮은 자료나 샘플코드가 있으신분은 공유해주시면 감사하겠습니다
'golang' 카테고리의 다른 글
[Golang] Cache 사용하기 (0) | 2023.12.08 |
---|---|
[golang] kubernetes Operator 만들기 Kubebuilder API (0) | 2023.11.16 |
[golang] kubernetes Operator 만들기 Kubebuilder 설치 (0) | 2023.11.16 |
[golang] kubernetes Operator 만들기 Kubebuilder Controller-runtime 6 - Controller (0) | 2023.11.16 |
[golang] kubernetes Operator 만들기 Kubebuilder Controller-runtime 5 - Reconciler (0) | 2023.11.16 |