TACO 에서는 Kubernetes 에 워크로드를 배포하기 위해서 Decapod 라는 자체 빌드 및 배포 체계를 갖고 있다. Decapod 는 Helm Chart 의 value override 기능과 Kustomize 의 plugin 기능을 개발하여 적용한 또 다른 value override 를 모두 사용하고 있다.
Helm Chart 와 Kustomize 모두 value oeverride 기능을 모두 제공하는데 왜 2가지를 모두 사용할까? 그 이유는 Helm Chart 는 이미 다양하게 제공되고 있는 것들이 많아 가져다 쓰면 되고, value 값들을 하나의 yaml 파일로 합쳐서 관리하기 위해서 Kustomize 의 plugin 을 개발하여 사용하고 있다.
즉, Decapod 체계는 다음과 같은 장점이 있다.
- Helm Chart 기반으로 default custom value 값을 지정할 수 있다. (decapod-base-yaml)
- Kustomize plugin 을 개발하여 각 사이트마다 갖는 여러 helm chart 의 고유 value 값들을
1개의 yaml 파일
에 합쳐서 관리할 수 있다.
하지만 Helm Chart 를 제공하지 않는 app 들은 어떻게 지원할까? 예를 들어 Kubeflow 의 경우 Helm Chart 를 제공하지 않지만 Kustomize 를 제공하고 있으니 이를 지원하는 방법도 필요해 보인다.
Kustomize 활용을 위한 기본 디렉토리 (base repo)
kustomize 는 설치되어 있다고 가정하고 바로 활용을 위한 기본 디렉토리를 살펴보자.
$ tree
.
├── LICENSE
├── README.md
└── service-mesh
└── nginx
├── aws-msa-reference
│ ├── kustomization.yaml
│ └── site-values.yaml
└── base
├── kustomization.yaml
├── nginx-deployment.yaml
├── nginx-service.yaml
└── site-values.yaml
소스 홈 디렉토리 아래에는 service-mesh
라는 서비스 디렉토리가 있다. 여기에는 nginx, istio, jaeger, kaili 등 다양한 application 이 동시에 설치되어야 하는데 각 app 을 나타내는 디렉토리 (여기서는 편의상 nginx 만 설명한다)가 존재한다.
nginx 설치를 위해서는 보통 nginx-deployment.yaml 과 nginx-service.yaml 이 필요하며 이를 base 디렉토리에 위치시킨다.
$ cat nginx-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-blue
name: nginx-blue
spec:
replicas: 1
selector:
matchLabels:
app: nginx-blue
version: blue
template:
metadata:
labels:
app: nginx-blue
version: blue
spec:
containers:
- image: seungkyua/nginx:blue
name: nginx
$ cat nginx-service.yaml
---
apiVersion: v1
kind: Service
metadata:
name: nginx-blue-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-blue
version: blue
type: LoadBalancer
여기까지는 Helm chart 와 동일하다. 다만 chart 는 template 을 활용하여 value 값을 override 할 수 있는데 반하여 kustomize 는 kustomize.yaml 을 통해서 value 값을 override 할 수 있다.
kustomize.yaml 을 지정하고 기본적으로 업데이트할 디폴트 값을 site-values.yaml 이라는 파일에 지정한다.
resources
는 kubernetes 에 설치할 리소스들에 대한 yaml 리스트이고 patchesStrategicMerge
는 kustomize 에서 제공하는 yaml 합성 기능 중에 하나의 방법이다.
아래의 경우에는 site-values.yaml 값과 nginx-deployment.yaml, nginx-service.yaml 값을 합쳐서 만든다.
중복되는 경우에는 site-values.yaml 값을 우선시 한다.
$ cat kustomization.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- nginx-deployment.yaml
- nginx-service.yaml
patchesStrategicMerge:
- site-values.yaml
site-values.yaml 에는 override 할 default value 값을 가진다.
deployment 는 replicas 값을, service 는 NodePort 타입과 nodePort 값을 가진다. (이것을 base 값이라 생각하면 이해하기 쉽다. nginx helm chart 는 기본값이 replicas 1 인데 우리는 기본 값을 replicas 2 로 의도한 것이다.)
$ cat site-values.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-blue
spec:
replicas: 2
---
apiVersion: v1
kind: Service
metadata:
name: nginx-blue-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
nodePort: 32080
type: NodePort
여기서 잠깐. nginx-deployment.yaml 과 nginx-service.yaml 값을 처음부터 바꿔서 넣으면 site-values.yaml 이 필요하지 않을 텐데 왜 굳이 이걸 만들지?
그건 kustomize 혹은 helm chart 를 제공하기 때문에 가져다 쓰는 경우도 많은데 원래의 작성 값들을 바꿔서 관리하지 않으려고 하는 의도이다. 업스트림에서 만들어 진 것이 있으면 원본은 그대로 가져다 쓰는 것이 추후 유지 보수 관점에서 편리하기 때문이다.
이제 여기까지 만든 내용을 kustomize 로 build 해 보자.
$ cd service-mesh/nginx
$ kustomize build base
--- output ---
apiVersion: v1
kind: Service
metadata:
name: nginx-blue-svc
spec:
ports:
- nodePort: 32080
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-blue
version: blue
type: NodePort
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-blue
name: nginx-blue
spec:
replicas: 2
selector:
matchLabels:
app: nginx-blue
version: blue
template:
metadata:
labels:
app: nginx-blue
version: blue
spec:
containers:
- image: seungkyua/nginx:blue
name: nginx
Site 별 디렉토리 (Site repo)
이제 특정한 사이트에 다른 값으로 설치해야 한다고 가정해 보자.
aws-msa-reference 라는 신규 사이트 디렉토리를 만들고 kustomize.yaml 과 value 값을 모아둔 site-values.yaml 을 만든다.
$ tree
.
├── LICENSE
├── README.md
└── service-mesh
└── nginx
├── aws-msa-reference
│ ├── kustomization.yaml
│ └── site-values.yaml
└── base
├── kustomization.yaml
├── nginx-deployment.yaml
├── nginx-service.yaml
└── site-values.yaml
지금은 service-mesh/nginx 디렉토리 아리에 aws-msa-reference 가 있지만 이 디렉토리는 다른 repo 에서 관리하다가 kustomize build 를 하려할 때 해당 디렉토리로 복사해 오는 방법을 쓸 수 있다. (decapod 에서는 실제로 decapod-site 라는 repo 에 따로 사이트 값들을 관리하고 build 할 때 복사하는 방식을 사용하고 있다)
kustomize.yaml 과 site-values.yaml 을 보자.
$ cat kustomization.yaml
---
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
bases:
- ../base
patchesStrategicMerge:
- site-values.yaml
$ cat site-values.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-blue
spec:
replicas: 3
---
apiVersion: v1
kind: Service
metadata:
name: nginx-blue-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
type: LoadBalancer
새로운 신규 사이트에는 replicas 를 3으로 Service Type 을 LoadBalancer 로 설치하고자 한다.
이를 build 하면 다음과 같다.
$ kustomize build aws-msa-reference
--- output ---
apiVersion: v1
kind: Service
metadata:
name: nginx-blue-svc
spec:
ports:
- nodePort: 32080
port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-blue
version: blue
type: LoadBalancer
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: nginx-blue
name: nginx-blue
spec:
replicas: 3
selector:
matchLabels:
app: nginx-blue
version: blue
template:
metadata:
labels:
app: nginx-blue
version: blue
spec:
containers:
- image: seungkyua/nginx:blue
name: nginx
결과가 site 별로 지정한 값으로 잘 변경되었다.
어디에 적용할까?
kustomize 로 빌드된 결과 yaml 들을 특정 repo 에 저장하고 Argo CD
와 같은 tool 을 적용하면 효과적인 GitOps
체계를 만들 수 있다.
Tekton pipeline
이나 Argo workflow
, Jenkins pipeline
으로 CI 를 구축하고 Argo CD
로 CD 를 연결하면 GitOps CICD
를 구축할 수 있다. (이것까지 글로 써볼까? ㅎ)