본 콘텐츠의 이미지 및 내용은 AI로 생성되었습니다.
본 콘텐츠의 이미지 및 내용을 무단으로 복제, 배포, 수정하여 사용할 경우 저작권법에 의해 법적 제재를 받을 수 있습니다.
이미지 로딩 중...
AI Generated
2025. 12. 1. · 17 Views
Helm Chart 작성 및 ML 배포 완벽 가이드
Kubernetes 환경에서 Helm Chart를 활용하여 머신러닝 모델을 배포하는 방법을 다룹니다. 패키지 매니저의 개념부터 실제 ML 서비스 배포까지 단계별로 학습합니다.
목차
1. Helm 기초 개념
김개발 씨는 오늘도 Kubernetes 클러스터에 새로운 서비스를 배포하고 있습니다. YAML 파일만 벌써 10개가 넘어갑니다.
Deployment, Service, ConfigMap, Secret, Ingress... 매번 이렇게 많은 파일을 관리해야 하는 걸까요?
Helm은 Kubernetes의 패키지 매니저입니다. 마치 Ubuntu의 apt나 macOS의 Homebrew처럼, 복잡한 Kubernetes 애플리케이션을 하나의 패키지로 묶어서 관리할 수 있게 해줍니다.
Helm을 사용하면 수십 개의 YAML 파일을 하나의 Chart로 관리하고, 버전 관리와 롤백까지 손쉽게 처리할 수 있습니다.
다음 코드를 살펴봅시다.
# Helm 설치 확인
helm version
# 공식 저장소 추가
helm repo add stable https://charts.helm.sh/stable
helm repo update
# 사용 가능한 Chart 검색
helm search repo nginx
# Chart 설치 (Release 생성)
helm install my-nginx stable/nginx-ingress
# 설치된 Release 목록 확인
helm list
# Release 상태 확인
helm status my-nginx
김개발 씨는 입사 6개월 차 DevOps 엔지니어입니다. 회사에서 Kubernetes를 도입한 지 얼마 되지 않아, 모든 배포 작업을 kubectl apply 명령어로 처리하고 있었습니다.
문제는 서비스가 늘어날수록 관리해야 할 YAML 파일도 기하급수적으로 늘어난다는 것이었습니다. 어느 날 선배 개발자 박시니어 씨가 김개발 씨의 화면을 보더니 물었습니다.
"혹시 Helm 써본 적 있어요?" 그렇다면 Helm이란 정확히 무엇일까요? 쉽게 비유하자면, Helm은 마치 이사 전문 업체와 같습니다.
이사할 때 책, 옷, 그릇을 하나씩 옮기면 시간도 오래 걸리고 빠뜨리기도 쉽습니다. 하지만 이사 업체에 맡기면 모든 짐을 체계적으로 포장하고, 라벨을 붙이고, 한 번에 운반해줍니다.
Helm도 마찬가지입니다. 여러 개의 Kubernetes 리소스를 하나의 패키지로 묶어서 관리합니다.
Helm이 없던 시절에는 어땠을까요? 개발자들은 Deployment, Service, ConfigMap, Secret 등 수많은 YAML 파일을 직접 관리해야 했습니다.
환경별로 다른 설정이 필요하면 파일을 복사해서 수정했고, 이 과정에서 실수가 빈번하게 발생했습니다. 더 큰 문제는 버전 관리였습니다.
이전 버전으로 롤백하려면 어떤 파일을 어떻게 바꿔야 하는지 일일이 기억해야 했습니다. 바로 이런 문제를 해결하기 위해 Helm이 등장했습니다.
Helm에서는 몇 가지 핵심 용어를 알아야 합니다. 먼저 Chart는 Kubernetes 애플리케이션을 정의하는 패키지입니다.
하나의 Chart 안에 필요한 모든 리소스 정의가 들어있습니다. Release는 Chart를 클러스터에 설치한 인스턴스입니다.
같은 Chart를 여러 번 설치하면 각각 다른 Release가 됩니다. Repository는 Chart를 저장하고 공유하는 저장소입니다.
위의 코드를 살펴보겠습니다. 먼저 helm version으로 Helm이 제대로 설치되었는지 확인합니다.
그 다음 helm repo add 명령어로 공식 저장소를 추가합니다. 이제 helm search repo 명령어로 원하는 Chart를 검색할 수 있습니다.
마지막으로 helm install 명령어 하나로 복잡한 nginx-ingress를 설치할 수 있습니다. 실제 현업에서는 어떻게 활용할까요?
예를 들어 마이크로서비스 아키텍처를 운영한다고 가정해봅시다. 각 서비스마다 Deployment, Service, HPA, PDB 등 최소 4-5개의 리소스가 필요합니다.
서비스가 20개라면 관리해야 할 파일이 100개가 넘습니다. Helm을 사용하면 각 서비스를 하나의 Chart로 만들어 깔끔하게 관리할 수 있습니다.
하지만 주의할 점도 있습니다. 초보자들이 흔히 하는 실수는 Helm만 설치하고 Kubernetes 기본 개념을 건너뛰는 것입니다.
Helm은 Kubernetes 위에서 동작하는 도구이므로, 기본 리소스 개념을 먼저 이해해야 합니다. 또한 공개 저장소의 Chart를 그대로 사용하기보다는 내부 정책에 맞게 커스터마이징하는 것이 좋습니다.
다시 김개발 씨의 이야기로 돌아가 봅시다. 박시니어 씨의 조언을 듣고 Helm을 도입한 김개발 씨는 배포 시간을 절반으로 줄일 수 있었습니다.
"이렇게 편한 도구가 있었다니!"
실전 팁
💡 - helm install 전에 helm template으로 생성될 리소스를 미리 확인하세요
- helm upgrade --install을 사용하면 설치와 업그레이드를 하나의 명령어로 처리할 수 있습니다
2. Chart 구조 이해하기
박시니어 씨가 김개발 씨에게 직접 Chart를 만들어보라고 했습니다. "공개 Chart를 쓰는 것도 좋지만, 우리 서비스에 맞는 Chart를 만들 줄 알아야 해요." 김개발 씨는 빈 폴더 앞에서 어디서부터 시작해야 할지 막막했습니다.
Helm Chart는 정해진 디렉토리 구조를 따릅니다. Chart.yaml은 Chart의 메타데이터를 정의하고, values.yaml은 기본 설정값을 담습니다.
templates 폴더에는 실제 Kubernetes 리소스 템플릿이 들어가며, Helm은 이 구조를 인식하여 패키지로 처리합니다.
다음 코드를 살펴봅시다.
# Chart 기본 구조 생성
helm create ml-service
# 생성된 디렉토리 구조
ml-service/
Chart.yaml # Chart 메타데이터
values.yaml # 기본 설정값
charts/ # 의존성 Chart
templates/ # Kubernetes 리소스 템플릿
deployment.yaml
service.yaml
ingress.yaml
_helpers.tpl # 템플릿 헬퍼 함수
NOTES.txt # 설치 후 안내 메시지
김개발 씨는 helm create 명령어를 실행했습니다. 순식간에 여러 파일과 폴더가 생성되었습니다.
하지만 각각이 무슨 역할을 하는지 알 수 없었습니다. 박시니어 씨가 옆에서 하나씩 설명해주기 시작했습니다.
Helm Chart의 구조를 이해하려면 먼저 전체 그림을 봐야 합니다. 마치 건축 설계도를 생각해보면 쉽습니다.
건물을 지으려면 설계도 표지에 건물 이름과 설계자 정보가 있고, 별도의 사양서에 자재 규격이 정리되어 있으며, 실제 도면들이 여러 장 있습니다. Chart도 마찬가지입니다.
Chart.yaml이 표지, values.yaml이 사양서, templates 폴더가 도면에 해당합니다. Chart.yaml은 Chart의 신분증입니다.
이 파일에는 Chart의 이름, 버전, 설명, 유지관리자 정보 등이 들어갑니다. 특히 중요한 것은 두 가지 버전입니다.
version은 Chart 자체의 버전이고, appVersion은 Chart가 배포하는 애플리케이션의 버전입니다. 이 두 가지를 구분해서 관리해야 나중에 혼란이 없습니다.
values.yaml은 설정의 중앙 집중소입니다. 이 파일에 정의된 값들은 templates 폴더의 모든 템플릿에서 참조할 수 있습니다.
개발 환경과 운영 환경에서 다른 설정을 적용하고 싶다면, values.yaml은 그대로 두고 환경별로 다른 values 파일을 만들어 덮어씌우면 됩니다. templates 폴더는 실제 마법이 일어나는 곳입니다.
이 폴더 안의 YAML 파일들은 일반적인 Kubernetes 매니페스트가 아닙니다. Go 템플릿 문법으로 작성된 템플릿입니다.
Helm이 이 템플릿을 처리할 때 values.yaml의 값들을 주입하여 최종 매니페스트를 생성합니다. _helpers.tpl 파일은 조금 특별합니다.
언더스코어로 시작하는 파일은 Helm이 Kubernetes 리소스로 렌더링하지 않습니다. 대신 다른 템플릿에서 재사용할 수 있는 헬퍼 함수를 정의하는 용도로 사용합니다.
예를 들어 Chart 이름을 생성하는 로직을 여러 곳에서 사용한다면, _helpers.tpl에 정의해두고 호출하면 됩니다. charts 폴더는 의존성을 관리합니다.
만약 여러분의 Chart가 Redis나 PostgreSQL 같은 다른 Chart에 의존한다면, 해당 Chart들이 이 폴더에 위치합니다. Chart.yaml의 dependencies 섹션에 정의하면 helm dependency update 명령어로 자동으로 다운로드됩니다.
실제 ML 서비스를 배포할 때는 어떤 구조가 좋을까요? 추론 서버를 배포한다면 Deployment로 Pod를 정의하고, Service로 네트워크를 노출하고, HPA로 오토스케일링을 설정하고, ConfigMap으로 모델 경로 같은 설정을 관리합니다.
이 모든 것이 하나의 Chart 안에 깔끔하게 정리됩니다. 김개발 씨는 이제 Chart 구조가 머릿속에 그려지기 시작했습니다.
"생각보다 체계적이네요!"
실전 팁
💡 - helm create로 생성된 기본 템플릿을 분석하면서 학습하면 효과적입니다
- .helmignore 파일로 Chart 패키징 시 제외할 파일을 지정할 수 있습니다
3. Values 파일 작성
김개발 씨는 ML 모델 서버를 개발 환경과 운영 환경에 각각 배포해야 합니다. 개발 환경은 CPU 1개면 충분하지만, 운영 환경은 GPU 4개가 필요합니다.
매번 YAML 파일을 수정해야 할까요? 박시니어 씨가 웃으며 말했습니다.
"values 파일을 나누면 돼요."
Values 파일은 Chart의 설정값을 외부에서 주입하는 메커니즘입니다. 기본 values.yaml에 공통 설정을 정의하고, 환경별로 values-dev.yaml, values-prod.yaml을 만들어 필요한 부분만 덮어씁니다.
이렇게 하면 하나의 Chart로 여러 환경을 유연하게 관리할 수 있습니다.
다음 코드를 살펴봅시다.
# values.yaml (기본 설정)
replicaCount: 1
image:
repository: ml-inference-server
tag: "1.0.0"
pullPolicy: IfNotPresent
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "1Gi"
cpu: "1000m"
model:
path: "/models/latest"
batchSize: 32
# values-prod.yaml (운영 환경 덮어쓰기)
replicaCount: 3
resources:
requests:
memory: "4Gi"
nvidia.com/gpu: 1
limits:
memory: "8Gi"
nvidia.com/gpu: 1
김개발 씨는 처음에 개발 환경용 Chart와 운영 환경용 Chart를 따로 만들려고 했습니다. 그러나 박시니어 씨가 말렸습니다.
"그러면 나중에 로직 하나 바꿀 때 두 곳을 다 수정해야 해요. 유지보수의 악몽이죠." Values 파일의 핵심은 관심사의 분리입니다.
Chart의 템플릿은 "무엇을 배포할 것인가"를 정의합니다. Values 파일은 "어떤 설정으로 배포할 것인가"를 정의합니다.
이 두 가지를 분리함으로써 하나의 Chart를 여러 상황에서 재사용할 수 있습니다. 마치 옷을 생각해보면 이해하기 쉽습니다.
같은 디자인의 셔츠라도 사이즈와 색상은 다양하게 만들 수 있습니다. 셔츠의 기본 패턴(템플릿)은 하나이고, 사이즈와 색상(Values)만 바꿔서 여러 제품을 생산하는 것입니다.
Values 파일은 계층 구조를 가질 수 있습니다. 위 코드에서 resources 아래에 requests와 limits가 있고, 그 아래에 다시 memory와 cpu가 있습니다.
템플릿에서는 .Values.resources.requests.memory처럼 점으로 연결하여 접근합니다. 이 구조 덕분에 관련된 설정을 논리적으로 그룹화할 수 있습니다.
ML 서비스를 배포할 때 특히 중요한 설정들이 있습니다. GPU 리소스 요청, 모델 경로, 배치 사이즈, 워커 수 등은 환경마다 다르게 설정해야 하는 경우가 많습니다.
이런 값들을 모두 values.yaml에 정의해두면, 나중에 설정을 변경할 때 템플릿을 건드릴 필요가 없습니다. 여러 values 파일을 조합해서 사용할 수도 있습니다.
helm install 명령어에 -f 옵션을 여러 번 사용하면 됩니다. 나중에 지정한 파일이 앞선 파일의 값을 덮어씁니다.
예를 들어 -f values.yaml -f values-prod.yaml -f values-gpu.yaml처럼 사용할 수 있습니다. 명령줄에서 개별 값을 직접 지정할 수도 있습니다.
--set 옵션을 사용하면 됩니다. helm install my-release ./ml-service --set replicaCount=5처럼 사용합니다.
하지만 복잡한 설정은 파일로 관리하는 것이 더 안전하고 추적하기도 쉽습니다. 주의할 점은 values 파일에 민감한 정보를 넣지 않는 것입니다.
API 키, 데이터베이스 비밀번호 같은 정보는 Kubernetes Secret으로 별도 관리하고, 필요하다면 External Secrets나 Sealed Secrets 같은 도구를 활용해야 합니다. values 파일은 보통 Git에 커밋되므로 민감 정보가 노출될 위험이 있습니다.
김개발 씨는 이제 환경별 values 파일을 만들어 같은 Chart를 개발, 스테이징, 운영 환경에 각각 다른 설정으로 배포할 수 있게 되었습니다.
실전 팁
💡 - helm show values [CHART]로 Chart의 기본 values를 확인할 수 있습니다
- values 파일에 주석을 상세히 달아두면 다른 팀원들이 설정을 이해하기 쉽습니다
4. Templates 만들기
이제 김개발 씨는 실제 템플릿을 작성할 차례입니다. values.yaml에서 값을 어떻게 가져오는지, 조건문과 반복문은 어떻게 사용하는지 궁금해졌습니다.
박시니어 씨가 말했습니다. "Go 템플릿 문법만 알면 어렵지 않아요."
Helm 템플릿은 Go 템플릿 엔진을 사용합니다. 이중 중괄호 {{ }}로 동적 값을 삽입하고, if-else로 조건부 렌더링, range로 반복 처리를 할 수 있습니다.
템플릿을 잘 작성하면 하나의 Chart로 다양한 상황에 대응하는 유연한 배포가 가능합니다.
다음 코드를 살펴봅시다.
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-inference
labels:
app: {{ .Chart.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Chart.Name }}
template:
spec:
containers:
- name: inference
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
resources:
{{- toYaml .Values.resources | nindent 12 }}
env:
{{- range .Values.env }}
- name: {{ .name }}
value: {{ .value | quote }}
{{- end }}
김개발 씨는 처음 템플릿 파일을 열었을 때 당황했습니다. 익숙한 YAML이지만, 중간중간 이상한 중괄호 표현이 섞여 있었습니다.
"이게 다 뭐죠?" Helm 템플릿의 핵심은 값 주입입니다. 일반 YAML 파일은 정적입니다.
한번 작성하면 바뀌지 않습니다. 하지만 템플릿은 동적입니다.
{{ }} 안에 표현식을 넣으면, Helm이 렌더링할 때 실제 값으로 치환합니다. 가장 많이 사용하는 것이 .Values 객체입니다.
values.yaml에 정의한 모든 값은 .Values를 통해 접근할 수 있습니다. 예를 들어 values.yaml에 replicaCount: 3이 있다면, 템플릿에서 {{ .Values.replicaCount }}라고 쓰면 3으로 치환됩니다.
.Release 객체는 현재 설치에 대한 정보를 담고 있습니다. .Release.Name은 helm install 시 지정한 릴리스 이름, .Release.Namespace는 설치되는 네임스페이스입니다.
여러 릴리스를 같은 네임스페이스에 설치할 때 이름 충돌을 방지하려면 .Release.Name을 리소스 이름에 포함시키는 것이 좋습니다. .Chart 객체는 Chart.yaml의 정보를 제공합니다.
.Chart.Name은 Chart 이름, .Chart.Version은 Chart 버전입니다. 라벨이나 어노테이션에 이 정보를 넣어두면 나중에 어떤 Chart로 배포되었는지 추적하기 쉽습니다.
조건부 렌더링은 if-else로 처리합니다. 예를 들어 GPU가 필요한 경우에만 특정 설정을 추가하고 싶다면 {{- if .Values.gpu.enabled }}로 조건을 감싸면 됩니다.
중괄호 앞의 하이픈 -는 공백을 제거하는 역할을 합니다. 이것을 잘 활용해야 렌더링된 YAML이 깔끔해집니다.
반복문은 range를 사용합니다. 위 코드에서 환경 변수 목록을 반복 처리하는 부분을 보면, {{- range .Values.env }}로 시작해서 {{- end }}로 끝납니다.
그 사이의 내용이 리스트의 각 항목마다 반복됩니다. toYaml과 nindent는 자주 쓰이는 함수입니다.
복잡한 객체를 YAML 형식으로 변환할 때 toYaml을 사용하고, 들여쓰기를 맞출 때 nindent를 사용합니다. 이 두 함수를 파이프(|)로 연결하면 깔끔한 출력을 얻을 수 있습니다.
템플릿을 작성한 후에는 반드시 검증해야 합니다. helm template ./ml-service 명령어로 렌더링 결과를 미리 확인할 수 있습니다.
실제 클러스터에 배포하기 전에 YAML이 의도대로 생성되었는지 꼭 확인하세요. 김개발 씨는 몇 번의 시행착오 끝에 템플릿 문법에 익숙해졌습니다.
"처음엔 복잡해 보였는데, 패턴이 있네요!"
실전 팁
💡 - helm lint로 Chart 문법 오류를 사전에 검사할 수 있습니다
- _helpers.tpl에 공통 로직을 정의하고 include로 재사용하세요
5. Kubernetes ML 앱 배포
드디어 실전입니다. 김개발 씨는 지금까지 배운 내용을 종합하여 실제 ML 추론 서버를 Kubernetes에 배포해보기로 했습니다.
모델 로딩, 헬스체크, 오토스케일링까지 고려해야 합니다. 박시니어 씨가 말했습니다.
"ML 워크로드는 일반 웹 서버와 다른 점이 많아요."
ML 애플리케이션은 모델 로딩 시간, GPU 리소스, 배치 처리 등 특수한 요구사항이 있습니다. initContainer로 모델을 미리 다운로드하고, readinessProbe로 모델 로딩 완료를 확인하며, HPA로 추론 요청량에 따라 자동 확장하는 것이 일반적인 패턴입니다.
다음 코드를 살펴봅시다.
# templates/deployment.yaml (ML 특화)
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-ml-inference
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
initContainers:
- name: model-downloader
image: {{ .Values.modelDownloader.image }}
command: ["python", "download_model.py"]
env:
- name: MODEL_URI
value: {{ .Values.model.uri }}
volumeMounts:
- name: model-storage
mountPath: /models
containers:
- name: inference
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: 8080
readinessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 30
periodSeconds: 10
김개발 씨는 일반 웹 서버를 배포하듯이 ML 서버를 배포했다가 낭패를 본 적이 있습니다. 컨테이너가 시작되자마자 트래픽이 들어왔는데, 모델 로딩이 끝나지 않아 모든 요청이 실패했습니다.
ML 워크로드는 일반 애플리케이션과 다른 특성이 있습니다. 첫째, 모델 로딩 시간입니다.
대형 언어 모델의 경우 수 GB에 달하는 가중치를 메모리에 올리는 데 수 분이 걸릴 수 있습니다. 이 시간 동안 서비스가 준비되지 않았음을 Kubernetes에 알려야 합니다.
이 문제를 해결하는 첫 번째 방법이 initContainer입니다. initContainer는 메인 컨테이너가 시작되기 전에 실행되는 컨테이너입니다.
여기서 모델을 다운로드하고 공유 볼륨에 저장해두면, 메인 컨테이너는 이미 준비된 모델을 바로 로드할 수 있습니다. S3나 GCS에서 모델을 가져오는 작업을 initContainer에서 처리하는 것이 일반적입니다.
두 번째 핵심은 readinessProbe입니다. Kubernetes는 readinessProbe가 성공해야만 해당 Pod에 트래픽을 보냅니다.
ML 서버에서는 /health 엔드포인트가 모델 로딩이 완료되었을 때만 200을 반환하도록 구현합니다. initialDelaySeconds를 넉넉하게 설정하여 모델 로딩 시간을 확보하세요.
livenessProbe도 중요하지만 주의가 필요합니다. livenessProbe가 실패하면 Kubernetes가 Pod를 재시작합니다.
ML 서버에서 긴 추론이 진행 중일 때 잘못된 livenessProbe 설정으로 Pod가 재시작되면 낭패입니다. timeoutSeconds를 충분히 길게 설정하세요.
GPU 리소스 요청도 정확히 해야 합니다. nvidia.com/gpu: 1처럼 GPU 개수를 명시적으로 요청합니다.
GPU는 분할이 안 되므로 requests와 limits를 같은 값으로 설정해야 합니다. 노드에 GPU가 부족하면 Pod가 Pending 상태로 남게 됩니다.
**HPA(Horizontal Pod Autoscaler)**로 자동 확장도 설정할 수 있습니다. 다만 ML 워크로드는 스케일 아웃에 시간이 걸립니다.
새 Pod가 뜨고 모델을 로딩하는 동안 기존 Pod들이 부하를 감당해야 합니다. 여유 있는 스케일링 정책을 설정하거나, Knative 같은 서버리스 프레임워크를 고려할 수도 있습니다.
PodDisruptionBudget도 설정해두면 좋습니다. 노드 업그레이드나 클러스터 유지보수 시 최소한의 Pod가 유지되도록 보장합니다.
ML 서비스는 스케일 업에 시간이 걸리므로 갑자기 모든 Pod가 종료되면 서비스 장애로 이어질 수 있습니다. 김개발 씨는 이런 설정들을 Chart에 반영했습니다.
첫 배포에서 바로 문제없이 동작하는 것을 보고 뿌듯해했습니다.
실전 팁
💡 - GPU 노드 풀과 CPU 노드 풀을 분리하고, nodeSelector로 적절한 노드에 스케줄링하세요
- 모델 버전 관리를 위해 이미지 태그에 모델 버전을 포함시키는 것이 좋습니다
6. Chart Repository 구축
김개발 씨가 만든 Chart가 팀 내에서 인기를 끌기 시작했습니다. 다른 팀원들도 이 Chart를 사용하고 싶어했습니다.
매번 파일을 복사해서 공유하기엔 번거롭습니다. 박시니어 씨가 제안했습니다.
"우리도 Chart Repository를 만들어봐요."
Chart Repository는 Chart를 저장하고 공유하는 HTTP 서버입니다. 패키징된 Chart(.tgz)와 index.yaml 파일을 제공합니다.
GitHub Pages, S3, ChartMuseum 등 다양한 방법으로 구축할 수 있으며, 팀 내에서 표준화된 Chart를 공유하는 데 필수적입니다.
다음 코드를 살펴봅시다.
# Chart 패키징
helm package ./ml-service
# 출력: ml-service-1.0.0.tgz
# index.yaml 생성/업데이트
helm repo index . --url https://charts.example.com
# ChartMuseum 실행 (Docker)
docker run -d \
--name chartmuseum \
-p 8080:8080 \
-e STORAGE=local \
-e STORAGE_LOCAL_ROOTDIR=/charts \
-v $(pwd)/charts:/charts \
ghcr.io/helm/chartmuseum:v0.16.0
# Chart 업로드 (ChartMuseum API)
curl --data-binary "@ml-service-1.0.0.tgz" \
http://localhost:8080/api/charts
# Repository 추가 및 사용
helm repo add myrepo http://localhost:8080
helm install my-ml myrepo/ml-service
처음에 김개발 씨는 Chart 폴더를 압축해서 슬랙으로 공유했습니다. 하지만 버전이 올라갈 때마다 다시 공유해야 했고, 누가 어떤 버전을 쓰는지 파악하기 어려웠습니다.
Chart Repository는 이런 문제를 깔끔하게 해결합니다. 마치 회사 도서관을 생각해보면 됩니다.
책을 개인적으로 보관하면 다른 사람이 빌리기 어렵습니다. 하지만 도서관에 등록해두면 누구나 목록을 검색하고, 원하는 책을 빌려갈 수 있습니다.
Chart Repository도 마찬가지입니다. Repository의 핵심은 두 가지입니다.
첫째는 패키징된 Chart 파일입니다. helm package 명령어를 실행하면 Chart 디렉토리가 .tgz 파일로 압축됩니다.
이 파일에 이름과 버전이 포함되어 있어 다양한 버전을 함께 보관할 수 있습니다. 둘째는 index.yaml 파일입니다.
이 파일은 Repository에 있는 모든 Chart의 목록과 메타데이터를 담고 있습니다. helm repo update를 실행하면 이 파일을 다운로드하여 로컬에 캐싱합니다.
helm search repo를 실행하면 이 캐시를 검색합니다. 가장 간단한 Repository는 정적 파일 서버입니다.
GitHub Pages에 Chart와 index.yaml을 올려두면 바로 Repository로 사용할 수 있습니다. CI/CD 파이프라인에서 Chart를 빌드하고 GitHub Pages로 배포하면 자동화도 됩니다.
좀 더 기능이 필요하다면 ChartMuseum을 사용합니다. ChartMuseum은 Helm Chart 전용 서버입니다.
API를 통해 Chart를 업로드하고, 버전 관리도 자동으로 처리해줍니다. 인증 기능도 있어서 비공개 Chart를 안전하게 관리할 수 있습니다.
클라우드 서비스를 사용하는 방법도 있습니다. AWS ECR, Google Artifact Registry, Azure Container Registry 모두 Helm Chart를 저장하는 기능을 제공합니다.
OCI 레지스트리 표준을 따르기 때문에 컨테이너 이미지와 Chart를 같은 곳에서 관리할 수 있습니다. Repository를 팀에 공유할 때는 문서화가 중요합니다.
각 Chart가 무엇을 하는지, 어떤 values를 설정해야 하는지 README를 잘 작성해야 합니다. Chart 안에 README.md를 넣어두면 helm show readme 명령어로 확인할 수 있습니다.
김개발 씨는 ChartMuseum을 사내 Kubernetes 클러스터에 배포하고, 팀 전체가 공유하는 Chart Repository를 구축했습니다.
실전 팁
💡 - OCI 레지스트리를 사용하면 helm registry login으로 인증하고 helm push로 업로드할 수 있습니다
- CI/CD에서 Chart 버전을 자동으로 증가시키는 스크립트를 작성하면 편리합니다
7. 버전 관리 전략
ML 모델이 업데이트될 때마다 Chart도 업데이트해야 합니다. 하지만 어떤 버전 체계를 따라야 할까요?
이전 버전으로 롤백하려면 어떻게 해야 할까요? 박시니어 씨가 말했습니다.
"버전 관리 전략이 명확해야 운영이 편해져요."
Helm에서는 Chart 버전과 앱 버전을 별도로 관리합니다. Semantic Versioning을 따르는 것이 권장되며, Helm의 rollback 기능으로 이전 Release로 쉽게 되돌릴 수 있습니다.
버전 히스토리를 잘 관리하면 문제 발생 시 빠르게 대응할 수 있습니다.
다음 코드를 살펴봅시다.
# Chart.yaml 버전 관리
apiVersion: v2
name: ml-inference
version: 2.1.0 # Chart 버전 (MAJOR.MINOR.PATCH)
appVersion: "1.5.0" # 앱/모델 버전
# Release 히스토리 확인
helm history my-ml-service
# REVISION STATUS CHART APP VERSION
# 1 superseded ml-inference-1.0.0 1.0.0
# 2 superseded ml-inference-2.0.0 1.3.0
# 3 deployed ml-inference-2.1.0 1.5.0
# 이전 버전으로 롤백
helm rollback my-ml-service 2
# 특정 버전 설치
helm install my-ml myrepo/ml-inference --version 2.0.0
# 업그레이드 시 변경사항 미리보기
helm diff upgrade my-ml ./ml-inference -f values-prod.yaml
김개발 씨는 모델을 업데이트했는데 성능이 오히려 떨어지는 일을 겪었습니다. 급하게 이전 버전으로 돌아가려 했지만, 어떤 설정이었는지 기억나지 않았습니다.
결국 한 시간 넘게 서비스가 불안정했습니다. 버전 관리 전략은 이런 상황에서 생명줄이 됩니다.
Helm에서 관리하는 버전은 두 가지입니다. version은 Chart 자체의 버전으로, Chart.yaml이나 템플릿이 바뀌면 올립니다.
appVersion은 Chart가 배포하는 애플리케이션의 버전으로, 컨테이너 이미지나 모델이 바뀌면 올립니다. Semantic Versioning 규칙을 따르는 것이 좋습니다.
MAJOR.MINOR.PATCH 형식에서, MAJOR는 호환되지 않는 변경, MINOR는 하위 호환되는 기능 추가, PATCH는 버그 수정에 올립니다. 예를 들어 필수 values 항목이 추가되어 기존 values 파일로는 설치가 안 되면 MAJOR를 올려야 합니다.
Helm은 모든 Release의 히스토리를 저장합니다. helm history 명령어로 언제 어떤 Chart 버전이 배포되었는지 확인할 수 있습니다.
각 배포의 상태(deployed, superseded, failed)도 보여줍니다. 이 정보는 Kubernetes Secret에 저장되어 있습니다.
롤백은 helm rollback 명령어 하나로 가능합니다. revision 번호만 지정하면 해당 시점의 상태로 되돌립니다.
중요한 점은, 롤백도 하나의 새로운 revision으로 기록된다는 것입니다. 따라서 롤백의 롤백도 가능합니다.
업그레이드 전에는 변경사항을 미리 확인하는 것이 좋습니다. helm-diff 플러그인을 설치하면 helm diff upgrade 명령어로 현재 상태와 새 Chart의 차이를 볼 수 있습니다.
의도치 않은 변경이 없는지 확인한 후 업그레이드하세요. Git과 연동한 버전 관리도 중요합니다.
Chart 소스코드를 Git으로 관리하고, 태그를 릴리스 버전과 일치시킵니다. CI/CD 파이프라인에서 Git 태그를 기반으로 Chart를 빌드하고 배포하면 추적이 쉬워집니다.
ML 워크로드에서는 모델 버전 관리도 함께 고려해야 합니다. appVersion에 모델 버전을 반영하거나, values에 별도의 모델 버전 필드를 만들어 관리합니다.
모델 레지스트리(MLflow, Weights & Biases 등)와 연동하면 더욱 체계적인 관리가 가능합니다. 김개발 씨는 이제 버전 관리 전략을 수립하고, 팀 전체가 같은 규칙을 따르도록 문서화했습니다.
"이제 롤백할 일이 있어도 걱정 없어요!"
실전 팁
💡 - helm upgrade 시 --atomic 옵션을 주면 실패 시 자동으로 롤백됩니다
- helm-diff 플러그인은 프로덕션 배포 전 필수 검증 도구입니다
이상으로 학습을 마칩니다. 위 내용을 직접 코드로 작성해보면서 익혀보세요!
댓글 (0)
함께 보면 좋은 카드 뉴스
Istio 보안 완벽 가이드
마이크로서비스 환경에서 필수적인 Istio 보안 기능을 실무 중심으로 설명합니다. mTLS부터 인증, 인가까지 단계별로 학습하여 안전한 서비스 메시를 구축할 수 있습니다.
Istio 트래픽 관리 완벽 가이드
Istio의 트래픽 관리 기능을 마스터하는 완벽 가이드입니다. VirtualService와 DestinationRule을 활용한 라우팅부터 트래픽 분할, 헤더 기반 라우팅까지 실무에 필요한 모든 내용을 다룹니다.
Istio 설치와 구성 완벽 가이드
Kubernetes 환경에서 Istio 서비스 메시를 설치하고 구성하는 방법을 초급 개발자도 쉽게 이해할 수 있도록 실무 스토리와 비유로 풀어낸 가이드입니다. istioctl 설치부터 사이드카 주입까지 단계별로 학습합니다.
서비스 메시 완벽 가이드
마이크로서비스 간 통신을 안전하고 효율적으로 관리하는 서비스 메시의 핵심 개념부터 실전 도입까지, 초급 개발자를 위한 완벽한 입문서입니다. Istio와 Linkerd 비교, 사이드카 패턴, 실무 적용 노하우를 담았습니다.
Helm 마이크로서비스 패키징 완벽 가이드
Kubernetes 환경에서 마이크로서비스를 효율적으로 패키징하고 배포하는 Helm의 핵심 기능을 실무 중심으로 학습합니다. Chart 생성부터 릴리스 관리까지 체계적으로 다룹니다.