Kubernetes

AEWS [3기] 8주차 - K8S CI/CD 와 kustomize

yu3papa 2025. 3. 29. 21:34

DevOps 라는 용어는 다양한 정의가 있습니다. 마이크로소프트에서는 아래와 같이 정의를 하고 있습니다.

개발(Dev)과 운영(Ops)의 합성어인 DevOps는 고객에게 지속적으로 가치를 제공하도록 지원하는 사람, 프로세스 및 기술의 합집합입니다. 팀에는 DevOps가 어떤 의미일까요? DevOps는 개발, IT 운영, 품질 엔지니어링, 보안 등 이제껏 서로 단절되었던 역할들이 서로 조율하고 협업하여 더욱 안정적이고 뛰어난 제품을 생산할 수 있도록 지원합니다. DevOps 방식과 도구를 비롯한 DevOps 문화를 도입하는 팀은 고객 요구 사항에 보다 효과적으로 대응하고, 더욱 안심하고 애플리케이션을 빌드하며, 비즈니스 목표를 더 빨리 달성할 수 있습니다.

 

위와 같이 고객에서 기업의 서비스를 빠르게 노출하기 위해 아래와 같은 Best Practice를 기업환경에서 많이 사용합니다.

CI/CD 에 대해서는 제가 작성한 아래의 블로그를 참조해 주세요.

https://blog.naver.com/yu3papa/223701797853

 

[CI/CD 3주차] - Jenkins CI/ArgoCD + K8S

1. 실습환경 구성 Jenkins, GitHub, EC2 스테이징서버는 "[CI/CD 1주차] - Jenkins CI/C...

blog.naver.com

 

CI/CD의 핵심은 자동화 입니다. 사람의 개입없이 고객에게 빠르게 기능을 노출하기 위해 Jenkins 난 ArgoCD를 사용하고 있습니다.

이번 블로그에서는 쿠버네티스 환경에서 GitOps를 지원하는 ArgoCD에서 사용 가능한 도구인 kustomize에 대해 알아 보겠습니다.

kustomize란

K8S 리소스 메니페스트(yaml 파일)을 “변경하지 않고 필드를 재정의”하여 새로운 K8S 리소스 메니페스트(yaml 파일) 정의를 생성하는 도구

kustomize는 INPUT의 받은 YAML 파일을 "kustomization.yaml" 파일을 이용하여 여러가지 변환 작업을 거친후 최종 YAML 파일을 배포하는 방식으로 동작하며, kubectl 바이너리에 일부 기능이 포함되어 있어 따로 설치가 필요하지 않습니다.

[root@k8s-cp ~]# kubectl version
Client Version: v1.29.2
Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3
Server Version: v1.29.2


[root@k8s-cp ~]# kubectl kustomize --help
Build a set of KRM resources using a 'kustomization.yaml' file. The DIR argument must be a path to a directory
containing 'kustomization.yaml', or a git repository URL with a path suffix specifying same with respect to the
repository root. If DIR is omitted, '.' is assumed.

Examples:
  # Build the current working directory
  kubectl kustomize

  # Build some shared configuration directory
  kubectl kustomize /home/config/production

  # Build from github
  kubectl kustomize https://github.com/kubernetes-sigs/kustomize.git/examples/helloWorld?ref=v1.0.6

Options:
    --as-current-user=false:
        use the uid and gid of the command executor to run the function in the container
...(생략)...

 

kustomize의 핵심은 kustomization.yaml 파일이며, 각종 변환 및 생성 규칙을 정의하고 있습니다.

 

ImageTagTransformer

K8S CI/CD 환경에서 가장 빈번한 배포 패턴을 POD에서 수행중이 이미지의 신규버전을 배포하는 일입니다.

kustomization.yaml 파일에 사용하는 ImageTagTransformer 를 이용하여 최종 배포될 이미지의 태그를 변경하는 실습을 진행해 보겠습니다.

# 작업 폴더 및 파일 생성 + deployment.yaml 파일과 kustomization.yaml 파일 내용 작성
[root@k8s-cp ~]# mkdir -p ~/kustomize/01
[root@k8s-cp ~]# touch ~/kustomize/01/deployment.yaml
[root@k8s-cp ~]# touch ~/kustomize/01/kustomization.yaml

# kubectl kustomize를 실행하고 원본과 다르게 출력되는 부분을 확인
[root@k8s-cp 01]# kubectl kustomize 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: guestbook
spec:
  replicas: 1
...(생략)...

 

LabelTransformer

  • K8S에서 Label은 중요한 아키텍처 요소로 리소스를 필터링하고, 선택하는 용도로 사용합니다.
  • kustomize 의 "commonLabels" 를 이용하면 동일한 Label을 관리할 수 있습니다.
# 위 실습에 이어서 kustomization.yaml 파일을 아래와 같이 수정하고, kubectl kustomize를 실행하고 원본과 다르게 출력되는 부분을 확인

 

kustomize를 이용하여 방명록 샘플웹어플리케이션을 배포해 보겠습니다.

# MySQL DBMS 컨테이너를 실행
[root@k8s-cp ~]# docker container run -d \
 --name=guestbookdb \
 --restart=always \
 -e MYSQL_ROOT_PASSWORD=jadecross \
 -e MYSQL_DATABASE=guestbook \
 -p 3306:3306 \
 mysql:8.3

# kustomize를 이용하여 방명록 웹어플리케이션 Deployment 배포
[root@k8s-cp ~]# cd ~/kustomize/01
root@k8s-cp 01]# kubectl kustomize | kubectl apply -f -
deployment.apps/guestbook created

# default 네임스페이스에 배포된 리소스 확인
[root@k8s-cp ~]# kubectl get all -o wide
NAME                            READY   STATUS    RESTARTS   AGE     IP              NODE       NOMINATED NODE   READINESS GATES
pod/guestbook-8676fc744-9cnmp   1/1     Running   0          2m35s   10.102.249.15   k8snode1   <none>           <none>

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   9h    <none>

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE     CONTAINERS   IMAGES                       SELECTOR
deployment.apps/guestbook   1/1     1            1           2m35s   main         yu3papa/helm_guestbook:1.0   app=guestbook

NAME                                 DESIRED  CURRENT  READY  AGE    CONTAINERS  IMAGES                      SELECTOR
replicaset.apps/guestbook-8676fc744  1        1        1      2m35s  main        yu3papa/helm_guestbook:1.0  app=guestbook
                                                                                                             ,pod-template-hash=8676fc744

# 브라우저를 이용하여 방명록 접속


# kustomize를 이용하여 방명록 웹어플리케이션 Deployment 삭제
root@k8s-cp 01]# kubectl kustomize | kubectl delete -f -
deployment.apps "guestbook" deleted

 

Resources 섹션

 

# 위 실습환경에서 serivce.yaml 파일을 추가 + kustomization.yaml 파일에  리소스 추가 --> kubectl kustomize 결과를 확인


# kubectl kustomize 결과를 이용하여 default 네임스페이스에, “방명록” 웹어플리케이션의 Deployment 와 Service 리소스 생성
root@k8s-cp 02]# kubectl kustomize | kubectl apply -f -
service/guestbook created
deployment.apps/guestbook created

[root@k8s-cp 02]# kubectl get all
NAME                            READY   STATUS    RESTARTS   AGE
pod/guestbook-8676fc744-r68x2   1/1     Running   0          23s

NAME                 TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
service/guestbook    LoadBalancer   10.110.123.13   <pending>     80:32065/TCP   24s
service/kubernetes   ClusterIP      10.96.0.1       <none>        443/TCP        9h

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/guestbook   1/1     1            1           23s

NAME                                  DESIRED   CURRENT   READY   AGE
replicaset.apps/guestbook-8676fc744   1         1         1       23s

# “방명록” 웹어플리케이션 서비스가 정상 수행되는지 확인


# kubectl kustomize 결과를 이용하여 default 네임스페이스에, “방명록” 웹어플리케이션의 Deployment 와 Service 리소스 삭제
root@k8s-cp 02]# kubectl kustomize | kubectl delete -f -
service "guestbook" deleted
deployment.apps "guestbook" deleted

 

Generators

  • 필드 또는 K8S 리소스를 생성
    • 원하는 동작에 대한 Built-in 플러그인을 찾아서 사용
      • configMapGenerator
      • secretGenerator
  • configMapGenerator

 

ConfigMap from Literals

  • The key/value are separated by a = sign (left side is the key)
  • The value of each literal will appear as a data item in the ConfigMap keyed by its key.
# 작업 폴더 및 파일 생성
[root@k8s-cp ~]# mkdir -p ~/kustomize/03; cd $_
[root@k8s-cp 03]# touch kustomization.yaml

 

ConfigMap from env file

  • The key/value pairs inside of the environment file are separated by a = sign (left side is the key)
  • The value of each line will appear as a data item in the ConfigMap keyed by its key.
  • Pairs may span a single line only.
# “방명록” 웹어플리케이션에서 사용할 MySQL DBMS 접속정보를 갖는 “db.env” 파일 생성
[root@k8s-cp 03]# touch db.env

 

교차 편집(Cross-Cutting)

  • kustomize가 동작할 때 연관관계가 있는 다른 필드를 자동 수정
# “방명록” 웹어플리케이션 deployment.yaml 파일 생성 + kustomization.yaml 수정 후 “kubectl kustomize” 명령을 수행하고 결과 확인

 

NamespaceTransformer

 

Base/Overlays 패턴

base kustomize 실행 결과를 다른 kustomize에서 사용하는 패턴

 

 

실습 개요

  • DEV, TEST, PROD 환경에 각기 다른 DBMS 연결 정보를 가지고 실행되도록 kustomize 이용
# 공통으로 사용할 정보인 base 디렉토리와 파일 생성
mkdir -p ~/kustomize/05/base
touch ~/kustomize/05/base/deployment.yaml
touch ~/kustomize/05/base/service.yaml
touch ~/kustomize/05/base/kustomization.yaml

# PROD 환경에 특화된 정보로 사용할 overlays/prod 디렉토리와 파일 생성
mkdir -p ~/kustomize/05/overlays/prod
touch ~/kustomize/05/overlays/prod/deployment-patch.yaml
touch ~/kustomize/05/overlays/prod/db.env
touch ~/kustomize/05/overlays/prod/kustomization.yaml

# 디렉토리 구조 확인
[root@k8s-cp ~]# tree ~/kustomize/05/
/root/kustomize/05/
├── base
│   ├── deployment.yaml
│   ├── kustomization.yaml
│   └── service.yaml
└── overlays
    └── prod
        ├── db.env
        ├── deployment-patch.yaml
        └── kustomization.yaml

 

공통으로 사용할 base 파일 작업

# 공통으로 사용할 정보인 base 디렉토리의 kustomize build 결과 확인
[root@k8s-cp ~]# cd ~/kustomize/05/
[root@k8s-cp 05]# kubectl kustomize ./base

PROD 환경에 특화된 overlays/prod 파일 작업 

 

# PROD 환경에 특화된 overlays/prod 디렉토리의 kustomize build 결과 확인
[root@k8s-cp ~]# cd ~/kustomize/05/
[root@k8s-cp 05]# kubectl kustomize ./overlays/prod

 

운영환경에 방명록 배포

# PROD 환경에 사용할 MySQL DBMS 를 컨테이너로 배포
[root@k8s-cp ~]# docker container run -d --restart=always --name=guestbookdb-pord \
                                     -e MYSQL_DATABASE=guestbook -e MYSQL_ROOT_PASSWORD=jadecross2 \
                                     -p 33062:3306 mysql:8.3

# kustomize 의 base/overlays 기법을 이용하여 PROD 환경에 방명록 배포
[root@k8s-cp ~]# cd ~/kustomize/05

[root@k8s-cp 05]# kubectl create ns prod
namespace/prod created

[root@k8s-cp 05]# kubectl kustomize ./overlays/prod | kubectl apply -f -
configmap/guestbook-cm-cg5kd2b26k created
service/guestbook created
deployment.apps/guestbook created

# prod 네임스페이스에 생성된 K8S 리소스 목록을 조회하고, guestbook 서비스의 CLUSTER-IP 로 방명록 접속
[root@k8s-cp 05]# kubectl -n prod get all
NAME                             READY   STATUS    RESTARTS   AGE
pod/guestbook-5566674b9c-76stt   1/1     Running   0          2m18s
pod/guestbook-5566674b9c-snnm8   1/1     Running   0          2m18s

NAME                TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
service/guestbook   LoadBalancer   10.97.42.246   <pending>     80:31445/TCP   6m14s

NAME                        READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/guestbook   2/2     2            2           6m14s

NAME                                   DESIRED   CURRENT   READY   AGE
replicaset.apps/guestbook-5566674b9c   2         2         2       6m14s