Инструменты пользователя

Инструменты сайта


k8s:helm

Helm Charts

habr
habr2

Helm - менеджер пакетов для k8s. Позволяет обернуть приложения в пакеты и работать с ними
Charts - собсна пакеты, включают в себя все что нужно приложению для запуска в k8s. Позволяет работать с приложением как с цельным пакетом а не набором отдельных манифестов

  • Chart.yaml основной файл, собсна описание приложения
  • Values.yaml файл с переменными, распарсенные данные и прочие переменные нужно сюда передать очевидно
  • Template/ - директория содержит шаблоны манифестов, использует данные из Chart.yaml и Values.yaml
  • Template/NOTES.txt - readme, тоже шаблонизируется из файлов выше
  • Templates/*.tpl - именованные шаблоны
  • Charts/ - директория подчартов, если требуются другие чарты, они размещаются здесь
  • .helmignore - файл для исключения файлов из собираемого пакета

Post-Renderers

Есть функционал для добавления логики после подготовки манифестов но перед применением
По сути сводится к баш скрипту, через который прогоняется текстовый поток всех манифестов, в нем с-но можно делать правки
Вызывается параметр в команде запуска хельма

helm install my-chart ./mychart --post-renderer ./post-render.sh

Helm Dependencies

Зависимости можно описать в «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"

To use

:!: Команды

Чарт - предварительно настроенный шаблон ресурсов
Релиз - чарт, развернутый с помощью Helm в k8s

  • create - создает новый чарт с указанным именем
  • package - упаковать каталог чарта в архив
  • show [chart|values|all] <chart-name> - показать информацию о чарте
  • get - расширенная информация о релизе
  • verify - верификация чарта
  • search - поиск в чарте
  • pull - загрузить чарт из репы
  • repo - работа с репами
  • install - установить чарт
  • upgrade - обновить релиз
  • list - список релизов
  • status - статус релиза
  • rollback - откат релиза на предыдущую версию
  • history - история релизов
  • test - запустить тесты релиза
  • uninstall - деинсталлировать релиз
  • completion - создает сценарий автозаполнения
  • dependency - управление зависимостями
  • env - информация о среде
  • lint - проверить чарт на возможные проблемы
  • plugin - работа с плагинами
  • template - локальное отображение шаблонов (?)
  • version -
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"
:!: IF

Включение/Отключение частей кода с помощью переменных
Объявляем нужные переменные в «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 -}}
:!: FOR

Для циклов используется оператор «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 }}
:!:
 
k8s/helm.txt · Последнее изменение: 2024/12/13 14:15 — admin