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 стало ещё проще»;
Автор: Иван Михейкин