Поради та підказки для розробки чартів
Цей посібник містить поради та підказки, про які розробники чартів Helm дізнались під час створення чартів промислової якості.
Знайомство з функціями шаблону
Helm використовує шаблони Go для шаблонування ваших ресурсних файлів. Хоча Go поставляється з кількома вбудованими функціями, ми додали багато інших.
По-перше, ми додали всі функції з
бібліотеки Sprig, за винятком env
і expandenv
, з міркувань безпеки.
Ми також додали дві спеціальні функції шаблонів: include
і required
. Функція include
дозволяє додавати інший шаблон і передавати результати іншим функціям шаблонів.
Наприклад, цей фрагмент шаблону включає шаблон з назвою mytpl
, потім приводить результат у нижньому регістрі та обертає його в подвійні лапки.
value: {{ include "mytpl" . | lower | quote }}
Функція required
дозволяє оголосити певний запис значення обовʼязковим для рендерингу шаблону. Якщо значення порожнє, рендеринг шаблону завершиться з повідомленням про помилку, наданим користувачем.
Наступний приклад використання функції required
оголошує запис для .Values.who
обовʼязковим і виводить повідомлення про помилку, якщо цього запису не вистачає:
value: {{ required "Потрібен дійсний запис .Values.who!" .Values.who }}
Використовуйте лапки для рядків, не використовуйте лапки для цілих чисел
Коли ви працюєте з рядковими даними, завжди безпечніше використовувати лапки для рядків, ніж залишати їх без лапок:
name: {{ .Values.MyName | quote }}
Але при роботі з цілими числами не беріть значення в лапки. Це може викликати помилки парсингу всередині Kubernetes.
port: {{ .Values.Port }}
Це зауваження не стосується значень змінних середовища, які повинні бути рядками, навіть якщо вони представляють цілі числа:
env:
- name: HOST
value: "http://host"
- name: PORT
value: "1234"
Використання функції include
Go надає спосіб включати один шаблон в інший за допомогою вбудованої директиви template
. Однак вбудована функція не може використовуватися в конвеєрах шаблонів Go.
Щоб включити шаблон і виконати операцію з його результатом, Helm має спеціальну функцію include
:
{{ include "toYaml" $value | indent 2 }}
Вищезазначене включає шаблон з назвою toYaml
, передає йому $value
, а потім передає результат з цього шаблону у функцію indent
.
Оскільки в YAML важливі відступи, це чудовий спосіб включати фрагменти коду, зберігаючи відступи в релевантному контексті.
Використання функції required
Go надає спосіб налаштувати опції шаблону для керування поведінкою при зверненні до ключа, якого немає в map. Це зазвичай налаштовується за допомогою template.Options("missingkey=option")
, де option
може бути default
, zero
або error
. Якщо встановити цю опцію з помилкою, виконання зупиниться з помилкою, але це стосуватиметься кожного відсутнього ключа в map. Можуть бути ситуації, коли розробник чарту захоче застосувати цю поведінку лише для певних значень у файлі values.yaml
.
Функція required
дає розробникам можливість оголосити значення обовʼязковим для роботи в шаблоні. Якщо значення відсутнє в values.yaml
, шаблон повертає повідомлення про помилку, надане розробником.
Наприклад:
{{ required "Потрібен дійсний foo!" .Values.foo }}
Наведена вище конструкція використає шаблон, коли .Values.foo
визначено, але не зможе це зробити та вийде з помилкою, коли .Values.foo
не визначено.
Використання функції tpl
Функція tpl
дозволяє розробникам оцінювати рядки як шаблони всередині іншого шаблону. Це корисно для передачі рядка шаблону як значення до чарту або використання зовнішніх конфігураційних файлів. Синтаксис: {{ tpl TEMPLATE_STRING VALUES }}
.
Приклади:
# значення
template: "{{ .Values.name }}"
name: "Tom"
# шаблон
{{ tpl .Values.template . }}
# результат
Tom
Використання зовнішнього конфігураційного файлу:
# зовнішній конфігураційний файл conf/app.conf
firstName={{ .Values.firstName }}
lastName={{ .Values.lastName }}
# значення
firstName: Peter
lastName: Parker
# шаблон
{{ tpl (.Files.Get "conf/app.conf") . }}
# результат
firstName=Peter
lastName=Parker
Створення секретів для отримання образів
Секрети для отримання образів по суті є комбінацією registry, username та password. Вони можуть знадобитися у застосунку, який ви розгортаєте, але для їх створення потрібно кілька разів запустити base64
. Ми можемо написати допоміжний шаблон, щоб скласти файл конфігурації Docker для використання у вигляді даних для секрету. Ось приклад:
По-перше, припустимо, що облікові дані визначені у файлі values.yaml
наступним чином:
imageCredentials:
registry: quay.io
username: someone
password: sillyness
email: someone@host.com
Ми визначаємо наш допоміжний шаблон наступним чином:
{{- define "imagePullSecret" }}
{{- with .Values.imageCredentials }}
{{- printf "{\"auths\":{\"%s\":{\"username\":\"%s\",\"password\":\"%s\",\"email\":\"%s\",\"auth\":\"%s\"}}}" .registry .username .password .email (printf "%s:%s" .username .password | b64enc) | b64enc }}
{{- end }}
{{- end }}
Нарешті, ми використовуємо допоміжний шаблон у більшому шаблоні для створення маніфесту секрету:
apiVersion: v1
kind: Secret
metadata:
name: myregistrykey
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: {{ template "imagePullSecret" . }}
Автоматичне викатування розгортань
Часто ConfigMaps або Secrets підключаютсья як конфігураційні файли в контейнери або є інші зовнішні зміни залежностей, які вимагають перезапуску podʼів. Залежно від застосунку, перезапуск може знадобитися, якщо вони оновлюються при наступному helm upgrade
, але якщо самі специфікації deployment не змінюються, застосунок продовжує працювати зі старою конфігурацією, що призводить до неконсистентного deployment.
Функція sha256sum
може бути використана для забезпечення оновлення секції анотацій розгортання, якщо змінюється інший файл:
kind: Deployment
spec:
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
[...]
ПРИМІТКА: Якщо ви додаєте це до бібліотечного чарту, ви не зможете отримати доступ до вашого файлу в $.Template.BasePath
. Замість цього можна посилатися на ваше визначення за допомогою {{ include ("mylibchart.configmap") . | sha256sum }}
.
У випадку, коли ви завжди хочете перезапустити свій deployment, ви можете використати аналогічний крок з анотацією, як вище, замінивши його випадковим рядком, щоб він завжди змінювався і викликав перезапуск deployment:
kind: Deployment
spec:
template:
metadata:
annotations:
rollme: {{ randAlphaNum 5 | quote }}
[...]
Кожен виклик функції шаблону генеруватиме унікальний випадковий рядок. Це означає, що якщо необхідно синхронізувати випадкові рядки, що використовуються декількома ресурсами, всі відповідні ресурси повинні бути в одному файлі шаблону.
Обидва ці методи дозволяють вашому deployment використовувати вбудовану логіку стратегії оновлення, щоб уникнути простоїв.
ПРИМІТКА: Раніше ми рекомендували використовувати прапорець --recreate-pods
як інший варіант. Цей прапорець було позначено застарілим у Helm 3 на користь більш декларативного методу, описаного вище.
Скажіть Helm не видаляти ресурс
Іноді є ресурси, які не слід видаляти під час виконання команди helm uninstall
. Розробники чартів можуть додати анотацію до ресурсу, щоб запобігти його видаленню.
kind: Secret
metadata:
annotations:
helm.sh/resource-policy: keep
[...]
Анотація helm.sh/resource-policy: keep
говорить Helm не видаляти цей ресурс, коли операція Helm (така як helm uninstall
, helm upgrade
або helm rollback
) призвела б до його видалення. Однак, цей ресурс стає сиротою. Helm більше не керує ним у будь-який спосіб. Це може призвести до проблем, якщо використовувати helm install --replace
для релізу, який вже був видалений, але зберіг ресурси.
Використання "Partials" та включень шаблонів
Іноді ви хочете створити деякі багаторазові частини у вашому чарті, незалежно від того, чи це блоки або часткові шаблони. І часто, чистіше зберігати їх у власних файлах.
У теці templates/
, будь-який файл, що починається з підкреслення (_
), не призначений для виведення файлу маніфесту Kubernetes. Таким чином, за домовленістю, допоміжні шаблони та часткові шаблони розміщуються у файлі _helpers.tpl
.
Складні чарти з багатьма залежностями
Багато чартів у CNCF Artifact Hub є "будівельними блоками" для створення складніших застосунків. Але чарти можуть бути використані для створення екземплярів великомасштабних застосунків. У таких випадках один основний чарт може мати декілька вкладених субчартів, кожен з яких функціонує як частина цілого.
Найкращою практикою для збирання складного застосунку з окремих частин є створення основного чарту, який надає глобальні конфігурації, а потім використання підтеки charts/
для вбудовування кожного з компонентів.
YAML — це надмножина JSON
Згідно зі специфікацією YAML, YAML є надмножиною JSON. Це означає, що будь-яка допустима структура JSON має бути дійсною в YAML.
Це має перевагу: іноді розробникам шаблонів може бути простіше виразити структуру даних з синтаксисом, схожим на JSON, ніж мати справу з чутливістю YAML до пробілів.
Як правило, шаблони повинні відповідати синтаксису, схожому на YAML, якщо синтаксис JSON суттєво не знижує ризик виникнення проблем з форматуванням.
Будьте обережні з генерацією випадкових значень
У Helm є функції, які дозволяють генерувати випадкові дані, криптографічні ключі тощо. Вони цілком придатні для використання. Але майте на увазі, що під час оновлень шаблони виконуються знову. Коли виконання шаблону генерує дані, що відрізняються від останнього виконання, це викликає оновлення цього ресурсу.
Встановлення або оновлення релізу однією командою
Helm надає можливість виконати встановлення або оновлення як одну команду. Використовуйте helm upgrade
з командою --install
. Це змусить Helm перевірити, чи реліз вже встановлено. Якщо ні, буде виконано встановлення. Якщо так, то наявний реліз буде оновлено.
$ helm upgrade --install <назва релізу> --values <файл значень> <тека чарту>