Kubernetes

[데보션영] K8s 스터디 : 커스텀 컨트롤러

kchabin 2024. 10. 2. 21:15

오늘 스터디 주제는 Custom Controller

Kubebuilder 설치

https://book.kubebuilder.io/quick-start

Go를 먼저 설치한다.

GOPATH 환경변수 확인

# download kubebuilder and install locally.
curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)"
chmod +x kubebuilder && sudo mv kubebuilder /usr/local/bin/

 

shell auto completion

 

CRD -> Custom Resource Definition

- yaml 파일에 kind 다음에 metadata ~ 

 

controller는 yaml을 해석하고 이런 pod(그외다수)를 띄워라 해주는것.

커스텀 리소스 : kind를 내가 지정한 타입으로 만들 수 있음 

 

core 그룹 : k8s가 기본으로 제공하는 pod, configmap

 

GVK

  • Group, Version. Kind
  • api 쿼리 대상

 

kubebuilder 설치 후 프로젝트 만들기

 

mkdir -p ~/projects/guestbook
cd ~/projects/guestbook
kubebuilder init --domain my.domain --repo my.domain/guestbook

다음 단계에 리소스 정의하는 걸 알려준다.

Create an API

guestbook이라는 kind를 만들고 싶다

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

 

이제 해야할 건 make manifests

 

스켈레톤 코드가 생성되는게 opnapi codegen같다.

 

 

https://devocean.sk.com/blog/techBoardDetail.do?ID=164942&boardType=techBlog

// GuestbookSpec defines the desired state of Guestbook
type GuestbookSpec struct {
	// INSERT ADDITIONAL SPEC FIELDS - desired state of cluster
	// Important: Run "make" to regenerate code after modifying this file

	// Foo is an example field of Guestbook. Edit guestbook_types.go to remove/update
	Foo string `json:"foo,omitempty"`
}

여기선 Foo string 인데 Pod라면 PodSpec struct 안에 containers array 이런 형태로 들어가 있을 것.

 

배포하고나면 pod 컨트롤러가 status 값을 적어줌 -> 아 그래서 데보션 실습할 때 배포한 파일에 status가 있었구나

 

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

	Spec   GuestbookSpec   `json:"spec,omitempty"`
	Status GuestbookStatus `json:"status,omitempty"`
}

 

spec:
  guestbookspec의 멤버들이 쫙

 

TypeMeta 내부로 들어가봐도 이런 struct가 있다.

type TypeMeta struct {
	// Kind is a string value representing the REST resource this object represents.
	// Servers may infer this from the endpoint the client submits requests to.
	// Cannot be updated.
	// In CamelCase.
	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
	// +optional
	Kind string `json:"kind,omitempty" protobuf:"bytes,1,opt,name=kind"`

	// APIVersion defines the versioned schema of this representation of an object.
	// Servers should convert recognized schemas to the latest internal value, and
	// may reject unrecognized values.
	// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
	// +optional
	APIVersion string `json:"apiVersion,omitempty" protobuf:"bytes,2,opt,name=apiVersion"`
}

 

 

type GuestbookList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata,omitempty"`
	Items           []Guestbook `json:"items"`
}

plural도 반드시 있어야 한다. kubectl get pods 쓸수있으니까

 

 

 

여기엔 controller-gen이 CRD를 자동으로 만들어준다.

생성된 CRD

 

 

webapp.my.domain_guestbooks.yaml

api가 crd를 쿼리해와서 validation하는 용도

- 쿠버네티스는 선언적이기 때문

- etcd 이전에 api가 validation -> etcd는 db같은 역할임. 너무 쓸데없는 가비지 값이 들어오면 안됨

일종의 api extension

---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  annotations:
    controller-gen.kubebuilder.io/version: v0.16.1
  name: guestbooks.webapp.my.domain
spec:
  group: webapp.my.domain
  names:
    kind: Guestbook
    listKind: GuestbookList
    plural: guestbooks
    singular: guestbook
  scope: Namespaced
  versions:
  - name: v1
    schema:
      openAPIV3Schema:
        description: Guestbook is the Schema for the guestbooks API
        properties:
          apiVersion:
            description: |-
              APIVersion defines the versioned schema of this representation of an object.
              Servers should convert recognized schemas to the latest internal value, and
              may reject unrecognized values.
              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
            type: string
          kind:
            description: |-
              Kind is a string value representing the REST resource this object represents.
              Servers may infer this from the endpoint the client submits requests to.
              Cannot be updated.
              In CamelCase.
              More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
            type: string
          metadata:
            type: object
          spec:
            description: GuestbookSpec defines the desired state of Guestbook
            properties:
              foo:
                description: Foo is an example field of Guestbook. Edit guestbook_types.go
                  to remove/update
                type: string
            type: object
          status:
            description: GuestbookStatus defines the observed state of Guestbook
            type: object
        type: object
    served: true
    storage: true
    subresources:
      status: {}

 

쿠버네티스의 모든 리소스는 go 언어로 struct가 존재한다.

마샬/언마샬(?) = 직렬화/역직렬화

 

A 라이브러리 : 객체를 json으로 바꾸고 api 호출해서 넣어줌

난 struct를 작성하고 A 라이브러리를 사용하는 것

내가 만든 컨트롤러가 계속 api 쿼리를 하다가 내가 만든 커스텀 리소스가 들어오면 컨트롤러가 yaml을 보고 선언적으로 상태를 맞춤

 

Mutation -> Validation

 

func (r *GuestbookReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
	_ = log.FromContext(ctx)

	// TODO(user): your logic here

	return ctrl.Result{}, nil
}

Reconcile -> current와 desire를 맞추는 것

make run하면 controller가 컴파일해서 로컬에서 실행됨. 이 reconcile 메서드는 무한루프로 계속 호출됨

 

make run 한 번 해봤는데 cluster가 없어서 안되는 듯

ctrl+c로 종료하기 전까지 계속 loop를 도는 것 같음.

- 클러스터가 없어서 그럼 -> 전에 썼던 minikube를 시작해놓고 make run 해보면됨

 

cronjob 커스텀 컨트롤러 만들기 

https://devocean.sk.com/blog/techBoardDetail.do?ID=165109

 

Custom Controller 3 - CronJob 구현하기

 

devocean.sk.com

 

자기 클러스터 내부에서만 실행하는 것과 외부 리소스 쿼리 차이 고려

reconcile은 long query가 걸릴 수 있음. -> 루프가 안돌게됨