Files
service-catalog/agent/update_catalog/docs/design/01-helm-diff-engine.md
T
2026-03-06 17:08:31 +09:00

7.5 KiB

Helm Diff Engine 설계

1. 개요

두 버전의 Helm Chart를 비교하여 Structured Diff JSON을 생성하는 컴포넌트. 모든 출력은 deterministic하며 LLM을 사용하지 않는다.


2. Chart Version Detector

역할

새로운 Helm Chart 버전 출시를 감지한다.

감지 방법

방법 설명 적합 대상
Repo 디렉토리 스캔 manifests/helm/<chart>/ 하위 버전 디렉토리 변화를 감지 dip-catalog 구조
Git diff 기반 감지 최신 커밋에서 추가된 <version>/ 디렉토리 파악 dip-catalog 구조
Helm repo index.yaml 주기 스캔 등록된 repo의 index 파일 직접 파싱 외부/사내 Helm repo
ArtifactHub API 조회 https://artifacthub.io/api/v1/packages/helm/{org}/{chart} 공개 chart
GitHub Release Webhook 차트 소스 저장소의 release 이벤트 구독 GitHub 기반 차트
Cron 기반 스케줄링 위 방법들을 주기적으로 실행 공통

출력

{
  "chart": "airflow",
  "repo": "apache",
  "current_version": "1.2.3",
  "latest_version": "1.3.0",
  "detected_at": "2025-01-01T00:00:00Z"
}

dip-catalog 차트 업데이트 흐름 (버전 디렉토리 유지)

신규 버전이 감지되면 dip-catalog 구조에 맞춰 버전 디렉토리를 추가한다. 기존 버전 디렉토리는 유지한다.

1) helm pull <repo>/<chart> --version <new>       # 최신 차트 다운로드
2) tar xzf <chart>-<new>.tgz                      # 압축 해제
3) manifests/helm/<chart>/<new>/ 로 이동          # 버전 디렉토리 생성
4) chart_updater: 이전 버전 디렉토리에서 파일 복사
     - custom-values.yaml   → 그대로 복사
     - CUSTOM-README.md     → 그대로 복사 (배포 관련 내용 유지)
     - BUILD-README.md      → 복사 + 버전 번호 치환 (from_version → to_version)
5) generate_upgrade_doc → CUSTOM-README.md에 업그레이드 주의사항 섹션 추가 (항상 실행)

3. Helm Diff Engine

입력

{
  "chart": "airflow",
  "from_version": "1.2.3",
  "to_version": "1.3.0",
  "values_override": {},
  "chart_path": "manifests/helm/airflow/1.3.0"
}

dip-catalog 구조에서는 chart_path를 우선 사용한다.

처리 단계

1. (repo 구조) helm pull <repo>/<chart> --version <from>  →  chart_old/
2. (repo 구조) helm pull <repo>/<chart> --version <to>    →  chart_new/
1'. (dip-catalog) manifests/helm/<chart>/<from>/ 복사 → chart_old/
2'. (dip-catalog) manifests/helm/<chart>/<to>/ 복사   → chart_new/
3. values.yaml 비교       → Values Diff
4. helm template 결과 비교 → Template Diff
5. CRD schema 비교        → CRD Diff
6. Chart.yaml 비교        → Dependency Diff
7. 결과 병합              → Structured Diff JSON

helm template 표준 옵션

재현성을 위해 아래 옵션을 고정한다.

helm template <chart> \
  --values values_override.yaml \
  --include-crds \
  --kube-version <target_k8s_version> \
  --api-versions <explicit_api_versions>

target_k8s_versionapi-versions는 환경별 설정값으로 관리한다. dip-catalog의 경우 custom-values.yaml이 존재하면 values_override 기본값으로 적용한다.

에러 처리

상황 대응
helm pull 실패 재시도 3회 → 실패 시 알림 후 중단
chart 미존재 로그 기록 + 스킵
helm template 렌더링 오류 오류 내용 JSON에 포함, partial diff 생성
네트워크 타임아웃 60s timeout 설정, 재시도

4. Values Diff 설계

비교 항목

  • added: 신규 버전에서 추가된 key
  • removed: 신규 버전에서 삭제된 key
  • changed: default 값이 변경된 key
  • type_changed: 값의 타입이 변경된 key (string → int 등)

처리 방식

values.yaml을 flat key 형태로 변환 후 비교한다.

  • dip-catalog에서는 custom-values.yaml을 기본 values_override로 사용한다.
# 중첩 구조 예시
image:
  tag: 1.2.3
  pullPolicy: IfNotPresent

# flat key 변환 결과
image.tag: 1.2.3
image.pullPolicy: IfNotPresent

주의: key 이동(rename)은 removed + added로 표현된다. 의미적 rename 감지는 기본 비활성화하며, 필요한 경우 heuristic(유사도 기반) 옵션으로 제공한다.

출력

{
  "values": {
    "added": ["resources.limits.cpu", "resources.limits.memory"],
    "removed": ["ingress.enabled"],
    "changed": {
      "image.tag": { "old": "1.2.3", "new": "1.3.0" },
      "replicaCount": { "old": 1, "new": 2 }
    },
    "type_changed": [
      { "key": "workers.replicas", "old_type": "string", "new_type": "integer" }
    ]
  }
}

5. Template Diff 설계

처리 방식

helm template <chart_old> --values values_override.yaml > old.yaml
helm template <chart_new> --values values_override.yaml > new.yaml

YAML을 리소스 단위로 분리 후 비교한다 (kind + metadata.name 기준).

  • generateName만 존재하는 리소스는 템플릿 파일명 + 순번으로 안정적 ID를 생성한다.
  • Cluster-scoped 리소스는 namespace를 무시한다.

비교 리소스 타입

리소스 분석 항목
Deployment / StatefulSet container image, env, resource limits, replicas
Service port, targetPort, type
Ingress rules, TLS, annotations
ConfigMap data key 추가/삭제/변경
CRD 별도 CRD Diff로 처리
ServiceAccount annotations

출력

{
  "templates": {
    "Deployment/airflow-scheduler": {
      "image_changed": true,
      "image": { "old": "apache/airflow:1.2.3", "new": "apache/airflow:1.3.0" },
      "env_added": ["AIRFLOW__CORE__NEW_SETTING"],
      "env_removed": [],
      "resource_limits_changed": true
    },
    "Service/airflow-webserver": {
      "port_changed": false
    }
  }
}

6. CRD Diff 설계

비교 항목

항목 설명
schema 변경 OpenAPI v3 schema 필드 변경
required 필드 추가 기존 CR에 영향
field 제거 기존 CR의 해당 필드 무시됨
version 변경 storage version 변경 시 migration 필요
webhook 변경 conversion webhook 추가/제거

출력

{
  "crd": {
    "AirflowCluster": {
      "changed": true,
      "breaking": true,
      "breaking_reasons": ["required field added: spec.executor"],
      "schema_changed": true,
      "version_changed": false,
      "fields_removed": [],
      "fields_added": ["spec.executor"],
      "required_fields_added": ["spec.executor"]
    }
  }
}

7. Dependency Diff 설계

Chart.yaml의 dependencies 블록 비교.

{
  "dependencies": {
    "added": ["redis"],
    "removed": [],
    "version_changed": {
      "postgresql": { "old": "12.1.0", "new": "13.0.0" }
    }
  }
}

8. 최종 Structured Diff JSON

LLM Summarizer에 전달되는 통합 출력:

{
  "chart": "airflow",
  "from_version": "1.2.3",
  "to_version": "1.3.0",
  "generated_at": "2025-01-01T00:00:00Z",
  "values": { ... },
  "templates": { ... },
  "crd": { ... },
  "dependencies": { ... },
  "errors": []
}

errors 필드에는 렌더링 실패 등의 부분적 오류를 포함한다. LLM은 이를 참고하여 분석 범위를 명시해야 한다.


9. 관련 문서