
쿠버네티스에서는 리소스를 배포할 때 yaml형식의 매니페스트 파일을 통해 내용들을 정의한다.
단일 Pod, Deployment 같은 간단한 배포의 경우 작성해야 할 yaml파일이 많지 않지만 sa, pvc, clusterrole 등 여러 가지 리소스들을 활용하여 배포해야 할 경우 이를 모두 일일이 작성하고 관리한다면 매우 비효율적일 것이다.
이러한 불편함을 해소하기 위해 만들어진 것이 Helm이다.
Helm 이란?
Helm은 쿠버네티스 패키지 관리자로 CNCF의 졸업 프로젝트이며 Linux의 yum/apt
, Node.js의 npm
처럼 패키지들을 쿠버네티스에 쉽게 배포할 수 있도록 도와준다.
아래는 Helm을 이용하면 얻을 수 있는 장점이다.
- 여러 개의 쿠버네티스 리소스들을 간편하게 배포 가능하
- Helm Chart라는 동일한 템플릿을 이용하기 때문에 커뮤니티, 인터넷에서 정보가 많음
- 배포된 리소스들을 일관성 있게 파악하고 관리할 수 있음
- 버전 관리 기능을 통해 Rollback 등 유연하게 배포가 가능
먼저 간단하게 Helm의 구조를 알아보자. 아래는 Wordpress를 배포하는 Helm Chrat 구조의 예시이다.
wordpress/
ㄴChart.yaml # 차트에 대한 정보를 가진 YAML 파일
ㄴLICENSE # 옵션: 차트의 라이센스 정보를 가진 텍스트 파일
ㄴREADME.md # 옵션: README 파일
ㄴvalues.yaml # 차트에 대한 기본 환경설정 값들
ㄴvalues.schema.json # 옵션: values.yaml 파일의 구조를 제약하는 JSON 파일
ㄴcharts/ # 이 차트에 종속된 차트들을 포함하는 디렉터리
ㄴtemplates/ # values와 결합될 때, 유효한 쿠버네티스 manifest 파일들이 생성될 템플릿들의 디렉터리
기존 레거시 배포와 다르게 리소스 배포를 간편하게 할 수 있는 이유는 미리 템플릿화 된 Helm Chart 구조를 이용해 필요한 정보만 입력하여 배포할 수 있기 때문이다.
templates
디렉토리 안을 보면 리소스 배포에 필요한 매니페스트 파일들이 모여있는 걸 볼 수 있다.
$ ls -l
total 124
-rw-r--r-- 1 user user 4686 Dec 23 05:28 NOTES.txt
-rw-r--r-- 1 user user 9463 Dec 23 05:28 _helpers.tpl
-rw-r--r-- 1 user user 686 Dec 23 05:28 config-secret.yaml
-rw-r--r-- 1 user user 20605 Dec 23 05:28 deployment.yaml
-rw-r--r-- 1 user user 740 Dec 23 05:28 externaldb-secrets.yaml
-rw-r--r-- 1 user user 189 Dec 23 05:28 extra-list.yaml
-rw-r--r-- 1 user user 1774 Dec 23 05:28 hpa.yaml
-rw-r--r-- 1 user user 705 Dec 23 05:28 httpd-configmap.yaml
-rw-r--r-- 1 user user 3223 Dec 23 05:28 ingress.yaml
-rw-r--r-- 1 user user 1193 Dec 23 05:28 metrics-svc.yaml
-rw-r--r-- 1 user user 1407 Dec 23 05:28 networkpolicy-backend-ingress.yaml
-rw-r--r-- 1 user user 1316 Dec 23 05:28 networkpolicy-egress.yaml
-rw-r--r-- 1 user user 3632 Dec 23 05:28 networkpolicy-ingress.yaml
-rw-r--r-- 1 user user 1074 Dec 23 05:28 pdb.yaml
-rw-r--r-- 1 user user 1978 Dec 23 05:28 postinit-configmap.yaml
-rw-r--r-- 1 user user 1573 Dec 23 05:28 pvc.yaml
-rw-r--r-- 1 user user 1076 Dec 23 05:28 secrets.yaml
-rw-r--r-- 1 user user 835 Dec 23 05:28 serviceaccount.yaml
-rw-r--r-- 1 user user 1956 Dec 23 05:28 servicemonitor.yaml
-rw-r--r-- 1 user user 2985 Dec 23 05:28 svc.yaml
-rw-r--r-- 1 user user 1808 Dec 23 05:28 tls-secrets.yaml
파일들 중 svc.yaml
을 예시로 확인해보면 값들이 대부분 변수처리 되어 있다.
apiVersion: v1
kind: Service
metadata:
name: {{ include "common.names.fullname" . }}
namespace: {{ .Release.Namespace | quote }}
labels: {{- include "common.labels.standard" ( dict "customLabels" .Values.commonLabels "context" $ ) | nindent 4 }}
{{- if or .Values.service.annotations .Values.commonAnnotations }}
{{- $annotations := include "common.tplvalues.merge" ( dict "values" ( list .Values.service.annotations .Values.commonAnnotations ) "context" . ) }}
annotations: {{- include "common.tplvalues.render" ( dict "value" $annotations "context" $) | nindent 4 }}
{{- end }}
spec:
type: {{ .Values.service.type }}
{{- if and .Values.service.clusterIP (eq .Values.service.type "ClusterIP") }}
clusterIP: {{ .Values.service.clusterIP }}
{{- end }}
{{- if or (eq .Values.service.type "LoadBalancer") (eq .Values.service.type "NodePort") }}
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy | quote }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerSourceRanges)) }}
loadBalancerSourceRanges: {{ .Values.service.loadBalancerSourceRanges }}
{{- end }}
{{- if and (eq .Values.service.type "LoadBalancer") (not (empty .Values.service.loadBalancerIP)) }}
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
{{- end }}
{{- if .Values.service.sessionAffinity }}
sessionAffinity: {{ .Values.service.sessionAffinity }}
{{- end }}
{{- if .Values.service.sessionAffinityConfig }}
sessionAffinityConfig: {{- include "common.tplvalues.render" (dict "value" .Values.service.sessionAffinityConfig "context" $) | nindent 4 }}
{{- end }}
ports:
- name: http
port: {{ .Values.service.ports.http }}
protocol: TCP
targetPort: http
{{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.http))) }}
nodePort: {{ .Values.service.nodePorts.http }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
- name: https
port: {{ .Values.service.ports.https }}
protocol: TCP
targetPort: {{ .Values.service.httpsTargetPort }}
{{- if (and (or (eq .Values.service.type "NodePort") (eq .Values.service.type "LoadBalancer")) (not (empty .Values.service.nodePorts.https))) }}
nodePort: {{ .Values.service.nodePorts.https }}
{{- else if eq .Values.service.type "ClusterIP" }}
nodePort: null
{{- end }}
{{- if .Values.service.extraPorts }}
{{- include "common.tplvalues.render" (dict "value" .Values.service.extraPorts "context" $) | nindent 4 }}
{{- end }}
{{- $podLabels := include "common.tplvalues.merge" ( dict "values" ( list .Values.podLabels .Values.commonLabels ) "context" . ) }}
selector: {{- include "common.labels.matchLabels" ( dict "customLabels" $podLabels "context" $ ) | nindent 4 }}
해당 값들은 Helm Chart에서 최상위 경로에 있는 values.yaml
파일에 선언되어 있는 값을 참조하게 되어있다.
때문에 사용자 입장에서는 복잡한 설정 없이 Chart에서 제공하는 values.yaml
파일만 입력해서 배포가 가능한 것이다.
values.yaml
파일은 아래 내용처럼 구성되어 있다.
global:
imageRegistry: ""
## E.g.
## imagePullSecrets:
## - myRegistryKeySecretName
##
imagePullSecrets: []
storageClass: ""
## @section Common parameters
##
## @param kubeVersion Override Kubernetes version
##
kubeVersion: ""
## @param nameOverride String to partially override common.names.fullname template (will maintain the release name)
##
nameOverride: ""
## @param fullnameOverride String to fully override common.names.fullname template
##
fullnameOverride: ""
## @param commonLabels Labels to add to all deployed resources
##
commonLabels: {}
## @param commonAnnotations Annotations to add to all deployed resources
##
commonAnnotations: {}
## @param clusterDomain Kubernetes Cluster Domain
##
clusterDomain: cluster.local
## @param extraDeploy Array of extra objects to deploy with the release
##
extraDeploy: []
## Enable diagnostic mode in the deployment
##
diagnosticMode:
## @param diagnosticMode.enabled Enable diagnostic mode (all probes will be disabled and the command will be overridden)
##
enabled: false
## @param diagnosticMode.command Command to override all containers in the deployment
##
command:
- sleep
## @param diagnosticMode.args Args to override all containers in the deployment
##
args:
- infinity
Chart에서 필요한 설정값들에 대한 형식은 기본적으로 제공되기 때문에 값에 대한 내용만 사용자가 입력해 주면 각 리소스 yaml에 적용되어 배포된다.
Helm 설치하기
쿠버네티스에서 Helm으로 리소스를 배포해 보기 위해 먼저 Helm 바이너리를 설치한다.
- 스크립트로 설치하기
$ curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
$ chmod 700 get_helm.sh
$ ./get_helm.sh
스크립트 설치 이외에 패키지 매니저(apt, yum 등)를 통해서도 설치 가능하다.
자세한 내용은 여기를 참고하면 된다.
- 버전 확인
현재 Helm은 Version 3
로 릴리스 되고 있기 때문에 3.13.1
버전이 설치되었다.(2023년 12월 31일 기준)
$ helm version
version.BuildInfo{Version:"v3.13.1", GitCommit:"3547a4b5bf5edb5478ce352e18858d8a552a4110", GitTreeState:"clean", GoVersion:"go1.20.8"}
서비스 배포하기
Helm을 통해 서비스를 배포하기 위해서는 아래의 과정들을 거치게 된다.
과정내용 중 Helm repo는 원하는 Chart를 사용하기 위해 필수로 해야 하며 Chart 다운이나 values.yaml
작성의 경우 기본으로 제공되는 내용들을 수정할 필요가 있을 때만 수행하면 된다.
아래 예시에서는 커스텀 values 파일을 이용한 Apache
설치를 진행해 본다.
- Helm repo 추가
$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories
helm repo list
명령어로 현재 추가된 Helm repository의 목록을 확인할 수 있다.
$ helm repo list
NAME URL
bitnami https://charts.bitnami.com/bitnami
- Helm chart 다운
$ helm pull bitnami/apache
$ tar -xvf apache-10.2.4.tgz
$ ls -l
total 36
drwxr-xr-x 1 user user 4096 Dec 31 12:48 apache
-rw-r--r-- 1 user user 35248 Dec 31 12:47 apache-10.2.4.tgz
- values.yaml 작성
기본으로 제공되는 values.yaml
파일 내용 중 resource와 관련된 부분을 재정의 해본다.
$ vi values.yaml
#아래 내용을 작성
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
- Helm install
설치에 사용하는 명령어 형식은 helm install <배포할 리소스 이름> <다운로드 한 Chart 디렉토리>
이다.
위에서 정의한 커스텀 values.yaml
파일을 사용하기 위해 -f
옵션으로 파일을 지정해 주어 설치를 진행한다.
추가로 values.yaml 파일을 커스텀할 필요 없이 기본 제공되는 내용으로 배포해도 된다면 chart를 로컬에 다운하지 않고 helm install <배포할 리소스 이름> <온라인 차트 경로>
를 통해 바로 배포할 수도 있다.
$ helm install apache-helm apache -f values.yaml
NAME: apache-helm
LAST DEPLOYED: Sun Dec 31 13:27:49 2023
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: apache
CHART VERSION: 10.2.4
APP VERSION: 2.4.58
** Please be patient while the chart is being deployed **
1. Get the Apache URL by running:
** Please ensure an external IP is associated to the apache-helm service before proceeding **
** Watch the status using: kubectl get svc --namespace default -w apache-helm **
export SERVICE_IP=$(kubectl get svc --namespace default apache-helm --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
echo URL : http://$SERVICE_IP/
WARNING: You did not provide a custom web application. Apache will be deployed with a default page. Check the README section "Deploying your custom web application" in https://github.com/bitnami/charts/blob/main/bitnami/apache/README.md#deploying-a-custom-web-application.
잘 설치되었는지 Pod 목록을 출력하여 확인한다.
$ kubectl get pod -A
NAMESPACE NAME READY STATUS RESTARTS AGE
default apache-helm-5f44d895d5-rps6x 1/1 Running 0 64s
helm list
명령으로도 배포된 리소스 목록을 확인할 수 있다.
해당 명령 같은 경우 네임스페이스의 영향을 받기 때문에 모든 네임스페이스에서 리소스를 검색하도록 -A
옵션을 사용했다.
$ helm list -A
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
apache-helm default 1 Sun Dec 31 13:27:49.7209287 +0900 KST deployed apache-10.2.4 2.4.58
커스텀 values.yaml
파일에 작성한 내용이 실제 배포에도 적용되었는지 확인한다.
$ kubectl edit pod apache-helm-5f44d895d5-rps6x
작성한 내용대로 배포된 Pod의 리소스가 적용된 것을 볼 수 있다.
Rollback 기능 활용하기
위에서 설명한 대로 Helm으로 배포한 서비스는 버전(Revision)이 부여되어 버전관리가 가능하다.
그리고 이 버전을 통해 서비스를 Rollback 할 수 있는 기능을 지원한다.
현재 배포된 Apache 서비스의 버전 정보를 확인해 보자.
$ helm history apache-helm
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sun Dec 31 13:27:49 2023 deployed apache-10.2.4 2.4.58 Install complete
Revision은 1
로 지정되었으며 Status가 배포 완료 상태임을 알 수 있다.
두 번째 배포를 위해 이번에는 이미지 버전을 변경하여 재배포해본다.
$ vi values.yaml
resources:
limits:
cpu: 200m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
#아래 내용 추가
image:
registry: docker.io
repository: bitnami/apache
tag: 2.4-debian-11
pullPolicy: IfNotPresent
재배포할 때는 helm upgrade
라는 명령을 이용한다.
$ helm upgrade apache-helm apache -f values.yaml
Release "apache-helm" has been upgraded. Happy Helming!
NAME: apache-helm
LAST DEPLOYED: Sun Dec 31 13:28:26 2023
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
CHART NAME: apache
CHART VERSION: 10.2.4
APP VERSION: 2.4.58
** Please be patient while the chart is being deployed **
1. Get the Apache URL by running:
** Please ensure an external IP is associated to the apache-helm service before proceeding **
** Watch the status using: kubectl get svc --namespace default -w apache-helm **
export SERVICE_IP=$(kubectl get svc --namespace default apache-helm --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
echo URL : http://$SERVICE_IP/
WARNING: You did not provide a custom web application. Apache will be deployed with a default page. Check the README section "Deploying your custom web application" in https://github.com/bitnami/charts/blob/main/bitnami/apache/README.md#deploying-a-custom-web-application.
WARNING: Rolling tag detected (bitnami/apache:2.4-debian-11), please note that it is strongly recommended to avoid using rolling tags in a production environment.
+info https://docs.bitnami.com/containers/how-to/understand-rolling-tags-containers/
helm 명령어를 통해 history를 다시 확인해 보자.
$ helm history apache-helm
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sun Dec 31 13:27:49 2023 superseded apache-10.2.4 2.4.58 Install complete
2 Sun Dec 31 13:28:26 2023 deployed apache-10.2.4 2.4.58 Upgrade complete
Revision 1
번 배포는 superseded
로 상태가 바뀌고 Revision 2
의 배포가 완료되었음을 확인할 수 있다.
values.yaml
에서 변경해 두었던 이미지 버전이 잘 적용되었는지 확인해 본다.
Apache 2.4.58
버전 이미지를 사용했던 Revision1에서 Apache 2.4
버전 이미지를 사용하는 Revision 2
로 업데이트되어 배포되었음을 확인할 수 있다.
이제 Revision 2
에서 다시 Revision 1
으로 Rollback 해서 첫 배포 상태로 되돌려본다.
명령어는 helm rollback <배포한 리소스 이름> <Release 번호>
형식으로 사용하면 된다.
$ helm rollback apache-helm 1
Rollback was a success! Happy Helming!
이후 새로 배포된 Pod의 이미지 버전이 다시 2.4.58
로 되어있는지 확인해 본다.
$ kubectl get pod apache-helm-5f44d895d5-nr5rv -o yaml | grep image
image: docker.io/bitnami/apache:2.4.58-debian-11-r3
imagePullPolicy: IfNotPresent
정상적으로 첫 배포 상황으로 Rollback이 이루어진 것을 확인할 수 있다.
참고자료
Helm Rollback
헬름 - 쿠버네티스 패키지 매니저
helm.sh
'Kubernetes' 카테고리의 다른 글
Kubeadm으로 쿠버네티스 설치하기 (0) | 2024.01.14 |
---|---|
Ingress를 활용하여 웹 트래픽 제어하기 (0) | 2024.01.06 |
쿠버네티스 컨트롤러 알아보기 (0) | 2023.12.17 |
AKS를 사용하여 쿠버네티스 구성하기 (0) | 2023.12.10 |
관리형 쿠버네티스 알아보기 (0) | 2023.12.03 |