0. Contents


1. Overview

맥북 · 측정 환경: 눌러서 설명 보기맥북 · 측정 환경helm template 만 · 빈 KUBECONFIG · 동시 3개 · nice 19공개 차트 21개: 눌러서 설명 보기공개 차트 21개워크로드 53개 · 목표 칸 209개ingress-nginxcert-managerkube-prometheus-stackprometheusgrafanalokiargo-cdmetrics-serverexternal-secretsexternal-dnstraefikpodinfovaultkyvernocluster-autoscaleraws-load-balancer-controllerharboropentelemetry-collectorsealed-secretsjenkinsredispodinfo 6.17.0: 눌러서 설명 보기podinfo 6.17.0예시 차트. 다른 차트도 같은 길을 지난다values.yaml: 눌러서 설명 보기values.yamlreplicaCount: 1logLevel: infoimage.tag: 6.17.0extraEnvs: []resources: { … }…templates/deployment.yaml: 눌러서 설명 보기templates/deployment.yamlreplicas:{{ .Values.replicaCount }}image: "{{ …repository }}:{{ .Values.image.tag }}"① 기본 렌더: 눌러서 설명 보기1기본 렌더지금 칸의 값을 읽는다② 후보 모으기: 눌러서 설명 보기2후보 모으기지금 값과 같은 키이름이 맞는 키 replica · tag …replicas 칸의 후보 7개③ 표시값을 넣어 다시 렌더: 눌러서 설명 보기3표시값을 넣어 다시 렌더replicaCount: 137④ 판정: 눌러서 설명 보기4판정키가 아니라 렌더 결과만 본다렌더 결과: 눌러서 설명 보기렌더 결과Deployment kr-podinfospec.replicas: 눌러서 설명 보기spec.replicas키 replicaCount1 → 137image: 눌러서 설명 보기image키 image.tagpodinfo:6.17.0 → 6.17.987resources: 눌러서 설명 보기resources키 resources137m · 137Mi / 337m · 337Mienv: 눌러서 설명 보기env키 extraEnvsKUKIE_MARKER_ENV판정: 눌러서 설명 보기판정합격: 눌러서 설명 보기합격: 목표 칸 = 표시값불합격: 눌러서 설명 보기불합격: 칸은 바뀌었지만 표시값이 아님기록: 눌러서 설명 보기기록: 요청 안 한 칸도 바뀜 (합격 중 31칸)방식 A: 눌러서 설명 보기방식 A · ② 를 코드가21개 차트, 칸 209개찾음 191 / 209 (91.4%)렌더링 1,135번 · 59.9초토큰 0방식 B: 눌러서 설명 보기방식 B · ② 를 Sonnet 이놓친 칸이 있는 5개 차트, 칸 62개찾음 60 / 62 (A 는 55)207초789,744 토큰A 가 놓친 18칸: 눌러서 설명 보기A 가 놓친 18칸하드코딩 9: 눌러서 설명 보기하드코딩 9규칙 4: 눌러서 설명 보기규칙 4조합 2: 눌러서 설명 보기조합 2렌더 실패 2: 눌러서 설명 보기렌더 실패 2스키마 거부 1: 눌러서 설명 보기스키마 거부 1절반은 바꿀 키가 없는 칸이다두 방식은 ② 만 다르다. ③ ④ 는 같은 렌더 검사라 키를 고른 방법만 비교한다실측 결과이고 제품 연결 전이다. 지금 Kukie 는 Helm 앱을 PR 로 고치지 못한다. 방식 B 는 LLM 에 유리하게 뽑은 표본이다
키를 추측으로 믿지 않는다 — 값을 넣어 렌더링한 결과로만 합격을 정한다
칸을 누르면 설명이 열린다

배경

  • 02편의 PR 경로는 plain 과 Kustomize 만 지원한다. 두 형식은 고칠 위치가 형식으로 정해져 코드가 고른다
  • Helm 앱은 values 키를 고쳐야 하는데, 어느 키가 어느 칸으로 가는지는 차트마다 다르다
  • 코드로 찾을지 LLM 에게 맡길지 정하려면 숫자가 필요해 공개 차트로 쟀다

이 글의 질문

  • 고칠 키를 맞게 찾았다는 것을 무엇으로 판단하는가
  • 코드만으로 몇 칸을 찾는가. 왜 못 찾는가
  • LLM 을 쓰면 얼마나 더 찾고, 무엇을 내는가
  • 렌더링 한 번은 얼마나 드는가

측정 범위

항목값
대상공개 차트 21개, 워크로드 53개
목표 칸209개. 레플리카, 이미지 태그, 리소스, 환경변수
도구Helm 4.2.2, helm template 만, --kube-version 1.33.0
제외주 컨테이너 외 컨테이너, 커스텀 리소스, 기존 환경변수 수정

2. Why Helm Is Different — Helm 의 차이

2.1 형식별 고칠 위치

형식고칠 곳위치를 정하는 것
plainYAML 의 그 칸apiVersion · kind · name · namespace
Kustomizeoverlay 의 replicas: · images: · patches:kustomization 문법
Helmvalues 의 어떤 키차트 작성자의 템플릿

2.2 키와 칸의 거리

① 기본 렌더② 후보 모으기③ 표시값 렌더④ 판정차트values 키템플릿렌더 결과 칸특징차트작성자의코드podinforeplicaCountspec.replicas키 하나 → 칸 하나argo-cdapplicationSet.replicasspec.replicas워크로드마다 다른 키ingress-nginxcontroller.image.tagdigestimagedigest 를 함께 비워야 태그가 반영됨vaultserver.ha.replicasha.enabledspec.replicasHA 를 켜야 레플리카 값이 쓰임cert-managerimage.tagimage키가 values 주석에만 있어 후보에서 빠짐plain 과 Kustomize 는 고칠 위치가 형식으로 정해진다 — Helm 은 템플릿이라는 코드를 사이에 둔다
같은 칸이라도 키 이름은 차트 작성자가 정한다 — 위치를 규칙으로 고정할 수 없다
  • 키 이름만으로는 맞다고 할 수 없다. 같은 이름의 키가 다른 워크로드나 다른 조건에 쓰인다
  • 차트를 읽어도 헬퍼와 조건이 겹치면 결과를 눈으로 확정하기 어렵다

2.3 합격 기준

키를 고른 근거로 합격을 정하지 않는다. 값을 넣고 렌더링한 결과만 본다. 방식 A 와 방식 B 에 같은 판정을 쓰면 키를 고른 방법만 비교할 수 있다.

3. Code Search — 코드 방식

3.1 표시값 렌더링

① 기본 렌더② 후보 모으기③ 표시값 렌더④ 판정tools/hv.py (요약)MARK_REPLICAS = 1371MARK_RES = {"requests": {"cpu": "137m", "memory": "137Mi"},"limits": {"cpu": "337m", "memory": "337Mi"}}def target_hit(target, base, new):if target == "replicas":2if new.get("replicas") == MARK_REPLICAS:return True, ""if new.get("replicas") != base.get("replicas"):3return False, "changed-not-marker"return False, ""...def side_effects(base_surface, new_surface, noise, key, cname, target):want = cell_paths(key, cname)[target][0]4# 요청한 칸 말고 바뀐 칸을 모은다1눈에 띄는 표시값기본값으로 잘 안 쓰는 값을 넣는다태그는 semver 분기가 안 갈리게앞자리를 살린다2합격목표 칸이 표시값과 같다3불합격칸이 바뀌었지만 표시값이 아니다값을 가공하는 키일 수 있다4다른 칸 변화합격과 따로 기록한다무작위 값은 비교에서 뺀다렌더링만 쓴다 — helm template 과 빈 KUBECONFIG, 플러그인 없음, 의존 차트는 먼저 받아 두고 네트워크를 쓰지 않는다
표시값이 목표 칸에 그대로 나타나야 합격이다 — 값이 바뀌기만 한 키는 합격이 아니다

3.2 후보 좁히기

① 기본 렌더② 후보 모으기③ 표시값 렌더④ 판정렌더링 횟수, 같은 눈금전수 시험 (중단): 모든 키 × 모든 칸계획 47,761번 · 맥북 부하 31까지 올라 중단후보 시험실제 1,135번 · 59.9초 · 동시 실행 3개 · nice 19전수 계획의 약 2.4%규칙 1: 같은 값지금 렌더 값과 같은 키규칙 2: 이름replica · tag · resources · env칸당 평균 후보 17.0개첫 합격까지 평균 2.51번후보를 좁혀 놓친 칸이 있는지가 다음 질문이다 — 4.2 의 18칸이 그 답이다키가 있는데 후보에서 빠진 칸은 cert-manager 3칸과 pushgateway 1칸이었다. 전수 시험 실행의 시간은 쓰지 않았다
모든 키를 시험할 이유가 없다 — 지금 값이나 이름으로 먼저 좁힌다

3.3 측정 안전 조건

고객이 올릴 차트를 다루는 일의 예행이라 공개 차트에도 같은 제한을 걸었다.

  • helm install, upgrade, --dry-run=server, 플러그인을 쓰지 않는다
  • 빈 KUBECONFIG 를 준다
  • 기본값으로 렌더링이 안 되는 차트 5개는 최소 값(base-values.json)을 넣었다
  • 시험 Pod 의 무작위 이름 같은 값은 비교에서 뺐다

4. Results — 코드 방식 결과

4.1 21개 차트 결과

목표찾음다른 칸 변화 없음첫 합격까지 평균 시도칸당 평균 후보
레플리카39 / 50271.9031.5
이미지 태그49 / 53402.1811.2
리소스53 / 53452.2510.4
환경변수50 / 53483.6015.8
합계191 / 209 (91.4%)1602.5117.0

4.2 놓친 18칸

① 기본 렌더② 후보 모으기③ 표시값 렌더④ 판정목표 칸 209개를 한 칸씩레플리카39 / 50이미지 태그49 / 53리소스53 / 53환경변수50 / 53찾음찾음 · 다른 칸도 바뀜 31하드코딩 9스키마 거부 · 렌더 실패 3규칙이 놓침 4키 조합 2이번 측정에서 바꾸지 못함 12칸하드코딩레플리카 7 · 환경변수 2템플릿에 값이 박혀 있다스키마 거부external-dnsreplicaCount 최대 1렌더 실패jenkins 0 또는 1loki 다른 모드와 충돌값으로 바꿀 수 있음 6칸규칙이 놓침cert-manager 태그 3pushgateway 환경변수 1키 조합ingress-nginx digestvault HA자동 스케일 0, 값 가공으로 실패 0, 하위 차트 0 — 걱정했던 원인은 이번 차트들에서 나오지 않았다오른쪽 6칸은 직접 렌더링해 확인했다. loki 는 키 조합을 확인하지 못해 렌더 실패 2칸에 남았다
놓친 18칸 중 절반은 찾을 키가 없었다 — 없는 키를 만들 수는 없다

4.3 다른 칸이 함께 바뀌는 키

합격한 191칸 중 31칸은 키를 바꾸면 요청하지 않은 칸도 함께 바뀌었다. 표시값이 목표 칸에 나타났으니 키는 맞지만, 사용자가 원한 변경인지는 코드가 알 수 없다.

  • 레플리카가 12칸으로 가장 많고, 이미지 태그 9칸, 리소스 8칸, 환경변수 2칸이다
  • 렌더 diff 를 카드에 보여 주고 사람이 판단하는 쪽이 후보다. 제품에서 어떻게 처리할지는 정하지 않았다

5. LLM Comparison — LLM 비교

5.1 비교 조건

항목값
대상방식 A 가 놓친 칸이 있고 키가 실제로 있는 5개 차트: cert-manager, ingress-nginx, vault, prometheus, loki. 62칸
모델Sonnet. 차트당 1회
입력코드가 모은 파일 목록(values, helper, 워크로드 템플릿). 방식 A 결과는 주지 않음
제한목표당 후보 최대 5개. 키 조합 허용
판정방식 A 와 같은 렌더 검사

LLM 에 유리한 표본이다. 방식 A 가 “바꿀 수 없음"으로 끝난 11칸이 있는 차트는 넣지 않았다. 21개 전체로 늘려 쟀을 때의 수치가 아니다.

5.2 목표별 결과

목표칸A 찾음B 찾음A 만B 만둘 다 못 찾음
레플리카141213011
이미지 태그161216040
리소스161616000
환경변수161515110
합계625560161
  • 합격한 60칸은 모두 첫 시도에 합격했다. 키 조합이 필요한 ingress-nginx 태그와 vault 레플리카도 찾았다
  • 실패 2칸 중 loki 본체 레플리카는 validate.yaml 이 거부했다
  • 나머지 node-exporter 환경변수는 칸이 바뀌었지만 표시값 이름과 달라 규칙상 실패다. 판정기가 좁은 영향도 있다

5.3 비용 비교

① 기본 렌더② 후보 모으기③ 표시값 렌더④ 판정표본 5개 차트의 칸 62개를 한 칸씩방식 A: 코드55 / 62렌더링 419번 · 10.6초 · 토큰 0방식 B: Sonnet60 / 62칸당 평균 1.34번 시도 · 207초 (차트당 22.8~97.2초) · 789,744 토큰A 다음 B61 / 62A 가 찾은 칸은 토큰을 쓰지 않고, 실패 칸의 차트만 B 로 보낸다둘 다 찾음 54A 만 1B 만 6못 찾음표본: A 가 놓친 칸이 있고 키가 실제로 있는 5개 차트, 차트당 1회 실행, 목표당 후보 최대 5개21개 전체로는 197 / 209 (94%). 나머지 16개 차트의 놓친 칸을 템플릿을 읽어 바꿀 수 없다고 분류해 A 값을 그대로 쓴 수치다
LLM 은 5칸을 더 찾았다 — 대신 토큰과 시간을 쓴다. 다만 LLM 에 유리하게 뽑은 표본이다

토큰은 서브에이전트의 기본 사용량을 포함한 값이다. 실제 서비스에서는 프롬프트와 캐시 구성에 따라 달라지므로 비용으로 환산하지 않았다.

5.4 올바른 변경의 판단

렌더 검사는 “이 키가 이 칸을 바꾼다"까지만 말해 준다. 코드와 LLM 모두 그 변경이 운영상 맞는지는 알 수 없다.

  • loki 레플리카처럼 키가 있어도 다른 모드와 충돌하는 칸이 있다
  • 차트 작성자가 값을 하드코딩한 칸은 values 로 바꾸지 않는 것이 맞을 수 있다
  • 최종 판단은 렌더 diff 를 보는 사람의 몫으로 남는다

6. Render Cost — 렌더링 비용

값 찾기는 후보마다 렌더링을 돌리므로 렌더링 비용이 설계를 정한다. 아래는 이번 측정의 렌더링 1,154번 기록이다. 맥북에서 helm 을 직접 실행했고, 동시 실행 3개, nice 19 다.

항목시간
중앙값0.083초
상위 5% 경계0.38초
상위 1% 경계0.51초
최대0.60초
차트시간 중앙값최대 메모리출력 크기
작은 차트 (podinfo 등)약 0.03초약 41MB약 5KB
kube-prometheus-stack0.11초83MB650KB
harbor (가장 느림)0.40초46MB55KB
kyverno (메모리 최대)0.33초137MB5.7MB

메모리는 차트별 기본 렌더링을 한 번씩 재서 얻었다. 정상 차트는 가볍지만, 메모리 137MB 는 모든 고객이 함께 쓰는 에이전트 파드(768Mi)에서 동시에 돌리기에 작지 않다. 고장 났거나 일부러 무겁게 만든 차트는 이 범위 밖이다. 이 숫자가 05편의 제한 값이 된다.

7. Discussion

7.1 확인 범위

내용확인 방법
방식 A 21개 차트실측. 원자료 보관
놓친 칸의 분류템플릿을 읽어 사람이 분류
키 조합 합격ingress-nginx, vault 는 직접 렌더 확인. loki 는 미확인
방식 B 5개 차트실측. 차트당 1회라 실행마다의 차이는 재지 않았다
제품 연결하지 않았다

7.2 남은 한계

  • 공개 차트만 쟀다. 회사 자체 차트는 이름 규칙이 더 제각각일 수 있다
  • 기존 환경변수 수정과 사이드카는 재지 않았다
  • 놓친 4칸을 잡는 후보 규칙을 더하면 수치가 오를 수 있지만 다시 재지 않았다
  • 측정은 Helm 4.2.2, 렌더링 파드는 Argo CD 에 맞춘 4.2.1 이다

7.3 첫 구현의 방향

단계방식근거
1코드로 후보를 좁혀 표시값 렌더91.4%, 토큰 없음, 초 단위
2실패한 칸만 LLM5개 차트에서 코드가 놓친 키를 대부분 찾음
3합격 키로 PR, 렌더 diff 를 카드에 표시다른 칸 변화는 사람이 판단

제안이고 구현 전이다. 먼저 코드만으로 시작해 놓친 칸의 안내 문구를 다듬어도 된다.

핵심 메시지

  • 판정 기준: 키 이름이 아니라 렌더 결과
    • 표시값이 목표 칸에 나타나야 합격이고, 방식과 무관하게 같은 검사를 쓴다
  • 코드 방식: 후보를 좁히면 충분히 빠르다
    • 렌더링 1,135번, 59.9초로 209칸 중 191칸을 찾았다
  • 못 찾은 칸: 절반은 찾을 키가 없다
    • 18칸 중 9칸이 하드코딩이다
  • LLM: 어려운 칸에만
    • 5칸을 더 찾지만 토큰 78만 개와 3분 반을 쓴다. 유리한 표본의 값이다

8. References

helm template 과 values 의 동작. 2장과 3장의 근거다.
→ Helm — helm template
→ Helm — Values Files
→ Helm — Schema Files
Application 의 Helm 소스와 values 지정 방식. 2.1 의 근거다.
→ Argo CD — Helm