[데보션영] K8s 스터디 : 커스텀 컨트롤러
오늘 스터디 주제는 Custom Controller
Kubebuilder 설치
https://book.kubebuilder.io/quick-start
Go를 먼저 설치한다.
# 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를 자동으로 만들어준다.
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
자기 클러스터 내부에서만 실행하는 것과 외부 리소스 쿼리 차이 고려
reconcile은 long query가 걸릴 수 있음. -> 루프가 안돌게됨