본문 바로가기
golang

[golang] kubernetes Operator 만들기 Kubebuilder Controller-runtime 4 - Builder

by weq155 2023. 11. 14.
반응형

 

 

[golang] kubernetes Operator 만들기 Controller-runtime 1 - Controller

[golang] kubernetes Operator 만들기 Controller-runtime 2 - Overview

[golang] kubernetes Operator 만들기 Controller-runtime 3 - Manager

[golang] kubernetes Operator 만들기 Controller-runtime 4 - Builder

Builder란?

Package builder는 다른 controller-runtime 라이브러리 등을 래핑 해서 간단한 패턴으로 만드는 역할이다.

builder 패키지로 빌드된 프로젝트는 추후 수정이 필요할 때 패키지를 기반으로 다시 수정할 수 있다.

https://pkg.go.dev/sigs.k8s.io/controller-runtime/pkg/builder

Builder 컴포넌트의 주된 목적은 주어진 Reconciler로 부터 controller를 생성하고

지정된 manager와 리소스에 바인딩 하는 역할

 

 

Builder 사용법

아래는 빌더 사용법의 예시

err = builder.
  ControllerManagedBy(mgr).  // Initialize the builder with the given manager
  For(&appsv1.ReplicaSet{}). // Specify the resource type to be watched
  Owns(&corev1.Pod{}).       // Specify the resource type that is owned by the ReplicaSet
  Complete(&ReplicaSetReconciler{})

 

 

ControllerManagedBy는 제공된 manager와 함께 builder를 초기화하며 controller에 바인딩하는 데 사용됨

For, Owns 또는 Watches function은 Reconciler가 변경할 리소스를 특정하는데 사용된다.

 

빌드 프로세스를 완료하기 위한 마지막 단계에서 Complete 또는 Build function를 호출한다.

Reconciler는 manager와 타겟 리소스로 구성한 내부적으로 주어진

Reconciler로부터 생성된 controller를 생성하는 argument이다.

 

 

 

정확한 Builder 내부의 동작

 

ControllerManagedBy

ControllerManagedBy는 제공된 manager가 시작할 새 controller를 반환한다.

 

이전 게시물에서 보았듯이 우리는 항상 Builder를 초기화하기 위해 Controller ManagedBy부터 시작한다.

 

ControllerManagedBy는 지정된 manager로 부터 builder 개체를 초기화하는 역할

func ControllerManagedBy(m manager.Manager) *Builder {
 return &Builder{mgr: m}
}

 

 

 

For, Owns, Watches

 

manager와 builder가 초기화된 후에 타겟 리소스를 설정한다.

위 함수들은 타겟 리소스를 구성하는 옵션을 제공한다.

함수를 구성하기 위해 필요한 2가지

  1. Reconciler가 실행될 타겟 리소스
  2. Reconciler가 리소스의 변경을 감지할 트리거

일반적으로는 For과 Owns 함수를 사용한다.

For : 타겟 리소스의 변경을 감지하고 Reconciler를 제공함 (For는 하나의 리소스에서만 사용됨)

Owns : For와 같은 기능을 하지만 owner object에서 동작함

 

설명만 봐서는 쉽게 이해하기 힘드니 예시를 확인해 보자

err = builder.
  ControllerManagedBy(mgr).  // Create the ControllerManagedBy
  For(&alpha1v1.Foo{}). // Foo is the Application API
  Owns(&corev1.Pod{}).       // Foo owns Pods created by it
  Complete(&FooReconciler{})

 

 

Reconciler logic에서 controller가 타겟 리소스로부터 다른 리소스를 생성하는 경우

Reconciler에서 Foo 리소스를 타겟 리소스로 판단하고 Foo가 Pod를 업데이트하는 경우

 

Kubernetes에는 ownerReferences라는 메커니즘이 있는데, 이 메커니즘은 ownerReferences라는 두 개체, 즉 owner와 controlled object 사이에 owner 관계를 만들 수 있다.

 

이때, controller의 Reconciler는 타겟 리소스와 다른 오브젝트 사이에 owner 관계를 참조하게 만들 수 있다.

 

 

이 경우에 Owns에 등록된 파드를 변경할 때 Owns를 사용할 수 있다.

Owns(&corev1.Pod{})

 

여기서 등록된 파드는 Reconciler를 트리거하지만 소유되지 않은 파드의 변경은 트리거 대상에서 제외된다.

Owns를 여러개의 리소스 타입으로도 구성할 수 있다.

 

ForOwn의 큰 차이점은

  1. For는 Reconciler당 하나의 리소스만 구성 가능
  2. Owns는 Reconciler를 다중 구성 가능

초보자의 경우 For과 Owners로 충분히 구성 가능하지만, 복잡한 구성이 필요할 때는 Watches를 사용할 수 있다.

 

Complete / Build

마지막으로 내부적으로 Build(Reconciler)를 호출하는 Complete(Reconciler)를 호출하여

지정된 manager와 타겟 리소스로 controller 빌드를 완료할 수 있다.

 

Build function 안에는 중요한 2가지 스텝이 있다.

  1. doController(Reconciler): 지정된 Reconciler와 Manager를 빌드
  2. doWatch(): 구성된 For, Owns, Watches를 기반으로 SourceEventHandler, Predicates를 설정하여 kubernetes API 서버에서 타겟 리소스의 변경을 감지함

doController

doController function에서는 ewController에서 새로운 Controller가 생성되어 blder.ctrl로 설정된 것을 볼 수 있다.

var newController = controller.New
...

func (blder *Builder) doController(r reconcile.Reconciler) error {
  ...
  // Retrieve the GVK from the object we're reconciling
  ...
  // Setup concurrency.

  // Setup cache sync timeout.

  // Setup the logger.

  // Build the controller and return.
  blder.ctrl, err = newController(controllerName, blder.mgr, ctrlOptions)
  return err
}

 

doWatch

 

구성된 For, Owners, Watch를 필요한 개체로 변환

blder.ctrl은 doController function에서 controller를 설정한다.

func (blder *Builder) doWatch() error {
  // Reconcile type
  if blder.forInput.object != nil { 
    typeForSrc, err := blder.project(blder.forInput.object, blder.forInput.objectProjection)
  ...
  // Watches the managed types
  for _, own := range blder.ownsInput {
    typeForSrc, err := blder.project(own.object, own.objectProjection)
  ...
  // Do the watch requests
  for _, w := range blder.watchesInput {
   ..
   if err := blder.ctrl.Watch(w.src, w.eventhandler, allPredicates...); err != nil {
  }
}

 

Summary

이번 게시물에서는 Builder 컴포넌트에 대해 공부해 보았다.

  1. Builder는 제공된 manager와 초기화됨
  2. 타겟리소스는 For과 Own으로 구성한다. For는 지정된 리소스, Owns는 controller에 소유된 리소스를 사용함
  3. controller 빌드를 마치면, Complete는 Reconciler와 함께 호출되며, Reconciler는 manager를 통해 controller를 설정하고 타겟 리소스의 변경 사항을 모니터링함.

 

 

 

 

Reperence

* 본 글은  Masato Naka의 medium 게시글을 참조 & 번역함

https://nakamasato.medium.com/kubernetes-operator-series-2-overview-of-controller-runtime-f8454522a539

 

Kubernetes Operator series 2 — Overview of controller-runtime

Overview of Kubernetes Operator with controller-runtime

nakamasato.medium.com

반응형

 

반응형