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) 설치
- Download : https://get.helm.sh/helm-v3.13.2-linux-amd64.tar.gz
- Site : https://helm.sh/docs/intro/install/
- Release : https://github.com/helm/helm/releases
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 확인하시기 바랍니다.
배포 코드 확인
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을 패키징한 것을 의미하는데 이곳에 작성하는 것들을 예로 들어보면 이름, 버전, 설명, 의존성 정보 등을 포함하게 됩니다.
Chart, values, _helper.tpl, helm command 작성법
실제로 어떻게 작성하는지 코드를 보고 싶다면 위에 배포코드 확인하는 부분에 들어가서 확인해 보시기 바랍니다.
resource 더 추가하기
필요한 .yaml파일이 있다면 아래와 같이 추가하고 문법에 맞게 수정 후 사용하시면 됩니다.
실습 후 정리
# 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) 설치
- Download : 별도 설치 필요없음 (kubectl v1.14부터 포함되어 있음) - 현재 v1.27.2 사용중
- Github : https://github.com/kubernetes-sigs/kustomize
- Site : https://kubectl.docs.kubernetes.io/
- kubernetes Docs : https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/
Kustomize Version 확인
kubectl version --short --client
자! 그럼 본격적으로 배포를 해보는 실습을 해봅시다.
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를 클릭하여 배포를 중단시켜주고 화면을 새로고침해 파라미터와 함께 빌드
라는 메뉴가 생기게 해줄겁니다.
파라미터와 함께 빌드 실행 후 PROFILE을 dev로 선택하고 빌드하기 클릭
우선 개발환경부터 배포를 해보도록 하겠습니다.
아래 이미지 처럼 파라미터와 함께 빌드
를 클릭 후 PROFILE
을 dev로 선택한 다음 빌드를 시작합니다.
Stage View 결과 확인
배포 시작에서 이번엔 yes를 클릭하고 Pod
이 정상적으로 올라왔는지 대쉬보드는 아래 커멘드를 이용해서 확인해 봅시다.
kubectl get pods -A
파라미터와 함께 빌드 실행 후 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 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
)
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. 이전 글중에 제가 일프로님 강의를 그대로 안따라하고 레파지토리로 인해 개고생한걸 기억하시나요?? 그때 개고생한 덕에 이번에 수정할때는 어디를 만져야하는지 금방 보이더라구요... 근데 귀찮습니다. 이글을 먼저 보시는분은 제글을 보고 따라하실 거면 레파지토리를 분리하는 짓은 하지 마시길...
실습 후 정리
다음 공부를 위해 메모리를 잡아먹는 이녀석들의 데이터를 초기화해 줍시다.
분명히 이슈가 생길텐데, 잘 따라오신분은 왜 발생하는지 금방 알아차릴 수 있을 겁니다.
도저히 모르시겠다면... 댓글로 남겨주세요!!
# 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
그림으로 보는 실습이해
이 글은 인프런의 일프로님 강의를 재정리하여 작성한 글입니다.
'FrameWorks > Kubernetes' 카테고리의 다른 글
[Kubernetes] ArgoCD 사용해보기 (2) - ArgoCD Image Updater를 이용한 자동 배포 (0) | 2025.03.16 |
---|---|
[Kubernetes] ArgoCD 사용해보기 (1) - ArgoCD 설치 및 기본 배포 (0) | 2025.03.15 |
[Kubernetes] Jenkins Pipeline - 기초부터 Blue, Green 까지 (0) | 2025.03.12 |
[Kubernetes] CI/CD 환경 구축하기 (0) | 2025.03.11 |
[Kubernetes] Component 동작으로 이해하기 (0) | 2025.03.11 |
댓글