kro 개념

kro 개념

kro가 커스텀 Kubernetes API를 만들고 리소스를 구성하는 핵심 개념을 설명합니다.

출처: 문서

본문

kro는 플랫폼 팀이 여러 리소스를 더 높은 수준의 추상화로 구성하는 커스텀 Kubernetes API를 만들 수 있게 합니다. 이 항목은 실제 예시를 살펴본 후, EKS용 kro 캐퍼빌리티를 사용하며 이해해야 할 핵심 개념을 설명합니다.

kro 시작하기

kro 캐퍼빌리티를 만든 후(kro 캐퍼빌리티 생성 참고), 클러스터에서 ResourceGraphDefinition을 사용해 커스텀 API 생성을 시작할 수 있습니다.

다음은 간단한 웹 애플리케이션 추상화를 만드는 완전한 예시입니다.

apiVersion: kro.run/v1alpha1
kind: ResourceGraphDefinition
metadata:
  name: webapplication
spec:
  schema:
    apiVersion: v1alpha1
    kind: WebApplication
    group: kro.run
    spec:
      name: string | required=true
      image: string | default="nginx:latest"
      replicas: integer | default=3
  resources:
  - id: deployment
    template:
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: ${schema.spec.name}
      spec:
        replicas: ${schema.spec.replicas}
        selector:
          matchLabels:
            app: ${schema.spec.name}
        template:
          metadata:
            labels:
              app: ${schema.spec.name}
          spec:
            containers:
            - name: app
              image: ${schema.spec.image}
              ports:
              - containerPort: 80
  - id: service
    template:
      apiVersion: v1
      kind: Service
      metadata:
        name: ${schema.spec.name}
      spec:
        selector:
          app: ${schema.spec.name}
        ports:
        - protocol: TCP
          port: 80
          targetPort: 80

이 ResourceGraphDefinition을 적용한 후, 애플리케이션 팀은 간소화된 API로 웹 애플리케이션을 만들 수 있습니다.

apiVersion: kro.run/v1alpha1
kind: WebApplication
metadata:
  name: my-app
spec:
  name: my-app
  replicas: 5

kro가 적절한 구성으로 Deployment와 Service를 자동으로 생성합니다. image가 지정되지 않았으므로 스키마의 기본값 nginx:latest를 사용합니다.

핵심 개념

중요

kro는 ResourceGraphDefinition을 생성 시점에 검증합니다(런타임이 아닌). RGD를 만들면 kro가 CEL 구문을 검증하고, 실제 Kubernetes 스키마에 대해 표현식을 타입 체크하고, 필드 존재를 확인하며, 순환 의존성을 감지합니다. 이는 RGD를 만들 때 즉시 오류가 발견되어 인스턴스를 배포하기 전에 잡힌다는 것을 의미합니다.

ResourceGraphDefinition

ResourceGraphDefinition(RGD)은 다음을 지정해 커스텀 Kubernetes API를 정의합니다.

  • 스키마(Schema) - SimpleSchema 형식의 API 구조(필드 이름, 유형, 기본값, 검증)
  • 리소스(Resources) - 만들 기본 Kubernetes 또는 AWS 리소스의 템플릿
  • 의존성(Dependencies) - 리소스가 서로 어떻게 관련되는지(필드 참조에서 자동 감지)

RGD를 적용하면 kro가 클러스터에 새 커스텀 리소스 정의(CRD)를 등록합니다. 애플리케이션 팀은 커스텀 API의 인스턴스를 만들 수 있고, kro가 모든 기본 리소스의 생성과 관리를 처리합니다. 자세한 내용은 kro 문서의 ResourceGraphDefinition Overview를 참고하세요.

SimpleSchema 형식

SimpleSchema는 OpenAPI 지식 없이 API 스키마를 정의할 수 있는 간소화된 방법을 제공합니다.

schema:
  apiVersion: v1alpha1
  kind: Database
  spec:
    name: string | required=true description="Database name"
    size: string | default="small" enum=small,medium,large
    replicas: integer | default=1 minimum=1 maximum=5

SimpleSchema는 required, default, minimum/maximum, enum, pattern 같은 제약 조건과 함께 string, integer, boolean, number 유형을 지원합니다. 자세한 내용은 kro 문서의 SimpleSchema를 참고하세요.

CEL 표현식

kro는 값을 동적으로 참조하고 조건부 로직을 추가하기 위해 Common Expression Language(CEL)을 사용합니다. CEL 표현식은 ${와 }로 감싸며 두 가지 방식으로 사용할 수 있습니다.

  • 독립 표현식 - 전체 필드 값이 단일 표현식입니다.
spec:
  replicas: ${schema.spec.replicaCount}  # Expression returns integer
  labels: ${schema.spec.labelMap}        # Expression returns object

표현식 결과가 전체 필드 값을 대체하며 필드의 예상 유형과 일치해야 합니다.

  • 문자열 템플릿 - 문자열 안에 하나 이상의 표현식이 포함됩니다.
metadata:
  name: "${schema.spec.prefix}-${schema.spec.name}"  # Multiple expressions
  annotation: "Created by ${schema.spec.owner}"      # Single expression in string

문자열 템플릿의 모든 표현식은 문자열을 반환해야 합니다. 다른 유형을 변환하려면 string()을 사용하세요: "replicas-${string(schema.spec.count)}".

  • 필드 참조 - schema.spec를 사용해 인스턴스 스펙 값에 접근합니다.
template:
  metadata:
    name: ${schema.spec.name}-deployment
    namespace: ${schema.metadata.namespace}  # Can also reference metadata
  spec:
    replicas: ${schema.spec.replicas}
  • 선택적 필드 접근 - 존재하지 않을 수 있는 필드에는 ?를 사용하세요.
# For ConfigMaps or Secrets with unknown structure
value: ${configmap.data.?DATABASE_URL}

# For optional status fields
ready: ${deployment.status.?readyReplicas > 0}

필드가 존재하지 않으면 표현식은 실패 대신 null을 반환합니다.

  • 조건부 리소스 - 조건이 충족될 때만 리소스를 포함합니다.
resources:
- id: ingress
  includeWhen:
    - ${schema.spec.enableIngress == true}
  template:
    # ... ingress configuration

includeWhen 필드는 불리언 표현식 목록을 받습니다. 리소스가 생성되려면 모든 조건이 참이어야 합니다. 현재 includeWhen은 schema.spec 필드만 참조할 수 있습니다.

  • 변환(Transformations) - 삼항 연산자와 함수로 값을 변환합니다.
template:
  spec:
    resources:
      requests:
        memory: ${schema.spec.size == "small" ? "512Mi" : "2Gi"}

    # String concatenation
    image: ${schema.spec.registry + "/" + schema.spec.imageName}

    # Type conversion
    port: ${string(schema.spec.portNumber)}
  • 교차 리소스 참조 - 다른 리소스의 값을 참조합니다.
resources:
- id: bucket
  template:
    apiVersion: s3.services.k8s.aws/v1alpha1
    kind: Bucket
    spec:
      name: ${schema.spec.name}-data

- id: configmap
  template:
    apiVersion: v1
    kind: ConfigMap
    data:
      BUCKET_NAME: ${bucket.spec.name}
      BUCKET_ARN: ${bucket.status.ackResourceMetadata.arn}

CEL 표현식에서 다른 리소스를 참조하면 자동으로 의존성을 만듭니다. kro가 참조된 리소스가 먼저 생성되도록 보장합니다. 자세한 내용은 kro 문서의 CEL Expressions를 참고하세요.

리소스 의존성

kro는 CEL 표현식에서 의존성을 자동으로 유추합니다. 순서를 지정하지 않고 관계를 기술합니다. 한 리소스가 CEL 표현식을 사용해 다른 리소스를 참조하면 kro가 의존성을 만들고 올바른 생성 순서를 결정합니다.

resources:
- id: bucket
  template:
    apiVersion: s3.services.k8s.aws/v1alpha1
    kind: Bucket
    spec:
      name: ${schema.spec.name}-data

- id: notification
  template:
    apiVersion: s3.services.k8s.aws/v1alpha1
    kind: BucketNotification
    spec:
      bucket: ${bucket.spec.name}  # Creates dependency: notification depends on bucket

${bucket.spec.name} 표현식이 의존성을 만듭니다. kro는 모든 리소스와 그 의존성의 방향성 비순환 그래프(DAG)를 만든 다음 생성 순서를 위한 위상 정렬(topological order)을 계산합니다.

  • 생성 순서 - 리소스는 위상 순서로 생성됩니다(의존성 먼저).
  • 병렬 생성 - 의존성이 없는 리소스는 동시에 생성됩니다.
  • 삭제 순서 - 리소스는 역위상 순서로 삭제됩니다(의존하는 것 먼저).
  • 순환 의존성 - 허용되지 않습니다. kro는 검증 중에 순환 의존성이 있는 ResourceGraphDefinition을 거부합니다.

계산된 생성 순서를 볼 수 있습니다.

kubectl get resourcegraphdefinition my-rgd -o jsonpath='{.status.topologicalOrder}'

자세한 내용은 kro 문서의 Graph inference를 참고하세요.

ACK로 구성

kro는 ACK용 EKS 캐퍼빌리티와 원활하게 작동해 AWS 리소스를 Kubernetes 리소스와 구성할 수 있습니다.

resources:
# Create S3 bucket with ACK
- id: bucket
  template:
    apiVersion: s3.services.k8s.aws/v1alpha1
    kind: Bucket
    spec:
      name: ${schema.spec.name}-files

# Inject bucket details into Kubernetes ConfigMap
- id: config
  template:
    apiVersion: v1
    kind: ConfigMap
    data:
      BUCKET_NAME: ${bucket.spec.name}
      BUCKET_ARN: ${bucket.status.ackResourceMetadata.arn}

# Use ConfigMap in application deployment
- id: deployment
  template:
    apiVersion: apps/v1
    kind: Deployment
    spec:
      template:
        spec:
          containers:
          - name: app
            envFrom:
            - configMapRef:
                name: ${config.metadata.name}

이 패턴을 사용하면 AWS 리소스를 만들고, 그 상세 정보(ARN, URL, 엔드포인트)를 추출해 애플리케이션 구성에 주입할 수 있습니다. 모두 단일 단위로 관리됩니다. 더 많은 구성 패턴과 고급 예시는 EKS용 kro 고려 사항을 참고하세요.

다음 단계

  • EKS용 kro 고려 사항 - EKS별 패턴, RBAC, ACK 및 Argo CD 통합 알아보기
  • kro 문서 - 고급 CEL 표현식, 검증 패턴, 문제 해결을 포함한 종합적인 kro 문서

더 알아보기 (Learn more)