FrameWorks/Kubernetes

[Kubernetes] Helm과 Kustomize 비교하며 사용하기

ABCD 2025. 3. 14.

목차

Helm과 Kustomize

공통점

중복 관리의 최소화

예를 들면 MSA환경에서 우리는 배포를 하기 위해 여러개의 .yaml파일이 필요할 겁니다.
환경은 비슷하기 때문에 .yaml파일에서 몇가지만 수정하면 되지만, 운영환경마다 또 여러개의 .yaml파일이 필요할 겁니다. 많은 MSA이 있고 다양한 운영환경이 있다면 N * M의 개수로 파일을 직접 만들어야 겠죠??

 

이를 방지하기 위해 하나의 파일로 명령어를 날려 .yaml파일을 자동으로 만들어주는 기능을 합니다.

다양한 배포 툴에서 지원

argo, github action 등의 다양한 오픈소스 라이브러리들을 사용할 수 있다는 점도 공통입니다.

차이점

  Helm Kustomize
배포 편의기능 갯수 200개 10개
한 패키지 당 활용 범위 마이크로 서비스 AND 다양한 배표 환경 마이크로 서비스 OR 다양한 배표 환경
사용 목적 프로젝트관리 패키징, 기업 제품 패키징 프로젝트관리 패키징
유즈케이스 대형 프로젝트, App 종류 5개 이상 간단한 프로젝트, App 종류 5개 미만

함수 방식의 Helm

Helm의 경우에는 직접 설치해서 사용해야합니다.

 

함수 방식이라 함은 명령어에 parameter를 넣어 사용하는 방식이라고 생각하시면 됩니다.
아래 명령어를 예시로 보시면 이해하시기 편할겁니다.

helm install api-tester-2221 ./appi --set port='80' --set profile='dev' --set nodeport='32222'

오버레이 방식의 Kustomize.io

Kustomize의 경우에는 v.1.14부터는 Kubectl에 내장되어 있습니다.

 

오버레이 방식이라 함은 병합하는 것이라고 생각하시면 이해하실 겁니다.
본인이 작성해 놓은 파일과 병합하려는 파일을 비교해 변경사항이라면 수정하고 신규사항이라면 추가로 넣어줍니다.

 

깃에 push하는 것과 비슷하죠??

 

Kubectl로 사용하기 위해서는 -k옵션을 주면 됩니다.

kubectl apply -k ./app/overlays/dev

이미지

그림으로 보는 최종 정리

이미지

Helm 실습

Helm(Ver. 3.13.2) 설치

CI/CD Server에서 helm 설치 (root 유저) - 인텔 PC용

curl -O https://get.helm.sh/helm-v3.13.2-linux-amd64.tar.gz
tar -zxvf helm-v3.13.2-linux-amd64.tar.gz
mv linux-amd64/helm /usr/bin/helm

CI/CD Server에서 helm 설치 (root 유저) - M시리즈용

yum install -y tar
curl -O https://get.helm.sh/helm-v3.13.2-linux-arm64.tar.gz
tar -zxvf helm-v3.13.2-linux-arm64.tar.gz
mv linux-arm64/helm /usr/bin/helm

확인하기

jenkins 유저로 전환해서 확인

su - jenkins -s /bin/bash
helm

Helm 템플릿 생성하기

# command
helm create ${template_name}
# 실습용 command
helm create api-tester

New view 만들기

+ 버튼을 눌러서 새 보기 만들기

조회명 : 222 Type : List View

Helm 배포 시작하기

item name 입력 및 Pipeline 선택

Enter an item name에 '2221-deploy-helm' 입력 Pipeline 선택 OK 버튼 클릭합니다.

Configure > General > GitHub project > Project url

Project url : https://github.com/k8s-1pro/kubernetes-anotherclass-sprint2/

▶ Github URL - k8s-1pro를 (본인의 Username으로 변경가능)

Configure > Advanced Project Options > Pipeline

Definition : Pipeline script from SCM
Definition > SCM : Git
Definition > SCM > Repositories > Repository URL : https://github.com/k8s-1pro/kubernetes-anotherclass-sprint2.git
Definition > SCM > Branches to build > Branch Specifier : */main
Definition > SCM > Branches to build > Additional Behaviours > Sparse Checkout paths > Path : 2221
Definition > Script Path : 2221/Jenkinsfile

저장 후 지금 빌드 실행 그리고 Stage View 결과 확인

※ 배포 되기전 꼭 배포될 템플릿 Logs 확인하시기 바랍니다.

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Helm 실습 - Helm 배포 시작하기 - 저장 후 지금 빌드 실행 그리고 Stage View 결과 확인

배포 코드 확인

Helm배포 코드 << 클릭하면 배포 코드를 확인할 수 있습니다.

Helm Package 설명

Helm 템플릿 생성 (init)

helm create api-tester
cd api-tester
ls charts Chart.yaml templates values.yaml

패키지 구성

api-tseter(template name, root dir)

이 폴더는 템플릿을 생성했을 때 작성하는 template_name이 됩니다.
하위에 아래의 그림과 같이 패키지가 생성되어 있는 것을 활인 할 수 있습니다.

charts

이 폴더는 서브차트 폴더입니다.
이 폴더의 기능은 우리가 특정 App을 배포를 함에 있어 반드시 필요한 App들을 이 하위에 넣게 됩니다.
그러면 Helm.yaml파일을 생성할대 이 폴더를 스캔해 같이 만들어줍니다.

templates

이게 우리가 만들어놓은 template용 .yaml파일을 넣는 위치가 됩니다.

  • testers : 테스트용 폴더로 App의 통신상태가 원활한지 확인할 수 있습니다.

templates - _helpers.tpl

이 파일은 우리가 개발을 할 경우 전역으로 관리하고 싶은 변수를 전역변수로 넣고 사용하는 것 처럼 templates폴더 내에서 전역으로 사용하기 위한 변수를 정의하는 파일입니다.

templates - NOTES.txt

배포 후 안내문구를 작성하는 파일입니다.
마치 README.md와 같은?? (확실하진 않음)

.helmignore

.gitignore처럼 사용하는 파일입니다. 추가 설명은 안해도 되겠죠??

Chart.yaml

차트의 기본정보를 선언하는 곳입니다.
Helm에서 차트란 App을 패키징한 것을 의미하는데 이곳에 작성하는 것들을 예로 들어보면 이름, 버전, 설명, 의존성 정보 등을 포함하게 됩니다.

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Helm Package 설명 - 패키지 구성 - Chart.yaml

Chart, values, _helper.tpl, helm command 작성법

실제로 어떻게 작성하는지 코드를 보고 싶다면 위에 배포코드 확인하는 부분에 들어가서 확인해 보시기 바랍니다.

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Helm Package 설명 - Chart, values, _helper.tpl, helm command 작성법

resource 더 추가하기

필요한 .yaml파일이 있다면 아래와 같이 추가하고 문법에 맞게 수정 후 사용하시면 됩니다.

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Helm Package 설명 - resource 더 추가하기

실습 후 정리

# helm 조회
helm list -n anotherclass-222
# helm 삭제
helm uninstall -n anotherclass-222 api-tester-2221
# 다음 작업을 위해 namespace 삭제
kubectl delete ns anotherclass-222

Kustomize.io

Helm과 비교해보는 패키지 구성

Kustomize의 경우에는 Helm의 경우보다 구조가 간단합니다.
하지만, 조금 귀찮은 점은 Command Line으로 해당 폴더를 편하게 만들 수 없고 직접 만들어주어야 한다는 점인데요.

 

정해진 이름은 없고 결국은 베이스가될 패키지(폴더)를 지정해 주어야 하기 때문에 각 패키지에 대한 네이밍은 자유입니다.

 

또한, Kustomize의 경우에는 변수로써 채우는 것이 아닌 병합을 하는것이기 때문에 파일 구성이 간단하죠.

 

베이스가 되어야할 패키지와 병합할 파일의 패키지를 나누기만 하면 됩니다. 이 때 각 하위에는 반드시 Kustomization.yaml파일을 포함해야 하는데요. 이 파일은 배포할 파일 선택 및 공통값 설정에 사용됩니다.

 

자! 패키지 구성이 완전히 같진 않지만 비슷하게 비교를 해보자면 다음과 같습니다.

templates vs base

베이스가 될 .yaml파일을 명시하는 곳입니다.

Chart.yaml, values.yaml vs overlays

Helm에서는 Chat.yaml이나 values.yaml에 변수값을 지정하여 넣어줬지만, Kustomize에서는 그냥 .yaml파일에 병합할 내용을 네이밍 규칙에 맞게 작성만 해주면 됩니다.

이미지

Kustomize 실습

Kustomize(Ver. 5.0.1) 설치

Kustomize Version 확인

kubectl version --short --client

자! 그럼 본격적으로 배포를 해보는 실습을 해봅시다.

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Kustomize 실습 - Kustomize(Ver. 5.0.1) 설치 - Kustomize Version 확인

item name 입력 및 Pipeline 선택

Enter an item name에 '2222-deploy-kustomize' 입력 Copy form에 '2221-deploy-helm' 입력 후 OK 버튼 클릭을 클릭해 item을 만들어줍니다.

Configure > Advanced Project Options > Pipeline

Definition > SCM > Branches to build > Additional Behaviours > Sparse Checkout paths > Path : 2222
Definition > Script Path : 2222/Jenkinsfile

저장 후 지금 빌드 실행 후 Abort 그리고 페이지 새로고침 하기

최초 실행시엔 매개변수 입력 버튼이 안나오는데요.
yes를 클릭하게 될 경우 dev, qa, prod중 dev가 그래서 우리는 Abort를 클릭하여 배포를 중단시켜주고 화면을 새로고침해 파라미터와 함께 빌드라는 메뉴가 생기게 해줄겁니다.

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Kustomize 실습 - Configure > Advanced Project Options > Pipeline - 저장 후 지금 빌드 실행 후 Abort 그리고 페이지 새로고침 하기

파라미터와 함께 빌드 실행 후 PROFILE을 dev로 선택하고 빌드하기 클릭

우선 개발환경부터 배포를 해보도록 하겠습니다.
아래 이미지 처럼 파라미터와 함께 빌드를 클릭 후 PROFILE을 dev로 선택한 다음 빌드를 시작합니다.

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Kustomize 실습 - Configure > Advanced Project Options > Pipeline - 파라미터와 함께 빌드 실행 후 PROFILE을 dev로 선택하고 빌드하기 클릭

Stage View 결과 확인

배포 시작에서 이번엔 yes를 클릭하고 Pod이 정상적으로 올라왔는지 대쉬보드는 아래 커멘드를 이용해서 확인해 봅시다.

kubectl get pods -A

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - Kustomize 실습 - Configure > Advanced Project Options > Pipeline - Stage View 결과 확인

파라미터와 함께 빌드 실행 후 PROFILE을 qa, prod로 선택하고 빌드하기 클릭 그리고 대시보드 확인

이번엔 다른 환경으로도 배포를 해보고 정상 동작하는지 한번 확인해보세요.

배포 코드 확인

Kustomize 배포 코드 << 다음을 클릭하여 소스코드를 확인해보세요.

실습 후 정리

다음 실습 환경을 위해 만들어 두었던 데이터는 초기화를 해둡시다.

# namespace 삭제
kubectl delete ns anotherclass-222-dev
kubectl delete ns anotherclass-222-qa
kubectl delete ns anotherclass-222-prod

배포 파이프라인 구축 후 마주하게 되는 고민들

보안은??

이전까지 실습하던 환경은 보안에 취약한 형태였습니다...
아우....

 

이유를 알아볼까요??

kubectl config...

우리는 이 파일을 Master Node에서 복사해서 사용해서 kubectl명령어를 사용했었죠??

 

이것은 보안에 취약한 방법입니다....
이유는 Jeknins서버를 누구나 접속 할 수 있다거나, 혹여나 뚫려버리면 해당 kubectl명령어로 무슨짓을 할지 모르는 상황이 발생할 수 있기 때문이죠.

docker login...

도커도 문제가 많습니다.

 

Jenkins와 마찬가지로 서버 자체에 로그인을 해서 사용했기 때문에 기록에 남게 되는데요.
아래 명령어를 통해 우리의 이력이 남게됩니다.

cat ~/.docker/config.json

이를 방지하려면 매번 로그인하고 로그아웃을 해주어야 합니다.
하지만, 개발자들이 누굽니까... 겁나 귀찮죠...?

 

우선 이 문제부터 해결해 봅시다.

Jenkins의 Credential

Credential??

Jenkins에서 내부에서 사용할 수 있게 인증서를 만드는 방법입니다.
이는 단방향 암호화는 아니지만 암호화 작업이 들어갑니다. 때문에 서버가 뚫리지 않는이상은 안전하다고 볼 수 있습니다.

 

그러면 한번 어떻게 작업하는지 실습을 해보겠습니다.

Credential 실습

item name 입력 및 Pipeline 선택

Enter an item name에 2224-deploy-helm 입력하고 Copy form에 2223-deploy-helm 입력 후 OK 버튼 클릭해 item을 만들어 줍시다.

Configure > Advanced Project Options > Pipeline

Definition > SCM > Branches to build > Additional Behaviours > Sparse Checkout paths > Path : 2224
Definition> Script Path : 2224/Jenkinsfile

Credential 등록하기

Dashboard > Jenkins 관리 > Credentials > System > Global credentials (unrestricted) 에서 Add Credentials 클릭합니다.

Docker 접속정보 Credentials 등록

우선 Jenkins Server에서 로그인한 도커를 로그아웃 해줍니다.

docker logout

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - 배포 파이프라인 구축 후 마주하게 되는 고민들 - Credential 실습 - Docker 접속정보 Credentials 등록

Kubernetes config 파일 Credentials 등록

우선 우리는 config파일을 등록해줄꺼기 때문에 파일을 밖으로 빼내주는 사전 작업이 필요합니다.
그 후 아래 위치로 이동해 config파일이 동작하지 않게 이름을 변경해줍니다.

  • Windows에서 이동 방법 : /var/lib/jenkins/.kube/를 입력 후 config 파일이 나오면 내 PC 바탕화면으로 드래그 하시면 되요.
  • Mac에서 이동 방법 : scp root@192.168.56.30:/var/lib/jenkins/.kube/config ~/Desktop/k8s-master-config
# config 파일 위치
/var/lib/jenkins/.kube
# 파일 이름 변경
mv config config_bak

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - 배포 파이프라인 구축 후 마주하게 되는 고민들 - Credential 실습 - Kubernetes config 파일 Credentials 등록

)

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - 배포 파이프라인 구축 후 마주하게 되는 고민들 - Credential 실습 - Kubernetes config 파일 Credentials 등록

Jenkinsfile 내용

// Docker 사용
steps {
script{
withCredentials([usernamePassword(credentialsId: 'docker_password', passwordVariable: 'PASSWORD', usernameVariable: 'USERNAME')]) {
sh "echo " + '${PASSWORD}' + " | docker login -u " + '${USERNAME}' + " --password-stdin"
// Kubernetes config 사용
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) { // 암호화로 관리된 config가 들어감
sh "kubectl apply -f ./2224/deploy/kubectl/namespace-dev.yaml --kubeconfig " + '${KUBECONFIG}'
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
" -n anotherclass-222-dev --install --kubeconfig " + '${KUBECONFIG}'

참고사항

잦은 배포 - Versioning 무의미, 계획된 배포 - Versioning 필수 - Jenkinsfile 내용

environment {
APP_VERSION = '1.0.1'
BUILD_DATE = sh(script: "echo `date +%y%m%d.%d%H%M`", returnStdout: true).trim()
// 위에 date 포맷 오류가 있어요. %y%m%d.%H%M%S가 맞습니다)
TAG = "${APP_VERSION}-" + "${BUILD_DATA}"
stage('컨테이너 빌드 및 업로드') {
steps {
script{
// 도커 빌드
sh "docker build ./2224/build/docker -t 1pro/api-tester:${TAG}"
sh "docker push 1pro/api-tester:${TAG}"
stage('헬름 배포') {
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
...
" --set image.tag=${TAG}" // Deployment의 Image에 태그 값 주입

docker tag 변경 명령 (to latest)

상황에 따라 최근 안정화된 버전을 latest로 관리하고 있다면 태그는 다음과 같이 변경할 수 있습니다.

docker tag 1pro/api-tester:${TAG} 1pro/api-tester:latest
docker push 1pro/api-tester:latest

업로드 후 CI/CD Server에 만들어진 이미지 삭제 - Jenkinsfile 내용

stage('컨테이너 빌드 및 업로드') {
steps {
script{
// 도커 빌드
sh "docker build ./${CLASS_NUM}/build/docker -t ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
sh "docker push ${DOCKERHUB_USERNAME}/api-tester:${TAG}"
sh "docker rmi ${DOCKERHUB_USERNAME}/api-tester:${TAG}" // 이미지 삭제
}
}
}

네임스페이스는 배포와 별도로 관리 - Jenkinsfile 내용

실습을 위해 다른 Namespace로 인해 충돌이 발생하는 것을 막기 위해 따로 관리했던 것일 뿐 이렇게 하는 것은 자유입니다.

stage('네임스페이스 생성') { // 배포시 apply로 Namespace 생성 or 배포와 별개로 미리 생성 (추후 삭제시 별도 삭제)
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "kubectl apply -f ./2224/deploy/kubectl/namespace-dev.yaml --kubeconfig " + '"${KUBECONFIG}"'
...
stage('헬름 배포') {
steps {

Helm 부가기능 (배포 후 Pod 업그레이드가 안될 수 있음) - deployment.yaml 내용

이 기능은 배포를 위한 기능입니다.
Deployment의 변경사항을 감지하여 재배포를 시도하는 것은 template영역입니다.
하지만 이미지는 변경이 되었지만 template의 데이터가 변경이 된것이 아닐때에는 반영이 안되는 것이지요. 이럴때 사용할 수 있습니다.

 

이렇게 되면 template안에 metadata.annotation 속성에 항상 난수로 데이터를 채우게 되는데, 이렇게 자동으로 배포를 하게끔 만들 수 있습니다.

apiVersion: apps/v1
kind: Deployment
spec:
template:
metadata:
annotations:
rollme: {{ randAlphaNum 5 | quote }} // 항상 새 배포를 위해 랜덤값 적용

Helm 부가기능 (Pod가 완전 기동 될때까지 결과값 기다림) - helm command 명령어 내용

이 기능은 --wati옵션을 주는 것인데요.
이 옵션을 넣어주면 Helm이 자체적으로 App이 배포된 후에 통신이 이루어지는 지를 자동적으로 체크할 때까지 작업을 이어나가지 않고 기다리게 됩니다.

 

--timeout옵션을 통해 최대 얼마만큼 기다릴 것인지를 추가해서 사용할 수 있습니다.

stage('헬름 배포') {
steps {
withCredentials([file(credentialsId: 'k8s_master_config', variable: 'KUBECONFIG')]) {
sh "helm upgrade api-tester-2224 ./2224/deploy/helm/api-tester -f ./2224/deploy/helm/api-tester/values-dev.yaml" +
...
" --wait --timeout=10m" + // 최대 10분으로 설정

사용 안하는 이미지는 자동 삭제됨 - config.yaml 내용

쿠버네티스에는 쿠버네티스 가비지 컬렉터라는게 존재하는데요.
우리가 만든 이미지를 쿠버네티스가 감지하여 사용하지 않으면 삭제해주는 역할을 합니다.
만약 이러한 기능이 없다면 우리는 배포를 할때마다 생기는 이미지를 스스로 관리를 해주어야하는거죠.
아니면 스토리지가 가득차 뻗는 현상을 경험할 수 있습니다.

 

설정을 완료한 후에는 kubelet을 재시작하여 적용해 주어야 합니다.

// GC 속성 추가하기
vi /var/lib/kubelet/config.yaml
-----------------------------------
# 이미지 생성 후 해당 시간이 지나야 GC 대상이 됨 (Default : 2m)
imageMinimumGCAge : 3m
#Disk가 80% 위로 올라가면 GC 수행 (Default : 85)
imageGCHighThresholdPercent : 80
#Disk가 70% 밑으로 떨어지면 GC 수행 안함(Default : 80)
imageGCLowThresholdPercent : 70
----------------------------------
// kubelet 재시작
systemctl restart kubelet

Kubernetes docs : https://kubernetes.io/docs/concepts/architecture/garbage-collection/

Garbage Collection

Garbage collection is a collective term for the various mechanisms Kubernetes uses to clean up cluster resources. This allows the clean up of resources like the following: Terminated pods Completed Jobs Objects without owner references Unused containers and container images Dynamically provisioned P...

참고: kubernetes.io

파라미터와 함께 빌드 실행 후 PROFILE을 dev로 선택하고 빌드하기 클릭

그럼 이제 한번 배포를 해볼까요??

 

dev가 성공했다면 다른것도 한번 시도해보세요!!

 

cf. 이전 글중에 제가 일프로님 강의를 그대로 안따라하고 레파지토리로 인해 개고생한걸 기억하시나요?? 그때 개고생한 덕에 이번에 수정할때는 어디를 만져야하는지 금방 보이더라구요... 근데 귀찮습니다. 이글을 먼저 보시는분은 제글을 보고 따라하실 거면 레파지토리를 분리하는 짓은 하지 마시길...

[Kubernetes] Helm과 Kustomize 비교하며 사용하기 - 배포 파이프라인 구축 후 마주하게 되는 고민들 - Credential 실습 - 파라미터와 함께 빌드 실행 후 PROFILE을 dev로 선택하고 빌드하기 클릭

실습 후 정리

다음 공부를 위해 메모리를 잡아먹는 이녀석들의 데이터를 초기화해 줍시다.

 

분명히 이슈가 생길텐데, 잘 따라오신분은 왜 발생하는지 금방 알아차릴 수 있을 겁니다.
도저히 모르시겠다면... 댓글로 남겨주세요!!

# helm 조회
helm list -n anotherclass-222
# helm 삭제
helm uninstall -n anotherclass-222-dev api-tester-2224
helm uninstall -n anotherclass-222-qa api-tester-2224
helm uninstall -n anotherclass-222-prod api-tester-2224
# namespace 삭제
kubectl delete ns anotherclass-222-dev
kubectl delete ns anotherclass-222-qa
kubectl delete ns anotherclass-222-prod

그림으로 보는 실습이해

이미지

이 글은 인프런의 일프로님 강의를 재정리하여 작성한 글입니다.

728x90
반응형

댓글