차트 생성하기(Create Helm)

헬름 + 쿠버네티스 가이드북
이민석's avatar
Apr 30, 2024
차트 생성하기(Create Helm)

헬름 + 쿠버네티스 가이드북은 Bharath Thippireddy의 Helm Kubernetes Packaging Manager for Developers and DevOps을 보고 작성되었습니다.

가이드북의 전체 목차 및 인덱싱은 헬름 + 쿠버네티스 가이드북 문서를 참고해주세요.

사전 지식

  1. 필수 프로그램 설치 및 환경 구성

필수 프로그램 설치 및 환경 구성

Unchaptered (Blog) | 헬름 작동 과정(Helm in Action)에서 언급한 기본적인 Helm, Kubernetes-CLI(KUBECONFIG) 등이 완료된 상태로 진행해주세요.

헬름 차트 생성 및 사용

헬름 차트는 쿠버네티스 어플리케이션을 쉽게 패키징하고 배포하기 위한 도구입니다. 헬름 차트로 탬플릿화된 쿠버네티스 manifest 파일들의 모음을 구성하고 관리할 수 있습니다.

  1. 헬름 차트 만들기

  2. 헬름 차트로 설치하기

핼름 차트 만들기

  1. 헬름 차트 생성하기

    helm create firstchart
  2. 폴더 이동하기

    cd firstchart
  3. 파일 조회하기

    ls
    
    # Output
    
    Mode                 LastWriteTime         Length Name
    ----                 -------------         ------ ----
    d-----      2024-04-30  오후 11:37                charts
    d-----      2024-04-30  오후 11:37                templates
    -a----      2024-04-30  오후 11:37            349 .helmignore
    -a----      2024-04-30  오후 11:37           1146 Chart.yaml
    -a----      2024-04-30  오후 11:37           2363 values.yaml

헬름 차트로 설치하기

헬름 차트 만들기 이후에 진행하였습니다.

  1. 헬름 차트로 릴리즈하기

    1. 명령어

      helm install firstapp firstchart
    2. 결과

      NAME: firstapp
      LAST DEPLOYED: Wed May  1 13:23:56 2024
      NAMESPACE: default
      STATUS: deployed
      REVISION: 1
      NOTES:
      1. Get the application URL by running these commands:
        export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=firstchart,app.kubernetes.io/instance=firstapp" -o jsonpath="{.items[0].metadata.name}")
        export CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")
        echo "Visit http://127.0.0.1:8080 to use your application"
        kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

  1. 헬름 팟 네임 조회하기

    1. 네임 스페이스

      kubectl get pods --namespace default
    2. 네임 스페이스 + 라벨 셀렉터

      kubectl get pods --namespace default -l "app.kubernetes.io/name=firstchart,app.kubernetes.io/instance=firstapp"
    3. 네임 스페이스 + 라벨 셀렉터 + 전체 조회

      kubectl get pods --namespace default -l "app.kubernetes.io/name=firstchart,app.kubernetes.io/instance=firstapp" -o jsonpath="{.items}" | jq
    4. 네임 스페이스 + 라벨 셀렉터 + 1개 조회

      kubectl get pods --namespace default -l "app.kubernetes.io/name=firstchart,app.kubernetes.io/instance=firstapp" -o jsonpath="{.items[0]}" | jq
    5. 네임 스페이스 + 라벨 셀렉터 + 1개 조회 + 이름만 조회

      kubectl get pods --namespace default -l "app.kubernetes.io/name=firstchart,app.kubernetes.io/instance=firstapp" -o jsonpath="{.items[0].metadata.name}"

  1. 헬름 팟 네임 변수 등록하기 (필수)

    릴리즈 노트에서 나오는 구문 중에 export 로 임시변수를 선언하는 부분이 있습니다. 이 부분은 운영체제마다 다르게 적용됩니다.

    1. MacOS/Linux

        export POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=firstchart,app.kubernetes.io/instance=firstapp" -o jsonpath="{.items[0].metadata.name}")
    2. Windows Powershell

      $POD_NAME=$(kubectl get pods --namespace default -l "app.kubernetes.io/name=firstchart,app.kubernetes.io/instance=firstapp" -o jsonpath="{.items[0].metadata.name}")

  1. 헬름 팟 포트 조회하기

    1. 헬름 팟

      kubectl get pod --namespace default $POD_NAME
    2. 헬름 팟 + 헬름 팟 구성요소

      kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec}" | jq
    3. 헬름 팟 + 헬름 팟 구성요소 + 컨테이너 구성요소

      kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers}" | jq 
    4. 헬름 팟 + 헬름 팟 구성요소 + 컨테이너 구성요소 + 컨테이너 별 포 트 메타데이터

      kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[*].ports}" | jq
    5. 헬름 팟 + 헬름 팟 구성요소 + 컨테이너 구성요소 + 컨테이너 별 포트 메타데이터 + 컨테이너 별 포트

      kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[*].ports[*].containerPort}" | jq

  1. 헬름 팟 포트 변수 등록하기 (필수)

     $CONTAINER_PORT=$(kubectl get pod --namespace default $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}")

  1. 헬름 포트포워딩 하기 (필수)

    kubectl --namespace default port-forward $POD_NAME 8080:$CONTAINER_PORT

  1. NGINX 접속해보기 (테스트, 필수)

    curl http://localhost:8080

헬름 차트 분석

여러 번에 걸쳐서 말했던 것 처럼 헬름은 쿠버네티스 패키지 관리자입니다. 헬름 차트는 헬름을 파일 형태로 기록한 것입니다.

  1. Chart.yaml

  2. templates/deployment.yaml

  3. templates/_helpers.tpl

  4. values.yaml

Chart.yaml

헬름 차트를 생성하면 나오는 Chart.yaml 파일은 차트에 대한 정보를 가진 YAML 파일입니다.

  • (필수) 기본 차트 구조

    apiVersion: v2  # Helm API 버전 지정
    name: firstchart  # 차트의 이름 지정
    description: 쿠버네티스를 위한 헬름 차트  # 차트에 대한 설명
    
    # 차트의 종류를 나타내는 속성
    # 가능한 값:
    # - application
    # - library
    # - plugin
    type: application  
    
    version: 0.1.0  # 차트의 버전
    appVersion: "1.16.0"  # 애플리케이션의 실제 버전

  • (선택) 옵션 요소

    Chart.yaml의 (필수) 기본 차트 구조에 추가할 수 있는 옵션들입니다.

    icon: http://www.bharaththippireddy.com/project.jpg
    
    keywords:
      - sample
      - example
    
    home: http://www.bharaththippireddy.com/
    
    sources:
      - http:///www.bharaththippireddy.com
      - /www.bharaththippireddy.com
    
    maintainers:
      - name: unchaptered
        email: workstation19961002@gmail.com
    
      - name: John
        email: test@test.com

templates/deployment.yaml

templates/는 values와 결합될 때, 유효한 쿠버네티스 manifest 파일들이 생성될 탬플릿들의 디렉토리입니다.
여기서 templates/deployment.yaml는 deployment 오브젝트를 배포하기 위한 탬플릿 파일입니다.

  • (기본) 기본 구성 요소

    이중 브라켓 {{ }} 안에는 고 탬플릿 문법(Go Template Syntax)으로 작성되어 있습니다.

    이 문법은 Go Template Preview 사이트를 통해서 연습할 수 있습니다.

    apiVersion: apps/v1  # 이 리소스의 API 버전
    kind: Deployment  # 이 리소스의 종류 (여기서는 Deployment)
    
    metadata:  # 리소스의 메타데이터 섹션
      name: {{ include "firstchart.fullname" . }}  # 리소스의 이름을 Helm 템플릿으로 동적으로 설정
      labels:  # 리소스의 레이블 섹션
        {{- include "firstchart.labels" . | nindent 4 }}  # Helm 템플릿을 사용하여 레이블을 동적으로 설정
    
    spec:  # Deployment의 스펙 섹션
      {{- if not .Values.autoscaling.enabled }}  # autoscaling이 비활성화되어 있지 않은 경우에만 아래 라인을 포함
    
      replicas: {{ .Values.replicaCount }}  # 복제본 수를 Helm 값으로 설정
      {{- end }}
    
      selector:  # 파드 선택기
        matchLabels:  # 선택된 파드와 매치할 레이블
          {{- include "firstchart.selectorLabels" . | nindent 6 }}  # Helm 템플릿을 사용하여 선택기 레이블을 동적으로 설정
    
      template:  # 파드 템플릿 정의
        metadata:  # 파드의 메타데이터 섹션
          {{- with .Values.podAnnotations }}  # 파드 어노테이션 값이 있는 경우에만 아래 라인을 포함
    
          annotations:  # 파드의 어노테이션 섹션
            {{- toYaml . | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 어노테이션에 적용
          {{- end }}
    
          labels:  # 파드의 레이블 섹션
            {{- include "firstchart.labels" . | nindent 8 }}  # Helm 템플릿을 사용하여 레이블을 동적으로 설정
            {{- with .Values.podLabels }}  # 추가 파드 레이블 값이 있는 경우에만 아래 라인을 포함
            {{- toYaml . | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 추가 레이블에 적용
            {{- end }}
    
        spec:  # 파드 스펙 섹션
          {{- with .Values.imagePullSecrets }}  # 이미지 풀 시크릿 값이 있는 경우에만 아래 라인을 포함
    
          imagePullSecrets:  # 이미지 풀 시크릿 목록
            {{- toYaml . | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 이미지 풀 시크릿에 적용
          {{- end }}
    
          serviceAccountName: {{ include "firstchart.serviceAccountName" . }}  # 서비스 계정 이름을 Helm 템플릿으로 동적으로 설정
    
          securityContext:  # 파드 보안 컨텍스트
            {{- toYaml .Values.podSecurityContext | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 보안 컨텍스트에 적용
    
          containers:  # 파드 내의 컨테이너 목록
    
            - name: {{ .Chart.Name }}  # 컨테이너 이름을 Helm 템플릿으로 동적으로 설정
    
              securityContext:  # 컨테이너 보안 컨텍스트
                {{- toYaml .Values.securityContext | nindent 12 }}  # Helm 값을 YAML 형식으로 변환하여 보안 컨텍스트에 적용
    
              image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"  # 이미지 및 버전을 Helm 값으로 설정
    
              imagePullPolicy: {{ .Values.image.pullPolicy }}  # 이미지 풀 정책을 Helm 값으로 설정
    
              ports:  # 컨테이너 내의 포트 목록
                - name: http  # 포트의 이름
                  containerPort: {{ .Values.service.port }}  # 컨테이너 포트
                  protocol: TCP  # 프로토콜
    
              livenessProbe:  # Liveness 프로브 섹션
                {{- toYaml .Values.livenessProbe | nindent 12 }}  # Helm 값을 YAML 형식으로 변환하여 Liveness 프로브에 적용
    
              readinessProbe:  # Readiness 프로브 섹션
                {{- toYaml .Values.readinessProbe | nindent 12 }}  # Helm 값을 YAML 형식으로 변환하여 Readiness 프로브에 적용
    
              resources:  # 컨테이너의 리소스 섹션
                {{- toYaml .Values.resources | nindent 12 }}  # Helm 값을 YAML 형식으로 변환하여 리소스에 적용
              {{- with .Values.volumeMounts }}  # 볼륨 마운트 값이 있는 경우에만 아래 라인을 포함
    
              volumeMounts:  # 볼륨 마운트 목록
                {{- toYaml . | nindent 12 }}  # Helm 값을 YAML 형식으로 변환하여 볼륨 마운트에 적용
              {{- end }}
    
          {{- with .Values.volumes }}  # 볼륨 값이 있는 경우에만 아래 라인을 포함
    
          volumes:  # 파드의 볼륨 목록
            {{- toYaml . | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 볼륨에 적용
          {{- end }}
          {{- with .Values.nodeSelector }}  # 노드 선택자 값이 있는 경우에만 아래 라인을 포함
    
          nodeSelector:  # 파드에 대한 노드 선택자
            {{- toYaml . | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 노드 선택자에 적용
          {{- end }}
          {{- with .Values.affinity }}  # 어피니티 값이 있는 경우에만 아래 라인을 포함
     
          affinity:  # 파드에 대한 어피니티 섹션
            {{- toYaml .Values.affinity | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 어피니티에 적용
    
          {{- with .Values.tolerations }}  # 허용 조건 값이 있는 경우에만 아래 라인을 포함
     
          tolerations:  # 허용 조건 목록
            {{- toYaml . | nindent 8 }}  # Helm 값을 YAML 형식으로 변환하여 허용 조건에 적용
          {{- end }}  # tolerations 섹션 마무리

templates/_helpers.tpl

templates/_helpers.tpl은 차트 전체에서 다시 사용 가능한 탬플릿 핼퍼를 제공하는 공간입니다. 이 파일은 VSC의 익스텐션, Go Template Support(ID : jinliming2.vscode-go-template)을 사용하는 것으로 편하게 볼 수 있습니다.

{{/*
Expand the name of the chart.
*/}}
{{- define "firstchart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "firstchart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "firstchart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}

{{/*
Common labels
*/}}
{{- define "firstchart.labels" -}}
helm.sh/chart: {{ include "firstchart.chart" . }}
{{ include "firstchart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}

{{/*
Selector labels
*/}}
{{- define "firstchart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "firstchart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}

{{/*
Create the name of the service account to use
*/}}
{{- define "firstchart.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "firstchart.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

values.yaml

values.yaml파일은 차트의 기본값을 포함하고 있다.
이 파일은 helm install 혹은 helm upgrade 과정에 사용자 재정의가 가능하다.

replicaCount: 1  # 파드의 복제본 수 설정

image:
  repository: nginx  # 사용할 이미지의 저장소 설정
  pullPolicy: IfNotPresent  # 이미지 풀링 정책 설정
  tag: ""  # 사용할 이미지의 태그 설정 (비어있는 경우)

service:
  type: ClusterIP  # 서비스 유형 설정
  port: 80  # 서비스 포트 설정

ingress:
  enabled: false  # 인그레스 활성화 여부 설정
  className: ""  # 인그레스 클래스 설정
  annotations: {}  # 인그레스에 대한 주석 설정
  hosts:  # 호스트 설정
    - host: chart-example.local  # 사용할 호스트명
      paths:  # 경로 설정
        - path: /  # 경로
          pathType: ImplementationSpecific  # 경로 타입
  tls: []  # TLS 설정

autoscaling:
  enabled: false  # 오토스케일링 활성화 여부 설정
  minReplicas: 1  # 최소 복제본 수 설정
  maxReplicas: 100  # 최대 복제본 수 설정
  targetCPUUtilizationPercentage: 80  # 대상 CPU 사용률 설정

volumes: []  # 볼륨 설정 (비어있음)

volumeMounts: []  # 볼륨 마운트 설정 (비어있음)

nodeSelector: {}  # 노드 선택자 설정 (비어있음)

tolerations: []  # 허용 설정 (비어있음)

affinity: {}  # 어피니티 설정 (비어있음)

실무 전략

헬름 차트를 현업 워크로드에서 사용가능하게 만들어주는 몇 가지 전략에 대해서 소개합니다.

  1. 핼름 패키지(helm package)

  2. 헬름 이그노어(.helmignore)

헬름 패키지(helm package)

  1. 패키지하기

    1. 문법

      helm package <RELEASE_NAME>
    2. 미리보기

      helm package firstchart

  1. 파일 조회하기

    ~\sample> ls | grep -e "first"
    d-----        2024-04-30  ?? 11:37                firstchart
    -a----        2024-05-01   ?? 2:48           4065 firstchart-0.1.0.tgz

  1. 하위 종속성 파일 모두 업데이트 + 패키지하기

    1. 문법

      helm package <RELEASE_NAME> -u
    2. 미리보기

      helm package firstchart -u

  1. 압축 파일 경로 지정 + 패키지하기

    1. 문법

      helm package <RELEASE_NAME> -d <FOLDER_DESTINATION>
    2. 미리보기

      helm package firstchart ./output/

헬름 이그노어(helm ignore)

.gitignore와 같은 방식으로 헬름 이그노어(.helmignore)를 사용할 수 있다. .helmignore에 있는 파일은 헬름 패키지(helm package) 시, 해당 파일이 제외된다.

헬름 공식 사이트에 The .helmignore Guide가 존재한다.

헬름 린트(helm lint)

Chart.yaml가 포한된 디렉토리에서 helm lint 명령어를 통해서 파일의 유효성 검사를 진행할 수 있습니다.

결론

헬름 차트를 이용해서 핼름을 더욱 스마트하게 쓸 수 있다.

  1. 헬름 차트 전 : helm install <릴리즈네임> <오너>/<차트이름> 등을 활용한 설치

  2. 헬름 차트 후 : helm install <릴리즈네임> <차트이름> 등을 활용한 탬플릿화된 설치

Share article

Unchaptered