IT/Kubernetes

[Kubernetes] Helm Chart 만들기

wookiist 2021. 6. 18. 13:55

Prologue

일반적으로 Kubernetes Manifest 파일은 정적인 형태입니다. 따라서 데이터를 수정하기 위해선 파일 자체를 수정해야 합니다. 잘 관리를 한다면야 큰 어려움은 없겠지만, 문제는 CI/CD 등 자동화된 파이프라인을 구축해서 애플리케이션 라이프사이클을 관리할 때 발생합니다.

보통 애플리케이션 이미지를 새로 빌드하게 되면, 빌드 넘버가 변경됩니다. 이렇게 되면 새로운 이미지를 사용하기 위해 Kubernetes Manifest의 Image도 변경되어야 합니다. 하지만 Kubernetes Manifest를 살펴보면, 이를 변경하기 쉽지 않다는 것을 깨닫게 됩니다. Image Tag가 별도로 존재하지 않고 Image 이름에 붙어있기 때문입니다. 이를 자동화 파이프라인에서 변경하려면, sed 명령어를 쓰는 등의 힘든 작업을 (눈물의 똥꼬쇼를)해야 합니다.

Image Tag는 굉장히 단적인 예제입니다. 이 외에도 배포하는 이름에 따라 ConfigMap을 바꿔주고, 또 배포할 때마다 큰 틀은 같지만 조금씩 다른 형태로 데이터를 배포해야 할 때, 매번 Manifest를 수정하는 것은 너무나 비효율적입니다.

Helm Chart는 이런 어려움을 단번에 해결해줍니다. 물론 차트를 처음 만들 때는 번거롭긴 합니다. 필요로 하는 데이터를 template 형태로 작성해서 관리하고 있어야 하고, 단순히 배포만 하면 끝나던 것이 아니라, Helm 차트 자체를 관리해야 하는 노고도 추가됩니다. 그럼에도 불구하고 Helm Chart는 훌륭한 도구이며, 개인적인 의견으론 반드시 사용해야 하는(!) 도구라고 생각합니다.

이번 포스트에선 Helm Chart를 직접 생성해보면서 어떻게 Helm Chart를 만들고 관리할 수 있는지 알아보겠습니다.

Helm Chart

이번 포스트를 진행하기 위해 wookiist 라는 이름의 차트를 만들어보며 설명해보겠습니다.

Chart 생성

helm create 명령을 사용해서 차트를 생성합니다. helm create 명령을 이용해 만든 차트는 nginx를 예제로 사용하고 있습니다. 다음과 같이 정상적으로 생성되었는지 확인해봅니다.

$ helm create wookiist
$ ls -al wookiist
total 24
drwxr-xr-x   7 jaewook  staff   224  6 18 13:15 .
drwxr-xr-x   9 jaewook  staff   288  6 18 13:15 ..
-rw-r--r--   1 jaewook  staff   349  6 18 13:15 .helmignore
-rw-r--r--   1 jaewook  staff  1144  6 18 13:15 Chart.yaml
drwxr-xr-x   2 jaewook  staff    64  6 18 13:15 charts
drwxr-xr-x  10 jaewook  staff   320  6 18 13:15 templates
-rw-r--r--   1 jaewook  staff  1875  6 18 13:15 values.yaml

Chart.yaml 수정

Chart.yaml 파일을 살펴보겠습니다.

apiVersion: v2
name: wookiist
description: A Helm chart for Kubernetes

# A chart can be either an 'application' or a 'library' chart.
#
# Application charts are a collection of templates that can be packaged into versioned archives
# to be deployed.
#
# Library charts provide useful utilities or functions for the chart developer. They're included as
# a dependency of application charts to inject those utilities and functions into the rendering
# pipeline. Library charts do not define any templates and therefore cannot be deployed.
type: application

# This is the chart version. This version number should be incremented each time you make changes
# to the chart and its templates, including the app version.
# Versions are expected to follow Semantic Versioning (https://semver.org/)
version: 0.1.0

# This is the version number of the application being deployed. This version number should be
# incremented each time you make changes to the application. Versions are not expected to
# follow Semantic Versioning. They should reflect the version the application is using.
# It is recommended to use it with quotes.
appVersion: "1.16.0"

apiVersion, name, description, type, version, appVersion 필드를 입력 받습니다. 위 데이터는 helm create를 수행하면 자동으로 생성되는 데이터입니다. Chart.yaml 파일에는 차트의 기본적인 정보가 담기게 되므로, 실사용할 때는 잘 작성해두어야 합니다. 다만, 이 포스트에서는 Helm 차트를 직접 생성해본다는 데에 의의를 두고 있으므로, 심도 있게 다루지는 않겠습니다. 후에 다른 포스트에서 이 파일에 들어갈 수 있는 정보를 좀 더 다뤄보겠습니다.

values.yaml 수정

values.yaml 파일을 살펴보겠습니다. 사실 살펴볼 것도 없이 굉장히 명확합니다. 이 파일에 기록되는 데이터는 후에 설명 드릴 template 디렉터리 밑에 위치한 Manifest Template 파일들과 결합하여 실제 Kubernetes Manifest를 만들게 됩니다.

# Default values for wookiist.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.

replicaCount: 1

image:
  repository: nginx
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: ""

imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""

serviceAccount:
  # Specifies whether a service account should be created
  create: true
  # Annotations to add to the service account
  annotations: {}
  # The name of the service account to use.
  # If not set and create is true, a name is generated using the fullname template
  name: ""

podAnnotations: {}

podSecurityContext: {}
  # fsGroup: 2000

securityContext: {}
  # capabilities:
  #   drop:
  #   - ALL
  # readOnlyRootFilesystem: true
  # runAsNonRoot: true
  # runAsUser: 1000

service:
  type: ClusterIP
  port: 80

# 이하 생략 ...
  • replicaCount는 Pod를 몇 개 띄울지 지정하는 필드입니다. Deployment의 spec.replicas에 대응하는 값입니다.
  • image.repositoryspec.template.spec.containers.image 의 image tag를 제외한 앞 부분에 대응하는 값입니다.

Template 수정

Template 디렉터리에는 Kubernetes Manifest로 변환할 템플릿 파일들이 위치합니다. 이 파일들은 이 Chart를 통해 생성될 서비스의 전체 오브젝트에 해당합니다. 만약 ConfigMap을 생성해야 한다면, ConfigMap.yaml 을 생성해서 정의에 맞게끔 수정하여 넣어 두면 되는 식입니다. 또한 helm create를 통해서 생성했을 때의 Deployment 템플릿에는 들어있지 않은 필드를 추가해야 하는 경우 기존에 정의된 값들과 비슷하게 정의하면 됩니다. volume이나 env 등등이 이에 해당합니다. env를 예로 들면 이렇습니다.

env:
  {{- range .Values.env }}
  - name: {{ .name }}
    value: {{ .value }}
  {{- end }}

위 내용을 Deployment 파일에 추가해주면 됩니다. 물론, Deployment 파일의 형식은 지켜주셔야 합니다. env 필드는 spec.template.spec.containers.env 에 위치해야 합니다. 추가로 range는 해당 값이 리스트 형태로 정의되어 있을 때, 해당 리스트를 순회하면서 하나씩 데이터를 넣어주게 됩니다. 일종의 for문이라고 생각하시면 됩니다.

여기서 정의한 .Values.env 에 대응할 수 있도록 values.yaml 파일에도 env 필드를 추가해주어야 합니다. 예를 들어, values.yaml 에 다음과 같이 정의해두었다면, helm으로 Kubernetes Manifest를 생성했을 때, env 필드가 채워져서 들어가게 됩니다.

env:
- name: "IP"
  value: "192.168.1.1"
- name: "PORT"
  value: "8080"

중요한 것은 Helm을 사용하게 되면, Kubernetes Manifest의 직접 수정 없이 모든 것을 변수의 형태로 외부에서 정의할 수 있다는 것입니다.

Chart 활용하기

지금까지 생성한 차트를 활용하면 helm template을 이용해서 Kubernetes Manifest를 직접 생성해서 apply할 수도 있고, helm install을 이용해서 helm으로 애플리케이션을 배포할 수 있습니다.

참고

마무리

이렇게 오늘은 아주 간단하게만 helm chart를 생성하는 방법을 알아보았습니다. 너무 간단하게만 소개드린 것 같아 조금은 조심스러운 마음입니다. 추후 글을 추가로 올려서 자세한 방법을 소개해드리겠습니다.

여기까지 따라오시느라 고생 많으셨습니다. 만약 이 글이 도움이 되셨다면 글 좌측 하단의 하트❤를 눌러주시면 감사하겠습니다.

혹시라도 글에 이상이 있거나, 이해가 가지 않으시는 부분, 또는 추가적으로 궁금하신 내용이 있다면 주저 마시고 댓글💬을 남겨주세요! 빠른 시간 안에 답변을 드리겠습니다 😊

반응형