Проблема stateful-приложений в Kubernetes


Конфигурация, запуск и дальнейшее масштабирование приложений и служб осуществляются просто, если речь идёт о случаях, классифицируемых как stateless, т.е. без сохранения данных. Такие сервисы удобно запускать в Kubernetes, пользуясь его стандартными API, потому что всё происходит «из коробки»: по стандартным конфигурациям, без привлечения какой-либо специфики и магии.

Проще говоря, для запуска в кластере из контейнеров ещё пяти копий бэкенда на PHP/Ruby/Python требуется лишь 5 раз поднять новый сервер и скопировать исходники. Поскольку и исходники, и init-скрипт лежат в образе, масштабирование stateless-приложения становится совсем элементарным. Как хорошо известно любителям контейнеров и микросервисной архитектуры, сложности начинаются для приложений категории stateful, т.е. с сохранением данных, таких как базы данных и кэши (MySQL, PostgreSQL, Redis, ElasticSearch, Cassandra…). Это касается как софта, самостоятельно реализующего кворумный кластер (например, Percona XtraDB и Cassandra), так и софта, требующего отдельных управляющих утилит (такого, как Redis, MySQL, PostgreSQL…).

Сложности возникают по той причине, что исходников и запуска сервиса становится не достаточно — нужно выполнить еще некоторые действия. Как минимум — скопировать данные и/или присоединиться к кластеру. А если точнее, то эти сервисы требуют понимания, как их правильно масштабировать, обновлять и переконфигурировать без потери данных и их временной недоступности. Учёт этих потребностей и называется «эксплуатационными знаниями» (operational knowledge).

Операторы CoreOS


Для того, чтобы «запрограммировать» эксплуатационные знания, в конце прошлого года проект CoreOS представил «новый класс программного обеспечения» для платформы Kubernetes — Операторы (Operators, от англ. «operation», т.е. «эксплуатация»).

Операторы, используя и расширяя базовые возможности Kubernetes (в т.ч. StatefulSets, о разнице с которыми см. ниже), позволяют DevOps-специалистам добавить эксплуатационные знания в код приложений.

Цель Оператора — предоставить пользователю API, который позволяет управлять множеством сущностей stateful-приложения в кластере Kubernetes, не задумываясь о том, что у него под капотом (какие данные и что с ними делать, какие команды необходимо ещё выполнить для поддержания кластера). Фактически Оператор призван максимально упростить работу с приложением в рамках кластера, автоматизируя выполнение эксплуатационных задач, которые раньше приходилось решать вручную.

Как работают Операторы


ReplicaSets в Kubernetes позволяют указывать желаемое количество запущенных подов, а контроллеры следят за тем, чтобы их количество сохранялось (создавая и удаляя поды). Аналогично работает Оператор, который добавляет к стандартному ресурсу и контроллеру Kubernetes набор эксплуатационных знаний, позволяющих выполнять дополнительные действия для поддержания нужного количества сущностей приложения.

Чем это отличается от StatefulSets, предназначенных для приложений, требующих от кластера предоставить им такие stateful-ресурсы, как хранилище данных или статичные IP? Для таких приложений Операторы могут использовать StatefulSets (вместо ReplicaSets) в качестве основы, предлагая дополнительную автоматизацию: выполнять необходимые действия в случае падений, делать бэкапы, обновлять конфигурацию и т.п.

Итак, как же всё это работает? Оператор представляет собой демон-управлятор, который:

  1. подписывается на событийное API в Kubernetes;
  2. получает из него данные о системе (о своих ReplicaSets, Pods, Services и т.п.);
  3. получает данные о Third Party Resources (см. примеры ниже);
  4. реагирует на появление/изменение Third Party Resources (например, на изменение размера, изменение версии и так далее);
  5. реагирует на изменение состояние системы (о своих ReplicaSets, Pods, Services и т.п.);
  6. самое главное:

    1. обращается к Kubernetes API, чтобы создавать всё необходимое (опять же, свои ReplicaSets, Pods, Services…),
    2. выполняет некоторую магию (можно, для упрощения, думать, что Оператор заходит в сами поды и вызывает команды, например, для вступления в кластер или для апгрейда формата данных при обновлении версии).


По факту, как видно из картинки, в Kubernetes просто добавляется отдельное приложение (обычный Deployment с ReplicaSet), которое и называется Оператором. Оно живёт в обычном поде (обычно одном-единственном) и, как правило, отвечает только за свой Namespace. Это приложение-оператор реализует свой API — правда, не напрямую, а через Third Party Resources в Kubernetes.

Таким образом, после того, как мы создали в Namespace Оператора, мы можем добавлять в него Third Party Resources.

Пример для etcd (подробности см. ниже):

apiVersion: etcd.coreos.com/v1beta1
kind: Cluster
metadata:
  name: example-etcd-cluster
spec:
  size: 3
  version: 3.1.0

Пример для Elasticsearch:

apiVersion: enterprises.upmc.com/v1
kind: ElasticsearchCluster
metadata:
  name: example-es-cluster
spec:
  client-node-replicas: 3
  master-node-replicas: 2
  data-node-replicas: 3
  zones:
  - us-east-1c
  - us-east-1d
  - us-east-1e
  data-volume-size: 10Gi
  java-options: "-Xms1024m -Xmx1024m"
  snapshot:
    scheduler-enabled: true
    bucket-name: elasticsnapshots99
    cron-schedule: "@every 2m"
  storage:
    type: gp2
    storage-class-provisioner: kubernetes.io/aws-ebs

Требования, предъявляемые к Операторам


В CoreOS сформулировали основные паттерны, полученные инженерами во время работы над Операторами. Несмотря на то, что все Операторы индивидуальны (создаются под конкретное приложение со своими особенностями и потребностями), их создание должно опираться на своеобразный каркас, предъявляющий следующие требования:

  1. Установка должна производиться через единственный Deployment: kubectl create -f SOME_OPERATOR_URL/deployment.yaml — и не требовать дополнительных действий.
  2. При установке Оператора в Kubernetes должен создаваться новый сторонний тип (ThirdPartyResource). Для запуска экземпляров приложений (экземпляров кластеров) и дальнейшего управления ими (обновление версий, изменение размера и др.) пользователь будет использовать этот тип.
  3. При любой возможности необходимо использовать встроенные в Kubernetes примитивы, такие как Services и ReplicaSets, чтобы задействовать хорошо проверенный и понятный код.
  4. Необходима обратная совместимость Операторов и поддержка старых версий ресурсов, созданных пользователем.
  5. При удалении Оператора само приложение должно продолжить функционировать без изменений.
  6. У пользователей должна быть возможность определять желаемую версию приложения и выполнять оркестровку обновлений версии приложения. Отсутствие обновлений ПО — частый источник проблем эксплуатации и безопасности, поэтому Операторы должны помогать пользователям в этом вопросе.
  7. Операторы должны тестироваться инструментом типа Chaos Monkey, выявляющим потенциальные сбои в подах, конфигурациях и сети.

etcd Operator


Пример реализации Оператора — etcd Operator, подготовленный ко дню анонса этой концепции. Кластерная конфигурация etcd может быть сложной из-за необходимости поддержания кворума, потребности в переконфигурации членства в кластере, создания бэкапов и т.п. Например, масштабирование кластера etcd вручную означает необходимость создания DNS-имени для нового члена кластера, запуск новой сущности etcd, оповещения кластера о новом члене (etcdctl member add). В случае с Оператором пользователю достаточно будет изменить размер кластера — всё остальное произойдёт автоматически.

И поскольку etcd создали тоже в CoreOS, вполне логичным было увидеть появление его Оператора первым. Как он работает? Логика Оператора etcd определяется тремя составляющими:

  1. Наблюдение (Observe). Оператор следит за состоянием кластера по Kubernetes API.
  2. Анализ (Analyze). Находит отличия текущего статуса от желаемого (определённого пользовательской конфигурацией).
  3. Действие (Act). Устраняет обнаруженные различия с помощью API сервиса etcd и/или Kubernetes.



Для реализации этой логики в Операторе подготовлены функции Create/Destroy (создание и удаление членов кластера etcd) и Resize (изменение количества членов кластера). Проверка корректности её работоспособности проверялась с помощью утилиты, созданной по подобию Chaos Monkey от Netflix, т.е. убивающей поды etcd случайным образом.

Для полноценной эксплуатации etcd в Операторе предусмотрены дополнительные возможности: Backup (автоматическое и незаметное для пользователей создание резервных копий — в конфиге достаточно определить, как часто их делать и какое количество хранить, — и последующее восстановление данных из них) и Upgrade (обновление инсталляций etcd без простоя).

Как выглядит работа с Оператором?

$ kubectl create -f https://coreos.com/operators/etcd/latest/deployment.yaml
$ kubectl create -f https://coreos.com/operators/etcd/latest/example-etcd-cluster.yaml
$ kubectl get pods
NAME                             READY     STATUS    RESTARTS   AGE
etcd-cluster-0000                1/1       Running   0          23s
etcd-cluster-0001                1/1       Running   0          16s
etcd-cluster-0002                1/1       Running   0          8s
etcd-cluster-backup-tool-rhygq   1/1       Running   0          18s

Текущий статус etcd Operator — бета-версия, требующая для работы Kubernetes 1.5.3+ и etcd 3.0+. Исходный код и документация (включая инструкцию по применению) доступны на GitHub.

Создан и другой пример реализации от CoreOS — Prometheus Operator, но он пока находится в альфа-версии (не все запланированные функции реализованы).

Статус и перспективы


С момента анонса Операторов Kubernetes прошло 5 месяцев. В официальном репозитории CoreOS по-прежнему доступны лишь две реализации (для etcd и Prometheus). Обе ещё не достигли своих стабильных версий, но коммиты в них наблюдаются ежедневно.

Разработчики ожидают «будущее, в котором пользователи устанавливают Postgres Operators, Cassandra Operators или Redis Operators в своих кластерах Kubernetes и работают с масштабируемыми сущностями этих приложений так же легко, как сегодня это происходит с деплоем реплик stateless-приложений для веба». Первые Операторы от сторонних разработчиков действительно начали появляться:


На крупнейшей европейской конференции по свободному программному обеспечению FOSDEM, что проходила в феврале 2017 года в Брюсселе, Josh Wood из CoreOS анонсировал Операторов в докладе (по ссылке доступно видео!), что должно способствовать росту популярности этой концепции в более широком Open Source-сообществе.

P.S. Спасибо за интерес к статье! Подписывайтесь на наш хаб, чтобы не пропустить новые материалы и рецепты по DevOps и системному администрированию GNU/Linux — мы будем публиковать их регулярно!
Поделиться с друзьями
-->

Комментарии (2)


  1. shuron
    22.04.2017 23:32

    Простите если немного офтоп. На чем вы разворачивате ваш k8n? В Каком облаке? Если в амазоне то какой утилитой пользуетесь?


    1. D1abloRUS
      23.04.2017 12:07

      Могу вам посоветовать https://github.com/kubernetes-incubator/kargo, и cli тулзу поверх https://github.com/kubespray/kargo-cli, ее хотели под го переписать, но видимо пока нет времени.