devops
Prometheus 헬름 차트 분석하기 본문
Helm 차트를 무작정 만드는 것은 쉬우나, 더 적은 코드로 효율적으로 짜는 것은 쉽지않다. 그러기 위해선 이미 잘 만들어진 Helm 차트를 한번 뜯어보고 어떤 흐름제어와 함수들이 사용되었는 지를 확인해보면 좋다고 생각한다.
Prometheus는 웬만한 서비스들이 사용하는 모니터링 툴이자, 차트도 잘 짜여져있어 참고해보면 좋다.
Prometheus Helm chart
# Prometheus helm root path
Chart.yaml
Chart.lock
README.md
values.yaml
templates
- NOTES.txt
- _helpers.tpl
- alertmanager
- node-exporter
- server
- pushgateway
...
Chart dependency
Helm 차트에는 여러 차트가 종속되어 있어 단순히 helm install을 통해서 리소스를 생성할 수 없다. Chart.yaml을 살펴보면 아래와 같이 dependencies 섹터에 alertmanager, kube-state-metrics... 등의 차트들이 나열된 것을 볼 수 있다.
apiVersion: v2
name: prometheus
appVersion: v2.45.0
version: 23.0.0
kubeVersion: ">=1.16.0-0"
description: Prometheus is a monitoring system and time series database.
...
dependencies:
- name: alertmanager
version: "0.33.*"
repository: https://prometheus-community.github.io/helm-charts
condition: alertmanager.enabled
- name: kube-state-metrics
version: "5.8.*"
repository: https://prometheus-community.github.io/helm-charts
condition: kube-state-metrics.enabled
- name: prometheus-node-exporter
version: "4.18.*"
repository: https://prometheus-community.github.io/helm-charts
condition: prometheus-node-exporter.enabled
- name: prometheus-pushgateway
version: "2.3.*"
repository: https://prometheus-community.github.io/helm-charts
condition: prometheus-pushgateway.enabled
...
해당 차트의 version과 repository 위치가 입력되는데, 여기서 version의 경우, patch가 *로 입력되어있다. 이는 해당 major와 minor를 만족하는 버전에서 가장 최신의 patch를 설치하도록 한다. 사용 여부는 condition의 true, false로 결정된다. 당연히 values.yaml에서 지정한다.
그래서 prometheus helm chart를 설치하기 위해서는 다음과 같은 순서로 명령어를 진행한다.
- helm repo add (prometheus 레포지토리 추가)
- helm pull (prometheus 차트 다운로드)
- helm dependency update (종속된 패키지 다운로드)
- charts 라는 디렉토리와 함께 종속 패키지의 tgz 파일이 생성된다.
- Chart.lock 파일이 생성되어 다운된 종속 패키지의 내용이 담긴다.
- helm dependency list를 통해서 다운된 종속 패키지의 리스트 확인이 가능하다.
- helm install (prometheus와 종속된 패키지 설치)
주요 함수
1) SplitList
<splitList>
{{- $url := splitList "/" "helm.sh/docs/helm" }}
host {{ first $url }}
url 배열에 ["helm.sh" "docs" "helm"] 이 추가되고 host 변수에 $url의 첫번째 값인 helm.sh가 저장된다.
2) RegexMatch
<regexMatch>
regexmatch: {{ regexMatch ".*\\.ya?ml$" "config.yaml" }}
regex는 regular expression의 줄임말로, 첫번째 인자값과 두번째 인자값과 매치가 되면 True, 아니면 False를 출력한다.
3) Index
<index>
colors: "{{ index.Values.colors 0 }}"
# values.yaml
# colors:
# - "blue"
# - "red"
# - "green"
Values.yaml을 통해 colors가 위와 같이 선언되어 있다면 index함수에서는 가장 첫번째 값인 blue가 출력된다.
path: /{{ index.Values "server" "path" "prefix" }}/ready
# values.yaml
# server:
# path:
# prefix: "prom"
index 함수는 위와 같이 직접 경로를 지정해서 해당 값을 출력할 수 도 있다. 위 함수의 결과는 'prom/ready'가 출력된다.
4) semver
{{- $version := semver "1.2.3-alpha.1+123" -}}
시멘틱 버전을 관리하기 위한 함수로, 위와 같은 입력은 아래와 같이 변수로 지정되어 사용할 수 있다.
$version.Major = 1
$version.Minor = 2
$version.Patch = 3
$version.Prerelease = alpha.1
$version.Metadata = 123
$version.Original = 1.2.3-alpha.1+123
yaml 파일 살펴보기
[cm.yaml]
{{- if (empty .Values.server.configMapOverrideName) -}}
apiVersion: v1
kind: ConfigMap
metadata:
labels:
{{- include "prometheus.server.labels" . | nindent 4 }}
{{- with .Values.server.extraConfigmapLabels }}
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ template "prometheus.server.fullname" . }}
namespace: {{ include "prometheus.namespace" . }}
data:
allow-snippet-annotations: "false"
{{- $root := . -}}
{{- range $key, $value := .Values.ruleFiles }}
{{ $key }}: {{- toYaml $value | indent 2 }}
{{- end }}
{{- range $key, $value := .Values.serverFiles }}
{{ $key }}: |
{{- if eq $key "prometheus.yml" }}
global:
{{ $root.Values.server.global | toYaml | trimSuffix "\n" | indent 6 }}
{{- if $root.Values.server.remoteWrite }}
remote_write:
{{ $root.Values.server.remoteWrite | toYaml | indent 4 }}
{{- end }}
{{- if (empty .Values.server.configMapOverrideName) -}}
- cm.yaml을 보면 처음 Values.yaml 에 server.configMapOverrideName이 입력되지 않았다면 true가 출력되어 cm.yaml의 내용이 적용된다.
{{- include "prometheus.server.labels" . | nindent 4 }}
- metadata.labels에 include를 통해서 _helpers.tpl의 prometheus.server.labels의 내용들을 가져온다.
{{- range $key, $value := .Values.ruleFiles }}
{{ $key }}: {{- toYaml $value | indent 2 }}
{{- end }}
- Values.ruleFiles의 key와 value를 불러오는 것으로 아래와 같이 ruleFiles에 선언된 내용이 입력되는데 아쉽게도 선언되어 있진 않다.
[ingress.yaml]
{{- if .Values.server.ingress.enabled -}}
{{- $ingressApiIsStable := eq (include "ingress.isStable" .) "true" -}}
{{- $ingressSupportsIngressClassName := eq (include "ingress.supportsIngressClassName" .) "true" -}}
{{- $ingressSupportsPathType := eq (include "ingress.supportsPathType" .) "true" -}}
{{- $releaseName := .Release.Name -}}
{{- $serviceName := include "prometheus.server.fullname" . }}
{{- $servicePort := .Values.server.service.servicePort -}}
{{- $ingressPath := .Values.server.ingress.path -}}
{{- $ingressPathType := .Values.server.ingress.pathType -}}
{{- $extraPaths := .Values.server.ingress.extraPaths -}}
apiVersion: {{ template "ingress.apiVersion" . }}
kind: Ingress
metadata:
{{- if .Values.server.ingress.annotations }}
annotations:
{{ toYaml .Values.server.ingress.annotations | indent 4 }}
...
spec:
{{- if and $ingressSupportsIngressClassName .Values.server.ingress.ingressClassName }}
ingressClassName: {{ .Values.server.ingress.ingressClassName }}
{{- end }}
rules:
{{- range .Values.server.ingress.hosts }}
{{- $url := splitList "/" . }}
- host: {{ first $url }}
http:
paths:
...
{{- $releaseName := .Release.Name -}}
{{- $serviceName := include "prometheus.server.fullname" . }}
{{- $servicePort := .Values.server.service.servicePort -}}
{{- $ingressPath := .Values.server.ingress.path -}}
- Release.Name, _helpers.tpl에 선언된 server.fullname 그리고 values.yaml에 선언된 server.service.servicePort와 server.ingress.path가 각각 입된다.
{{- range .Values.server.ingress.hosts }}
{{- $url := splitList "/" . }}
- host: {{ first $url }}
http:
paths:
- values.yaml에서 server.ingress.hosts 값의 전체 주소가 '/'를 기준으로 나누어져 url 변수에 배열로 할당된다. 만약 hosts의 값이 'prometheus.com/login' 이라고 한다면 first에 할당된 변수는 prometheus.com이 되기 때문에 host에 선언된다.
[sts.yaml]
...
{{- if semverCompare ">=1.13-0" .Capabilities.KubeVersion.GitVersion }}
{{- if or (.Values.server.enableServiceLinks) (eq (.Values.server.enableServiceLinks | toString) "<nil>") }}
enableServiceLinks: true
{{- else }}
enableServiceLinks: false
{{- end }}
{{- end }}
...
{{- range .Values.configmapReload.prometheus.extraVolumeDirs }}
- --watched-dir={{ . }}
{{- end }}
...
{{- if semverCompare ">=1.13-0" .Capabilities.KubeVersion.GitVersion }}
- 1.13 버전보다 뒤의 값이 큰지를 판단하는 것으로 kubeversion에서 gitversion이 크다면 true가 된다.
{{- if or (.Values.server.enableServiceLinks) (eq (.Values.server.enableServiceLinks | toString) "<nil>") }}
- values.yaml에서 enbaleServiceLinks가 true면 or 조건이기 때문에 뒤이은 조건에 상관없이 if문은 true가 된다. 이 조건은enableServiceLinks의 값이 null인지 확인하는 것으로 볼 수 있다.
{{- range .Values.configmapReload.prometheus.extraVolumeDirs }}
- --watched-dir={{ . }}
{{- end }}
- watched-dir={{ . }}는 configmapReload.prometheus.extraVolumeDirs의 watched-dir key에 입력되는 모든 값을 말한다.
'DevOps > Opensource' 카테고리의 다른 글
helm chart 만드는 팁 (0) | 2023.07.09 |
---|---|
Grafana 헬름 차트 분석하기 (0) | 2023.07.09 |
Windows Mongodb Shutdown exitCode 100 에러 해결 방법 (0) | 2022.09.03 |
mysql 외부접속 안될 때, "Can't connect to MySQL server on 'ip'"해결방법 (0) | 2022.08.28 |
Prometheus(프로메테우스) 모니터링이란 (0) | 2022.07.15 |