Jsonnet 실무 가이드: 쿠버네티스 매니페스트 템플릿화

💡 핵심 요약 (Executive Summary)

본 가이드는 jsonnet 핵심 가이드 및 실전 아키텍처의 핵심 개념, 실전 구성 명령어 및 아키텍처 베스트 프랙티스를 다룹니다. 클라우드 네이티브 및 인프라 엔지니어링 실무에 즉시 활용 가능하도록 체계적으로 정리했습니다.

📑 Table of Contents
Installation
  1. jsonnet (c build or go build)
  2. jsonnet bundler — package manager
bash
brew install jsonnet jsonnet-bundler
Set up
bash
# initiate the package manager
jb init
# >> this will create jsonnetfile.json in your repository

# install k8s jsonnet lib
jb install github.com/jsonnet-libs/k8s-libsonnet/1.32@main

# after that you can use `jb install` to install all libs from jsonnetfile.json

your jsonnetfile.json should look like this

json
{
  "version": 1,
  "dependencies": [
    {
      "source": {
        "git": {
          "remote": "https://github.com/jsonnet-libs/k8s-libsonnet.git",
          "subdir": "1.32" #kubernetes version (lib version)
        }
      },
      "version": "main"
    }
  ],
  "legacyImports": true
}

and you will also have a new folder named vendor .

run it

you can use jsonnet to generate json output from jsonnet file

create hello.jsonnet file

json
// hello.jsonnet
{
  hello: "jsonnet" // << jsonnet key doesn't have double quote ""
}

the run jsonnet hello.jsonnet , you will get

json
{
   "hello": "jsonnet"
}

next, we will try using k8s jsonnet lib.

Get Supakorn Warodom’s stories in your inbox

Join Medium for free to get updates from this writer.

create deploy.jsonnet file

bash
local k = import "github.com/jsonnet-libs/k8s-libsonnet/1.32/main.libsonnet";

k.apps.v1.deployment.new("hello-deployment", replicas=1, containers=[], podLabels={})

to generate the json output, you will have to use this command

bash
jsonnet -J vendor deploy.jsonnet
# jsonnet -J <LibDirectory> <file>

# result
{
   "apiVersion": "apps/v1",
   "kind": "Deployment",
   "metadata": {
      "name": "hello-deployment"
   },
   "spec": {
      "replicas": 1,
      "selector": {
         "matchLabels": {
            "name": "hello-deployment"
         }
      },
      "template": {
         "metadata": {
            "labels": {
               "name": "hello-deployment"
            }
         },
         "spec": {
            "containers": [ ]
         }
      }
   }
}
Merge syntax
basic

use + to merge jsonnet’s object.

let’s use ‘+’ to add labels.app: “hello” to metadata, spec.selector.matchLabels and spec.template.metadata

bash
// deploy-merge.jsonnet

local k = import "github.com/jsonnet-libs/k8s-libsonnet/1.32/main.libsonnet";

k.apps.v1.deployment.new("hello-deployment", replicas=1, containers=[], podLabels={})
+{metadata: {
  name: "hello-deployment",
  labels: {app: "hello"}}}
+{spec: {
    selector: {matchLabels: {app: "hello"}},
    template: {metadata: {labels: {app: "hello"}}},
}}

the result will look like this

json
{
   "apiVersion": "apps/v1",
   "kind": "Deployment",
   "metadata": {
      "labels": {
         "app": "hello"
      },
      "name": "hello-deployment"
   },
   "spec": {
      "selector": {
         "matchLabels": {
            "app": "hello"
         }
      },
      "template": {
         "metadata": {
            "labels": {
               "app": "hello"
            }
         }
      }
   }
}

look carefully and you will see that spec.replicas and spec.template.spec is gone.

This is where you will need to use nested merge operator.

nested merge

the operator is +: .

bash
// deploy-merge-nested.jsonnet
local k = import "github.com/jsonnet-libs/k8s-libsonnet/1.32/main.libsonnet";

k.apps.v1.deployment.new("hello-deployment", replicas=1, containers=[], podLabels={})
+{metadata+: {
  // don't need to put `name: "hello-deployment"` here anymore
  labels+: {app: "hello"}}}
+{spec+: {
    selector+: {matchLabels+: {app: "hello"}},
    template+: {metadata+: {labels+: {app: "hello"}}},
}}

result

json
{
   "apiVersion": "apps/v1",
   "kind": "Deployment",
   "metadata": {
      "labels": {
         "app": "hello"
      },
      "name": "hello-deployment"
   },
   "spec": {
      "replicas": 1,
      "selector": {
         "matchLabels": {
            "app": "hello",
            "name": "hello-deployment"
         }
      },
      "template": {
         "metadata": {
            "labels": {
               "app": "hello",
               "name": "hello-deployment"
            }
         },
         "spec": {
            "containers": [ ]
         }
      }
   }
}

k8s 라이브러리를 사용해서도 같은 작업을 할 수 있습니다. (제 생각에는) 대부분의 k8s 라이브러리 함수는 중첩 병합(nested merge) 연산자로 구현되어 있습니다.

Enter 키를 누르거나 이미지를 클릭하여 전체 화면으로 보세요.

그래서 이렇게 다시 쓸 수 있어요

bash
local k = import "github.com/jsonnet-libs/k8s-libsonnet/1.32/main.libsonnet";

k.apps.v1.deployment.new("hello-deployment", replicas=1, containers=[], podLabels={})
+k.apps.v1.deployment.metadata.withNamespace("api")
+k.apps.v1.deployment.metadata.withLabels({app:"hello"})
+k.apps.v1.deployment.spec.selector.withMatchLabels({app:"hello"})
+k.apps.v1.deployment.spec.template.metadata.withLabels({app:"hello"})

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *