diff --git a/.claude/deploy-test-procedure.md b/.claude/deploy-test-procedure.md index 373d5de..6e68573 100644 --- a/.claude/deploy-test-procedure.md +++ b/.claude/deploy-test-procedure.md @@ -90,3 +90,30 @@ APP_POD_SELECTOR="" \ dip-catalog 에 아직 없다). 통과 항목만 쓰지 말고 발견된 문제와 미검증 항목을 반드시 남긴다. 6. 정리한다. 정리 명령은 문서에 함께 기록한다. + +## 같은 날 재빌드했다면 — `imagePullPolicy` 를 수동으로 건다 + +자체 빌드 태그에는 빌드일이 들어간다(`1.30.0-security-hardened-20260820`). **같은 날 두 번 +빌드하면 태그가 겹치고**, 노드가 캐시한 옛 digest 가 그대로 쓰여(`IfNotPresent`) 고친 것이 +반영되지 않은 채 "안 고쳐졌다" 로 보인다. 검증에서 이것을 실제로 밟았다. + +검증 대상 워크로드에만 걸고, digest 로 실제 이미지를 확인한다. + +``` sh +kubectl set image ... # 태그가 같으므로 이미지 교체로는 아무 일도 일어나지 않는다 +kubectl patch deployment -n --type=strategic -p \ + '{"spec":{"template":{"spec":{"containers":[{"name":"","imagePullPolicy":"Always"}]}}}}' +kubectl rollout restart deployment/ -n + +# 태그가 아니라 digest 를 본다 — 태그는 같으므로 아무것도 증명하지 못한다 +kubectl get pod -n -o jsonpath='{range .items[*]}{.status.containerStatuses[*].imageID}{"\n"}{end}' +``` + +**카탈로그 values 에는 넣지 않는다.** `Always` 면 파드 시작마다 kubelet 이 레지스트리에서 +digest 를 해석하므로, 레지스트리 장애·Docker Hub rate limit 이 파드 기동을 막는 경로가 +생긴다(rate limit 은 이 레포에서 실측된 문제다 — `DOCKERHUB_USER`/`TOKEN` 을 쓰는 이유). +태그 겹침은 **검증 시점에만** 생기는 문제이므로 그 대가를 운영 내내 지불할 이유가 없다. + +이것이 [#31](https://github.com/paasup/dip-catalog/issues/31) 의 결정이다 — 태그에 해시를 +붙이거나 digest 로 참조하는 방안은 채택하지 않았다. 태그가 "무엇을 검증했는지의 기록" 이라는 +성격을 유지한다. diff --git a/.claude/skills/self-build-image/SKILL.md b/.claude/skills/self-build-image/SKILL.md index 5efea32..ea73731 100644 --- a/.claude/skills/self-build-image/SKILL.md +++ b/.claude/skills/self-build-image/SKILL.md @@ -97,8 +97,9 @@ python3 scripts/build/check-rebuild-needed.py --reports [--apply `python3 scripts/build/check-rebuild-needed.py --reports [--image ] [--apply]` - **단, 같은 날 다시 빌드하면 그 태그가 겹친다.** 노드가 캐시한 옛 digest 가 그대로 쓰여 (`imagePullPolicy: IfNotPresent`) 고친 것이 반영되지 않은 채 "안 고쳐졌다" 로 보인다. - 배포 검증 중이라면 `imagePullPolicy: Always` 로 우회하고, digest 로 확인한다 — - `kubectl get pod -o jsonpath='{..imageID}'`. 프레임워크 차원의 미결 사항이다. + **검증 대상 워크로드에 `imagePullPolicy: Always` 를 수동으로 걸고 digest 로 확인한다** — + 절차는 [deploy-test-procedure.md](../../deploy-test-procedure.md) "같은 날 재빌드했다면" + 이 단일 출처다. **카탈로그 values 에는 넣지 않는다**(같은 문서에 이유). ## 마무리 diff --git a/MEMORY.md b/MEMORY.md index 2116a24..f667828 100644 --- a/MEMORY.md +++ b/MEMORY.md @@ -32,18 +32,16 @@ | # | 내용 | 상태 | |---|---|---| -| [#29](https://github.com/paasup/dip-catalog/issues/29) | airflow 반복 재배포 — 비결정적 webserver secret key + migrations job TTL 루프 | 조치안 확정, **로컬 미커밋** | -| [#31](https://github.com/paasup/dip-catalog/issues/31) | 자체 빌드: 같은 날 재빌드 시 태그 충돌로 노드 캐시가 반영을 막는다 | 선택지 3안, 미결정 | -| [#30](https://github.com/paasup/dip-catalog/issues/30) | `SBOM_PIPELINE_IMAGE` 를 `docker.io/paasup` 으로 이전할지 | 수동 작업 3종, 미결정 | -| [#32](https://github.com/paasup/dip-catalog/issues/32) | adc 이미지 배포 검증 미완료 (게이트만 PASS) | apisix-ingress-controller 와 함께 배포 필요 | +| [#42](https://github.com/paasup/dip-catalog/issues/42) | `applicationset` 참조 values 의 이미지 태그가 차단 CVE 태그(`20260803`)에 멈춰 있다 | dip-console 이 이 값을 어떻게 쓰는지 확인이 선행 | +| [#38](https://github.com/paasup/dip-catalog/issues/38) | airflow fernet key 비결정 — #29 와 같은 구조, 체크섬에 없어 시한폭탄 | sync 반복 시 값이 바뀌는지 **실측 미완** | +| [#37](https://github.com/paasup/dip-catalog/issues/37) | 게이트는 판정만 하고 제안하지 않는다 — 대응 레버 1번에 도구 지원 0 | 실증 완료, 구현 미착수 | | [#19](https://github.com/paasup/dip-catalog/issues/19) | 카탈로그 CVE 트리아지 기준선 | 게이트 강제 전환의 선행 조건 | | [#7](https://github.com/paasup/dip-catalog/issues/7) | CVE 조치 파이프라인 (상위 추적 이슈) | 게이트 강제력 전환 결정이 여기 있다 | | [#3](https://github.com/paasup/dip-catalog/issues/3) · [#9](https://github.com/paasup/dip-catalog/issues/9) | SBOM 파이프라인 도입 · postgresql-ha 대체 | 본문상 완결로 보인다 — **닫을지 확인 필요** | ## 진행 중 -- **PR [#28](https://github.com/paasup/dip-catalog/pull/28)** — argo-cd CVE 조치(7.7.0 제거 · - dex 비활성 · 자체 빌드). 리뷰 대기. +없다. 열린 PR 0건. ## 아직 이슈로 만들지 않은 것 @@ -51,6 +49,19 @@ 지우면 게이트가 PASS 로 떨어진다. 직전 버전을 없애는 결정이라 PR #28 에서 보류했다. - **자체 빌드 이미지의 정식 반영 경로** — argocd 는 로컬에서 빌드·push 했다. CI `build-image.yml`(`workflow_dispatch`)로 다시 태울지, 로컬 push 로 끝낼지. +- **레포 분리 시점의 두 작업** — ① `catalog.env` 의 카탈로그 매핑(`CHART_DIRS`·`TAG_STYLE`· + `TAG_BLOCK`)을 카탈로그 자산으로 떼어내고 `catalog-tag-update.yml` 로 반영, + ② 게이트를 composite action 으로(`workflow_call` 아님 — 스캔과 같은 job 에서 `$OUT_DIR` + 공유가 필요하다). 결합점 전체는 `.claude/image-authoring.md` "레포 분리 후 무엇이 끊기는가". +- **카탈로그 태그가 클러스터보다 앞서 있고 재검증 경로가 없다** — 게이트 PASS 만으로 + `patch-catalog-tag.py` 가 태그를 올린다. 2026-08-21 실측: 클러스터의 adc `20260812` · + apisix-ingress-controller `20260811` 이 검증된 것인데 카탈로그는 `20260813` · `20260820` + 이다. 소스 안 바뀐 재빌드라 위험은 낮지만 **게이트 PASS 는 동작을 증명하지 않는다** + (argocd `cp --update=none` 사례). [#32](https://github.com/paasup/dip-catalog/issues/32) + 코멘트에 실측을 남겼다. +- **워크플로 결함 3건** — `cve-edge-post.yml` 이 게이트를 안 부른다(판정기 두 벌) · + 인증 스텝이 `sbom.yml` 과 diff 0 으로 복붙 · `scripts/pipeline/Dockerfile` 을 빌드하는 + 워크플로가 없다(손으로 push). - **`doc/define-chart-resources.md` 에 cloudnative-pg·cnpg-cluster·etcd 전용 절이 없다** — 리소스 프로파일 자체는 각 차트의 `dip-resources-quotas.yaml` 에 있으므로 누락은 아니다. 이 문서만 보는 사람이 세 차트를 못 찾는 것뿐이라 급하지 않다.