kubernetes 패키지 매니저, Helm에 대해 알아보자

개요 - 쿠버네티스 리소스를 직접 다룰 때의 불편함

운영 중인 쿠버네티스 클러스터 안에는 수많은 리소스가 존재한다. Pod와 이를 관리하는 Deployment, 클러스터 내/외부와의 통신을 위한 Service, 변수 관리를 위한 Configmap 등이 이에 해당한다.

이러한 쿠버네티스 리소스들은 보통 리소스별로 별도의 yaml 파일에 명시하고 관리하게 되며, 아래와 같은 명령어를 통해 클러스터에 배포한다.

kubectl apply -f {resource name}

언뜻 보면 그렇게 복잡한 작업이 아니어보일 수 있지만, 매번 동일한 클러스터를 구성하기 위해 수십 개의 리소스에 대해 이 명령을 실행하는 것은 꽤나 귀찮은 일이 될 수 있다.

또한, 리소스의 변경 주기가 개별적으로 동작하니 변경 관리를 하기 어렵다. 언제 어떤 리소스를 업데이트했는지를 추적하기 어렵기 때문이다.

이러한 불편함을 해결하려면 어떻게 해야 할까? yaml 파일 하나에 모든 리소스를 몰아넣으면 해결될까? 리소스를 일괄적으로 다룰 수야 있겠으나 가독성도 떨어지고 같은 파일을 여러 명이 수정하는 일이 잦아져 어떤 사이드 이펙트가 생길지 모를 일이다.

대신 더 좋은 해결 방법이 있다. 바로 이 리소스들을 하나로 모아 적용하고, 이들의 변경을 추적하고 관리할 수 있는 훌륭한 매니저를 사용하는 방법이다.

 

 

Helm

정의

image (14).png

Helm은 쿠버네티스 애플리케이션을 패키징, 배포, 관리하기 위해 등장한 패키지 매니저로, Helm의 Chart는 여러 쿠버네티스 리소스를 하나로 묶어 손쉽게 배포, 버저닝, 공유할 수 있도록 돕는다.

Chart의 구조

이 Chart에 대해 좀 더 자세히 알아보자. 위에서 언급했듯 Chart는 쿠버네티스 리소스 관리를 돕는 도구이며 Helm 그 자체이다. (그래서 Helm Chart라는 표현을 많이 쓴다.)

이 Chart는 아래와 같은 구조로 구성된다.

Project/
  Chart.yaml          # 차트에 대한 정보를 가진 YAML 파일
  values.yaml         # 차트에 대한 기본 환경설정 값들
  charts/             # 하위 서브 차트들을 포함하는 디렉터리
  templates/          # k8s 리소스 묶음
      deployment.yaml
      service.yaml
      ...

이 글에서는 여기서 주의깊게 살펴보아야 할 Chart.yaml, values.yaml, templates/에 대해서만 간략하게 소개한다.

먼저 Chart.yaml은 아래와 같이 구성된다.

apiVersion: 차트 API 버전 (v1/v2)
name: 차트명
version: 차트 버전 (SemVer 2)
kubeVersion: 호환되는 쿠버네티스 버전의 SemVer 범위 (optional)
description: 이 프로젝트에 대한 간략한 설명 (optional)
type: 차트 타입 (application/library) (optional)
sources:
  - 이 프로젝트의 소스코드 URL 리스트 (optional)
dependencies:
    - 의존하는 차트 리스트 (optional)
maintainers:
    - 메인테이너들의 정보 (optional)
icon: 아이콘으로 사용될 SVG나 PNG 이미지 URL (optional)
deprecated: 차트의 deprecated 여부 (optional, boolean)
appVersion: 이 앱의 버전 (optional)

여기서 가장 중요한 것은 version 키값이다. 차트에는 SemVer(major.minor.patch) 버전이 명시되며, 이 버전은 차트에 변경 사항이 있을 때마다 업그레이드 되어야 한다.

그 외에도 차트 API의 버전을 명시하는 apiVersion, 차트가 배포하는 애플리케이션의 버전을 명시하는 appVersion이 있는데, 이 버전들을 헷갈리지 않고 잘 구분해야 한다.

이 Chart.yaml 파일에서의 구성은 Chart를 배포할 때 사용된다. 차트 버전을 기반으로 패키지 내 리소스의 변경 여부를 판별하고, 차트의 이름은 해당 파일의 name 키값과 동일하게 생성되는 방식이다.

templates 디렉토리 안에 들어가는 것은 k8s 리소스 명세들이다. 그리고 Helm의 특이점은, templates 디렉토리 내 리소스들에서 values.yaml 파일의 환경변수를 사용할 수 있다는 것이다. 이를 통해, 여러 리소스에서 공통적으로 사용하는 변수를 하나의 파일에서 관리할 수 있다.

또한, 이 values 파일은 하나의 패키지에 여러 개가 존재할 수 있다. 이는 패키지를 클러스터에 배포하는 시점에 오버라이딩이 가능하며, 기본값으로 지정되는 것은 루트 디렉토리의 values.yaml 파일이다.

장점

위에서 살펴본 Chart의 정의와 구조를 통해, Helm Chart를 사용하는 것은 아래와 같은 이점을 제공한다는 사실을 알 수 있다.

  • 패키징을 통한 일괄적 관리: 여러 쿠버네티스 리소스를 패키징하여 한 번에 적용 및 제거될 수 있도록 함
  • 버저닝 & Rollback 용이: Chart에는 버전이 존재하며, 이 버전을 기반으로 차트가 생성될 때 리소스의 상태가 기록되므로 쉽게 롤백 가능
  • 템플릿 기반으로 환경별 설정 관리에 용이: values.yaml 파일을 오버라이딩하여 실행 환경별로 서로 다른 변수를 주입할 수 있음

 

 

사용법

지금까지는 Helm이 무엇인지, Helm의 주요 구성요소인 Chart는 어떤 구조를 가지며 이로부터 우리가 얻을 수 있는 이점이 무엇인지를 살펴보았다.

해당 단락에서는 본격적으로 이 Helm Chart를 어떻게 생성하고 사용하는지를 알아보고자 한다.

우선, 이러한 동작을 수행하기 위해서는 Helm CLI라는 도구가 필요하다. 이 도구는 아래와 같이 설치할 수 있다.

# mac (brew)
brew install helm

 

# windows (choco)
choco install kubernetes-helm

우리가 이 Helm CLI를 사용할 때 알아야 할 주요 명령어는 아래와 같다.

  1. create
  2. install
  3. upgrade
  4. rollback
  5. repo add
  6. push
  7. search repo

create

helm create {directory-name}

helm create는 helm chart를 생성하는 명령어이다.

이 명령으로 위에서 살펴본 구조의 디렉토리를 만들 수 있다.

install, upgrade, rollback

이 명령들은 차트를 클러스터에 설치하고, 업그레이드/다운그레이드하기 위해 존재한다.

helm install {name} {directory-name}
helm upgrade {name} {directory-name}

먼저 설치와 업그레이드는 차트를 클러스터에 반영하는 작업이기 때문에 동일한 필수 인자를 요구한다.

또한, 앞서 말한 것과 같이 패키지 배포 시점에 환경변수를 오버라이딩할 수 있으며, --values 플래그와 함께 value 파일을 지정하거나 --set 플래그를 통해 단일 변수를 정의하는 방식이 사용 가능하다.

helm rollback {name} {version}

롤백 명령은 이전의 버전으로 리소스 구성을 되돌린다. 배포 후 패키지 구성의 문제로 장애가 발생했을 때 빠른 회복을 할 수 있어 아주 중요한 기능이다.

rollback 명령에 전달되는 version 인자는 릴리스 버전으로, helm history {name} 명령을 통해 확인할 수 있다.

repo add, push

Docker를 사용해본 사람이라면, Container Registry의 개념에 대해서는 잘 알고 있을 것이다. Helm Chart 또한 Docker Image와 유사한 개념이기 때문에 HTTP 등의 프로토콜을 통해 차트를 저장하고 조회할 수 있는 저장 공간을 필요로 한다.

여기서 소개할 명령들은 helm chart의 리포지토리를 선정하고 차트를 저장, 관리 및 탐색하기 위해 존재한다.

helm repo add {name} {url}

helm CLI가 내가 사용할 repository를 인식하도록 하기 위해, repo add 명령을 이용한다.

git remote 명령처럼, 위 명령을 실행한 뒤에야 repository 관련 명령들을 사용할 수 있다.

helm push {name}

내가 만든 차트를 repository에 업로드할 수도 있다. CI/CD 파이프라인을 구축하는 경우 CD 단계에서 차트 정보를 획득하기 위해 이 명령을 사용하게 될 확률이 높다.

CI/CD

말이 나온 김에 CI/CD에 대해 첨언하자면, 사실 helm을 이용하려는 사람들의 대다수는 이를 기반으로 CI/CD 파이프라인을 구축하려 할 것이다. Helm은 GitOps와도 상성이 좋다. Git 저장소에 Helm Chart 디렉토리를 포함시키고, GitHub Action / JenKins 등을 통해 변경을 추적해 패키징하고, ArgoCD / FluxCD 등을 통해 차트 배포를 수행한다면 어렵지 않게 Helm 기반의 CI/CD 파이프라인을 구축할 수 있을 것이다.

 

 

마치며 - Docker, Kubernetes, Helm

도커는 SW 설치 없이 애플리케이션을 실행할 수 있도록 하는 컨테이너화 기술을 제공한다. 우리는 도커를 통해 여러 머신에서 도커 구성만으로도 일관된 실행 환경을 구축할 수 있는 이점을 누려왔다.

하지만 도커만으로는 컨테이너를 운영할 때의 불편함과 복잡함을 해소할 수 없었고, 이를 해결하기 위해 쿠버네티스라는 시스템이 등장했다.

쿠버네티스는 컨테이너의 배포, 확장, 상태 체크 및 복구, 컨테이너 간 통신 등을 효율적으로 관리하는 시스템이었으며 우리는 이를 통해 컨테이너 기반의 애플리케이션을 효율적으로 운영하는 이점을 누려왔다.

하지만 클러스터를 구성하기 위해서는 상당히 많은 리소스가 필요하고, 이 리소스들을 각각 관리하고 필요에 따라 복원하는 것은 복잡한 일이었으며, 이를 해결하기 위해 등장한 것이 본 글에서 소개한 Helm이라고 볼 수 있다.

갑자기 Docker부터 Helm까지 살펴본 이유는, 이러한 발전 과정에 존재하는 템플릿 표준화에 대해 언급하기 위해서이다.

지난 번에 ECS vs EKS에서 비롯한 표준화에 대한 단상이라는 글을 작성했는데, 이에 대한 확장이라고 볼 수도 있겠다.

 

ECS vs EKS에서 비롯한 표준화에 대한 단상

최근에 처음으로 Kubernetes를 학습하게 되었다.기존부터 나는 Docker의 애용자였고, 서비스의 배포 및 관리를 위해 AWS ECS를 주로 사용하고 있었다.그러나 Kubernetes는 한 번도 다뤄본 적이 없었는데,

devpanpan.tistory.com

시스템이 복잡해지는 과정에서, 관리자는 “비효율적 반복 작업”의 존재에 대해 파악하게 되고, 이를 정형화하기 위해 템플릿을 정의하고 작성한다. 이러한 템플릿 표준화는 운영 효율성을 개선하고, 개발자들 간 소통을 원활하게 돕는다는 이점이 있다.

하지만, 표준화 또한 양날의 검이라고 볼 수도 있다. 표준화 템플릿을 이해하고 사용하기 위해서는 학습이 필요하고, 한 번 이러한 시스템을 구축하고 나면 이를 관리할 모든 관리자가 이 내용들을 숙지해야 하기 때문이다.

그럼에도 우리가 복잡한 시스템의 관리자라면, 이러한 학습 시간을 감안해서라도 표준화에 표준화를 적용할 필요가 있다고 본다. 시스템의 크기가 커질 수록 우리가 반복 작업에 사용하는 시간은 점점 더 많아질 것이고, 이는 우리가 더 중요한 일을 하는 것을 방해하게 될 것이므로.

 

 

출처

Helm 공식 문서

 

문서 홈

문서 구성에 관해 알아야 할 모든 것

helm.sh