79555215a0
"파이프라인이 chart CVE 조치와 커스텀 이미지 빌드 2개로 나뉘어 있는가" 를 확인하다가 실제
구성이 그 모델과 다른 것이 드러났다.
1. 워크플로는 3개다. cve-edge-post.yml 이 CLAUDE.md 에서 디렉토리 트리와 괄호 안에만
등장해 파이프라인으로 읽히지 않았다 — "2개" 인식의 근원이다.
2. doc/sbom-pipeline.md 가 두 축을 한 파일에 담고 있었다(자체 빌드 절 43줄).
커스텀 이미지가 별도 레포로 분리될 예정인데 이 상태로는 분리 때 파일을 찢어야 한다.
3. 그 문서가 이미 뒤집힌 결정을 담고 있었다 — "schedule 트리거는 없다. 블라인드 정기
재빌드는 제거했다" 인데 PR #40 이 schedule 을 추가했다.
축을 이렇게 갈랐다
-----------------
차트 카탈로그 축 sbom.yml · cve-edge-post.yml → doc/sbom-pipeline.md
자체 빌드 축 build-image.yml → .claude/image-authoring.md
doc/sbom-pipeline.md — 차트 축만 남긴다
- 상단에 "이 문서가 다루는 축" 을 두고 자체 빌드는 링크로 넘긴다
- 자체 빌드 절(43줄)을 image-authoring.md 로 이관
- sbom.yml ↔ cve-edge-post.yml 비교 표 신설. **판정기가 두 벌**이라는 사실을 명시했다 —
cve-edge-post.yml 은 집계를 워크플로 YAML 안의 인라인 python 으로 갖고 있어 승인 예외도
실효 등급도 적용하지 않는다. 같은 스캔 데이터에서 다른 숫자가 나올 수 있다
- PR 을 실제로 막는 게이트는 images/** PR 뿐이고 manifests/applicationset/** 는 아무
워크플로도 보지 않는다는 사각지대를 적었다
.claude/image-authoring.md — 자체 빌드 축의 단일 출처가 된다
- 이관받은 워크플로 서술 + "이 워크플로의 게이트는 강제다"(차트 축 warn-only 와 다르다는
사실이 지금까지 한 곳에만 있었다)
- schedule 결정 정정 — 지금 것은 블라인드가 아니라 CVE 트리거다. 수정 버전이 있는 차단
CVE 가 있을 때만 빌드하고 없으면 아무것도 하지 않는다. 거부된 것과 조건이 다르다
- "레포 분리 후 무엇이 끊기는가" 결합점 7개 표. 3번(탐지가 카탈로그를 읽는다)이 가장 크고,
게이트 공유는 workflow_call 이 아니라 composite action 이어야 한다는 것도 적었다
(workflow_call 은 별도 job 이라 $OUT_DIR 를 공유하지 못한다)
- 파일 상단에 "레포 분리 시 images/·scripts/build/·build-image.yml 과 함께 이동한다"
- #35 에서 실측한 매핑 함정 추가 — CHART_DIRS 에 없는 파일은 patch-catalog-tag.py 가
검사조차 하지 않아 cnpg-cluster/1.1.0 이 조용히 빠졌다
CLAUDE.md — 지도만 남긴다
두 축 비교 표(질문·워크플로·게이트 강도·소유 문서)로 바꾸고 메커니즘 서술을 걷어냈다.
cve-edge-post.yml 을 파이프라인으로 처음 등재했다.
검증
----
표의 사실 대조 각 워크플로의 cve-gate 호출·warn-only·활성 schedule 을 파일에서 확인
축 분리 sbom-pipeline.md 에 남은 build-image.yml 언급은 전부 링크·대조·시크릿
공유 문장(의도된 것)
뒤집힌 결정 "schedule 트리거는 없다" 잔존 0건
링크 3개 문서의 로컬 링크 전부 실재
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
247 lines
15 KiB
Markdown
247 lines
15 KiB
Markdown
# DIP Catalog — 하네스 엔지니어링 가이드
|
|
|
|
## 프로젝트 개요
|
|
|
|
DIP Catalog는 세 개의 독립 서브시스템으로 구성된다.
|
|
|
|
| 서브시스템 | 설명 | 경로 |
|
|
|-----------|------|------|
|
|
| **정적 카탈로그** | 엔터프라이즈 Helm 차트 버전 보관소 (2026-08-14 기준 차트 59개 / 버전 디렉토리 70개 — Kafka, Airflow, MLflow, KServe, OpenMetadata, APISIX, VictoriaMetrics 등) | `manifests/helm/` |
|
|
| **자동화 에이전트** | Helm 차트 신규 버전 감지 → Diff 분석 → 문서 생성 → GitHub PR 자동화 | `agent/update_catalog/` |
|
|
| **CVE/SBOM 게이트** | 카탈로그 이미지 SBOM·취약점 스캔 + 게이트 판정 (현재 warn-only) | `scripts/pipeline/`, `scripts/build/`, `doc/sbom-pipeline.md` |
|
|
|
|
카탈로그는 운영 클러스터 직접 변경과 무관하다. **모든 변경은 Git PR을 통해서만 이루어진다.**
|
|
|
|
---
|
|
|
|
## 디렉토리 구조
|
|
|
|
```
|
|
dip-catalog/
|
|
├── manifests/
|
|
│ ├── helm/<chart>/<version>/ # Helm 차트 정적 카탈로그 (각 버전 독립 디렉토리)
|
|
│ ├── applicationset/ # ArgoCD ApplicationSet 매니페스트
|
|
│ └── kustomize/ # Kustomize 오버레이 (Kubeflow, Model Registry)
|
|
├── agent/
|
|
│ └── update_catalog/
|
|
│ ├── skills/ # 자동화 Skills (Python, 각 Skill 독립 실행 가능)
|
|
│ ├── scripts/run_flow.sh # 전체 파이프라인 로컬 실행 스크립트
|
|
│ └── docs/ # 아키텍처·설계 문서 (한국어)
|
|
│ ├── design/ # 컴포넌트별 상세 설계 (00~05)
|
|
│ ├── decisions/ # ADR (아키텍처 결정 기록)
|
|
│ └── status.md # 구현 현황
|
|
├── scripts/
|
|
│ ├── pipeline/ # SBOM 생성 + CVE 스캔 + 게이트 판정 (sbom.yml/cve-edge-post.yml 이 쓴다)
|
|
│ ├── build/ # 자체 빌드 이미지 프레임워크 (build-image.yml 이 쓴다)
|
|
│ └── deploy-test/ # 배포 검증 스크립트 + fixtures (helm/kubectl 실행 전담)
|
|
├── images/<image>/ # 자체 빌드 하드닝 이미지 정의 (목록은 이 디렉토리가 단일 출처)
|
|
├── MEMORY.md # 현재 상태·미결 (작업 이어받을 때 여기서 시작 — 유지 규칙은 파일 안에)
|
|
└── doc/ # 차트 리소스 프로파일 + 스택 분류 + CVE/SBOM 파이프라인 + 운영 가이드
|
|
├── sbom-pipeline.md # SBOM 생성·스캔·게이트 메커니즘
|
|
├── cve-exceptions.json # 게이트 승인 예외 목록
|
|
├── catalog-stack-classification.md # 차트 스택 분류·우선순위(P0~P2)
|
|
├── define-chart-resources.md # 차트별 Small/Medium/Large 리소스 프로파일
|
|
├── decisions/ # ADR — 재측정으로 복원되지 않는 이미지·차트 선택 근거
|
|
└── migrations/ # 레포 간 이관 핸드오프 문서
|
|
```
|
|
|
|
---
|
|
|
|
## 정적 카탈로그 작업
|
|
|
|
### 차트 디렉토리 구조
|
|
|
|
각 `manifests/helm/<chart>/<version>/`에 다음 파일이 있어야 한다.
|
|
|
|
| 파일 | 역할 |
|
|
|------|------|
|
|
| `Chart.yaml` | Helm 차트 메타데이터 |
|
|
| `values.yaml` | 업스트림 기본값 |
|
|
| `custom-values.yaml` | PaaSup 전용 오버라이드 (Breaking Change 판단 기준) |
|
|
| `CUSTOM-README.md` | 업그레이드 주의사항 (자동 생성 + 수동 추가 가능) |
|
|
| `BUILD-README.md` | 차트 갱신 작업 가이드 (버전 정보 파싱에 사용됨 — 아래 주의) |
|
|
|
|
> `BUILD-README.md`는 업스트림 원문이 아니라 레포가 직접 쓰는 한국어 갱신 가이드다.
|
|
> `chart_version_detector`가 이 파일에서 `helm repo add <repo> <url>` 한 줄을 정규식으로
|
|
> 뽑아 업스트림 레포를 정한다 — **이 줄이 없으면 신규 버전 자동 감지가 조용히 실패한다**
|
|
> (`repo: null` → `latest_version: null`). 그래서 "변경 금지"가 아니라 **이 줄을 지우거나
|
|
> 형식을 바꾸지 않는 선에서 갱신 가능**이 정확한 규정이다. 2026-08-19 argo-cd에서 실제로
|
|
> 이 줄이 없어 감지가 실패해 추가했다.
|
|
|
|
실제 카탈로그는 이 5개를 전부 갖추지 않은 디렉토리가 있다(2026-08-14 기준 70개 중
|
|
`custom-values.yaml` 65 · `CUSTOM-README.md` 66 · `BUILD-README.md` 61). 배포 파라미터화용
|
|
`dip-values.yaml`(36) · `dip-questions.yaml`(23) · `dip-resources-quotas.yaml`(27) 계열은
|
|
차트에 따라 선택적으로 둔다.
|
|
|
|
### 신규 차트 추가
|
|
|
|
`manifests/helm/<chart>/<version>/` 디렉토리를 생성하고 위 5개 파일을 포함시킨다.
|
|
`custom-values.yaml`은 PaaSup 환경에 필요한 오버라이드만 작성한다. 기본값 전체를 복사하지 않는다.
|
|
|
|
### 리소스 프로파일
|
|
|
|
차트별 CPU/Memory/Storage 요구사항은 `doc/define-chart-resources.md`에 Small/Medium/Large 티어로 정의되어 있다. 신규 차트 추가 시 이 파일에도 리소스 정의를 추가한다.
|
|
|
|
---
|
|
|
|
## 자동화 Skills 작업
|
|
|
|
### 파이프라인 순서
|
|
|
|
```
|
|
chart_version_detector → chart_updater → helm_diff →
|
|
breaking_change_check → generate_upgrade_doc → update_docs_file → create_pr
|
|
```
|
|
|
|
각 Skill은 독립 실행 가능하다. JSON을 stdout으로 출력하며, 다음 Skill의 입력으로 전달된다.
|
|
|
|
### 로컬 실행
|
|
|
|
```bash
|
|
# 전체 파이프라인 실행 (필수 환경변수 오버라이드)
|
|
CATALOG_ROOT=/path/to/dip-catalog CHART=airflow \
|
|
bash agent/update_catalog/scripts/run_flow.sh
|
|
|
|
# 개별 Skill 실행 예시
|
|
python3 agent/update_catalog/skills/chart_version_detector/scripts/run.py \
|
|
--catalog-root /path/to/dip-catalog --chart airflow
|
|
|
|
python3 agent/update_catalog/skills/helm_diff/scripts/run.py \
|
|
--chart airflow --repo bitnami \
|
|
--chart-path /path/to/dip-catalog/manifests/helm/airflow/1.15.0 \
|
|
--from-version 1.15.0 --to-version 1.16.0
|
|
```
|
|
|
|
### 주요 환경변수
|
|
|
|
| 변수 | 설명 | 기본값 |
|
|
|------|------|--------|
|
|
| `CATALOG_ROOT` | dip-catalog 레포 절대 경로 | **하드코딩된 로컬 경로** (반드시 오버라이드) |
|
|
| `CHART` | 대상 차트명 | `airflow` |
|
|
| `USE_CLAUDE_CLI=1` | LLM 호출 활성화 (breaking=true 시 상세 가이드 생성) | 미설정 시 템플릿 기반 생성 |
|
|
|
|
> `run_flow.sh`의 `CATALOG_ROOT` 기본값은 songwonbin의 로컬 경로로 하드코딩되어 있다. 다른 환경에서 실행할 때 반드시 환경변수로 오버라이드한다.
|
|
|
|
### Skill 인터페이스 확인
|
|
|
|
각 Skill의 입출력 스키마는 `agent/update_catalog/skills/<skill>/SKILL.md`에 정의되어 있다.
|
|
|
|
---
|
|
|
|
## Claude Code Skills (`.claude/skills/`)
|
|
|
|
위 `agent/update_catalog/skills/`(결정론적 Python CLI 파이프라인)와 **용도가 다른 별개
|
|
체계**다. 혼동하지 않는다.
|
|
|
|
| 구분 | `agent/update_catalog/skills/` | `.claude/skills/` |
|
|
|------|-------------------------------|-------------------|
|
|
| 형식 | SKILL.md + `scripts/run.py` (JSON in/out) | Claude Code Agent Skill (frontmatter + 지시문) |
|
|
| 실행 | `python3 run.py --flags`, 파이프라인이 호출 | Claude Code 세션에서 관련 작업 시 자동 로드 |
|
|
| 용도 | 차트 버전 감지·diff·PR 생성 등 결정론적 자동화 | 차트마다 판단이 필요한 반복 편집·검증 절차 |
|
|
|
|
`.claude/skills/`의 Skill도 설계 원칙 #1을 지킨다 — helm/kubectl 실행은
|
|
`scripts/deploy-test/*.sh` 같은 스크립트가 전담하고, Skill은 편집·판단·검증 절차만 담당한다.
|
|
|
|
| Skill | 용도 |
|
|
|-------|------|
|
|
| [chart-to-cnpg](.claude/skills/chart-to-cnpg/SKILL.md) | 카탈로그 차트의 내장 bitnami postgresql 서브차트를 전용 cnpg-cluster로 전환 |
|
|
| [catalog-update-pipeline](.claude/skills/catalog-update-pipeline/SKILL.md) | 차트 신규 버전 감지 → diff → breaking 판정 → 문서 생성 파이프라인 실행 (`agent/update_catalog`) |
|
|
| [cve-remediation](.claude/skills/cve-remediation/SKILL.md) | 차단 CVE 대응 레버(태그 교체/베이스 OS 교체/자체 빌드/예외) 결정 — `sbom-cve-gate`·`self-build-image` 실행으로 위임 |
|
|
| [sbom-cve-gate](.claude/skills/sbom-cve-gate/SKILL.md) | SBOM 생성·CVE 스캔·게이트 판정 실행 및 결과 해석 (`scripts/pipeline`) |
|
|
| [self-build-image](.claude/skills/self-build-image/SKILL.md) | 자체 빌드 하드닝 이미지 추가·변경 (`scripts/build`, `images/`) |
|
|
|
|
각 Skill 은 절차 본문을 복제하지 않고 권위 있는 문서(`doc/sbom-pipeline.md`,
|
|
`.claude/image-authoring.md` 등)를 가리킨다 — 문서가 단일 출처이고, Skill 은 **실행 계약과
|
|
문서가 놓치기 쉬운 함정·현재 상태**만 담는다.
|
|
|
|
관련 참조 문서(Skill이 절차의 단일 출처로 삼는다):
|
|
[deploy-test-procedure.md](.claude/deploy-test-procedure.md) ·
|
|
[pitfalls.md](.claude/pitfalls.md) · [image-authoring.md](.claude/image-authoring.md)
|
|
|
|
---
|
|
|
|
## CVE/SBOM 게이트 작업
|
|
|
|
카탈로그가 참조하는 컨테이너 이미지의 취약점을 다룬다. **두 축**이고 각 축의 상세는 소유 문서가
|
|
갖는다 — 여기 메커니즘을 쓰지 않는다.
|
|
|
|
| 축 | 질문 | 워크플로 | 게이트 | 단일 출처 |
|
|
|----|------|---------|--------|----------|
|
|
| **차트 카탈로그** | 우리가 배포하는 이미지에 무엇이 있는가 | `sbom.yml`<br>`cve-edge-post.yml` | warn-only<br>**호출 안 함** | [doc/sbom-pipeline.md](doc/sbom-pipeline.md) |
|
|
| **자체 빌드** | 그 이미지를 어떻게 만드는가 | `build-image.yml` | **강제** | [.claude/image-authoring.md](.claude/image-authoring.md) |
|
|
|
|
- **차트 축은 warn-only 다** — 게이트가 실패해도 CI/PR 을 막지 않는다. 카탈로그 차트 전체가
|
|
이 게이트로 트리아지된 적이 없다. **자체 빌드 축의 게이트는 이미 강제다.**
|
|
- **`cve-edge-post.yml` 은 게이트를 부르지 않는다** — 같은 스캔 데이터에 판정기가 두 벌이라는
|
|
뜻이다(승인 예외·실효 등급 미적용). 외부 엔드포인트로 집계를 POST 하는 용도다.
|
|
- **자체 빌드는 대응 우선순위 3번**(상위 태그 교체 → 베이스 OS 교체 → 자체 빌드 → 예외 승인).
|
|
레버 판단은 [cve-remediation](.claude/skills/cve-remediation/SKILL.md) skill 이 갖는다.
|
|
**레지스트리 push·카탈로그 반영을 동반하는 빌드는 `workflow_dispatch` 수동 실행뿐이다** —
|
|
`schedule`·PR 트리거는 검증만 한다.
|
|
- 커스텀 이미지는 **별도 레포로 분리 예정**이다. 그때 끊기는 결합점은
|
|
[.claude/image-authoring.md](.claude/image-authoring.md) "레포 분리 후 무엇이 끊기는가".
|
|
- 승인 예외: `doc/cve-exceptions.json` · 현재 미결: [MEMORY.md](MEMORY.md)
|
|
|
|
---
|
|
|
|
## 작업 기록을 어디에 남기는가
|
|
|
|
같은 사실을 두 곳에 적지 않는다. 성격에 따라 목적지가 정해져 있다.
|
|
|
|
| 성격 | 목적지 |
|
|
|------|--------|
|
|
| **무엇을 왜 바꿨나** (완료된 작업의 경위) | 커밋 메시지 · PR 설명 · `images/<image>/README.md` |
|
|
| **다시 밟지 말아야 할 함정** | [.claude/pitfalls.md](.claude/pitfalls.md) · [.claude/image-authoring.md](.claude/image-authoring.md) · 해당 Skill |
|
|
| **후보를 비교해 하나를 고른 근거** | [doc/decisions/](doc/decisions/) — ADR. 선택지가 하나뿐인 조치는 여기 쓰지 않는다 |
|
|
| **추적·논의·배정이 필요한 미결** | GitHub 이슈 |
|
|
| **지금 상태와 다음에 할 일** | [MEMORY.md](MEMORY.md) — 위 셋에 속하면 여기 남기지 않고 링크만 |
|
|
|
|
`MEMORY.md` 는 완료 기록이 쌓이는 곳이 아니다. 항목이 "다음에 할 일" 이 아니게 되면 위 셋 중
|
|
하나로 내보내고 지운다 — 상세 규칙과 월 1회 점검 절차는 그 파일 안에 있다.
|
|
|
|
---
|
|
|
|
## 설계 원칙
|
|
|
|
아래 원칙을 위반하는 코드를 제안하거나 작성하지 않는다.
|
|
|
|
1. **LLM은 Helm CLI를 직접 실행하지 않는다.** helm 실행은 결정론적 Skill(Python)이 전담한다.
|
|
2. **Diff 생성은 100% deterministic이다.** Structured Diff JSON 형식을 사용하며 LLM이 직접 diff를 생성하지 않는다.
|
|
3. **LLM 입력은 반드시 Structured JSON이다.** 자유 텍스트나 raw helm output을 LLM에 직접 전달하지 않는다.
|
|
4. **Breaking Change 판단은 Rule Engine이 먼저 수행한다.** `custom-values.yaml`의 실제 사용 키 기준으로 코드가 판단하며 LLM은 후순위다.
|
|
5. **LLM은 Markdown 설명 생성만 담당한다.** `breaking=true` 시에만 호출되며, `breaking=false`이면 템플릿 기반으로 생성한다.
|
|
6. **운영 환경은 Git PR로만 변경한다.** 클러스터 직접 변경이나 kubectl apply를 자동화 흐름에 포함하지 않는다.
|
|
7. **보안 경계**: 외부 입력(PR comment, webhook 등)은 신뢰 경계 밖으로 취급한다. 프롬프트 주입 방어를 기본 전제로 한다.
|
|
|
|
---
|
|
|
|
## 현재 구현 상태
|
|
|
|
| Step | 내용 | 상태 |
|
|
|------|------|------|
|
|
| **Step 1** | Skills 구현 (로컬 실행) | ✅ 거의 완료 |
|
|
| **Step 2** | Agent 프레임워크 POC (OpenClaw vs Nanobot) | 📋 계획 |
|
|
| **Step 3** | On-Cluster Agent 워크플로 정의 | 💡 구상 |
|
|
| **Step 4** | 보안 정책 수립 후 운영 | 💡 구상 |
|
|
|
|
**Step 1 세부 현황:**
|
|
- `chart_version_detector`, `chart_updater`, `helm_diff`, `breaking_change_check`, `generate_upgrade_doc`, `update_docs_file`: ✅ 구현 완료
|
|
- `create_pr`: ✅ 구현 (실제 GitHub 연동 테스트 미완료)
|
|
- `deploy_validate`: ❌ Phase 2 예정
|
|
|
|
---
|
|
|
|
## 주요 설계 문서
|
|
|
|
| 문서 | 설명 |
|
|
|------|------|
|
|
| [agent/update_catalog/docs/design/00-architecture-overview.md](agent/update_catalog/docs/design/00-architecture-overview.md) | 전체 아키텍처 + 설계 원칙 + 기술 스택 |
|
|
| [agent/update_catalog/docs/design/01-helm-diff-engine.md](agent/update_catalog/docs/design/01-helm-diff-engine.md) | Helm Diff Engine 상세 설계 |
|
|
| [agent/update_catalog/docs/design/02-breaking-change-rules.md](agent/update_catalog/docs/design/02-breaking-change-rules.md) | Breaking Change Rule Engine 판단 로직 |
|
|
| [agent/update_catalog/docs/design/03-llm-summarizer.md](agent/update_catalog/docs/design/03-llm-summarizer.md) | LLM Summarizer + Prompt 설계 |
|
|
| [agent/update_catalog/docs/design/04-skill-interface.md](agent/update_catalog/docs/design/04-skill-interface.md) | Skill 인터페이스 계약 (Agent-Skill) |
|
|
| [agent/update_catalog/docs/design/05-on-cluster-agent.md](agent/update_catalog/docs/design/05-on-cluster-agent.md) | On-Cluster Agent 설계 (Step 2~3) |
|
|
| [agent/update_catalog/docs/decisions/001-agentic-first.md](agent/update_catalog/docs/decisions/001-agentic-first.md) | 파이프라인 오케스트레이션 건너뛰기 결정 배경 |
|
|
| [agent/update_catalog/docs/status.md](agent/update_catalog/docs/status.md) | 구현 현황 상세 |
|
|
| [doc/sbom-pipeline.md](doc/sbom-pipeline.md) | SBOM 생성·CVE 스캔·게이트 파이프라인 상세 |
|