[k8s] Kustomize

2022. 12. 5. 10:23[ DevOps ]/[ k8s ]

Kustomize

kustomize는 쿠버네티스에서 오브젝트들의 Manifest들을 사용자가 원하는 방식대로 변경해서 쿠버네티스 환경에 배포할 수 있도록 하기 위한 목적으로 사용되는 플러그인이다. 과거에는 바이너리 파일을 다운로드해서 kubectl과 연동했다고 한다. 하지만 쿠버네티스 1.13 버전부터는 kubectl 커맨드의 기본 플러그인으로 자리 잡았다.

 

kustomize가 사용되는 대표적인 예시는 CI/CD 파이프라인 관리이다. (예를 들어, 애플리케이션의 Manifest 파일을 수정하여 GipOps 기반의 변경 사항을 발생시킬 때)

 

 

대표적인 기능 4가지

1) 리소스 집합을 구성하고 사용자 정의

- Manifest 파일들을 그룹으로 관리하고 한번에 실행, 삭제 등의 관리 기능

 

1) 원격에서 kustomize의 yaml파일을 포함한 Manifest를 가져와 생성

- GitHub 등 외부 원격 서버에 있는 Manifest 파일을 가져옴

 

2) 리소스에 대한 교차 편집 필드 설정

- Manifest 파일 중 일부를 편집(패치)하는 기능

 

4) Base, Overlay 패치

- Manifest 파일 중 공통이 되는 부분을 따로 빼내고 Overlay를 통해 특정 부분만 덮어 씌움

 

 

 

 

 

기본 사용법

kustomize는 k8s 1.13부터 kubectl 커맨드에 추가된 플러그인이다.

 

1. Kustomization 기본 명령어 (dry-run)

kubectl kustomize <Kustomization 디렉토리>

 

- Kustomization 디렉토리에는 Kustomization 하고자 하는 kustomize 기반의 Manifest들이 위치해야 한다.

- 해당 디렉토리에는 kustomization.yaml 파일이 위치해야 한다.

- 위 명령은 실제 오브젝트를 배포하는 것이 아니라 dry-run (가상으로 실행된 결과의 내용을 보여줌)을 실행한다.

 

 

2. Kustomization 리소스 적용

kubectl apply --kustomize <Kustomization 디렉토리>

kubectl apply -k <Kustomization 디렉토리>

- 만약 <Kustomization 디렉토리> 에는 kustomization.yaml 파일이 위치해야 한다.

 

 

 


 

kustomization의 교차 편집 필드

kustomization의 주요 4가지 기능 중 "소스에 대한 교차 편집 필드 설정"에 대한 내용이다. 

 

 

Kustomization 패치 방식 2가지

patchesStrategicMerge patchesJson6902
- 패치할 값들이 정의된 Manifest에는 패치 대상이 되는 원본 Manifest의 기본 템플릿과 같아야 함 (이를 통해 패치 대상을 식별) - JSON 패치 규약에 정의된 방식으로 패치 진행
- patch할 값들이 정의된 Manifest를 별도로 두고 해당 Manifest에는 JSON 패치 규약의 연산을 통해 패치할 부분을 정의함
- 리소스의 group, version, name, kind를 kustonization.yaml에 등록해야 함

 

cf. JSON 패치 규약

- YAML은 사람이 보기 좋은 형태로 작성되었을 뿐 기본적으로 JSON을 기반으로 한다. 이 방식은 JSON의 패치 규약을 따른다.

- 공식적으로 정의된 JSON 패치 규약은 링크(https://datatracker.ietf.org/doc/html/rfc6902)에 정의되어 있다.

- 뼈대가 되는 큰 부분은 동일하기 때문에 kustomization.yaml에 이러한 부분을 넣고, 패치할(추가, 변경할) 부분만 따로 manifest를 정의하여 patch 할 수 있다. 

- patchesJson6902 방식의 경우 패치 파일이 하나의 디렉토리에만 사용되는 게 아니라 여러 부분에서 재사용될 수 있다. 따라서 patchesStrategicMerge보다 변동사항에 더 유연하다.

- JSON 패치 규약에는 'add, remove, replace, move, copy, test' 연산이 제공된다. 보통 add, remove, replace를 많이 사용한다.

 

 


 

 

실습

실습1) kustomize로 Manifest 통합 관리

쿠버네티스 1.13 버전부터 kustomize는 기본적으로 kubectl에 내장된다.

kubectl --help

 

 

1-1) 실습할 Manifest 파일들(Deployment, Service를 kustomize로 관리)

- deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kust-nginx-deploy
spec:
  selector:
    matchLabels:
      run: ku-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: ku-nginx
    spec:
      containers:
      - name: ku-nginx
        image: nginx
        ports:
        - containerPort: 80

 

- service.yaml

apiVersion: v1
kind: Service
metadata:
  name: kust-nginx-sv
  labels:
    run: ku-nginx
spec:
  ports:
  - port: 80
    protocol: TCP
  selector:
    run: ku-nginx

 

- kustomization.yaml

resources:
- deployment.yaml
- service.yaml

 

 

1-2) kustomize 

- dry-run으로 확인

kubectl kustomize ./

- 위 명령은 실제 kustomize를 적용하는 것은 아니고 kustomize 된 파일을 확인하는 (dry-run) 명령이다.

 

 

1-3) 실제 배포 진행

kubectl apply --kustomize ./

- 네임스페이스는 default에 배포했다.

 

 

확인

 

 

1-4) 배포 삭제

kubectl delete --kustomize ./

 

- 각 Manifest 파일을 각각 kubectl apply -f 또는 delete를 통해 실행할 필요 없이 kustomize를 통해 한번에 배포 및 삭제할 수 있게 된다.

 

 

 

실습2) kustomize로 Manifest 특정 부분만 수정(패치)

2-1) 패치 전략: patchesStrategicMerge 사용

- deployment.yaml (위 실습 1에서와 같은 파일 사용)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kust-nginx-deploy
spec:
  selector:
    matchLabels:
      run: ku-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: ku-nginx
    spec:
      containers:
      - name: ku-nginx
        image: nginx
        ports:
        - containerPort: 80

 

- add_replica.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kust-nginx-deploy
spec:
  replicas: 3

 

- add_memory_limit.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kust-nginx-deploy
spec:
  template:
    spec:
      containers:
      - name: ku-nginx
        resources:
          limits:
            memory: 512Mi

 

- kustomization.yaml

resources:
- deployment.yaml

patchesStrategicMerge:
- add_replica.yaml
- add_memory_limit.yaml

 

* add-replica.yaml과 dd_memory_limit.yaml 파일은 deployment.yaml 파일이 패치 대상 Manifest임을 알 수 있도록 apiVersion부터 metadata/name 까지는 동일하게 작성해줘야 한다. (patchesStrategicMerge일 경우 해당)

 

 

dry-run 및 배포

kubectl kustomize ./
kubectl apply -k ./

 

 

실행확인

- deployment.yaml에는 replicas가 2지만 add_replica.yaml에서 replicas를 3으로 했기 때문에 이 부분이 패치되어 반영되어 있음을 확인할 수 있다.

 

 

 

 

2-2) 패치 전략: patchesJson6902 사용

patchesStrategicMerge 패치 전략도 결국 수정할 부분에 대해 원본 Manifest와 동일한 템플릿 형태로 추가적인 Manifest를 만들어야 한다는 단점이 있다. patchesJson6902 방식의 배치 전략을 사용하면 원본 Manifest의 템플릿을 유지하지 않으면서 정말 패치할 부분만을 정의한 Manifest로 관리할 수 있다. 결국 원본 Manifest의 템플릿을 유지하지 않으므로 패치만을 정의한 Manifest는 재사용될 수 있다.

 

 

- kustomization.yaml

resources:
- deployment.yaml

patchesJson6902:
- target:
    group: apps
    version: v1
    kind: Deployment
    name: kust-nginx-deploy
  path: patch.yaml

kustomization.yaml 파일에는 역시 패치할 대상을 명시해야 한다. 이때 group, version, kind, name을 작성해 줘야 한다. path에는 패치를 정의한 Manifest의 위치를 작성한다. 

 

 

- deployment.yaml (위 실습에서와 동일)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: kust-nginx-deploy
spec:
  selector:
    matchLabels:
      run: ku-nginx
  replicas: 2
  template:
    metadata:
      labels:
        run: ku-nginx
    spec:
      containers:
      - name: ku-nginx
        image: nginx
        ports:
        - containerPort: 80

 

 

- patch.yaml

- op: replace
  path: /spec/replicas
  value: 3

 

op는 Operation의 뜻으로 Json6902에서 정한 표준 연산을 사용한다. 총 5개의 연산(add, remove, replace, move, copy, test)이 지원된다.

 

- JSON 표준 연산 링크: https://datatracker.ietf.org/doc/html/rfc6902

 

 

 

dry-run 및 실행

kubectl kustomize ./
kubectl apply -k ./

# 총 3개의 Pod가 생성된 것을 확인

 

 

 

 

실습3) kustomize로 원격 시스템의 Manifest 가져오기 (실습 생략)

- kustomize.yaml

resources:
  - <https git 주소>

- 원격 시스템은 git 외에도 가능.

 

 

확인 후 default 네임스페이스에 바로 실행

kubectl kustomize <kustomize.yaml 파일 위치> | kubectl apply -f -

 

 


 

 

kustomize에서 제공되는 Base, Overlay 패치

Base와 Overlay(덮어 씌움) 패치는 Base를 기준으로 하는 Manifest에 kustomize로 설정한 부분을 Overlay 하는 kustomization의 기능이다. 대표적인 사용 예시로 개발 환경과 운영 환경을 분리할 경우가 해당된다. 만약 두 환경을 각가 dev, prod로 이름을 분리하여 관리하고 싶다면 각 환경에서 생성되는 API 리소스들을 구분시켜야 할 것이다. 네임스페이스로 구분할 수도 있지만 API 리소스의 이름에 직접적으로 prefix를 붙여 구분할 수도 있다.

 

 

예시

Manifest 관리 디렉토리 구성을 위와 같이 두고, base에는 위 실습에서 다룬 것과 같이 기본적으로 모든 환경에서 사용되는 공통적인 부분을 명시하고 dev, prod 디렉토리에서는 아래와 같이 bases와 namePrefix 필드를 통해 기본으로 사용할 부분과 덮어씌울 부분을 구분한다.

 

 

- dev/kustomization.yaml

bases:
- ../base
namePrefix: dev-

 

kubectl kustomize ./dev를 실행하면 dry-run 형태로 yaml 파일이 보이는데, 각 Deployment와 Service의 name 필드 앞에 prefix로 'dev-'가 추가된 형태로 선언된다.

 

결과 확인

[base에 선언된 API 이름]

* Deployment name: kust-nginx-deploy

* Service name: kust-nginx-sv

 

[kubectl kustomize ./dev]

* Deployment name: dev-kust-nginx-deploy

* Service name: dev-kust-nginx-sv

 

 

namePrefix 외, commonLabels 필드를 통해 모든 리소스에 등록할 label을 선언할 수도 있다.

 

bases:
- ../base
commonLabels:
  app: in-dev
namePrefix: dev-

 

 

cf. 그 외 제공되는 필드

 

https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#kustomize-feature-list

 

 

 

 

Reference

- RFC 6902, https://datatracker.ietf.org/doc/html/rfc6902

- k8s kustomize docs, https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/

- k8s kustomize base overlay, https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/#bases-and-overlays