Overview
Kubernetes Operator와 Custom Resource Definitions (CRDs) 대해서 알아본다.
Kubernetes Operator
Kubernetes 생태계에서 Operator는 Kubernetes 애플리케이션을 패키징, 배포, 관리하는 방법이다. Kubernetes 애플리케이션은 Kubernetes에 배포되고 Kubernetes API 및 kubectl 도구를 사용하여 관리된다. Operator는 클러스터 상태를 감시한 다음 필요한 경우 변경을 수행하거나 요청하는 루프인 컨트롤러의 Kubernetes 원칙을 따른다. Operator는 Kubernetes를 확장하여 특정 애플리케이션의 전체 수명주기 관리를 자동화한다.
왜 Operator를 사용해야 할까?
Kubernetes Operator는 애플리케이션 로직을 관리하고 Kubernetes Control Plane의 일부이다. 따라서 루프를 실행하여 클러스터의 실제 상태와 원하는 상태를 확인하고 , 두 상태가 멀어질 때 이를 조정하는 역할을 하는 컨트롤러이다. 단순성과 유연성, 그리고 자동화는 오퍼레이터 생성을 가능하게 할 뿐만 아니라 이는 Kubernetes 아키텍처의 초석을 형성하는 기본 원칙이다.
Operator는 본질적으로 도메인별 지식이 내장된 맞춤형 컨트롤러이다. 특정 애플리케이션을 배포, 업그레이드, 구성, 복구 및 확장하는 방법을 알고 있다. Operator 패턴은 소프트웨어에서 애플리케이션을 관리하고, 일반적인 작업을 자동화하고, Kubernetes 기반 애플리케이션 관리 방법을 제공하는 방법에 대한 운영 지식을 포착하는 것을 목표로 한다.
Operator는 사용자 정의 리소스 세트(Custom Resource)와 해당 리소스에 대한 사용자 정의 컨트롤러(Custom Controllers)로 구현된다. 사용자 정의 리소스는 애플리케이션의 구성 스키마 역할을 하며 컨트롤러는 애플리케이션의 상태가 사용자 정의 리소스에 설명된 원하는 상태와 일치하도록 작동한다.
- 사용자 정의 리소스(Custom Resource): 새로운 리소스 유형 생성을 허용하도록 Kubernetes API를 확장한다. 사용자 정의 리소스는 원하는 애플리케이션 상태를 정의한다.
- 사용자 정의 컨트롤러(Custom Controllers): 사용자 정의 리소스를 관찰하고 애플리케이션의 실제 상태가 사용자 정의 리소스에 정의된 원하는 상태와 다르다는 것을 감지하면 차이점을 조정하기 위한 조치를 취한다.
Operator는 애플리케이션을 관리하기 위해 Kubernetes의 `control loop` 개념을 사용한다. 애플리케이션의 상태를 지속적으로 모니터링하고 원하는 상태와의 불일치를 수정하기 위해 애플리케이션별 조치를 취한다.
- 애플리케이션 배포 및 잠재적인 지원 서비스 자동 배포
- 복잡한 상태 저장 애플리케이션을 포함하여 업그레이드 및 다운그레이드를 원활하게 처리
- 애플리케이션 구성 및 비밀 관리
- 로드 또는 기타 지표를 기반으로 자동 확장
- 오류 복구, 비정상 인스턴스 자동 교체 또는 재구성
- 백업 및 복원
오퍼레이터를 개발하기 위한 프레임워크 및 도구들이 있다.
- 오퍼레이터 SDK(Operator SDK): 오퍼레이터의 개발, 테스트, 패키징을 도와준다.
- 오퍼레이터 생명주기 관리자(Operator Lifecycle Manager) (OLM): 쿠버네티스 클러스터 상의 오퍼레이터들을 관리하며, 오퍼레이터의 설치, 업데이트 및 생명주기 관리를 담당한다.
- 오퍼레이터 미터링(Operator Metering): 오퍼레이터가 사용하는 자원에 대한 보고를 위한 것이다.
Kubernetes Custom Resource Definitions (CRDs)란?
Kubernetes 사용자 정의 리소스 정의(CRD)는 사용자 정의 리소스로 Kubernetes 기능을 확장할 수 있는 강력한 기능이다. CRD를 사용하면 포드, 배포 또는 서비스와 같은 표준 Kubernetes 리소스가 처리되는 방식과 유사한 방식으로 Kubernetes 클러스터 내에 고유한 특정 리소스를 생성할 수 있다. 이는 Kubernetes 플랫폼을 기반으로 맞춤형 애플리케이션이나 통합을 개발하는 데 매우 유용할 수 있다.
사용자 정의 리소스는 기본 Kubernetes 설치에서 반드시 사용할 수 있는 것은 아닌 Kubernetes API의 확장이다. 이는 기본적으로 제공되는 리소스 외에 새로운 리소스를 추가하여 요구 사항에 맞게 Kubernetes를 사용자 정의하는 방법이다.
- 확장성(Extensibility): kubectl 및 기타 Kubernetes API 클라이언트와 함께 사용할 수 있는 자체 API로 Kubernetes를 확장할 수 있다.
- 유연성(Flexibility): 기본 Kubernetes 리소스처럼 작동하는 새 리소스를 정의할 수 있다.
- 통합(Integration): CRD는 사용자 지정 리소스를 기반으로 애플리케이션과 해당 구성 요소를 관리하는 사용자 지정 컨트롤러인 연산자를 구축하는 데 유용하다.
CRD를 구현하려면 다른 Kubernetes 리소스와 마찬가지로 YAML을 사용하여 정의한다. 이 정의는 새로운 종류의 리소스, 해당 이름 및 스키마를 지정합니다. 스키마는 CRD(사용자 지정 리소스라고도 함) 인스턴스 구성의 유효성을 검사하는 데 사용된다.
CRD 정의의 기본 구조는 다음과 같다.
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
# Name of the CRD
name: crdtype.mycompany.com
spec:
# Group name to which the CRD belongs
group: mycompany.com
# List of versions
versions:
- name: v1
served: true
storage: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
myField:
type: string
# Scope of the CRD (Namespaced or Cluster)
scope: Namespaced
names:
# Plural name used in the URL
plural: crdtypes
# Singular name used as an alias
singular: crdtype
# Kind is the serialized kind of the resource
kind: CrdType
# ShortNames allow shorter string to match your resource on kubectl
shortNames:
- ct
클러스터에서 CRD를 정의하고 적용한 후에는 Kubernetes의 다른 리소스와 마찬가지로 해당 인스턴스를 생성하고 관리할 수 있다.
다음은 사용자 정의 리소스의 기본 예이다.
apiVersion: mycompany.com/v1
kind: CrdType
metadata:
name: example-crdtype
spec:
myField: "Hello, world!"
- 일반적으로 CRD는 CRD 자체와 사용자 정의 컨트롤러로 구성된 연산자의 일부이다. 컨트롤러는 사용자 지정 리소스와 관련된 이벤트를 감시하고 이에 따라 리소스를 생성, 업데이트, 삭제 또는 조정하여 반응한다.
- 버전 관리(Versioning): 기존 리소스에 지장을 주지 않도록 CRD의 버전을 신중하게 관리하고 업그레이드 및 지원 중단을 신중하게 처리하는 것이 중요하다.
- 검증(Validation): CRD 정의의 OpenAPI 스키마 사양을 사용하여 사용자 지정 리소스를 검증하고 Kubernetes API에 저장되기 전에 기대치를 충족하는지 확인한다.
- 성능(Performance): 특히 대규모 클러스터에서 사용자 지정 컨트롤러가 성능에 미치는 영향을 주시한다.
Operator 핵심 구성요소
Custom Resource Definition (CRD)
- Kubernetes API의 확장을 정의
- 새로운 리소스 타입을 선언적으로 정의
- 예시
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: namespacesyncs.sync.somaz94.github.io
spec:
group: sync.somaz94.github.io
names:
kind: NamespaceSync
plural: namespacesyncs
scope: Namespaced
versions:
- name: v1
served: true
storage: true
Custom Resource (CR)
- CRD의 인스턴스
- 사용자가 정의한 설정을 포함
- 예시
apiVersion: sync.somaz94.github.io/v1
kind: NamespaceSync
metadata:
name: my-sync
spec:
sourceNamespace: source-ns
configMapName:
- config1
- config2
Controller
- CR을 감시하고 관리하는 컨트롤 루프
- 원하는 상태와 현재 상태를 조정
- Reconciliation 로직 구현
Kubebuilder
Kubebuilder는 Kubernetes Operator를 개발하기 위한 SDK이다. Go 언어를 사용하여 CRD와 Controller를 쉽게 개발할 수 있게 해주는 프레임워크이다.
Kubebuilder 프로젝트 구조
.
├── Dockerfile
├── Makefile # 빌드, 테스트, 배포 등의 명령어
├── PROJECT # 프로젝트 메타데이터
├── api/ # CRD API 정의
│ └── v1/
│ ├── groupversion_info.go
│ ├── namespacesync_types.go
│ └── zz_generated.deepcopy.go
├── config/ # Kubernetes 매니페스트
│ ├── crd/
│ ├── rbac/
│ ├── manager/
│ └── samples/
├── internal/
│ └── controller/ # 컨트롤러 로직
└── main.go # 프로그램 진입점
주요 명령어
프로젝트 생성
# 새 프로젝트 초기화
kubebuilder init --domain somaz94.github.io --repo github.com/somaz94/k8s-namespace-sync
# API 생성
kubebuilder create api --group sync --version v1 --kind NamespaceSync
빌드 및 배포
# CRD 생성
make install
# Controller 실행
make run
# Docker 이미지 빌드
make docker-build
# Kubernetes에 배포
make deploy
API 정의 예시
type NamespaceSyncSpec struct {
// 소스 네임스페이스
SourceNamespace string `json:"sourceNamespace"`
// 동기화할 ConfigMap 이름 목록
ConfigMapName []string `json:"configMapName,omitempty"`
// 동기화할 Secret 이름 목록
SecretName []string `json:"secretName,omitempty"`
// 제외할 네임스페이스 목록
Exclude []string `json:"exclude,omitempty"`
}
Controller 구현
func (r *NamespaceSyncReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
log := log.FromContext(ctx)
// NamespaceSync 객체 조회
var namespaceSync syncv1.NamespaceSync
if err := r.Get(ctx, req.NamespacedName, &namespaceSync); err != nil {
return ctrl.Result{}, client.IgnoreNotFound(err)
}
// 비즈니스 로직 구현
// ...
return ctrl.Result{}, nil
}
Kubebuilder 마커(Markers)
// +kubebuilder:resource:scope=Namespaced
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp"
개발 워크플로우
API 설계
- CRD 스펙 정의
- 타입 정의
- 검증 규칙 추가
Controller 구현
- Reconciliation 로직 작성
- 이벤트 핸들링
- 에러 처리
테스트
- 단위 테스트
- 통합 테스트
- End-to-End 테스트
배포
- Docker 이미지 빌드
- Kubernetes 매니페스트 생성
- 클러스터에 배포
장점
표준화된 구조
- 일관된 프로젝트 레이아웃
- 모범 사례 적용
자동 생성
- 보일러플레이트 코드 생성
- RBAC 매니페스트 생성
- CRD 매니페스트 생성
개발 편의성
- 빌트인 테스트 프레임워크
- 디버깅 도구
- 문서화 지원
확장성
- 커스텀 웹훅 지원
- 메트릭 통합
- 로깅 통합
보일러 플레이트란?
보일러플레이트는 최소한의 변경으로 여러 곳에서 재사용되는 코드를 의미한다. Kubebuilder는 위 명령어를 통해 다음과 같은 보일러플레이트 코드를 자동으로 생성한다.
마치며
다음시간에는 kubebuilder를 사용해서 Operator를 생성하는 방법에 대해서 알아보겠다.
https://github.com/somaz94/k8s-namespace-sync
Reference
https://www.cncf.io/blog/2022/06/15/kubernetes-operators-what-are-they-some-examples/
'Container Orchestration > Kubernetes' 카테고리의 다른 글
Helm Chart 생성 및 패키징 (gh-pages) (1) | 2024.12.20 |
---|---|
Kubernetes Operator(CRD, CR) 생성(With kubebuilder) (0) | 2024.12.17 |
Kubernetes Headless Service란? (0) | 2024.12.03 |
Kubernetes Deployment Strategy (0) | 2024.11.26 |
Helm Chart Template 문법 (0) | 2024.11.15 |