본문 바로가기

[Helm] Helm Quick Start 본문

DevOps

[Helm] Helm Quick Start

겨울바람_ 2024. 8. 10. 19:43

Helm?

헬름은 The Package Manager for Kubernetes, 즉 쿠버네티스의 패키지 관리를 위한 툴이다.

 

여기서 패키지란, Helm Charts를 패키징한 것을 의미한다. 여기서 차트란 쿠버네티스의 리소스 yaml 파일을 템플릿화하여 메타 정보 파일 등을 압축한 파일을 뜻한다.

 

템플릿이란 쿠버네티스 환경에서 특정 프로그램을 실행시킬 수 있도록 해주는 리소스인 Deployment 혹은 Service 등을 포함하는 일종의 리소스 모음을 의미한다.

Helm Chart Structure

Helm의 공식문서를 살펴보면 헬름 차트는 이와 같은 구조를 갖는다. 구조에서 확인할 수 있는 각 파일 및 폴더는 다음과 같은 역할을 한다.

 

templates/ 디렉토리는 template 파일을 보관하기 위한 디렉토리이다.

 

Helm이 Chart를 검사할 때 templates/ 내부에 존재하는 파일들을 template rendering engine으로 전송한다. 그리고 템플릿 엔진은 탬플릿의 실행 결과를 취합하여 쿠버네티스로 보낸다.

values.yaml 파일은 Chart 내부의 기본 값을 포함하는데, 해당 파일의 값을 helm install, helm upgrade 중에 템플릿 값에 덮어씌울 수 있다. 즉, value.yaml을 통해 동적으로 템플릿 파일을 구성할 수 있다.

 

Chart.yaml 파일은 Chart의 버전, 이름 등 메타 정보와 설명을 포함하며, 템플릿 내부에서 접근할 수 있다.

 

charts/ 디렉토리는 다른 차트 파일들을 포함하기 위한 용도다.

Deploy Nginx using helm

Create template files

원하는 텍스트 에디터를 사용해 deployment.yamlservice.yaml을 작성해보자. 필자는 templates/ 디렉토리 내부에 nginx 생성을 위한 deployment.yamlservice.yaml을 아래와 같이 각각 작성했다.

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-for-helm
spec:
  selector:
    matchLabels:
      app: nginx-for-helm
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-for-helm
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        ports:
        - containerPort: 80
# templates/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
  labels:
    run: nginx-for-helm
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: nginx-for-helm

 

tree 명령어로 다음과 같은 구조를 확인할 수 있다.

Create Chart.yaml

Chart.yaml 에 대해 나와있는 공식문서를 살펴보면 Chart.yaml 파일에 포함되는 요소가 굉장히 많은 것을 확인할 수 있다. 이 중 필수적으로 들어가야하는 것은 apiVersionname, version이고 나머지는 부가적인 요소이기 때문에 필수 요소에 대해 먼저 알아보도록 하자.

 

apiVersion은 Helm Chart에 대한 버전을 의미하며 과거에는 v1을 주로 사용했지만 Helm 3부터는 v2 사용이 필수적이다.

 

name은 해당 Chart의 이름을 의미하며 version 또한 Chart의 버전을 의미하기에 두 요소는 임의로 작성하면 된다.

위 내용을 바탕으로 Chart.yaml 파일을 작성해보자. Chart.yaml 파일은 templates/ 디렉토리와 동일한 depth에 작성해주면 된다.

apiVersion: v2
name: chart-for-nginx
version: 0.0.

 

tree 명령어로 다음과 같은 구조를 확인할 수 있다.

Create values.yaml

values.yaml 파일을 사용하면 외부에서 템플릿의 값을 동적으로 변경할 수 있다. values.yaml을 사용하기 위해서는 적용하고자 하는 위치에 템플릿 문법을 사용해야 한다.

 

values.yaml 파일에는 템플릿에 적용하고자 하는 값을 작성해줘야 한다. 만약 Nginx 배포에 사용되는 이미지를 동적으로 적용하고자 한다면, image: nginx:latest와 같은 값을 values.yaml 파일에 작성해둬야 한다.

 

위의 예시대로 이미지를 동적으로 변경하고자 한다면 템플릿의 이미지 필드를 다음과 같이 템플릿 문법을 통해 대체하면 된다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-for-helm
spec:
  selector:
    matchLabels:
      app: nginx-for-helm
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-for-helm
    spec:
      containers:
      - name: nginx
        image: {{ .Values.image }}
        ports:
        - containerPort: 80

 

{{ .Values.image }} 라는 문법은 values.yaml 파일에 위치한 필드들 중 image를 키 값으로 가지는 값이 대입된다는 것을 알려주는 것이다.

 

tree 명령어로 다음과 같은 구조를 확인할 수 있다.

Deploy

이렇게 작성된 Helm Chart를 통해 Nginx를 배포해보자. helm install <release-name> <chart-name> 명령어를 통해 간단히 배포가 가능하다.

 

release-name은 사용자가 임의로 작성 가능하며, chart-name의 경우 지금까지 작성한 Helm Chart의 위치를 입력하면 된다. 성공적으로 Helm Chart를 작성했다면 아래의 그림과 같이 성공적으로 배포가 된 것을 확인할 수 있다.

deployment.yaml 파일에서 replica 값을 2로 설정했기 때문에 2개의 Pod가 동작 중이며, Deployment 리소스와 Service 리소스 또한 정상적으로 실행 중인 것을 확인할 수 있다.

image 또한 우리가 values.yaml을 통해 동적으로 지정한 nginx:latest 이미지가 적용되어 있는 것을 확인할 수 있다.

Release Template

위에서 작성 예제에는 한 가지 문제점이 있는데, deployment.yamlmetadata.name 값이 nginx-deployment로 고정되어 있기 때문에 하나의 release만 생성이 가능하다는 것이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx-for-helm
spec:
  selector:
    matchLabels:
      app: nginx-for-helm
  replicas: 2
  template:
    metadata:
      labels:
        app: nginx-for-helm
    spec:
      containers:
      - name: nginx
        image: {{ .Values.image }}
        ports:
        - containerPort: 80

 

만약 helm install first-nginx . 명령어를 실행한 뒤에 helm install second-nginx . 명령어를 수행하게 되면 아래와 같이 에러가 발생하며 release에 실패하는 것을 확인할 수 있다.

이러한 문제점을 해결하기 위해 Release Template 문법이 필요하다. 사용 방법은 values.yaml을 사용했을 때와 거의 동일하다. 동적으로 변경하고자 하는 부분에 문법을 적용시키면 된다.

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
  labels:
    app: {{ .Values.app-name }}
spec:
  selector:
    matchLabels:
      app: {{ .Values.app-name }}
  replicas: 2
  template:
    metadata:
      labels:
        app: {{ .Values.app-name }}
    spec:
      containers:
      - name: nginx
        image: {{ .Values.image }}
        ports:
        - containerPort: 

---
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
  labels:
    run: {{ .Values.app-name }}
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: {{ .Values.app-name }}

 

편의를 위해 두 템플릿의 metadata.name을 동일하게 설정했고 nginx-for-helm을 추출하여 values.yaml 파일을 통해 동적으로 주입하는 방식으로 변경했다.

 

Release Template을 사용한 방식으로 release를 배포하게 되면 first-nginxsecond-nginx 모두 잘 배포가 되는 것을 확인할 수 있다.

DeploymentService, Pod 또한 성공적으로 생성됐다. 배포된 리소스의 이름 또한 {{ .Release.Name }}을 통해 지정한대로 변경되어 실행되는 것을 확인해볼 수 있다.

Release Template 문법은 이외에도 여러가지 기능이 많이 존재하는데 대표적으로 특정 Namespace에 배포할 수 있는 {{ .Release.Namespace }}가 존재한다. 사용하기 위해서는 템플릿 파일에 metadata.namespace 항목을 추가하고 {{ .Release.Namespace }}을 적용해주면 된다.

# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
  namespace: {{ .Release.Namespace }}
  labels:
    app: {{ .Values.app-name }}
spec:
  selector:
    matchLabels:
      app: {{ .Values.app-name }}
  replicas: 2
  template:
    metadata:
      labels:
        app: {{ .Values.app-name }}
    spec:
      containers:
      - name: nginx
        image: {{ .Values.image }}
        ports:
        - containerPort: 

---
# service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}
  namespace: {{ .Release.Namespace }}
  labels:
    run: {{ .Values.app-name }}
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: {{ .Values.app-name }}

 

{{ .Release.Namespace }}을 사용하기 위해서는 Namespace가 사전에 생성되어 있어야 한다. 만약 Helm을 실행하는 동시에 Namespace를 생성하고자 한다면 --create-namespace -n 옵션을 사용하면 되지만, 이는 언제 누가 Namespace를 생성했는지 추적하기가 어렵기 때문에 무분별한 사용은 지양하는 편이 좋다.

 

기존에 생성되어 있던 Namespace인 helmprac에 배포하고자 한다면, helm install -n helmprac first-nginx . 명령어를 사용하면 된다.

Values.yaml override

Helm Chart의 기존 values.yaml파일의 일부 값을 변경하고자 할 때 사용할 수 있는 방법이다. 예를 들어 기존에 설정해둔 image: nginx:latestimage: nginx:stable로 변경하고 싶을 때 사용할 수 있다.

 

첫번 째 방법은 --set 옵션을 사용하는 것이다.

 

helm install --set image=nginx:stable first-nginx . 명령어를 통해 배포되는 Nginx의 이미지의 버전을 stable로 변경할 수 있다.

하지만 --set 옵션을 사용하는 방법은 변경하고자 하는 변수가 많을 경우에는 효율적이지 못하다. 이러한 문제점을 해결하기 위해 파일에 변경하고자 하는 값을 설정해두는 방법이 있다.

 

helm install -f <file-path> <release-name> <chart-name> 명령어를 통해 실행 가능하다.

 

텍스트 에디터를 통해 my-values.yaml 파일을 생성하고 동적으로 변경하고자 하는 값인 Nginx의 이미지를 입력하자. values.yaml을 작성할 때와 동일하게 image: nginx:stable을 입력해주면 된다.

 

그리고 helm install -f my-values.yaml first-nginx . 명령어를 실행시키면, 다음과 같이 Nginx의 이미지 버전이 stable로 변경되어 배포되는 것을 확인할 수 있다.

Comments