Cloudplane — это управляемая хостинговая платформа, построенная на Kubernetes с использованием наших собственных шаблонов ресурсов. Мы оценили несколько инструментов для создания шаблонов и в итоге остановились на CUE. Вот как мы пришли к такому выводу.

Go

В основе Cloudplane лежит оператор Kubernetes, который расширяет API Kubernetes различными типами, такими как Application:

Наш уровень шаблонов использует ресурсы приложения для создания ресурсов Kubernetes, таких как развертывания и сервисы, аналогично тому, что диаграммы Helm делают с values. Поскольку мы написали наш оператор на Go, казалось логичным использовать Go и для шаблонизации. Но быстро стало очевидно, что такой подход плохо масштабируется.

С одной стороны, Go не является элегантным языком. Создание ресурсов Kubernetes в Go значительно более многословно, чем, например. YAML и интерполяция строк с помощью заполнителей трудно читаются. Вдобавок ко всему, в Go нет встроенной поддержки слияния объектов (но есть мерго).

Go работает, когда у вас мало ресурсов, но для тяжелых случаев использования шаблонов вам нужен язык, предназначенный для этой цели.

Jsonnet

Jsonnet обещает быть JSON плюс шаблоны, и это именно то, что он предлагает. Он позволяет включать другие файлы и имеет множество полезных функций, таких как переменные и функции. Jsonnet в целом был довольно приличным опытом, и мы могли бы остановиться на этом.

Но Jsonnet — это динамический язык, практически не интегрирующийся с редактором, и мы настоятельно предпочитаем статические типы для подсказок редактора и автозаполнения. Так что мы продолжали искать.

Дхолл

Dhall — функциональный язык конфигурирования и программирования. Статическая типизация и ее чисто функциональный характер — это то, что нам понравилось в Dhall, но для языка конфигурации он может быть до смешного многословным и трудным для чтения. Следующий YAML:

Превращается в этот Дхолл:

Но самая большая проблема с Dhall — производительность. Создание даже небольших шаблонов может занять несколько минут и гигабайт оперативной памяти, а плагин Dhall VS Code оказался для нас почти непригодным. Это известная проблема, и пока она не будет решена, мы не можем рекомендовать Dhall для пользователей Kubernetes.

Шлем

Helm — менеджер пакетов для Kubernetes. Нам нравится использовать его для сторонних зависимостей, но шаблоны в Helm не очень хороши. Он использует YAML, язык данных, чувствительный к пробелам, и накладывает на него универсальный механизм текстовых шаблонов. Диаграммы, как правило, полны шаблонов и хаков с отступами.

Изначально мы начали со сторонних диаграмм Helm, но часто сталкивались с проблемами, связанными с секретами. Мы предоставляем все виды учетных данных через секреты, а поды имеют простой механизм для внедрения переменных среды из них:

К сожалению, большинство диаграмм требуют передачи секретов в виде простого текста в объекте значений, и если они поддерживают секреты, ключи часто не настраиваются. Самая большая сила Helm, а также его самая большая слабость — это абстракция через значения, вам не нужно думать о базовых ресурсах K8s, но когда они важны для вас, ваш единственный путь вперед — разветвление диаграммы.

Мы продолжаем использовать Helm для сторонних пакетов, но для собственных нужд решили использовать…

CUE

CUE — это статически типизированный язык конфигурации, который также поддерживает проверки. Как и Jsonnet, это надмножество JSON, но со многими полезными расширениями, такими как комментарии, переменные, модули и, конечно же, типы. Он не так силен в шаблонизации, как Jsonnet, у него нет функций, но пока мы не сталкивались с серьезными препятствиями.

Его дизайн вдохновлен Go, все файлы в одном каталоге (называемом пакетом) объединяются в один и тот же вывод. Поскольку конфигурация может быть распределена по многим файлам (и модулям), CUE имеет строгие правила относительно того, что вы можете и чего не можете делать.

Как вы могли догадаться, CUE делает кавычки и фигурные скобки в основном необязательными. Он не такой гладкий, как YAML, но намного лучше, чем необработанный JSON.

Киллер-фича для пользователей Kubernetes заключается в том, что CUE может импортировать типы Go:

cue get go k8s.io/api/core/v1

Эта команда извлечет исходный код Go и преобразует его в CUE, чтобы мы получили полную проверку типа:

У нас есть некоторые проблемы с CUE. Во-первых, его синтаксис очень необычен, _|_ назначается при возникновении ошибки, а "\(foo)-bar" — это то, как выглядит интерполяция строк. Мы бы с радостью отказались от совместимости с JSON в пользу более элегантного языка.

Программируемость также ограничена. Есть встроенные функции, которые можно вызывать, но определение пользовательских функций невозможно. Есть if, но нет else. Многого можно добиться с помощью некоторых хитростей, но еще раз хотелось бы, чтобы это были встроенные концепции с элегантным синтаксисом.

CUE — это молодой проект с некоторыми трудностями, но мы думаем, что CUE — это будущее шаблонов Kubernetes. Его принятие быстро растет, и Dagger и Acorn являются одними из его недавних последователей.

Первоначально опубликовано на https://cloudplane.org.