Helm - менеджер пакетов для k8s. Позволяет обернуть приложения в пакеты и работать с ними
Charts - собсна пакеты, включают в себя все что нужно приложению для запуска в k8s. Позволяет работать с приложением как с цельным пакетом а не набором отдельных манифестов
Есть функционал для добавления логики после подготовки манифестов но перед применением
По сути сводится к баш скрипту, через который прогоняется текстовый поток всех манифестов, в нем с-но можно делать правки
Вызывается параметр в команде запуска хельма
helm install my-chart ./mychart --post-renderer ./post-render.sh
Зависимости можно описать в «Chart.yaml» или «requirements.yaml», указав название, версию, репозиторий нужных чартов. Тогда хельм будет автоматически их все тянуть
Для работы с ними есть команды «helm dependency [list, update, build]«
Есть стандартный порядок, можно им управлять с помощью хуков
Задается аннотацией прямо в манифесте, так же у хуков есть «вес», в рамках одного и того же шага
apiVersion: external-secrets.io/v1beta1 kind: SecretStore metadata: ... annotations: "helm.sh/hook": pre-install "helm.sh/hook-weight": "-2"
Чарт - предварительно настроенный шаблон ресурсов
Релиз - чарт, развернутый с помощью Helm в k8s
helm install <release name> <chart name> # Тест итогового манифеста helm install --dry-run test-release ./helm-chart # Переопределение параметров при запуске (можно указать файлом) helm install -n kubectl-ns --set certificateSecretStore.enabled=false my-app ./helm-chart helm install -n kubectl-ns -f ./my-app-values.yaml my-app ./helm-chart
# Просто переменная metadata: name: {{ .Release.Name }}-certificate-secret-store --- # Вставляем шаблон "helm-chart.labels" и передаем вывод через шаблонную ф-ю "nident" # в данном случае она добавляет пробелы (4шт) metadata: labels: {{- include "helm-chart.labels" . | nindent 4 }} --- #
Есть ф-я «toYaml», пока неясно как но видимо в чем то помогает
spec: ... template: ... spec: containers: - name: {{ .Release.Name }}-app image: {{ .Values.deployment.image }} ports: - name: {{ .Values.clusterip.targetPort }} containerPort: {{ .Values.deployment.containerPort }} resources: {{- toYaml .Values.deployment.resources | nindent 10 }} {{- if .Values.lockboxSecretStore.enabled }} env: {{- range .Values.lockboxSecretStore.externalSecret.data }} - name: {{ .secretKey }} valueFrom: secretKeyRef: name: {{ $.Release.Name }}-lockbox-secret key: {{ .secretKey }} {{- end }} {{- end }}
values.yaml в данном случае такой
clusterip: port: 80 targetPort: http deployment: replicaCount: 1 image: "" containerPort: 8080 resources: requests: cpu: "150m" memory: "400Mi" limits: cpu: "250m" memory: "600Mi"
Включение/Отключение частей кода с помощью переменных
Объявляем нужные переменные в «values.yaml», значение по умолчанию «true»
lockboxSecretStore: enabled: true certificateSecretStore: enabled: true
Затем в манифесте проверка переменных, ветвление
{{- if .Values.certificateSecretStore.enabled -}} apiVersion: external-secrets.io/v1beta1 kind: SecretStore ... {{- end }}
При запуске, переменную можно переопределить
helm install --dry-run --set certificateSecretStore.enabled=false test-release ./helm-chart
Пример с IF. Переменные в шаблоне
В двух циклах проверяем наличие чего либо во вложенном списке, если есть присваиваем контрольной переменной значение и на основании создаем или не создаем манифест
{{ $my_var := false }} {{- range $svc := .Values.list_sys_services }} {{- range $port := $svc.listen_ports }} {{ $my_var = true }} {{- end }} {{- end }} {{- range $svc := .Values.list_plugin_services }} {{- range $port := $svc.listen_ports }} {{ $my_var = true }} {{- end }} {{- end -}} {{- if $my_var }} manifest: "exist" var_before: {{ $my_var }} {{- end -}}
Для циклов используется оператор «range»
lockboxSecretStore: enabled: true externalSecret: secretId: "" data: - secretKey: JDBC_URL property: JDBC_URL - secretKey: DB_USERNAME property: DB_USERNAME - secretKey: DB_PASSWORD property: DB_PASSWORD
spec: ... data: {{- range .Values.lockboxSecretStore.externalSecret.data }} - secretKey: {{ .secretKey }} remoteRef: key: {{ $.Values.lockboxSecretStore.externalSecret.secretId }} property: {{ .property }} {{- end }}
Знак $ - операторы «range» и «with» создают свою область видимости (точка указывает на текущую область). Чтобы получить значения из «values.yaml» нужно задать корневую область видимости, что и делает этот параметр
★ Если файл yaml то все должно быть четко yaml, иначе шаблонизатор падает
прям душнила …….
★ «удалятры» (-) удаляют пустые строки
helm template . –debug
# Values my_string: "this string" my_list: ["this", "list"] my_empty_list: [] # В шаблоне string: {{ .Values.my_string }} list: {{ .Values.my_list }} empty_list: {{ .Values.my_empty_list }} none_list: {{ .Values.my_none_list }} # Вывод string: this string list: [this list] empty_list: [] none_list:
В случае несуществующей переменной, в блоке IF можно дополнительно не приседать, если переменной нет то блок IF не отработает
{{- if .Values.no_exist_var }} no_exist_var: exist {{ end }}
Цикл при несуществующей переменной тоже нормально отрабатывает
Еще пример по работе с циклом. Обращение к элементу
{{- range $item := .Values.my_list }} item: {{ $item }} {{- end }} # Альтернатива {{- range .Values.my_list }} item: {{ . }} {{- end }}
Вставка содержимого файла в шаблоне
Переменные
config_service_version: v1 config_service_dir: config service: test
Шаблон
--- apiVersion: v1 kind: ConfigMap metadata: name: {{ .Values.service }}-{{ .Values.config_service_version }} data: config.json: |- {{ .Files.Get (printf "%s/%s-%s.json" .Values.config_service_dir .Values.service .Values.config_service_version ) | indent 4 }} config_base64.json: |- {{ .Files.Get "my-file.json" | indent 4 | b64enc }}
Специально для манифестов
Эти функции сами подставляются в формате «имя-файла: значение», секреты сразу кодируются
apiVersion: v1 kind: ConfigMap metadata: name: conf data: {{ (.Files.Glob "foo/*").AsConfig | indent 2 }} --- apiVersion: v1 kind: Secret metadata: name: very-secret type: Opaque data: {{ (.Files.Glob "bar/*").AsSecrets | indent 2 }}
Проверка существования файла
{{ $res := .Files.Glob "input_files/resources.zip" }} {{- if $res }} apiVersion: v1 kind: Secret type: Opaque metadata: name: my-secrets labels: app: my-app data: {{ ($res).AsSecrets | indent 2 }} {{ end }}
★ Область видимости, если объявлена в блоке, будет доступна только в блоке, глобальные так же доступны в блоке, имена могут пересекаться
★ »:=» объявляет новую переменную, «=» присваивает значение существующей
# Объявили переменную {{ $my_var := "first" }} port1: {{ $my_var }} # Присвоили новое значение {{- $my_var = "second" }} port2: {{ $my_var }} # Внутри блока (цикла) присвоили новое значение {{ range $svc := .Values.list_sys_services }} {{ $my_var = "three" }} var_in_range_after: {{ $my_var }} # Если использовать := то будет новая, локальная переменная, имя может пересекаться с глобальной {{ $my_var = "this_is_local" }} # здесь уже применяется локальная var_in_range_after: {{ $my_var }} {{- end }} # здесь глобальная, с обновленным значением, "three" var_after_range: {{ $my_var }}