Автогенерація секретів у Helm

Автогенерація секретів у Helm

Команда Kubernetes aaS від Mail.ru переклала коротку замітку про те, як автоматично генерувати секрети Helm під час оновлення. Далі текст від автора статті – технічного директора Intoware, компанії-розробника SaaS-рішень.

Контейнери – це круто. Спочатку я був супротивником контейнерів (соромно зізнатися), але тепер я повністю підтримую використання цієї технології. Якщо ви читаєте це, то, сподіваюся, успішно плавали морями Docker, усвідомили переваги Kubernetes і зробили своє життя набагато простіше з Helm.

Проте деякі речі явно складніші, ніж мають бути.

Як автоматично генерувати секрети під час оновлення?

Секрет Kubernetes — це ресурс, який містить пари ключ/значення, які ви хочете використовувати у своєму коді. Це можуть бути рядки підключення до бази даних, паролі електронної пошти тощо. Використовуючи секрети, ви створюєте чіткий розділ між кодом і налаштуваннями, що дозволяє легко налаштовувати різні розгортання без зміни кодової бази.

Часто зустрічається ситуація, коли два модулі повинні взаємодіяти за допомогою загального ключа. Ніхто за межами кластера не повинен знати цей ключ, оскільки він призначений для зв'язку від одного до іншого всередині кластера.

Створення секретів

Зазвичай, щоб створити секрет у Helm, потрібно:

  • описати секрет у файлі значень;
  • перевизначити його у процесі деплою;
  • послатися нею всередині деплою/пода;
  • … профіт!

Зазвичай це виглядає приблизно так:

apiVersion: v1
kind: Secret
metadata:
  name: my-super-awesome-api-key
type: Opaque
stringData:
  apiKey: {{ .Values.MyApiKeySecret | quote }}

Простий секрет Kubernetes, який використовує значення з values.yml

Але, скажімо, ви не хочете вказувати свій секрет у файлі значень.

Існує багато варіантів, коли для розгортання потрібен загальний ключ, який має бути згенерований під час встановлення.

У наведеному вище прикладі зі зв'язком між модулями небажано ділитися секретом за межами розгортання. Тому дуже бажано, щоб Helm мав механізми автоматичного створення секрету без необхідності його безпосередньої вказівки.

Хукі

Хуки дозволяють запускати код у певних місцях у процесі встановлення. Можливо, є завдання з налаштування, яке необхідно запустити після першої установки, або, можливо, необхідно очищення перед виконанням будь-якого оновлення.

Для вирішення нашої проблеми додавання ключа, що генерується при встановленні, ідеально підходять передустановкові хуки. Але є одна проблема: ви не можете автоматично згенерувати секрет один раз при оновленні. Хуки працюватимуть при кожному оновленні.

Якщо ви згенерували свій секрет, і ваша перша установка ще не відбулася, тоді припиніть читання, передустановковий хук відмінно підійде для вас.

Але якщо секрет є частиною оновлення (можливо, нової функції, якої не було під час встановлення), то прикро, що неможливо створити передустановковий хук, який би спрацював лише один раз.

Функції

Функції Helm дозволяють додавати різні елементи скриптів у сценарії розгортання.

apiVersion: v1
kind: Secret
metadata:
  name: my-super-awesome-api-key
type: Opaque
stringData:
  apiKey: {{ uuidv4 | quote }} #Generate a new UUID and quote it

У цьому прикладі показано, що значення секрету apiKey буде новий UUID, згенерований під час установки.

Helm включає дійсно велику бібліотеку функцій, яка використовує приголомшливі функції шаблонів GO і бібліотеку функцій Sprig для створення розгортань, що настроюються.

Функція Lookup

У Helm 3.1 додано функція Lookup, яка дозволяє запросити існуючий деплой та:

  • перевірити існування ресурсів;
  • повернути значення наявного ресурсу для подальшого використання.

Використовуючи обидві ці можливості, ми можемо створити одноразовий динамічно згенерований секрет!

# 1. Запросить существование секрета и вернуть в переменной $secret
{{- $secret := (lookup "v1" "Secret" .Release.Namespace "some-awesome-secret" -}}
apiVersion: v1
kind: Secret
metadata:
  name: some-awesome-secret
type: Opaque

# 2. Если секрет существует, взять его значение как apiKey (секрет использует кодирование Base64, так что используйте ключ "data")
{{ if $secret -}}
data:
  apiKey: {{ $secret.data.apiKey }}

# 3. Если секрет не существует — создать его (в этот раз используйте "stringData", так как будет обычное значение)!
{{ else -}}
stringData:
  apiKey: {{ uuidv4 | quote }}
{{ end }}

Щоразу, коли нове оновлення застосовується до сервера, Helm або генеруватиме нове значення секрету (якщо секрету ще немає), або повторно використовувати існуюче значення.

Успіхів!

Що ще почитати на тему:

  1. Три рівні автомасштабування в Kubernetes та як їх ефективно використовувати.
  2. Kubernetes у дусі піратства з шаблоном по впровадженню.
  3. Наш канал Навколо Kubernetes у Телеграмі.

Джерело: habr.com

Додати коментар або відгук