[k8s] Controller, Control Loop, Custom Controller, Operator

2022. 9. 10. 20:22[ DevOps ]/[ k8s ]

Controller란?

 

공식문서에 따르면 쿠버네티스에서 컨트롤러는 클러스터의 상태를 관찰 한 다음, 필요한 경우에 생성 또는 변경을 요청하는 '컨트롤 루프'이다. 그렇다면 컨트롤 루프(Control Loop)란 무엇인가? 

 

 

컨트롤 루프(Control Loop)

- 컨트롤 루프는 쿠버네티스에서만 사용되는 용어는 아니며 공식문서에 따르면 컨트롤 루프란 종료되지 않으면서 시스템 상태를 조절하는 루프라고 한다.

- 컨트롤 루프는 컨트롤러를 실행시킨다.

- 컨트롤 루프는 크게 3가지 행위를 한다. (모니터링, 상태 차이 발견, 액션)

- 3가지 행위를 통해 '현재 상태를 의도한 상태와 같아지도록 만드는 역할'을 한다.

 

 

 

예시

'kubectl create deployment web-pod --image=nginx --replicas=3' 커맨드를 수행 플로우

 

1) 요청을 API 서버가 먼저 받고 API 서버는 etcd로부터 정보를 얻어오고 스케줄러에게 요청한다.

2) 스케줄러는 어느 노드에 배치할지 결정하고 API 서버로 알려준다.

3) API 서버는 컨트롤러에게 nginx 파드 3개를 보장하라고 요청한다.

4) API 서버는 결정된 노드로 pod를 실제로 배치하기 시작한다.

5) 이후 컨트롤러는 3개의 Nginx pod가 정상적으로 실행 중인지를 계속해서 감시한다.

6) 특정 Pod에 문제가 생기면 컨트롤러는 이를 감지하고 API 서버로 Pod 재시작을 요청한다.

7) API 서버는 다시 스케줄러에게 요청해서 Pod를 배치할 노드를 결정받는다.

 

 

- 사용자가 어떠한 상태로 만들어 달라고 요청(kubectl)하면 이는 '의도한 상태'이다.

- '현재 상태'를 의도한 상태와 비교해서 현재 상태를 의도한 상태로 맞춰가는 액션을 한다.

- 이는 컨트롤 루프가 무한루프를 돌면서 '상태 차이를 발견'함으로써 실행된다.

- 이런 역할을 하는 컴포넌트가 쿠버네티스의 컨트롤러이다.

 

 

 

 

Controller의 종류

쿠버네티스 클러스터는 항상 2가지의 상태(desired state, current state)를 가지며 쿠버네티스에서 기본으로 제공되는 컨트롤러는 Control Plan에서 동작한다는 점을 기억하고 넘어가자. 컨트롤러는 크게, 쿠버네티스에서 자체적으로 제공되는 컨트롤러와 커스텀 컨트롤러로 구분된다.

 

1. control plane에서 실행되는 일반적인 Control Loop

https://developers.redhat.com/articles/2021/06/22/kubernetes-operators-101-part-2-how-operators-work#how_operators_reconcile_kubernetes_cluster_states

 

 

- '일반적인' 쿠버네티스 클러스터에서는 controller manager가 reconciliation loop(조정 루프, 컨트롤 루프)에서 컨트롤러들을 실행시키는 구조이다.

- controller manager가 실행하는 컨트롤 루프 안에서는 Reconcile()이라는 메소드를 실행시키면서 각 컨트롤러가 실행되도록 하는 구조로 동작한다.

- 컨트롤러가 실행되면 컨트롤러는 current state를 desired state로 맞추는 작업을 수행한다.

 

 

2. worker nodes에서 실행되는 Control Loop

https://developers.redhat.com/articles/2021/06/22/kubernetes-operators-101-part-2-how-operators-work#how_operators_reconcile_kubernetes_cluster_states

 

- 위에서 설명한 일반적인 컨트롤러는 Control Plane에서 실행되지만 오퍼레이터에 의한 컨트롤러는 워커 노드에서 실행된다. 이는 오퍼레이터가 워크로드로써 쿠버네티스 클러스터에 배포되기 때문이다.

- 다른 워크로드와 마찬가지로 master 클러스터는 워커 노드의 오퍼레이터 워크로드를 호스팅한다.

- control plane의 controller manager는 컨트롤러의 리스트를 가지고 있으며, 각 오퍼레이터 컨트롤러는 controller manager의 컨트롤 루프에 추가된다.

- control plane의 controller manager가 실행되면 컨트롤 루프가 실행되고 여기서는 control plane에 있는 표준 컨트롤러와 워커 노드에 있는 오퍼레이터 컨트롤러를 모두 실행시킨다.

- 따라서 표준 컨트롤러와 마찬가지로 오퍼레이터 컨트롤러의 Reconcile()를 호출하여 오퍼레이터 컨트롤러가 실행되고 오퍼레이터 컨트롤러는 current state를 desired state로 맞추는 작업을 수행한다.

- control plane은 controller manager에 등록된 컨트롤러 목록에 대해 Reconcile() 메소드만을 호출하기 때문에 표준 컨트롤러인지 커스텀 컨트롤러인지 모른 채로 동작하게 된다.

 

 


 

 

표준 Controller의 종류

 

표준 컨트롤러는 위와 같이 크게 5종류가 있으며 자세한 설명은 추가로 작성한 포스팅을 참고하십시오.

 

1. ReplicationController

- Pod 개수를 보장한다는 성질을 가장 기본으로 가지는, 컨트롤러 중에서 가장 basic 한 컨트롤러

- API 버전 1에서 만들어짐

- 포스팅: https://jh-labs.tistory.com/504

 

2. ReplicaSet, Deployment

- Replication Controller로 운영하다가 부족한 부분들이 생겨났고 이를 보완하고자 ReplicaSet이 등장

- ReplicaSet은 'RS보다 다양한 형태의 label을 사용하여 Pod를 컨트롤'

- Deployment는 ReplicaSet의 부모역할을 하며 'ReplicaSet을 컨트롤함과 동시에 Rolling Update 기능을 추가로 제공'

- ReplicaSet 포스팅: https://jh-labs.tistory.com/505

- Deployment 포스팅: https://jh-labs.tistory.com/506

 

3. DaemonSet

- (워커) 노드 당 1개의 Pod를 보장하며 Rolling Update를 지원

- 로그 에이전트, 모니터링 애플리케이션 동작시 유용

- DaemonSet 포스팅: https://jh-labs.tistory.com/516

 

4. Stateful Sets

- 'Pod의 이름, 저장소를 보장'해주는 컨트롤러

- Rolling Update를 지원

- StatefulSets 포스팅: https://jh-labs.tistory.com/521

 

5. Job, CronJob

- Job은 배치 처리에 적합한 컨트롤러

- Job 컨트롤러는 Job의 종료 상태에 따라 '비정상 종료일 경우에는 재시작'

- Job을 부모 입장에서 컨트롤해주는 CronJob 컨트롤러는 크론식을 기반으로 '예약 처리 지원'

- Job 포스팅: https://jh-labs.tistory.com/528

- CronJob 포스팅: https://jh-labs.tistory.com/533

 

 

 

* 위와 같이 쿠버네티스는 다양한 형태의 컨트롤러를 제공하기 때문에 애플리케이션을 다양한 형태로 동작시킬 수 있다. 애플리케이션의 특성에 맞게 컨트롤러를 선택하면 된다.

 


 

커스텀 컨트롤러(Custom Controller)

- 오퍼레이터(Operator) 개발은 커스텀 컨트롤러를 기능 개발하는 것이다.

- 오퍼레이터를 기반으로 구현한 커스텀 컨트롤러 역시, 표준 컨트롤러와 동작 방식이 같다. Control Plane의 컨트롤 루프에서 Reconcile() 메소드가 실행되는 원리이다.

- 애플리케이션 운영에 추가적으로 자동화하고 싶은 부분을 개발하면 된다. 오퍼레이터가 애플리케이션을 자동화하는 것이므로 결국엔 오퍼레이터 핵심 기능은 컨트롤러를 custom으로 만들고 만들어진 컨트롤러가 매번 컨트롤 루프를 돌면서 현재 상태를 의도한 상태로 맞추도록 자동화하는 것이 된다.

- 커스텀 컨트롤러는 etcd나 Memcached와 같은 CRD를 Deployment나 Service 같은 워크로드로 재조정함으로써 구현한다.

- 표준 컨트롤러와 커스텀 컨트롤러 모두 current state를 desired state와 같게 만드는 역할을 한다는 점은 공통점이다. 하지만 오퍼레이터에서는 desired state을 custom resource로써 관리한다. 

 


 

오퍼레이터(operator) 패턴

오퍼레이터 패턴은 쿠버네티스 자체적으로 제공하는 기능은 아니며 사용자가 쿠버네티스를 이용해서 작업을 자동화할 때 사용되는 것이 오퍼레이터 익스텐션이다. 운영을 하면서 설정 등을 자동화하고 싶을 때 사용되는 패턴이다.(설정에 국한된 표현은 아님) 아래는 쿠버네티스 공식문서를 참고했다.

 

https://kubernetes.io/ko/docs/concepts/extend-kubernetes/operator/

 

 

대표적인 예: 프로메테우스(Prometheus) 오퍼레이터

- 일반 프로메테우스는 configmap에 설정하고 프로메테우스 Pod 재시작해야 하지만 프로메테우스 오퍼레이터는 Pod 재시작 과정이 필요 없다.

- 프로메테우스를 Pod로 실행시킬 때 프로메테우스 Pod에 대한 설정은 configmap으로 관리한다.

- 프로메테우스 설정(rule)은 일반적으로 자주 변경된다. Rule이 바뀔 때마다 configmap을 바꾸고 프로메테우스 Pod를 재실행해서 변경한 rule을 적용시켜야 하는 수동 작업은 매우 번거로운 작업이다.

- 이러한 불편함은 오퍼레이터 컨트롤러를 개발함으로써 자동화할 수 있다.

- 프로메테우스 설정(Rule)을 쿠버네티스 CRD(CustomResourceDefinitions)로 정의하고 오퍼레이터가 설정 적용을 자동화할 수 있도록 한다.

 

 

 

 

오퍼레이터에서 자동화하려는 내용을 직접 개발해야 한다. 수많은 애플리케이션들이 있고 각 애플리케이션마다 자동화하려는 관점이 다르기 때문이다. 쿠버네티스에서는 이런 자동화를 위한 가이드를 제시한다. 또는 프로메테우스 오퍼레이터처럼 기존에 이미 제공되고 있는 오퍼레이터를 사용할 수도 있는데, 이때 아래 2가지 요소를 이해해야 한다.

 

1) 쿠버네티스 컨트롤 루프 (컨트롤러 컴포넌트)

2) 애플리케이션 아키텍처와 동작 이해

- 결국 오퍼레이터 개발은 애플리케이션 자동화를 위한 것이므로 애플리케이션 동작을 이해하는 것이 중요하다.

 

 

cf. 쿠버네티스 CRD와 오퍼레이터 관계

 

 

- 쿠버네티스 CRD(CustomResourceDefinitions)를 이용해서 '의도한 상태를 정의'하고 오퍼레이터 커스텀 컨트롤러가 루프를 돌면서 상태 불일치를 발견하고 그 상태를 일치시키도록 액션을 한다.

 

 

 

 

 

 

 

Reference

- k8s operator pattern, https://kubernetes.io/ko/docs/concepts/extend-kubernetes/operator/

- k8s controller docs, https://kubernetes.io/ko/docs/concepts/architecture/controller/

- RedHat k8s opperator, https://developers.redhat.com/articles/2021/06/22/kubernetes-operators-101-part-2-how-operators-work#