k8s Operator란?

쿠버네티스 오퍼레이터는 애플리케이션의 배포, 관리, 운영을 자동화하여 효율성을 높입니다.

k8s Operator란?
Photo by Joseph Barrientos / Unsplash

개요

쿠버네티스 확장 개념인 오퍼레이터(operator)패턴에 대해 정리하고 작성하였습니다.

쿠버네티스 오퍼레이터란 무엇인가요?

쿠버네티스 오퍼레이터는 쿠버네티스의 기능을 확장하여 특정 애플리케이션이나 서비스의 배포, 관리 및 운영을 자동화하는 특수한 컨트롤러입니다.

오퍼레이터 패턴의 목표는 서비스 또는 서비스 세트를 관리하는 사람 운영자의 주요 목표를 파악하는 것입니다. 특정 애플리케이션과 서비스를 담당하는 사람 운영자는 시스템이 어떻게 작동해야 하는지, 배포 방법, 문제 발생 시 대응 방법에 대한 깊은 지식을 가지고 있습니다. 쿠버네티스에서 워크로드를 실행하는 사람들은 종종 반복적인 작업을 처리하기 위해 자동화를 사용하는 것을 선호합니다. 오퍼레이터 패턴은 쿠버네티스 자체에서 제공하는 것 이상으로 작업을 자동화하기 위해 코드를 작성하는 방법을 보여줍니다.

쿠버네티스는 웹 앱, 모바일 백엔드 및 API 서비스와 같은 상태 비저장 애플리케이션을 작동 방식에 대한 추가 지식 없이도 관리하고 확장할 수 있습니다. 쿠버네티스의 기본 제공 기능은 이러한 작업을 쉽게 처리하도록 설계되었습니다. 하지만 데이터베이스와 같은 상태 저장 애플리케이션은 전문 지식과 처리가 필요합니다. 쿠버네티스 오퍼레이터는 이러한 도메인 지식을 쿠버네티스 확장에 인코딩하여 수명 주기 관리를 자동화합니다.


쉽게 말해, 쿠버네티스 오퍼레이터는 애플리케이션 배포를 단순화하는 쿠버네티스 확장 기능입니다. 컨트롤러와 사용자 지정 객체 정의를 제공하여 애플리케이션 작동 방식을 자세히 알지 못해도 새 애플리케이션을 신속하게 배포할 수 있도록 지원합니다. 오퍼레이터는 사람의 관리자의 주요 목표를 반영하도록 설계되었습니다. 복잡한 시스템을 쿠버네티스 클러스터에 수동으로 배포하는 것은 애플리케이션에 필요한 Pod, StatefulSet, 서비스, ConfigMap 및 볼륨을 생성하고 연결해야 하기 때문에 종종 집중적인 작업이 필요합니다. 오퍼레이터를 사용하면 postgresql과 같은 사용자 지정 애플리케이션별 객체 유형을 사용하여 기본 쿠버네티스 구성을 자동화할 수 있습니다. 오퍼레이터는 이러한 동작을 가능하게 하는 CRD와 함께 제공되는 컨트롤러를 제공합니다.

쿠버네티스 오퍼레이터 작동 방식

쿠버네티스에서 오퍼레이터는 애플리케이션별 컨트롤러로, 쿠버네티스 애플리케이션을 패키징, 배포 및 관리하는 데 도움이 됩니다. 일반적으로 쿠버네티스 애플리케이션은 쿠버네티스 애플리케이션 프로그래밍 인터페이스(API) 및 kubectl 도구를 통해 실행하고 관리합니다. 오퍼레이터를 사용하면 쿠버네티스 API의 기능을 확장하여 구조화된 프로세스를 사용하여 애플리케이션 인스턴스를 자동으로 구성, 생성 및 관리할 수 있습니다. 오퍼레이터는 쿠버네티스 컨트롤러 및 리소스의 기본 기능을 사용하지만 애플리케이션별 또는 도메인 지식을 추가하여 관리하는 애플리케이션의 전체 수명 주기를 자동화합니다.

제어 루프 및 조정

오퍼레이터는 쿠버네티스 객체를 모니터링하는 컨트롤러를 사용합니다. 이러한 컨트롤러는 사용자 지정 리소스 정의(CRD)라고 하는 사용자 지정 객체를 추적하기 때문에 일반 쿠버네티스 컨트롤러와 약간 다릅니다. CRD는 구조화된 데이터(원하는 애플리케이션 상태)를 저장하고 검색할 수 있는 장소를 제공하는 쿠버네티스 API의 확장입니다. 오퍼레이터는 특정 유형의 사용자 지정 리소스와 관련된 클러스터 이벤트를 추적합니다. 이러한 사용자 지정 리소스는 추가, 업데이트 및 삭제의 세 가지 유형의 이벤트를 추적할 수 있습니다. 오퍼레이터는 정보를 수신하면 사용자 지정 컨트롤러 스케일링 주기의 일부로 쿠버네티스 클러스터 또는 외부 시스템을 원하는 상태로 만들기 위한 조치를 취합니다.

쿠버네티스 오퍼레이터 워크플로를 요약하면 다음과 같습니다.

  • 사용자가 CRD를 변경합니다.
  • 오퍼레이터는 CRD를 추적하고 변경 이벤트를 식별합니다.
  • 오퍼레이터는 CRD 상태를 원하는 상태와 조정합니다.
  • 오퍼레이터는 클러스터 상태를 원하는 상태로 조정합니다.

오퍼레이터는 애플리케이션의 실제 상태와 원하는 상태를 비교하여 조치를 결정합니다. 예를 들어 원하는 복제본 수가 현재 복제본 수를 초과하면 오퍼레이터는 복제본을 더 추가합니다. 오퍼레이터는 쿠버네티스 API 서버와 상호 작용하여 애플리케이션의 실제 상태를 원하는 상태에 맞춥니다. 필요에 따라 쿠버네티스 리소스가 생성, 업데이트 또는 삭제됩니다. 조정 루프는 애플리케이션의 상태가 원하는 상태와 동기화된 상태로 유지되도록 합니다. 원하는 구성을 유지하기 위해 클러스터의 변경 사항을 감시합니다. 오퍼레이터에는 오류 및 복구를 처리하는 로직이 포함되어야 합니다.

사용자 지정 리소스 정의(CRD)

사용자 지정 리소스 정의(CRD)를 사용하여 오퍼레이터는 사용자가 Pod, 서비스 및 배포와 같은 기본 쿠버네티스 객체에 대해 걱정할 필요 없이 더 높은 수준의 추상화에서 애플리케이션과 상호 작용할 수 있도록 합니다. CRD를 통해 사용자는 애플리케이션 구성에 집중할 수 있으며 오퍼레이터는 이러한 구성을 기반으로 필요한 쿠버네티스 리소스를 자동으로 관리합니다.

쿠버네티스 API와의 상호 작용

쿠버네티스에서 오퍼레이터는 사용자 지정 컨트롤러로 표현되며 향상된 리소스로 쿠버네티스 API를 확장하고 이를 관리하는 데 필요한 사용자 지정 로직을 포함합니다.

Operator SDK

Operator SDK는 개발자가 쿠버네티스 API의 복잡성에 대한 지식 없이도 전문 지식을 바탕으로 오퍼레이터를 빌드할 수 있도록 지원합니다. Operator SDK는 다음과 같은 다양한 언어를 지원합니다.

쿠버네티스 오퍼레이터를 만드는 방법은 다음과 같습니다.

  • 관리하려는 리소스에 대한 CRD를 정의합니다.
  • 리소스 인스턴스를 감시할 수 있는 사용자 지정 컨트롤러를 작성합니다.
  • Operator SDK를 사용하여 오퍼레이터를 빌드합니다.
  • kubectl을 사용하여 리소스 인스턴스를 생성합니다.

쿠버네티스 오퍼레이터를 만들 때 따라야 할 몇 가지 모범 사례는 다음과 같습니다.

  • 애플리케이션당 하나의 오퍼레이터를 개발합니다.
  • 비동기 동기화 루프를 사용합니다.
  • 테스트 기반 개발 방식을 채택합니다.
  • Operator SDK를 사용합니다.
  • 선언적 API를 사용합니다.
  • 과도하게 채워진 함수를 피합니다.
  • 외부 종속성을 래핑합니다.

쿠버네티스 오퍼레이터의 주요 기능 및 장점

쿠버네티스 오퍼레이터는 다음과 같은 주요 기능을 제공합니다.

  • 수명 주기 관리: 오퍼레이터는 배포, 업그레이드 및 스케일링을 통해 데이터베이스와 같은 복잡한 상태 저장 애플리케이션의 전체 수명 주기를 관리합니다. 또한 애플리케이션 로직을 적용하여 백업 및 복원과 같은 작업을 자동화할 수 있습니다.
  • 선언적 관리: 오퍼레이터는 CRD와 같은 K8s 추상화를 활용하여 사용자 지정 리소스를 통해 애플리케이션의 간단한 선언적 관리를 제공합니다.
  • 보안: 오퍼레이터는 암호화, 비밀 관리 및 액세스 제어와 같은 최고의 보안 조치를 통합하여 애플리케이션을 보호합니다. 이러한 조치는 앱마다 사용자 지정할 수 있습니다.
  • 자동화된 배포 및 스케일링
  • CRD
  • 자가 치유 기능
  • 사용자 지정 컨트롤러 지원
  • 구성 관리
  • 확장성 지원

쿠버네티스 오퍼레이터 사용 사례

쿠버네티스 오퍼레이터는 클러스터 내에서 애플리케이션 및 서비스를 관리하고 자동화하는 데 몇 가지 주요 사용 사례가 있습니다.

  • 데이터베이스 관리: MySQL 또는 Postgres와 같은 오퍼레이터를 사용하여 데이터베이스를 배포, 업그레이드, 백업 및 복원합니다.
  • 스토리지 프로비저닝: 상태 저장 애플리케이션의 특정 요구 사항에 따라 스토리지 작업을 프로비저닝하고 관리합니다
  • 로그 및 모니터링: Elasticsearch 또는 Prometheus와 같은 로깅 및 모니터링 도구를 배포하여 분석 및 메트릭 수집을 단순화합니다.
  • CI/CD 도구 배포: 오퍼레이터에서 Jenkins와 같은 도구를 사용하여 CI/CD 파이프라인의 배포, 구성 및 스케일링을 자동화합니다.
  • 메시징 시스템 통합: RabbitMQ와 같은 시스템을 관리할 수 있는 메시징 오퍼레이터를 사용하여 클러스터 스케일링, 업그레이드 및 상태 확인을 자동으로 수행합니다.
  • 서비스 메시 도구 사용: Istio와 같은 서비스 메시 도구를 설치하여 애플리케이션 트래픽을 관리하고 카나리아 롤아웃을 자동화하는 등의 작업을 수행합니다.
  • 백업 및 복원: 특정 애플리케이션에 대한 재해 복구 시스템을 활용하고 애플리케이션을 자동으로 백업합니다.

쿠버네티스 오퍼레이터 예시

쿠버네티스 오퍼레이터의 예를 찾고 있다면 OperatorHub.io에서 확인해볼 수 있습니다.

쿠버네티스 오퍼레이터, Helm, 컨트롤러 비교

위에서 언급했듯이 오퍼레이터는 컨트롤러의 한 유형이므로 실제로는 별개의 것이 아닙니다.

Notion Image

그러나 오퍼레이터는 쿠버네티스에서 사용할 수 있는 여러 컨트롤러 중 하나일 뿐이며 다른 "네이티브" 컨트롤러와 달리 오퍼레이터는 기본적으로 쿠버네티스에 내장된 리소스를 관리하지 않습니다. 그렇기 때문에 오퍼레이터에는 사용자 지정 리소스 정의 또는 CRD가 필요합니다. 쿠버네티스에 어떤 Pod와 컨테이너를 실행할지 알려주는 매니페스트를 생성하여 애플리케이션을 실행할 수 있는 배포 컨트롤러와 같은 다른 유형의 컨트롤러를 사용하여 애플리케이션을 배포할 수 있습니다.

Helm은 차트, 템플릿 및 버전 관리와 같은 패키징 형식을 통해 쿠버네티스에 애플리케이션을 설치하고 업그레이드하는 프로세스를 간소화합니다. Helm은 애플리케이션의 초기 배포에 중점을 둡니다. 반대로 오퍼레이터는 애플리케이션이 배포된 후 지속적인 수명 주기에 더 중점을 둡니다.

오퍼레이터는 Helm 차트가 중단된 부분부터 시작하여 다음과 같은 반복적인 관리 작업을 자동화합니다.

  • 로드 메트릭을 기반으로 자동 스케일링
  • 업그레이드된 버전이 앱을 손상시키지 않도록 보장
  • 오류 수정 및 고가용성 보장

Operator 간단한 예시

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: simplewebapps.example.com
spec:
  group: example.com
  versions:
    - name: v1
      served: true
      storage: true
      schema:
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                replicas:
                  type: integer
                  description: 원하는 웹 애플리케이션 파드 개수
                  default: 1
                message:
                  type: string
                  description: 웹 애플리케이션에 표시할 메시지
                  default: "Hello, Kubernetes Operator!"
  scope: Namespaced
  names:
    plural: simplewebapps
    singular: simplewebapp
    kind: SimpleWebApp
    shortNames:
    - swa
apiVersion: example.com/v1
kind: SimpleWebApp
metadata:
  name: my-webapp
spec:
  replicas: 3
  message: "Welcome to my awesome web app!"

CRD를 통해 위와같이 선언할 수 있습니다.

apiVersion: example.com/v1
kind: SimpleWebApp
metadata:
  name: my-webapp
spec:
  replicas: 5 # replicas 값 변경 (3 -> 5)
  message: "Hello, updated message!" # message 값 변경
  1. CustomResource 수정 요청:
    • 사용자가 kubectl apply -f my-webapp.yaml 명령을 실행하여 my-webapp CR을 업데이트합니다.
  2. API 서버 알림:
    • 쿠버네티스 API 서버는 SimpleWebApp 오퍼레이터에게 CustomResource 수정 이벤트를 알립니다.
  3. 오퍼레이터 컨트롤 루프 시작:
    • 오퍼레이터는 이벤트 알림을 받고 컨트롤 루프를 시작합니다.
  4. 객체 상태 관찰 및 분석:
    • 오퍼레이터는 my-webapp CR을 관찰하고, 변경된 spec.replicasspec.message ("Hello, updated message!") 를 확인합니다. 현재 파드 개수가 3개이고, 메시지도 이전 메시지인 것을 확인합니다.
  5. 액션 수행 (파드 스케일 아웃 및 메시지 업데이트):
    • 오퍼레이터는 desired 상태를 맞추기 위해 다음과 같은 액션을 수행합니다.
    • 파드 스케일 아웃: 파드 개수를 5개로 늘리기 위해 2개의 파드를 추가로 생성합니다.
    • 메시지 업데이트: 실행 중인 파드들의 메시지를 "Hello, updated message!" 로 업데이트합니다. (파드 재시작 등을 통해 업데이트).
  6. 상태 업데이트 및 지속적 모니터링:
    • 파드 스케일 아웃 및 메시지 업데이트가 완료되면, 오퍼레이터는 my-webapp CR의 상태(Status)를 업데이트하고, 컨트롤 루프를 다시 시작하여 지속적으로 모니터링합니다.

장애 상황 및 자동 복구 예시

만약 5개의 파드 중 2개의 파드가 어떤 이유로 인해 실패(Failed) 상태가 되었다고 가정해 보겠습니다.

  1. 파드 실패 이벤트 발생: 쿠버네티스는 파드 실패 이벤트를 감지하고 오퍼레이터에게 알립니다.
  2. 오퍼레이터 컨트롤 루프 시작: 오퍼레이터는 이벤트 알림을 받고 컨트롤 루프를 시작합니다.
  3. 객체 상태 관찰 및 분석: 오퍼레이터는 my-webapp CR을 관찰하고, spec.replicas 는 여전히 5이지만, 현재 실행 중인 파드 개수가 3개로 줄어든 것을 확인합니다.
  4. 액션 수행 (파드 복구): 오퍼레이터는 desired 상태를 맞추기 위해 실패한 2개의 파드를 대체할 새로운 파드를 생성하는 액션을 수행합니다.
  5. 상태 업데이트 및 지속적 모니터링: 새로운 파드 생성이 완료되면, 오퍼레이터는 my-webapp CR의 상태(Status)를 업데이트하고, 컨트롤 루프를 다시 시작하여 지속적으로 모니터링합니다.

Reference