[기술노트 116회] YTT 시리즈 ① - 템플릿 엔진 알아보기

 

YTT는 쿠버네티스 매니페스트를 구성하고 관리하는 데 사용되는 강력한 템플릿 엔진입니다. 

 

<YTT 시리즈>는 쿠버네티스 환경에서 YAML 템플릿을 관리하는 데 중요한 역할을 하는

YTT에 대한 이해를 제공하고자 작성되었습니다.

 

[YTT 기술 튜토리얼]

  1. YTT 템플릿 엔진 알아보기
  2. 함수 및 검증 데이터
  3. 패칭 (오버레이)

3가지 시리즈로 진행하여 YTT의 기본 개념 및 사용법부터,
쿠버네티스 환경에서 필요한 다양한 기능 및 활용 방법에 대해 다룰 예정입니다. 

 


 

기본 개념에 대해 알아보기에 앞서서 자주 사용되는 용어를 소개해드립니다.

 

용어 설명
쿠버네티스 컨테이너 오케스트레이션 플랫폼으로, 컨테이너화된 애플리케이션을 배포하고 확장하며
관리하는 데 사용.
YTT  [YAML Templating Tool] 쿠버네티스 YAML 파일을 템플릿화하고 관리하는 도구로,
YAML 기반의 템플릿을 사용하여 쿠버네티스 매니페스트를 생성.
(YTT는 쿠버네티스 YAML 파일을 생성하기 위한 템플릿 엔진)
YAML 템플릿 YAML 형식으로 작성된 템플릿으로, 쿠버네티스 리소스를 정의하고 구성하는 데 사용.
템플릿 엔진 템플릿을 이용하여 동적으로 텍스트를 생성하는 소프트웨어.
패칭 (오버레이) 여러 YAML 파일 간의 차이를 관리하고 일부 구성을 덮어쓰는 기능으로,
YTT에서 유용하게 활용.
파이프라인 YTT에서는 여러 단계로 구성된 작업 흐름을 의미. 각 단계에서 입력을 처리하고
다음 단계로 전달.

 

 


ytt 템플릿 엔진 알아보기


0 들어가며

쿠버네티스 자원 배포와 각종 리소스 관리의 방법은 이미 다양하게 소개되었다. 그 중심에는 YAML로 일컬어지는 데이터 중심의 마크업 언어가 있다. 이러한 YAML 파일을 작성하다 보면 자연스럽게 모듈화를 고민하지 않을 수 없다. 이러한 모듈화 작업에는 다음과 같은 기능이 필요하게 된다.

  1. 중복 제거
  2. 조건 제어
  3. 함수
  4. 패칭(Patching) 또는 오버레이(overlaying)

이러한 기능을 제공하는 도구들중 대중적으로 많이 사용되는 도구들은 다음과 같은 것들이 있다.

  1. Helm(https://helm.sh/)
  2. Kustomize(https://kubernetes.io/docs/tasks/manage-kubernetes-objects/kustomization/)
  3. jsonnet(https://jsonnet.org/)
  4. Dhall(https://dhall-lang.org/)
  5. ytt(https://carvel.dev/ytt/)

이러한 도구들의 사용처가 주로 YAML 설정을 다루는 분야에 많이 쓰이다 보이 이들을 DCL(Data Configuration Language)라고 부르기도 한다. 여기서는 비교적 간단하고 직관적이며 프로그래밍 언어의 특징을 가진 ytt 템플릿 엔진을 살펴보고자 한다.

1. YAML 이란?

우리가 흔히 마크업 언어로 생각하고 있지만, 사실 YAML 에게는 더 큰 의미가 있다. YAML의 핵심은 문서 마크업이 아니라 데이터 중심에 있다는 것이다. 그래서, “YAML Ain’t Markup Language” 로 바꾸었다.

다음은 쿠버네티스 Deployment 정의 YAML의 예이다.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
  namespace: default
  labels:
    app.kubernetes.io/version: 0.1.0
    app.kubernetes.io/name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 1
  template:
    spec:
      containers:
        - name: frontend
          image: index.docker.io/k14s/image@sha256:6ab29951e0207fde6760f6db227f218f20e875f45b22e8ca0ee06c0c8cab32cd

 

여기서 주로 관심을 갖고 지켜볼 속성을 나열하자면 다음과 같을 것이다.

  1. namespace
  2. app
  3. image, image 태그

그런데, namespace 나 app 등의 속성 정보는 Service 등의 쿠버네티스 리소스 정의 부분에도 동일하게 들어갈만한 부분이다. 즉, 중복되는 항목이라 할 수 있다. 또한, replicas와 image(태그) 정보는 환경 별로 다른 값을 부여해야 한다.

정리하자면,

  1. 중복처리가 필요하다.
  2. 외부의 요청(환경)에 따라 다른 값을 주입할 수 있어야 한다.
  3. YAML파일을 분리하여 관리할 수 있어야 한다.

이러한 관점에서 YTT 를 살펴보도록 하자.

 

2. ytt의 특징

ytt의 특징은 https://carvel.dev/ytt/ 에 잘 설명되어 있다.

또한, 공식 웹사이트에서는 ytt를 실험해볼 수 있는 Playground도 제공하니 별도의 작업 없이 바로 테스트해볼 수 있다.

ytt는 Go 언어로 만들어졌으며(쿠버네티스 생태계의 third party 도구들이 그렇듯이) Git 허브 리파지터리에서 다양한 예제와 문서를 함께 제공하고 있다.

 

[YTT 소스코드 깃허브 리파지터리](https://github.com/carvel-dev/ytt)

 

GitHub - carvel-dev/ytt: YAML templating tool that works on YAML structure instead of text

YAML templating tool that works on YAML structure instead of text - carvel-dev/ytt

github.com

3. 설치

[설치](https://carvel.dev/ytt/docs/v0.46.x/install/)

 

Carvel - ytt - Install

Documentation for version v0.46.x is no longer actively maintained. The version you are currently viewing is a static snapshot. For up-to-date documentation, see the latest version. Install Via script (macOS or Linux) ¶ (Note that install.sh script instal

carvel.dev

# 리눅스
$ wget -O- https://carvel.dev/install.sh > install.sh
$ sudo bash install.sh
$ ytt version

# 맥 OS
$ brew tap carvel-dev/carvel
$ brew install ytt
$ ytt version

4. 간단한 테스트

이 글에서 사용한 YAML 파일은 ytt 공식 홈페이지에 공개된 코드를 이용했습니다.
#! config.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
  namespace: default
  labels:
    app.kubernetes.io/version: 0.1.0
    app.kubernetes.io/name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 1
  template:
    spec:
      containers:
        - name: frontend
          image: index.docker.io/k14s/image@sha256:6ab29951e0207fde6760f6db227f218f20e875f45b22e8ca0ee06c0c8cab32cd
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
  labels:
    app.kubernetes.io/version: 0.1.0
    app.kubernetes.io/name: frontend
spec:
  type: ClusterIP
  ports:
    - port: 80

"#!" 는 주석으로 사용된다.

yaml 파일에 기록된 내용중 중복 또는 주요 설정값들 데이터로 분리해보자(아래의 코드에서 #@ 으로 시작하는 부분).

#! config.yml

#@ name = "frontend"
#@ namespace = "default"
#@ version = "0.1.0"
#@ replicas = 1

apiVersion: apps/v1
kind: Deployment
metadata:
  name: #@ name + "-deployment"
  namespace: #@ namespace
  labels:
    app.kubernetes.io/version: #@ version
    app.kubernetes.io/name: #@ name
spec:
  selector:
    matchLabels:
      app: #@ name
  replicas: #@ replicas
  template:
    spec:
      containers:
        - name: #@ name
          image: index.docker.io/k14s/image@sha256:6ab29951e0207fde6760f6db227f218f20e875f45b22e8ca0ee06c0c8cab32cd
---
apiVersion: v1
kind: Service
metadata:
  name: #@ name + "-service"
  labels:
    app.kubernetes.io/version: #@ version
    app.kubernetes.io/name: #@ name
spec:
  type: ClusterIP
  ports:
    - port: 80

 

"#@" 는 변수를 지정하는 어노테이션(annotation)이다. 어노테이션에 대한 자세한 내용은 다음을 참고하자.

https://carvel.dev/ytt/docs/v0.46.x/lang-ref-annotation/

 

Carvel - ytt - Annotations

Documentation for version v0.46.x is no longer actively maintained. The version you are currently viewing is a static snapshot. For up-to-date documentation, see the latest version. Annotations Format ¶ @ann1-name [ann-arg1, ann-arg2, ..., keyword-ann-arg

carvel.dev

 

우선 변수로 따로 뽑아낼 내용들은 '#@ <name> = <value>' 형태로 지정한다. 이후 이렇게 정의된 값을 사용할 부분에서는 '#@ <name>' 형태로 지정하면 된다.

$ ytt -f config.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
  namespace: default
  labels:
    app.kubernetes.io/version: 0.1.0
    app.kubernetes.io/name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 1
  template:
    spec:
      containers:
      - name: frontend
        image: index.docker.io/k14s/image@sha256:6ab29951e0207fde6760f6db227f218f20e875f45b22e8ca0ee06c0c8cab32cd
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
  labels:
    app.kubernetes.io/version: 0.1.0
    app.kubernetes.io/name: frontend
spec:
  type: ClusterIP
  ports:
  - port: 80

의도한 형태로 잘 만들어졌다. 그리고, 변수들만 따로 분리하여 선언한 부분을 별도의 파일로 분리하면 더 깔끔해질것 같다. schema.yml 이라는 이름의 파일 생성한 후 변수들을 정의하자.

#! schema.yml
#@data/values-schema
---
name: "frontend"     #! ensures that any value for 'frontend' must be a string
namespace: "default" #! ensures that any value for 'default' must be a string
version: "0.1.0"     #! ensures that any value for 'version' must be a string
replicas: 1          #! ensures that any value for 'replicas' must be a int

 

물론 config.yml 파일에서는 외부의 파일로 분리된 변수들을 제거하고 변수들을 참조할 수 있도록 수정한다.

#! config.yml

#@ load("@ytt:data", "data")

apiVersion: apps/v1
kind: Deployment
metadata:
  name: #@ data.values.name + "-deployment"
  namespace: #@ data.values.namespace
  labels:
    app.kubernetes.io/version: #@ data.values.version
    app.kubernetes.io/name: #@ data.values.name
spec:
  selector:
    matchLabels:
      app: #@ data.values.name
  replicas: #@ data.values.replicas
  template:
    spec:
      containers:
        - name: #@ data.values.name
          image: index.docker.io/k14s/image@sha256:6ab29951e0207fde6760f6db227f218f20e875f45b22e8ca0ee06c0c8cab32cd
---
apiVersion: v1
kind: Service
metadata:
  name: #@ data.values.name + "-service"
  labels:
    app.kubernetes.io/version: #@ data.values.version
    app.kubernetes.io/name: #@ data.values.name
spec:
  type: ClusterIP
  ports:
    - port: 80

외부파일에 저장된 변수를 로드하고(#@ load("@ytt:data", "data")) 하고 변수가 필요한 부분에서는 #@ data.values.<name> 의 형태로 사용하면된다. 템플릿이 잘 만들어지는 실행해보자.

$ ytt -f config.yml -f schema.yml
# 또는
$ ytt -f .

apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend-deployment
  namespace: default
  labels:
    app.kubernetes.io/version: 0.1.0
    app.kubernetes.io/name: frontend
spec:
  selector:
    matchLabels:
      app: frontend
  replicas: 1
  template:
    spec:
      containers:
      - name: frontend
        image: index.docker.io/k14s/image@sha256:6ab29951e0207fde6760f6db227f218f20e875f45b22e8ca0ee06c0c8cab32cd
---
apiVersion: v1
kind: Service
metadata:
  name: frontend-service
  labels:
    app.kubernetes.io/version: 0.1.0
    app.kubernetes.io/name: frontend
spec:
  type: ClusterIP
  ports:
  - port: 80

 

5. 더 많은 기능들

지금까지 ytt 의 기초적인 내용들을 살펴봤다. 하지만, ytt를 더 강력하게 만드는 기능들이 있다. 데이터 설정 언어로서 제공하는 주요 기능들을 나열하자면 다음과 같다.

  • overlay
  • data validation
  • data type(String, Int, List, Dictionary, Struct)
  • 조건 제어(IF condition, For loop)
  • 함수(Function)
  • YAML 조각(fragment)

다음 글에서는 각 기능들에 대해 알아보도록 하자.

이 글을 공유하기

댓글

Designed by JB FACTORY