Move directory
This commit is contained in:
@@ -0,0 +1,281 @@
|
||||
# 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 기반 스케줄링 | 위 방법들을 주기적으로 실행 | 공통 |
|
||||
|
||||
### 출력
|
||||
|
||||
```json
|
||||
{
|
||||
"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
|
||||
|
||||
### 입력
|
||||
|
||||
```json
|
||||
{
|
||||
"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_version`과 `api-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로 사용한다.
|
||||
|
||||
```yaml
|
||||
# 중첩 구조 예시
|
||||
image:
|
||||
tag: 1.2.3
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# flat key 변환 결과
|
||||
image.tag: 1.2.3
|
||||
image.pullPolicy: IfNotPresent
|
||||
```
|
||||
|
||||
> **주의**: key 이동(rename)은 `removed` + `added`로 표현된다. 의미적 rename 감지는 기본 비활성화하며, 필요한 경우 heuristic(유사도 기반) 옵션으로 제공한다.
|
||||
|
||||
### 출력
|
||||
|
||||
```json
|
||||
{
|
||||
"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 설계
|
||||
|
||||
### 처리 방식
|
||||
|
||||
```bash
|
||||
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 |
|
||||
|
||||
### 출력
|
||||
|
||||
```json
|
||||
{
|
||||
"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 추가/제거 |
|
||||
|
||||
### 출력
|
||||
|
||||
```json
|
||||
{
|
||||
"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` 블록 비교.
|
||||
|
||||
```json
|
||||
{
|
||||
"dependencies": {
|
||||
"added": ["redis"],
|
||||
"removed": [],
|
||||
"version_changed": {
|
||||
"postgresql": { "old": "12.1.0", "new": "13.0.0" }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 최종 Structured Diff JSON
|
||||
|
||||
LLM Summarizer에 전달되는 통합 출력:
|
||||
|
||||
```json
|
||||
{
|
||||
"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. 관련 문서
|
||||
|
||||
- [02-breaking-change-rules.md](02-breaking-change-rules.md) — Breaking Change 판단 로직
|
||||
- [04-skill-interface.md](04-skill-interface.md) — `helm_diff` Skill 인터페이스
|
||||
Reference in New Issue
Block a user