클라우드 컴퓨팅 & NoSQL/도커 & 쿠버네티스

간단하게 알아보는 Kubernetes Operator의 개념과 Kopf 프레임웍

Terry Cho 2022. 12. 28. 15:17

간단하게 알아보는 Kubernetes Operator의 개념과 Kopf 프레임웍

조대협 (http://bcho.tistory.com)

 

쿠버네티스에는 Deployment, Service,Pod 등 여러 predefined resource가 있다. 이런 pre-defined resource 이외에 새로운 리소스를 정의해서 등록해서 사용할 수 있는데, 이를 Controller 또는 Operator라고 한다.

 

Controller와 Operator는 용어가 종종 혼용되어 사용되는데, 분류를 하자면  Controller는 Kubernetes에 이미 정의되어 있는 Pre-defined resource를 , Operator는 사용자가 정의한 애플리케이션 리소스를 지칭한다.

 

Operator는 Stateless application (Deployment)보다는 주로 Stateful application 정의에 많이 사용되는데, Stateful application (데이터 베이스와 같은)의 경우에는 서비스 기동 전후에 해야할 테스크들이 많기 때문에, 이를 위한 작업을 추가하여 Custom Operator를 만든다. 예를 들어 데이터 베이스 클러스터의 경우 주기적으로 백업을 자동으로 한다거나, 또는 마스터 노드가 다운 되었을때 Election 작업을 통해서 새로운 마스터 노드를 선출한다던가 등이 좋은 예이다. 

 

컨테이너 공유를 위한 DockerHub 처럼 Operator 들을 공유하는 사이트가 있는데, https://operatorhub.io/  에 여러 등록되어 있는 Operator들을 찾을 수 있다. 

 

그러면 어떻게 Operator를 구현하는지 어떻게 작동하는지에 대해서 간략하게 살펴보자

CRD

사용자 정의 리소스를 Custom Resource라고 한다. Service, Pod와 같은 리소스를 사용자가 직접 등록할 수 있다. Custom Resource를 등록하기 위해서 Custom Resource에 대한 스펙 (이름, 인자 등등)을 정의해야 하는데, 스펙을 정의한 YAML 문서를 Custom Resource Definition (CRD)라고 한다. 

 

아래는 HelloOperator라는 Custom Resource를 정의한 CRD YAML 파일이다. 

 

apiVersion: apiextensions.k8s.io/v1

kind: CustomResourceDefinition

metadata:

 name: helloopperators.terry.com

spec:

 scope: Namespaced

 group: terry.com

 versions:

   - name: v1

     served: true

     storage: true

     schema:

      openAPIV3Schema:

         type: object

 names:

   kind: HelloOperator

   plural: helloopperators

   singular: hellooperator

   shortNames:

     - helloop

 

 

<코드 crd.yaml>

 

이렇게 정의된 CRD를 쿠버네티스에 적용하려면 kubectl apply -f {CRD 파일명}을 이용하면, CRD를 등록할 수 있다. 

CR

CRD가 정의되었으면, 이 리소스는 쿠버네티스 클러스터 내에서 생성될 수 있다. 해당 리소스를 생성하기 위해서는 여타 다른 리소스 (Pod, Deployment)등과 같이 YAML 파일을 작성한 후에, kubectl apply -f  {리소스 파일}을 이용해서 생성할 수 있다. 

 

아래 파일은 위에서 정의한 CRD HelloOperator 리소스 오브젝트를 생성하는 YAML이다. 

 

 

apiVersion: terry.com/v1

kind: HelloOperator

metadata:

 name: my-helloworld

 

 

< 코드 obj.yaml>

 

간단한 설명을 위한 예제로 별도의 Parameter를 받지 않았지만, 실제 Operator를 개발할때는 필요한 인자를 정의해서 받을 수 있다. 

Operator

스펙을 정의하고 리소스 객체를 만들었으면,  이 리소스 객체에 대한 로직을 추가해야 한다. 이 로직 구현체를 Operator라고 한다. Operator는 Operator 개발 프레임웍을 이용해서 개발하는데, 각 프로그래밍 언어별로 다양한 SDK를 제공한다. 주요 SDK들은 다음과 같다.

이 글에서 사용한 Operator SDK는 파이썬 기반의 Kopf를 사용하였다. 아래는 Custom Resource Object를 생성시에 body와 함께 간단한 로그 메세지를 출력하는 코드이다. 

import kopf
import logging

@kopf.on.create('HelloOperator')

def create_fn(body, **kwargs):
  logging.info(f"### A handler is called with body: {body}")

< 코드 : helloOperator.py>

코드를 작성한 후에 Kopf 명령어를 이용하여 Operator를 다음과 같이 동작 시킨다.

 

% kopf run helloOperator.py --verbose

 

다음 앞에서 작성한 obj.yaml로 HelloOperator Custom Resource를 생성한다.

% kubectl apply -f obj.yaml

 

그러면 아래와 같이 Kopf 로그 메세지에서 아래와 같이 create_fn에서 출력한 로그가 나온것을 확인할 수 있다. 

 

개발 테스트이기 때문에, Operator를 별도의 개발환경에서 실행하였지만 운영 환경에서는 컨테이너로 패키징 하여 쿠버네티스 클러스터에 배포 해야 한다.

 

간단한 개념 설명을 위해서 생성 부분에 대한 이벤트 핸들러 (create_fn)만 정의하였지만, 상태가 update되거나 custom resource가 삭제될때 등에도 이벤트를 정의할 수 있다. 

일반적으로는 애플리케이션 기동을 위한  Pod나 Service 와 같은 다른 리소스들을 생성하는 로직을 구현한다. 

 

지금까지 정리한 개념을 그림으로 표현해보면 다음과 같다. 

<fig. CRD,CR 그리고 Operator 관계>

 

  1. CRD (Custom Resource Definition)으로 Custom Resource의 스펙을 정의한다.
  2. CRD 스펙에 따라서 Custom Resource (CR)을 생성할 YAML을 작성하고, 이를 통해서 Custom Resource를 생성한다.
  3. Custom Resource의 비지니스 로직인 Operator를 Operator SDK를 이용하여 작성한다.
    이 Operator는 Kubernetes Cluster API를 통하여 Custom Resource의 상태를 주기적으로 체크하고, 그에 따라서 알맞은 상태(Desired status) 로 변경하기 위한 로직을 수행한다.