본문 바로가기
golang

[Kubebuilder] kubernetes Operator get pod 만들기

by weq155 2023. 11. 17.
반응형
반응형

 

 

지난 글에선 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 관련해서 괜찮은 자료나 샘플코드가 있으신분은 공유해주시면 감사하겠습니다

반응형