스타일 가이드
이 문서는 GitLab Helm 차트 개발에 대한 다양한 지침과 모범 사례를 설명합니다.
네이밍 규칙
함수 이름 및 values.yaml
에서 사용될 속성에 대해 camelCase를 사용하고 있습니다.
예: gitlab.assembleHost
템플릿 함수는 해당하는 populized 값과 일치하도록 차트와 관련된 네임스페이스에 배치됩니다. 차트 전역(global) 함수는 일반적으로 gitlab.*
네임스페이스에 속합니다.
예시:
-
gitlab.redis.host
:gitlab
차트의 일부로 Redis 서버의 호스트 이름을 제공합니다. -
registry.minio.url
:registry
차트의 일부로 MinIO 호스트의 URL을 제공합니다.
values.yaml
의 일반 구조
여러 차트에서 동일한 정보를 제공해야 하는 경우, 예를 들어 Redis 및 PostgreSQL 연결 설정을 여러 차트에 제공해야 하는 경우처럼 표준 네이밍과 구조를 개요화합니다.
다른 서비스에 연결
redis:
host: redis.example.com
serviceName: redis
port: 8080
sentinels:
- host: sentinel1.example.com
port: 26379
password:
secret: gitlab-redis
key: redis-password
-
redis
- 현재 차트가 연결해야 하는 항목의 이름 -
host
- 기본적으로 serviceName의 사용을 무시하고values.yaml
에서host
를 사용합니다. 기본적으로 예시로0.0.0.0
을 사용합니다. Redis Sentinel을 사용하는 경우,host
속성은sentinel.conf
에 지정된 클러스터 이름으로 설정되어야 합니다. -
serviceName
- 기본적으로 사용하기 위해 호스트 대신 사용됩니다. 쿠버네티스 서비스 이름을 사용하여 연결합니다. -
port
- 연결할 포트입니다. 기본적으로 주석 처리하여 사용하지 않으며, 예시로 기본 포트를 사용합니다. -
password
- 암호를 포함하는 쿠버네티스 시크릿을 정의합니다. -
sentinels.[].host
- Redis HA 설정에 대한 Redis Sentinel 서버의 호스트 이름을 정의합니다. -
sentinels.[].port
- Redis Sentinel 서버에 연결할 포트를 정의합니다. 기본값은26379
입니다.
참고: 현재 Redis Sentinel 지원은 일반적으로 GitLab 차트에서 별도로 배포된 Sentinels만 지원합니다. 결과적으로, GitLab 차트를 통해 Redis 배포는 redis.install=false
로 비활성화되어야 합니다. Redis 암호를 포함하는 시크릿은 GitLab 차트를 배포하기 전에 수동으로 생성해야 합니다.
비밀 정보 공유
비밀 정보(예: 암호)를 저장하고 차트/팟 간에 공유하기 위해 시크릿을 사용합니다.
일반적으로 사용하는 필드는 다음과 같습니다:
- TLS/SSL 인증서 - TLS/SSL 인증서 공유
- 암호 - Redis 암호 공유
- 인증 토큰 - 서비스 간 인증 토큰 공유
- 기타 시크릿 - JWT 인증서 및 서명 키와 같은 기타 시크릿 공유
TLS/SSL 인증서
TLS/SSL 인증서는 유효한 쿠버네티스 TLS 시크릿으로 예상됩니다.
예를 들어, 레지스트리를 설정하는 경우:
registry:
tls:
secretName: <TLS 시크릿 이름>
차트 간에 TLS 인증서를 공유할 때, 글로벌 값으로 정의해야 합니다.
global:
ingress:
tls:
secretName: <TLS 시크릿 이름>
암호
예를 들어, redis
가 소유한 차트에서 다른 차트가 redis
암호를 참조해야 하는 경우입니다.
소유 차트는 다음과 같이 암호 시크릿을 정의해야 합니다:
password:
secret: <시크릿 이름>
key: <검색할 시크릿 내부의 키 이름>
다른 차트는 다음과 같이 동일한 암호 시크릿을 공유해야 합니다:
redis:
password:
secret: <시크릿 이름>
key: <시크릿 내부의 키 이름을 가져오기 위해>
인증 토큰
소유 차트는 다음과 같이 인증 토큰 시크릿을 정의해야 합니다:
authToken:
secret: <시크릿 이름>
key: <검색할 시크릿 내부의 키 이름>
다른 차트는 다음과 같이 동일한 인증 토큰 시크릿을 공유해야 합니다:
gitaly:
authToken:
secret: <시크릿 이름>
key: <시크릿 내부의 키 이름을 가져오기 위해>
예를 들어, gitaly
가 소유한 차트에서 다른 차트가 gitaly
의 authToken을 참조해야 하는 경우입니다.
기타 시크릿
registry
또는 gitaly
의 JWT 서명 인증서와 같은 기타 시크릿은 authToken
및 password
시크릿과 동일한 형식을 사용합니다.
한 차트에서 다른 차트로 이러한 시크릿을 공유하려면, 다음과 같이 registry
JWT 서명 인증서를 다른 차트와 공유하는 예제와 유사한 구성을 제공하십시오.
소유 차트는 다음과 같이 시크릿을 정의해야 합니다:
certificate:
secret: <시크릿 이름>
key: <검색할 시크릿 내부의 키 이름>
다른 차트는 다음과 같이 동일한 시크릿을 공유해야 합니다:
registry:
certificate:
secret: <시크릿 이름>
key: <시크릿 내부의 키 이름을 가져오기 위해>
함수 사용을 위한 기본 설정
우리는 gotmpl, Sprig 및 Helm에서 사용 가능한 다양한 기능에 대한 차트 개발 환경을 발전시켰으며, 관련하여 선호하는 기본 설정을 정립했습니다. 아래 섹션에서는 그 중 일부와 이에 대한 이유를 설명합니다.
indent 대신 nindent 사용
가능한 경우, indent
함수 대신 nindent
함수를 사용하십시오. 이 선호 사항은 가독성을 기반으로 하며, 특히 우리의 Helm 차트와 같이 복잡할 수 있는 것에 대해 적용됩니다. nindent
함수의 선호 사용은 커뮤니티 전체에 퍼져 있으며, 또한 이제는 helm create
명령으로 생성된 템플릿 내에서 기본 설정으로 사용됩니다.
다음은 그 이유를 쉽게 설명하는 두 가지 코드 스니펫입니다:
가독성이 좋음
gitlab.yml.erb: |
production: &base
gitlab:
host: {{ template "gitlab.gitlab.hostname" . }}
https: {{ hasPrefix "https://" (include "gitlab.gitlab.url" .) }}
{{- with .Values.global.hosts.ssh }}
ssh_host: {{ . | quote }}
{{- end }}
{{- with .Values.global.appConfig }}
max_request_duration_seconds: {{ default (include "gitlab.appConfig.maxRequestDurationSeconds" $) .maxRequestDurationSeconds }}
impersonation_enabled: {{ .enableImpersonation }}
application_settings_cache_seconds: {{ .applicationSettingsCacheSeconds | int }}
usage_ping_enabled: {{ eq .enableUsagePing true }}
username_changing_enabled: {{ eq .usernameChangingEnabled true }}
issue_closing_pattern: {{ .issueClosingPattern | quote }}
default_theme: {{ .defaultTheme }}
{{- include "gitlab.appConfig.defaultProjectsFeatures.configuration" $ | nindent 8 }}
webhook_timeout: {{ .webhookTimeout }}
{{- end }}
trusted_proxies:
{{- if .Values.trusted_proxies }}
{{- toYaml .Values.trusted_proxies | nindent 10 }}
{{- end }}
time_zone: {{ .Values.global.time_zone | quote }}
{{- include "gitlab.outgoing_email_settings" . | nindent 8 }}
{{- with .Values.global.appConfig }}
{{- if .incomingEmail.enabled }}
{{- include "gitlab.appConfig.incoming_email" . | nindent 6 }}
{{- end }}
{{- include "gitlab.appConfig.cronJobs" . | nindent 6 }}
gravatar:
가독성이 낮음
gitlab.yml.erb: |
production: &base
gitlab:
host: {{ template "gitlab.gitlab.hostname" . }}
https: {{ hasPrefix "https://" (include "gitlab.gitlab.url" .) }}
{{- with .Values.global.hosts.ssh }}
ssh_host: {{ . | quote }}
{{- end }}
{{- with .Values.global.appConfig }}
max_request_duration_seconds: {{ default (include "gitlab.appConfig.maxRequestDurationSeconds" $) .maxRequestDurationSeconds }}
impersonation_enabled: {{ .enableImpersonation }}
usage_ping_enabled: {{ eq .enableUsagePing true }}
username_changing_enabled: {{ eq .usernameChangingEnabled true }}
issue_closing_pattern: {{ .issueClosingPattern | quote }}
default_theme: {{ .defaultTheme }}
{{- include "gitlab.appConfig.defaultProjectsFeatures.configuration" $ | indent 8 }}
webhook_timeout: {{ .webhookTimeout }}
{{- end }}
trusted_proxies:
{{- if .Values.trusted_proxies }}
{{- toYaml .Values.trusted_proxies | indent 10 }}
{{- end }}
time_zone: {{ .Values.global.time_zone | quote }}
{{- include "gitlab.outgoing_email_settings" . | indent 8 }}
{{- with .Values.global.appConfig }}
{{- if .incomingEmail.enabled }}
{{- include "gitlab.appConfig.incoming_email" . | indent 6 }}
{{- end }}
{{- include "gitlab.appConfig.cronJobs" . | indent 6 }}
gravatar:
관련 이슈: #729 Refactoring: Helm templates
템플릿에서 toYaml
을 활용할 때
템플릿 파일에서 toYaml
을 사용하는 것을 삼가며, 이는 Kubernetes 및 원하는 커뮤니티 구성의 모든 기능을 지원하는 부담을 줄 수 있습니다. 우리의 주요 초점은 최소한의 구성을 사용하여 합리적인 기본 설정을 제공하는 데 있으며, Kubernetes의 더 고급 사용자를 위해 기본 설정을 재정의하는 능력을 제공하는 데에 기본 초점을 두고 있습니다. 이는 경우에 따라 처리되어야 하며, 물론 두 옵션 중 어느 것이 지원하기에 너무 번거롭거나 유지 관리하기 복잡한 템플릿을 제공하는지를 고려해야 합니다.
이와 같은 합리적인 기본 설정과 재정의 가능한 능력의 좋은 예시는 레지스트리 서브차트의 수평 팟 오토스케일러 구성에서 찾을 수 있습니다. 우리는 지원하기 쉬운 최소한의 구성을 기본 제공하는 것을 기본으로 삼으며, CPU 활용률을 통해 HPA를 제어하는 특정 구성을 커뮤니티에 노출시킴으로써, 보다 고급 사용자가 HPA의 다양한 메트릭을 대상으로 설정할 수 있게 하고, 따라서 사용자가 보다 복잡한 HPA 구성을 제공할 수 있는 경우에 대비해 if문을 활용할 수 있는 완벽한 예입니다.
위의 예시에서 최소한의 구성은 values.yaml
의 간단한 변경으로 이루어지며, 보다 고급 사용자는 이 지나치게 간단한 HPA 구성을 넘어서, .customMetrics
를 설정하여 HPA 메트릭 배열에 대한 적합한 Kubernetes API 호환 구성을 포함하는 배열로 override할 수 있습니다.
더 고급 사용자가 자신의 구성 파일을 불편해하지 않으면서도 가능한 한 쉽게 유지할 수 있도록 하는 것이 중요합니다.
템플릿 도우미 개발
차트 템플릿 도우미는 templates/_helpers.tpl
에 위치합니다. 여기에는 차트 내에서 사용되는 명명된 템플릿이 포함되어 있습니다.
이러한 템플릿을 사용할 때 Go 템플릿 구문에 관한 몇 가지 사항을 염두에 두어야 합니다.
작업에서 인쇄되지 않는 값 포착
Go 템플릿 구문에서 모든 작업( {{ }}
로 표시)은 문자열을 인쇄하는 것으로 예상됩니다.
제외한 경우는 제어 구조(정의, if, with, range) 및 변수 할당입니다.
이는 때로 인쇄되지 않을 것으로 의도된 출력을 포착하기 위해 변수 할당을 사용해야 할 수 있음을 의미합니다.
예를 들어:
{{- $details := .Values.details -}}
{{- $_ := set $details "serviceName" "example" -}}
{{ template "serviceHost" $details }}
위의 예에서는 출력에 몇 가지 추가 데이터를 추가한 후 템플릿 기능에 전달하기 위해 Map에 대한 몇 가지 포착합니다.
이를 통해$ _
변수에 할당하여set
함수의 출력을 포착했습니다. 이 할당이 없으면 템플릿은set
의 결과(수정된 Map을 반환함)를 문자열로 출력하려고 시도할 것입니다.
제어 구조 간 변수 전달
Go 템플릿 구문은 초기화( :=
)와 할당( =
)을 명확히 구분하며, 이는 범위에 영향을 받습니다.
결과적으로 제어 구조(if/with/range) 외부에 존재한 변수를 다시 초기화할 수 있지만, 제어 구조 내에서 선언된 변수는 외부에서 사용할 수 없음을 인식해야 합니다.
예를 들어:
{{- define "exampleTemplate" -}}
{{- $someVar := "default" -}}
{{- if true -}}
{{- $someVar := "desired" -}}
{{- end -}}
{{- $someVar -}}
{{- end -}}
위의 예에서exampleTemplate
를 호출하면 항상default
를 반환합니다. 왜냐하면desired
를 포함하던 변수는if
제어 구조 내에서만 접근할 수 있었기 때문입니다.
이 문제를 해결하기 위해 우리는 값이 다양한 범위에서 변경될 값을 보관할 Dictionary를 사용하거나 명시적으로 할당 연산자(=
대 :=
)를 사용하여 문제를 피하려고 노력합니다.
이 문제를 피하는 예제:
{{- define "exampleTemplate" -}}
{{- if true -}}
{{- "desired" -}}
{{- else -}}
{{- "default" -}}
{{- end -}}
Dictionary 사용 예제:
{{- define "exampleTemplate" -}}
{{- $result := dict "value" "default" -}}
{{- if true -}}
{{- $_ := set $result "value" "desired" -}}
{{- end -}}
{{- $result.value -}}
{{- end -}}
초기화 대 할당의 예제 (주의깊게 살펴보세요!)
{{- define "exampleTemplate" -}}
{{- $someVar := "default" -}}
{{- if true -}}
{{- $someVar = "desired" -}}
{{- end -}}
{{- $someVar -}}
{{- end -}}
템플릿 사용 예제:
{{- define "exampleTemplate" -}}
foo:
bar:
baz: bat
{{- end -}}
그리고 상기 내용을 변수 및 구성으로 가져오기:
{{- $fooVar := include "exampleTemplate" . | fromYaml -}}
{{- $barVar := merge $.Values.global.some.config $fooVar -}}
config:
{{ $barVar }}
템플릿 구성 파일
이 차트들은 클라우드 네이티브 GitLab 컨테이너를 사용합니다. 이러한 컨테이너는 ERB 또는 gomplate을 지원합니다.
지침:
- ConfigMap 내에서 템플릿 파일을 사용하십시오 (예:
gitlab.yml.erb
,config.toml.tpl
)- 항목은 템플릿으로 처리하려면 예상된 확장자를 반드시 사용해야 합니다.
- 템플릿을 사용하여 마운트된 파일 위치에서 비밀 내용을 채우십시오. (예: GitLab Pages
config
) - ERB (
.erb
)는 런타임 실행 중에 Ruby를 사용하는 모든 컨테이너에 사용할 수 있습니다. - gomplate (
.tpl
)은 모든 컨테이너에 사용할 수 있습니다.
ERB 사용:
표준 ERB를 사용하며, json
및 yaml
모듈이 미리로드되었음을 예상할 수 있습니다.
gomplate 사용:
컨테이너 내의 Ruby의 크기와 표면을 줄이기 위해 gomplate을 사용합니다. 우리는 Helm의{{ }}
사용과 충돌하지 않도록 gomplate 구문을 대체 구분 기호로 구성합니다. {% %}.
민감한 콘텐츠 템플릿화
시크릿은 올바르게 인코딩되거나 따옴표로 묶이지 않는 경우 유효하지 않은 YAML을 유발할 수 있는 문자를 포함할 수 있습니다. 특히 복잡한 암호의 경우, 이러한 문자열이 다양한 구성 형식에 추가되는 방법에 주의해야 합니다.
가이드라인:
- ERB / Gomplate 출력에서 인용 부호를 사용하세요.
- 가능한 경우 형식별 네이티브 인코더를 사용하세요.
- 렌더링된 YAML에는 YAML의 슈퍼셋인 JSON 문자열을 사용하세요.
- 렌더링된 TOML에는 TOML 문자열이 유사하게 이스케이핑되므로 JSON 문자열을 사용하세요.
- 따옴표로 묶인 문자열 내부와 같이 복잡성에 주의하세요. (예: 데이터베이스 연결 문자열 내부에 따옴표로 둘러싸인 문자열 등)
암호 인코딩 예시
Gitaly의 클라이언트 시크릿 토큰을 예로 들어보겠습니다. 이 값인 gitaly_token
은 YAML과 TOML에 템플릿으로 사용됩니다.
예시로 my"$pec!@l"p#assword%'
를 사용해 보겠습니다:
# YAML
gitaly:
token: "<%= File.read('gitaly_token').strip =>"
# TOML
[auth]
token = "<%= File.read('gitaly_token').strip %>"
렌더링된 결과는 유효하지 않은 YAML과 유효하지 않은 TOML입니다.
# YAML
gitaly:
token: "my"$pec!@l"p#assword%'"
(<unknown>): did not find expected key while parsing a block mapping at line 3 column 3
[auth]
token = "my"$pec!@l"p#assword%'"
Error on line 2: Expected Comment, Newline, Whitespace, or end of input but "$" found.
<%= File.read('gitaly_token').strip.to_json %>
로 변경하면 YAML과 TOML의 유효한 콘텐츠 형식이됩니다. <% %>
외부의 "
가 제거되었음을 주목하세요.
gitaly:
token: "my\"$pec!@l\"p#assword%'"
gomplate로도 동일한 작업을 수행할 수 있습니다: {% file.Read "gitaly_token" | strings.TrimSpace | data.ToJSON %}
gitaly:
# gomplate
token: {% file.Read "./token" | strings.TrimSpace | data.ToJSON %}
# ERB
token: <%= File.read('gitaly_token').strip.to_json %>
템플릿 차트 노트 (NOTES.txt)
Helm의 차트 노트 기능은 차트 설치 및 업그레이드 후에 유용한 정보와 후속 지침을 제공합니다.
이러한 차트 노트는 templates/NOTES.txt에 배치됩니다.
이러한 차트 노트를 작업할 때, 출력이 가독성 있고 실행 가능하도록 스타일을 유지해야 하는 몇 가지 사항이 있습니다.
노트 범주 선택
WARNING
및 NOTICE
두 가지 범주는 노트 출력에서 각 유형의 항목을 나타냅니다.
-
WARNING
은 설치를 최적화하기 위해 추가 조치가 필요함을 나타냅니다. -
NOTICE
는 추가 조치가 필요하지 않은 중요한 알림을 강조합니다.
NOTES.txt
의 각 항목은 이 두 범주 중 하나로 시작해야 합니다. 예를 들어:
{{- if eq true .Values.some.setting }}
{{ $WARNING }}
This message is a warning.
{{- end }}
{{- if eq true .Values.some.other.setting }}
{{ $NOTICE }}
This message is a notice.
{{- end }}
이러한 예시는 출력의 각 항목 사이의 일관된 제목과 간격을 보장하는 파일 상단에 포함된 미리 정의된 변수 중 하나를 사용합니다.