Shell-operator и addon-operator — Open Source-проекты компании «Флант» для администраторов Kubernetes, представленные в апреле 2019 года. Первый призван упростить создание K8s-операторов: для этого с ним достаточно писать простые скрипты (на Bash, Python и т.п.) или любые бинарники, которые будут вызываться в случае наступления определённых событий в Kubernetes API. Второй (addon-operator) — его «старший брат», цель которого — упростить установку Helm-чартов в кластер, используя для их настройки хуки shell-operator’а.
В последний раз мы рассказывали о возможностях shell-operator по состоянию на релиз v1.0.0-beta.11 (летом прошлого года), если не считать последовавшего доклада на KubeCon EU’2020, который знакомил с проектом тех, кто о нём ещё не знает. (К слову, этот доклад мы по-прежнему рекомендуем всем желающим разобраться, как shell-operator облегчает жизнь при создании операторов, и увидеть наглядные примеры его применения.)
За минувшее время и shell-operator, и addon-operator получили множество интересных новшеств, которым и посвящена эта статья.
Изменения в shell-operator v1.0.0-rc1
Хуки для shell-operator теперь можно использовать как обработчики для ValidatingWebhookConfiguration
— одного из вариантов admission webhook. Т.е. хук может проверить ресурс Kubernetes во время создания или редактирования и отклонить операцию, если ресурс не соответствует каким-то правилам. Таким правилом может быть такая политика: «можно создавать только ресурсы с образом из repo.example.com». Пример реализации подобной политики можно посмотреть в директории 204-validating-webhook. Shell-operator поддерживает такие хуки для кластеров Kubernetes с версией не ниже 1.16.
Иллюстрация того, как происходит конфигурация такого хука (фрагмент shell-хука из примера выше):
function __config__(){
cat <<EOF
configVersion: v1
kubernetesValidating:
- name: private-repo-policy.example.com
namespace:
labelSelector:
matchLabels:
# helm adds a 'name' label to a namespace it creates
name: example-204
rules:
- apiGroups: ["stable.example.com"]
apiVersions: ["v1"]
operations: ["CREATE", "UPDATE"]
resources: ["crontabs"]
scope: "Namespaced"
EOF
}
Другое новшество — группу произвольных метрик теперь можно удалить, вернув ключ action
:
{"group":"group_name_1", "action":"expire"}
Это удобно, когда пропадают объекты, сведения о которых были в метриках. Подробный пример разобран в документации.
Остальные значимые нововведения в shell-operator разбиты на категории:
1. Улучшения в потреблении ресурсов и производительности
-
Период ресинхронизации информеров теперь случайно распределён во времени. Без распределения все информеры одновременно обращались к API-серверу, что периодически создавало лишнюю нагрузку.
Введена экспоненциально возрастающая задержка между повторными запусками ошибочного хука.
В операциях на чтение в очередях сделаны read-only-локи вместо общего лока и на запись, и на чтение.
Добавлены метрики с процессорным временем и с потреблением памяти для каждого хука (см.
shell_operator_hook_run_sys_cpu_seconds
в METRICS).
2. Изменения в сборке образа
Теперь
flant/shell-operator
— это образ с поддержкой архитектур AMD64, ARM и ARM64 (привет любителям Raspberry Pi!).Бинарный файл
shell-operator
собирается статически и должен работать в любом Linux-дистрибутиве.Образ
flant/shell-operator
с Bash, kubectl и jq теперь только на основе Alpine. Если требуется другой дистрибутив, то бинарный файл можно взять из основного образа, а Dockerfile есть в примерах.Убрана директория
.git
, попавшая в образ по ошибке.Обновлены версии инструментов: Alpine 3.12, kubectl 1.19.4, Go 1.15.
Бинарный файл jq собран из того же коммита, что и libjq*, чтобы устранить проблемы производительности jq-1.6 (#206).
* Кстати, libjq-go — это наш небольшой Open Source-проект, предлагающий CGO bindings для jq. Он был создан для нужд shell-operator, но недавно мы встретили и другой пример его использования — в проекте Xbus. Это платформа французской компании для интеграции enterprise-систем, построенная поверх NATS. Здорово видеть, когда Open Source сам делает своё полезное дело даже в небольших проектах, от которых ничего особого не ожидаешь.
3. Менее значимые изменения
В лог при старте записываются предупреждения про файлы хуков без флага исполнения (+x).
Проект можно собирать без включения CGO. Теперь удобно использовать shell-operator в других проектах, если быстрый обработчик
jqFilter
не нужен.Добавлен
shell_lib.sh
, чтобы подключать shell framework одной строкой. Пример использования этой библиотеки мы демонстрировали в уже упомянутом докладе на KubeCon.
Новости addon-operator
Последний релиз addon-operator состоялся в начале прошлого года, с тех пор в нем было по-настоящему много изменений.
Одно из главных — поддержка схем OpenAPI для values. Можно задавать контракты для values, которые нужны для Helm, и для config values, которые хранятся в ConfigMap и используются для конфигурации модулей пользователем.
Например, такая схема определяет два обязательных поля для глобальных values (project
и clusterName
), а также два опциональных поля (строка clusterHostname
и объект discovery
без ограничений по ключам):
# /global/openapi/config-values.yaml
type: object
additionalProperties: false
required:
- project
- clusterName
minProperties: 2
properties:
project:
type: string
clusterName:
type: string
clusterHostname:
type: string
discovery:
type: object
Подробнее — см. в документации.
Ещё одно знаковое событие — экспериментальная поддержка написания хуков на языке Go. Для их работы придётся компилировать свой addon-operator, добавив импорты с путями к хукам. Пример их использования можно найти в каталоге 700-go-hooks.
Иллюстрация глобального хука на Go из примера выше:
package global_hooks
import "github.com/flant/addon-operator/sdk"
var _ = sdk.Register(&GoHook{})
type GoHook struct {
sdk.CommonGoHook
}
func (h *GoHook) Metadata() sdk.HookMetadata {
return h.CommonMetadataFromRuntime()
}
func (h *GoHook) Config() *sdk.HookConfig {
return h.CommonGoHook.Config(&sdk.HookConfig{
YamlConfig: `
configVersion: v1
onStartup: 10
`,
MainHandler: h.Main,
})
}
func (h *GoHook) Main(input *sdk.BindingInput) (*sdk.BindingOutput, error) {
input.LogEntry.Infof("Start Global Go hook")
return nil, nil
}
Реализация соответствующего SDK пока находится на уровне альфа-версии и не может похвастать достаточной документацией, но если вас заинтересовала такая возможность — смело спрашивайте в комментариях, а лучше — приходите в Tg-канал @kubeoperator.
Среди других ключевых изменений в addon-operator выделим следующие:
Поддержка установки модулей с помощью Helm 3.
Введены понятия «сходимости» и «сходимости при старте» — это название цикла рестарта всех модулей. Добавлен endpoint для readiness-пробы: Pod addon-operator’а переводится в состояние Ready, когда прошёл первый старт всех модулей, т.е. «сходимость при старте» достигнута.
Возможность включать модули из глобальных хуков, благодаря чему теперь проще регулировать состав модулей (ранее отключить модуль можно было только enabled-скриптом самого модуля).
Запуск информеров и запуск Synchronization для Kubernetes-хуков теперь производится в отдельных очередях, а также появилась возможность отключить ожидание выполнения таких хуков при старте.
Сборка образа изменена аналогично shell-operator’у: Alpine в качестве основы, мультиплатформенный образ, статический бинарный файл и т.д.
Доступно больше метрик для мониторинга состояния — подробнее в METRICS.
Также в addon-operator перекочевали многие улучшения из shell-operator, была актуализирована документация и сделаны другие мелкие правки. В данный момент заканчиваются работы по поддержке схем OpenAPI, после чего будет опубликован релиз v1.0.0-rc1.
Новые применения shell-operator
За минувшее время shell-operator обрёл не только новые возможности, но и новых пользователей. Среди них отметим следующие известные нам проекты:
В Confluent сделали проект Kafka DevOps. В нём реализована «модель production-окружения, в котором запущено streaming-приложение, пишущее в Apache Kafka на Confluent Cloud». Это окружение построено на основе Kubernetes, приложения и ресурсы в котором управляются в духе декларативной инфраструктуры. В частности, для этого реализованы операторы (Confluent Cloud Operator и Kafka Connect Operator) на основе на shell-operator. Подробнее об этом проекте можно почитать в блоге авторов, а совсем недавно они даже выпустили подкаст, где рассказывают о своём Kafka DevOps.
Образовательный проект edukates подготовил практическое занятие по shell-operator, однако его дальнейшая судьба осталась для нас под вопросом (найти его в опубликованном виде на сайте проекта нам не удалось).
Docker Captain из Германии создал специальный контроллер для обновления DNS-записей при рестарте pod’а с Traefik. Вскоре после этого он узнал про shell-operator и перевел свою разработку на его использование.
Solution Architect из Red Hat занялся созданием r53-operator — «оператора для кастомных доменов», который управляет доменами Ingress в AWS Route 53.
Если у вас тоже есть опыт применения shell-operator, будем рады соответствующим рассказам в GitHub Discussions проекта: собирая такие примеры, мы надеемся помочь широкому сообществу инженеров. Случаи использования addon-operator — гораздо более редкое явление, так что им мы будем рады вдвойне.
Заключение
Shell-operator и addon-operator давно используются нами в ежедневной работе. Основные проблемы изучены и устранены, а сейчас в проекты преимущественно добавляются новые возможности. В ближайших планах для shell-operator — поддержка conversion webhook и возможность писать хуки «без побочных эффектов», т.е. не вызывать kubectl для изменений в кластере, а возвращать в shell-operator набор действий (см. #94, #239).
Фактически оба проекта давно вышли из статуса beta, поэтому мы решили синхронизироваться с реальностью и представляем их версии rc1, а следующий релиз shell-operator в этом году может стать окончательным v1.0.0.
P.S. В ноябре прошлого года shell-operator преодолел рубеж в 1000 звёзд на GitHub, а addon-operator — более скромные 250. Спасибо всем, кто заинтересовался проектами!
P.P.S.
Читайте также в нашем блоге:
«Go? Bash! Встречайте shell-operator (обзор и видео доклада с KubeCon EU'2020)»;
«Простое создание Kubernetes-операторов с shell-operator: прогресс проекта за год»;
«Готовить Kubernetes-кластер просто и удобно? Анонсируем addon-operator»;
«Представляем shell-operator: создавать операторы для Kubernetes стало ещё проще»;