본문 바로가기

Helm (헬름)/Helm

Helm Chart 만들기 for kubernetes

# 간단한 Helm Chart를 생성하여 k8s 에 배포하는 작업을 해보자.

- k8s에서 수정한 코드를 배포하고 적용하는데 수분의 시간을 필요로 한다. 이유는 CI/CD를 태워야 하고, 해당 코드가 빌드가 되고 배포 및 적용하는데 까지 AWS CodeSeries를 기반으로 할때 10분 이상이 소요된다.

- 그리고 만약에 ConfigMap등의 정보를 변경하기라도 하게되면 매번 수동으로 하기엔 여간 번거로운 일이 아니다.

그래서 HelmChart를 활용하여 구성을 하면 보다 자유롭고 F/W화된 구성이 가능하다는 장점이 있다.

1. HelmChart 생성하기

- 여기서는 Seungkim 이라는 HelmChart를 생성해보자.

- Chart 생성 명령어는 아래와 같다.

만약 helm이 설치가 안되어 있다면, 아래의 링크를 통해 helm을 설치하자.

2023.02.20 - [Helm (헬름)/Helm] - windows10 에서 Helm을 설치해보자

 

windows10 에서 Helm을 설치해보자

# Windows10 에서 Helm을 설치하는 작업에 대해 알아보자. - 일단 Helm이 왜 필요하냐면, k8s에서 리소르를 패키지 형태로 제공하기 위해서는 Helm이 필요하다. - 일단 이정도로만 알고있고, Windows에서 Hel

may9noy.tistory.com

- Chart를 생성해보자. 여기서는 Seungkim이라는 Helm Chart를 생성할 예정이다. 아래와 같은 명령어를 통해 생성을 해보자.

- Helm Chart 생성

helm create 명령어를 사용해서 차트를 생성한다. helm create 명령을 이용해 만든 차트는 nginx를 예제로 하고 있고 아래와 같이 정상적으로 생성이 되었는지 확인한다. (일단은 cmd에서 실행해도 무방하고, git bash에서 생성해도 무방하다.)

$ helm create Seungkim
Creating Seungkim

- helm을 생성한 경로에 아래와 같이 폴더가 생성된 것을 확인 할 수 있다.

- 그리고 해당 폴더로 들어가보면 아래와 같이 기본 리소스가 생성되어 있는것을 확인 할 수 있다.

2. 다음 으로는 Chart.yaml 파일을 확인해보자.

- Chart.yaml 파일의 내용을 보면 아래와 같다.

파일의 내용을 보면 apiVersion, name, description, type, version, appVersion 필드를 값을 입력 받는다. Chart.yaml 파일에는 차트의 기본적인 정보가 담기게 되므로, 실사용할 때는 잘 작성해두어야 한다.

apiVersion: v2
name: Seungkim
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"

3. values.yaml 파일 수정하기

- values.yaml 파일을 살펴보면 이 파일에 기록되는 데이터는 후에 설명할 템플릿 디렉터리 밑에 위치한 Manifest Template 파일들과 결합하여 실제 Kubernetes Manifest를 만들게 된다.

- 여기서 주요 옵션을 살펴보면, replicaCount는 Pod를 몇 개 띄울지 지정하는 필드입니다. Deployment의 spec.replicas에 대응하는 값이다.

- image.repository는 spec.template.spec.containers.image 의 image tag를 제외한 앞 부분에 대응하는 값이다.

- values.yaml은 templates 디렉터리 내부에 있는 yaml 파일들을 작성할 때 동일한 값들을 하드코딩하지 않고 values.yaml에 설정한 변수를 통해 일괄적으로 사용할 수 있다. 예를들어 아래와 같이 values.yaml을 작성 했을때,

name: testapp
image:
  repository: nginx
  
service:
  type: ClusterIP
  port: 80

templates 디렉터리 내부 yaml 파일에서 testapp을 {{ .Values.name }}으로, nginx란 값을 {{ .Values.image.repository }}로 대체하여 작성할 수 있다. 또한, ClusterIP의 경우 {{ .Values.service.type }} 으로 작성하면 된다.

deployment, service, ingress 등 yaml 파일을 작성할 때 동일한 값이 많이 존재하는데, 이러한 값들을 values.yaml에 정의해놓으면 값을 모두 찾아 수정할 필요 없이 values.yaml에서의 값만 바꿔주면 되므로 편리하다.

# Default values for Seungkim.
# 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

ingress:
  enabled: false
  className: ""
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  hosts:
    - host: chart-example.local
      paths:
        - path: /
          pathType: ImplementationSpecific
  tls: []
  #  - secretName: chart-example-tls
  #    hosts:
  #      - chart-example.local

resources: {}
  # We usually recommend not to specify default resources and to leave this as a conscious
  # choice for the user. This also increases chances charts run on environments with little
  # resources, such as Minikube. If you do want to specify resources, uncomment the following
  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
  # limits:
  #   cpu: 100m
  #   memory: 128Mi
  # requests:
  #   cpu: 100m
  #   memory: 128Mi

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80
  # targetMemoryUtilizationPercentage: 80

nodeSelector: {}

tolerations: []

affinity: {}

Template 수정

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

한마디로, Kubernetes 애플리케이션 배포를 위해 작성해두었던 deployment.yaml, service.yaml, ingress.yaml 파일들을 helm templates 폴더 내부에 넣어주면 된다.

(참고로, 각각의 deployment.yaml, service.yaml, ingress.yaml 파일이 아닌 deployment.yaml 하나의 파일 내에 --- 로 구분하여 모든 내용을 작성해도 된다.)

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.100.100"
- name: "PORT"
  value: "8080"

중요한 것은 Helm을 사용하게 되면, Kubernetes Manifest의 직접 수정 없이 모든 것을 변수의 형태로 외부에서 정의할 수 있다는 것인데 추후에 적용을 진행해 보자.

Chart 활용

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

다음 가이드에서는 Chart를 활용한 애플리케이션 배포와 Chart Museum에 대해서도 알아보자.