ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Helm] 토픽 - 템플릿과 Values.yaml
    공부/쿠버네티스&헬름 2025. 3. 4. 00:48

    Helm Chart 템플릿은 Go 템플릿 언어로 작성되며 Sprig 라이브러리의 다양한 템플릿 함수와 특수 함수들이 추가적으로 제공됩니다.

    모든 템플릿 파일은 차트의 templates/ 폴더에 저장됩니다. Helm은 차트를 렌더링할 때 이 폴더의 모든 파일을 템플릿 엔진을 통해 처리합니다.

    템플릿 values 제공 방식은 두가지 방법으로 제공합니다.

    • values.yaml 파일
      • 차트 개발자는 values.yaml 파일을 통해 기본값을 제공할 수 있습니다.
    • 사용자 정의 values 파일
      • 차트 사용자는 사용자 정의 값을 담은 YAML 파일을 제공할 수 있습니다.
      • 이 파일은 helm install 명령어를 통해 전달됩니다.
      • 사용자 정의 값은 values.yaml 파일의 기본값을 재정의합니다.

    템플릿 파일

    템플릿 파일은 Go 템플릿을 작성하기 위한 표준 규칙을 따릅니다( 자세한 내용은 text/template Go 패키지 설명서 참조 ). 예시 템플릿 파일은 다음과 같습니다.

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: deis-database
      namespace: deis
      labels:
        app.kubernetes.io/managed-by: deis
    spec:
      replicas: 1
      selector:
        app.kubernetes.io/name: deis-database
      template:
        metadata:
          labels:
            app.kubernetes.io/name: deis-database
        spec:
          serviceAccount: deis-database
          containers:
            - name: deis-database
              image: {{ .Values.imageRegistry }}/postgres:{{ .Values.dockerTag }}
              imagePullPolicy: {{ .Values.pullPolicy }}
              ports:
                - containerPort: 5432
              env:
                - name: DATABASE_STORAGE
                  value: {{ default "minio" .Values.storage }}

    템플릿 작성자는 values.yaml 파일에 기본값을 정의하여 차트 사용자가 설정을 변경할 수 있도록 합니다. 예시에서는 다음과 같은 템플릿 값을 정의했습니다.

    • imageRegistry: 도커 이미지 레지스트리
    • dockerTag: 도커 이미지 태그
    • pullPolicy: 쿠버네티스 풀 정책
    • storage: 저장소 백엔드 (기본값: "minio")

    템플릿 작성자는 필요한 매개변수를 자유롭게 정의할 수 있으며, Helm은 특정 매개변수를 요구하지 않습니다. 차트 사용자는 values.yaml 파일을 수정하거나, helm install 명령어를 통해 사용자 정의 값을 제공하여 템플릿 값을 변경할 수 있습니다. 사용자 정의 값이 제공되면 values.yaml 파일의 기본값이 재정의됩니다.

    미리 정의된 values

    values.yaml 파일 또는 -set 플래그를 통해 제공되는 값들은 .Values 객체에서 접근할 수 있습니다.

    아래는 미리 정의된 values이고 모든 템플릿에서 사용할 수 있으며 재정의가 불가합니다.

    • Release.Name: 릴리스 이름 (차트 이름이 아님)
      • Release.Name은 사용자가 helm install 명령어에서 지정하는 릴리스 이름을 나타내며 Chart.yaml 파일의 name 필드에 정의된 차트 이름과는 다름
    • Release.Namespace: 차트가 릴리스된 네임스페이스
    • Release.Service: 릴리스를 진행한 서비스
    • Release.IsUpgrade: 현재 작업이 업그레이드 또는 롤백인 경우 true
    • Release.IsInstall: 현재 작업이 설치인 경우 true
    • Chart: Chart.yaml 파일의 내용
      • 예: .Chart.Version, .Chart.Maintainers
    • Files: 차트의 모든 비특수 파일을 포함하는 맵과 같은 객체
      • .helmignore 파일에 의해 제외되지 않은 추가 파일에 접근 가능
      • 파일 내용은 .Files.Get name 또는 .Files.GetBytes 함수를 사용하여 접근 가능
    • Capabilities: 쿠버네티스 버전 및 지원되는 API 버전에 대한 정보
      • 예: .Capabilities.KubeVersion, .Capabilities.APIVersions.Has "batch/v1"

    모든 values의 이름은 대소문자를 구분합니다. Chart.yaml 파일의 알 수 없는 필드는 삭제되어 .Chart 객체에서 접근할 수 없습니다. 따라서 임의의 구조화된 데이터를 템플릿에 전달하려면 values 파일을 사용해야 합니다.

    values.yaml

    values.yaml 예시는 다음과 같습니다.

    imageRegistry: "quay.io/deis"
    dockerTag: "latest"
    pullPolicy: "Always"
    storage: "s3"

    values 파일은 YAML로 포맷됩니다. 차트에는 기본 values.yaml 파일이 포함될 수 있습니다. Helm install 명령을 사용하면 사용자가 추가 YAML 값을 제공하여 values를 재정의할 수 있습니다.

    만약 myvals.yaml 파일에 storage: "gcs" 로 되어 있고 helm install로 values를 재정의 한다면 다음과 같이 병합이 됩니다.

    **$** helm install --generate-name --values=myvals.yaml wordpress
    
    ----
    # 병합된 values.yaml
    imageRegistry: "quay.io/deis"
    dockerTag: "latest"
    pullPolicy: "Always"
    storage: "gcs"

    이러한 values는 .Values 객체를 사용하여 템플릿 내부에서 접근할 수 있습니다.

    apiVersion: v1
    kind: ReplicationController
    metadata:
      name: deis-database
      namespace: deis
      labels:
        app.kubernetes.io/managed-by: deis
    spec:
      replicas: 1
      selector:
        app.kubernetes.io/name: deis-database
      template:
        metadata:
          labels:
            app.kubernetes.io/name: deis-database
        spec:
          serviceAccount: deis-database
          containers:
            - name: deis-database
              image: {{ .Values.imageRegistry }}/postgres:{{ .Values.dockerTag }}
              imagePullPolicy: {{ .Values.pullPolicy }}
              ports:
                - containerPort: 5432
              env:
                - name: DATABASE_STORAGE
                  value: {{ default "minio" .Values.storage }}

    scope, 의존성, values

    Helm Chart의 values 파일(values.yaml)은 최상위 차트뿐만 아니라 종속성 차트( charts/ 디렉토리에 포함된 차트)에 대한 설정도 정의할 수 있습니다. 즉, 하나의 values 파일로 차트와 그 의존성들에 대한 설정을 모두 관리할 수 있습니다.

    title: "My WordPress Site" # Sent to the WordPress template
    
    mysql:
      max_connections: 100 # Sent to MySQL
      password: "secret"
    
    apache:
      port: 8080 # Passed to Apache

    상위 레벨의 차트는 하위 레벨에 정의된 모든 변수에 접근할 수 있습니다. 예를 들어, WordPress 차트는 .Values.mysql.password를 통해 MySQL 차트의 비밀번호에 접근할 수 있습니다.

    하위 레벨의 차트는 상위 레벨의 값에 접근할 수 없습니다. 예를 들어, MySQL 차트는 WordPress 차트의 title 속성이나 Apache 차트의 port 속성에 접근할 수 없습니다.

    값은 네임스페이스로 관리되지만 하위 차트로 전달될 때 네임스페이스 접두사가 제거됩니다. WordPress 차트는 .Values.mysql.password로 MySQL 비밀번호에 접근하지만 MySQL 차트는 단순히 .Values.password로 접근합니다. 즉, 하위 차트에서는 자신의 범위 내에서 정의된 값에만 접근할 수 있습니다.

    global values

    2.0.0-Alpha.2부터 Helm은 특별한 전역 values을 지원합니다.

    title: "My WordPress Site" # Sent to the WordPress template
    
    global:
      app: MyWordPress
    
    mysql:
      max_connections: 100 # Sent to MySQL
      password: "secret"
    
    apache:
      port: 8080 # Passed to Apache

    values.yaml 파일에 global 섹션을 추가하여 전역 변수를 정의할 수 있습니다. 예시에서는 global 섹션에 app: MyWordPress를 추가했습니다.

    global 섹션에 정의된 값은 모든 차트에서 .Values.global.app 형식으로 접근할 수 있습니다. 예를 들어, mysql 템플릿과 apache 차트 모두 {{ .Values.global.app }}를 사용하여 app 변수에 접근할 수 있습니다.

    title: "My WordPress Site" # Sent to the WordPress template
    
    global:
      app: MyWordPress
    
    mysql:
      global:
        app: MyWordPress
      max_connections: 100 # Sent to MySQL
      password: "secret"
    
    apache:
      global:
        app: MyWordPress
      port: 8080 # Passed to Apache

    global 섹션을 통해 최상위 레벨의 변수를 모든 하위 차트와 공유할 수 있습니다. 이는 레이블과 같은 메타데이터 속성을 설정하는 데 유용합니다.

    하위 차트에서 선언된 global 변수는 하위 차트의 하위 차트(손자 차트)로 전달되지만, 상위 차트로는 전달되지 않습니다. 즉, 하위 차트는 상위 차트의 값에 영향을 줄 수 없습니다.

    상위 차트의 전역 변수는 하위 차트의 전역 변수보다 우선순위가 높습니다. 만약, 같은 이름의 전역 변수가 상위차트와 하위차트에 동시에 존재할경우 상위차트의 변수가 우선시 됩니다.

    values 스키마 파일

    차트 유지 관리자는 values.schema.json 파일을 사용하여 값(values)에 대한 스키마를 정의할 수 있습니다. 이를 통해 값의 구조와 유효성을 검증할 수 있습니다.

    스키마는 JSON Schema 형식으로 작성됩니다. 이를 통해 값의 데이터 유형, 필수 필드, 허용되는 값 범위 등을 정의할 수 있습니다.

    제공된 예시를 통해 값의 구조를 정의하고, 유효성을 검증할 수 있습니다.

    {
      "$schema": "https://json-schema.org/draft-07/schema#",
      "properties": {
        "image": {
          "description": "Container Image",
          "properties": {
            "repo": {
              "type": "string"
            },
            "tag": {
              "type": "string"
            }
          },
          "type": "object"
        },
        "name": {
          "description": "Service name",
          "type": "string"
        },
        "port": {
          "description": "Port",
          "minimum": 0,
          "type": "integer"
        },
        "protocol": {
          "type": "string"
        }
      },
      "required": [
        "protocol",
        "port"
      ],
      "title": "Values",
      "type": "object"
    }

    이 스키마는 values에 적용되어 다음 명령 중 하나가 호출되면 유효성을 검사합니다.

    • helm install
    • helm upgrade
    • helm lint
    • helm template

    values 권장사항

    네이밍 컨벤션

    변수 이름은 소문자로 시작해야 하며 단어는 카멜케이스(camelcase)로 구분해야 합니다.

    chicken: true
    chickenNoodleSoup: true

    Helm의 모든 내장 변수는 사용자 정의 값과 쉽게 구별할 수 있도록 대문자로 시작합니다( .Release.Name, .Capabilities.KubeVersion).

    flat 또는 중첩 values

    YAML은 유연한 형식이며 값을 중첩하거나 flat하게 할 수 있습니다.

    # 중첩 예시
    server:
      name: nginx
      port: 80
    
    # 플랫 예시  
    serverName: nginx
    serverPort: 80

    대부분의 경우, 중첩된 것보다 플랫을 선호해야 합니다. 그 이유는 템플릿 개발자와 사용자에게 더 간단하기 때문입니다.

    최적의 안전성을 위해 중첩된 값은 모든 수준에서 검사되어야 합니다.

    {{ if .Values.server }}
      {{ default "none" .Values.server.name }}
    {{ end }}

    모든 중첩 계층에 대해 존재 확인을 해야 합니다. 하지만 플랫 구성의 경우 이러한 확인을 건너뛸 수 있으므로 템플릿을 읽고 사용하기가 더 쉽습니다.

    {{ default "none" .Values.serverName }}

    타입 명확하게 하기

    YAML의 타입 변환 규칙은 때때로 직관적이지 않습니다. 예를 들어, foo: falsefoo: "false"는 서로 다른 값을 나타냅니다. 큰 정수(예: foo: 12345678)는 경우에 따라 과학적 표기법으로 변환될 수 있습니다.

    문자열은 명시적으로 따옴표로 감싸고 그 외의 값은 암시적으로 처리하는 것이 좋습니다. 즉, 모든 문자열을 따옴표로 묶는 것을 권장합니다. 정수 캐스팅 문제를 피하기 위해 정수를 문자열로 저장하고 템플릿에서 {{ int $value }}를 사용하여 문자열을 정수로 다시 변환하는 것이 유리할 수 있습니다.

    대부분의 경우, 명시적 타입 태그(예: foo: !!string 1234)는 존중되어 1234를 문자열로 처리합니다. 그러나 YAML 파서는 태그를 소비하므로, 타입 데이터는 한 번의 파싱 후에 손실됩니다.

    values를 어떻게 사용할지 고려하기

    • 값의 세 가지 소스:
      1. 차트의 values.yaml 파일
      2. helm install -f 또는 helm upgrade -f로 제공되는 values 파일
      3. helm install 또는 helm upgrade-set 또는 -set-string 플래그로 전달되는 값

    차트 사용자는 f 플래그 또는 -set 옵션을 통해 값을 재정의할 수 있다는 점을 염두에 두고 values 구조를 설계해야 합니다. -set 옵션은 표현력이 제한적이므로 values.yaml 파일을 작성할 때 -set으로 쉽게 재정의할 수 있도록 하는 것이 중요합니다. 이러한 이유로 values 파일을 맵(map)을 사용하여 구조화하는 것이 좋습니다.

    아래는 -set으로 다루기 힘든 구조 예시입니다.

    servers:
      - name: foo
        port: 80
      - name: bar
        port: 81

    Helm 2.4 이하 버전에서는 배열의 특정 요소에 접근하여 값을 설정하는 것이 -set 플래그로 불가능했습니다. Helm 2.5부터는 servers[0].port=80과 같은 방식으로 배열의 특정 요소에 접근할 수 있게 되었습니다.

    배열 인덱스를 사용하는 방식은 사용자가 이해하기 어렵고, 오류 발생 가능성이 높습니다. 특히, 나중에 servers 배열의 순서가 변경되면 설정이 잘못 적용될 수 있습니다.

    이러한 문제를 방지하기 위해 values.yaml 파일을 설계할 때 -set 플래그로 쉽게 재정의할 수 있는 구조를 고려해야 합니다. 맵(map)을 사용하여 값을 구조화하는 것이 배열 인덱스를 사용하는 것보다 더 안전하고 유연합니다.

    servers:
      foo:
        port: 80
      bar:
        port: 81

    위처럼 변경하면 --set servers.foo.port=80 와 같이 foo의 포트에 접근하는 것이 더 명확해집니다.

    상세한 주석 추가

    values.yaml 파일에 정의된 모든 속성은 문서화되어야 합니다. 문서화 문자열은 설명하는 속성의 이름으로 시작해야 합니다. 최소한 한 문장으로 속성에 대한 설명을 제공해야 합니다.

    -- 잘못된 예시
    
    # the host name for the webserver
    serverHost: example
    serverPort: 9191
    
    -- 잘된 예시
    # serverHost is the host name for the webserver
    serverHost: example
    # serverPort is the HTTP listener port for the webserver
    serverPort: 9191

    각 주석을 해당 문서의 매개변수 이름으로 시작하면 문서를 쉽게 grep하여 볼 수 있으며 문서화 도구가 문서 문자열과 해당 매개변수를 안정적으로 연관시킬 수 있습니다.

    변수 주입

    Values 객체는 차트로 전달된 값에 접근을 할 수 있는데 다음과 같은 우선순위를 가집니다.

    1. --set foo=bar
    2. -f values_xxx.yaml
    3. 서브차트일 경우, 부모 차트의 values.yaml
    4. 차트 생성 후 기본으로 생성된 values.yaml

    레퍼런스

    https://helm.sh/docs/topics/charts/#templates-and-values

    https://helm.sh/docs/chart_best_practices/values/

    댓글