Контроллеры в Kubernetes: StatefulSet

StatefulSet - это объект workload API, используемый для управления приложениями с отслеживанием состояния.

Управляет развертыванием и масштабированием набора Pod'ов, а также предоставляет гарантии относительно порядка и уникальности этих Pod'ов.

Подобно Deployment, StatefulSet управляет Pod'ами, основанными на идентичной спецификации контейнера. В отличие от Deployment, StatefulSet поддерживает липкую (sticky) идентификацию для каждого из своих Pod'ов. Эти Pod'ы созданы из одной и той же спецификации, но не являются взаимозаменяемыми: у каждого есть постоянный идентификатор, который он поддерживает при любом перепланировании.

StatefulSet работает по тому же шаблону, что и любой другой контроллер. Вы определяете желаемое состояние в объекте StatefulSet, а контроллер StatefulSet делает все необходимые обновления, чтобы получить его из текущего состояния.

Использование StatefulSet

StatefulSet полезны для приложений, которым требуется одно или несколько из следующего.

  • Стабильные, уникальные сетевые идентификаторы.
  • Стабильное, постоянное хранение.
  • Упорядоченные, изящное развертывание и масштабирование.
  • Упорядоченные, автоматические развертываемые обновления.

Выше стабильный является синонимом постоянства в Pod (пере)планировании. Если приложение не требует каких-либо стабильных идентификаторов или упорядоченного развертывания, удаления или масштабирования, вы должны развернуть свое приложение с контроллером, который предоставляет набор реплик без сохранения состояния. Такие контроллеры, как Deployment или ReplicaSet, могут лучше подходить для ваших потребностей без сохранения состояния.

Ограничения

  • Хранилище для данного Pod'а должно быть выделено поставщиком PersistentVolume на основе запрошенного класса хранилища или предварительно предоставлено администратором.
  • Удаление и/или уменьшение StatefulSet не приведет к удалению томов, связанных с StatefulSet. Это сделано для обеспечения безопасности данных, что, как правило, более ценно, чем автоматическая очистка всех связанных ресурсов StatefulSet.
  • StatefulSets в настоящее время требует, чтобы Headless Service отвечал за идентификацию сети Pod'ов. Вы несете ответственность за создание этого Сервиса.
  • StatefulSets не предоставляет никаких гарантий на прекращение работы Pod'ов при удалении StatefulSet. Чтобы добиться упорядоченного и плавного завершения Pod'ов в StatefulSet, можно уменьшить StatefulSet до 0 перед удалением.
  • При использовании Rolling Updates с политикой управления Pod по умолчанию (OrderedReady) можно попасть в неисправное состояние, которое требует ручного вмешательства для восстановления.

Компоненты

В приведенном ниже примере демонстрируются компоненты StatefulSet.

  • Headless Service, называемый nginx, используется для управления сетевым доменом.
  • StatefulSet, названный web, имеет спецификацию, которая указывает, что 3 копии контейнера nginx будут запущены в уникальных Pod'ах.
  • VolumeClaimTemplates обеспечат стабильное хранилище, используя PersistentVolumes, предоставляемый поставщиком PersistentVolume.

apiVersion: v1
kind: Service
metadata:
  name: nginx
  labels:
    app: nginx
spec:
  ports:
  - port: 80
    name: web
  clusterIP: None
  selector:
    app: nginx
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: web
spec:
  selector:
    matchLabels:
      app: nginx # должно соответствовать .spec.template.metadata.labels
  serviceName: "nginx"
  replicas: 3 # by default is 1
  template:
    metadata:
      labels:
        app: nginx # должно соответствовать .spec.selector.matchLabels
    spec:
      terminationGracePeriodSeconds: 10
      containers:
      - name: nginx
        image: k8s.gcr.io/nginx-slim:0.8
        ports:
        - containerPort: 80
          name: web
        volumeMounts:
        - name: www
          mountPath: /usr/share/nginx/html
  volumeClaimTemplates:
  - metadata:
      name: www
    spec:
      accessModes: [ "ReadWriteOnce" ]
      storageClassName: "my-storage-class"
      resources:
        requests:
          storage: 1Gi

Pod селектор

Вы должны установить .spec.selector поле StatefulSet, чтобы соответствовать меткам его .spec.template.metadata.labels. До выпуска Kubernetes 1.8 поле .spec.selector было по умолчанию, если оно опущено. В 1.8 и более поздних версиях, если не указать подходящий Pod селектор, это приведет к ошибке проверки при создании StatefulSet.

Идентификация Pod'а

Пакеты StatefulSet имеют уникальную идентификацию, состоящую из порядкового номера, идентификатора стабильной сети и стабильного хранилища. Идентификационные данные привязываются к Pod независимо от того, на каком узле он (повторно) запланирован.

Порядковый индекс

Для StatefulSet с N репликами каждому Pod в StatefulSet будет присвоен целочисленный порядковый номер, от 0 до N-1, который уникален для набора.

Стабильный идентификатор сети

Каждый Pod в StatefulSet получает свое имя хоста из имени StatefulSet и порядкового номера Pod. Шаблон для созданного имени хоста: $(имя statefulset)-$(порядковый номер). В приведенном выше примере будут созданы три Pod'а названные web-0,web-1,web-2. StatefulSet может использовать Headless Service для управления доменом своих Pod'ов. Домен, управляемый этой службой, имеет вид: $(service name).$(namespace).svc.cluster.local, где “cluster.local” - это кластерный домен. Когда создается каждый Pod, он получает соответствующий поддомен DNS в форме: $(podname).$(управляющий домен службы), где управляющая служба определяется полем serviceName в StatefulSet.

Как упоминалось в разделе об ограничениях, вы несете ответственность за создание Headless Service, отвечающей за сетевую идентификацию Pod'ов.

Вот несколько примеров выбора домена кластера, имени службы, имени StatefulSet и того, как это влияет на DNS-имена для Pod'ов StatefulSet.

Примечание. Для домена кластера будет установлен cluster.local, если не указано иное.

Стабильное хранение

Kubernetes создает один PersistentVolume для каждого VolumeClaimTemplate. В приведенном выше примере с nginx каждый Pod получит один PersistentVolume с классом хранения my-storage-class и 1 Gib выделенного хранилища. Если StorageClass не указан, будет использоваться StorageClass по умолчанию. Когда Pod (повторно) запланирован на узле, его volumeMounts монтируют PersistentVolumes, связанные с его утверждениями PersistentVolume. Обратите внимание, что PersistentVolumes, связанные с утверждениями PersistentVolume Pod'ов, не удаляются при удалении Pod'ов или StatefulSet. Это должно быть сделано вручную.

Метка имени Pod'а

Когда контроллер StatefulSet создает Pod, он добавляет метку statefulset.kubernetes.io/pod-name, которая устанавливается на имя Pod. Эта метка позволяет вам прикрепить Сервис к определенному Pod в StatefulSet.

Гарантии развертывания и масштабирования

  • Для StatefulSet с N репликами при развертывании Pod'ов они создаются последовательно в порядке {0..N-1}.
  • Когда Pod'ы удаляются, они завершаются в обратном порядке, начиная с {N-1..0}.
  • Перед применением операции масштабирования к Pod'у все его предшественники должны быть в рабочем состоянии и готовы.
  • Перед прекращением работы Pod'а все его преемники должны быть полностью отключены.

StatefulSet не должен указывать pod.Spec.TerminationGracePeriodSeconds, равный 0. Эта практика небезопасна и настоятельно не рекомендуется.

При создании приведенного выше примера nginx будут развернуты три Pod'а в следующем порядке: web-0, web-1, web-2. web-1 не будет развернут до тех пор, пока web-0 не будет запущен и готов, а web-2 не будет развернут до тех пор, пока web-1 не будет запущен и готов. Если произойдет сбой web-0, после того, как web-1 будет запущен и готов, но до запуска web-2, web-2 не будет запущен, пока web-0 не будет успешно перезапущен и не будет запущен и готов.

Если бы пользователь масштабировал развернутый пример, исправив StatefulSet так, чтобы replicas = 1, web-2 был бы прерван первым. web-1 не будет прерван до тех пор, пока web-2 не будет полностью отключен и удален. В случае сбоя web-0 после прекращения работы web-2 и его полного отключения, но до прекращения работы web-1, web-1 не будет завершен, пока web-0 не будет запущен и готов.

Политики управления Pod'ами (Pod Management Policies)

В Kubernetes 1.7 и более поздних версиях StatefulSet позволяет вам ослабить свои гарантии упорядочения, сохраняя свои уникальность и гарантии идентичности через свое поле .spec.podManagementPolicy.

OrderedReady Pod Management

OrderedReady управление Pod'ами по умолчанию для StatefulSets. Он реализует поведение, описанное выше.

Параллельное управление Pod'ами (Parallel Pod Management)

Параллельное управление Pod'ами сообщает контроллеру StatefulSet, что нужно запускать или завершать работу всех Pod'ов параллельно, и не ждать, пока Pod'ы станут работающими и готовыми или полностью прекратят работу до запуска или завершения другого Pod'а. Этот параметр влияет только на поведение операций масштабирования. Обновления не затрагиваются.

Стратегии обновлений

В Kubernetes 1.7 и более поздних версиях поле StatefulSet .spec.updateStrategy позволяет настраивать и отключать автоматические развертываемые обновления для контейнеров, меток, запросов/пределов ресурсов и аннотаций для Pod'ов в StatefulSet.

При удалении (On Delete)

Стратегия обновления OnDelete реализует устаревшее (1.6 и более раннее) поведение. Когда для StatefulSet .spec.updateStrategy.type установлено значение OnDelete, контроллер StatefulSet не будет автоматически обновлять Pod'ы в StatefulSet. Пользователи должны вручную удалить Pod'ы, чтобы контроллер создавал новые Pod'ы, которые отражают изменения, внесенные в .spec.template StatefulSet.

Раскатываемые обновления (Rolling Updates)

Стратегия обновления RollingUpdate реализует автоматическое, раскатываемое обновление для Pod'ов в StatefulSet. Это стратегия по умолчанию, когда .spec.updateStrategy не указывается. Когда для StatefulSet .spec.updateStrategy.type установлено значение RollingUpdate, контроллер StatefulSet удаляет и воссоздает каждый Pod в StatefulSet. Это будет происходить в том же порядке, что и завершение Pod (от наибольшего порядкового номера до наименьшего), обновляя каждый Pod по одному. Он будет ждать, пока обновленный Pod будет запущен и готов, прежде чем обновлять своего предшественника.

Разделы (Partitions)

Стратегия обновления RollingUpdate может быть разделена, указав .spec.updateStrategy.rollingUpdate.partition. Если указан раздел, все Pod'ы с порядковым номером, который больше или равен разделу, будут обновлены при обновлении .spec.template StatefulSet. Все Pod'ы с порядковым номером, меньшим, чем раздел, не будут обновлены, и, даже если они будут удалены, они будут воссозданы в предыдущей версии. Если .spec.updateStrategy.rollingUpdate.partition StatefulSet больше, чем его .spec.replicas, обновления его .spec.template не будут распространяться на его Pod. В большинстве случаев вам не нужно использовать раздел, но они полезны, если вы хотите поставить обновление, выполнить canary развертывание или выполнить поэтапное развертывание.

Принудительный откат (Forced Rollback)

При использовании Rolling Updates с политикой управления Pod по умолчанию (OrderedReady) можно попасть в неисправное состояние, которое требует ручного вмешательства для восстановления.

Если вы обновите шаблон Pod до конфигурации, которая никогда не станет Running и Ready (например, из-за неправильной бинарной конфигурации или ошибки конфигурации на уровне приложения), StatefulSet остановит развертывание и будет ждать.

В этом состоянии недостаточно вернуть шаблон Pod к хорошей конфигурации. Из-за известной проблемы StatefulSet будет продолжать ждать, пока сломанный Pod станет готовым (что никогда не происходит), прежде чем попытаться вернуть его обратно в рабочую конфигурацию.

После возврата шаблона вы также должны удалить все Pod'ы, которые StatefulSet уже пытался запустить с неверной конфигурацией. StatefulSet начнет воссоздавать Pod'ы, используя обратный шаблон.


Читайте также:


Комментарии

Популярные сообщения из этого блога

Контроллеры в Kubernetes: DaemonSet

Контроллеры в Kubernetes: ReplicaSet