Окончательное руководство по Kubernetes StatefulSet – CodesCode

Изучите управление состоянием приложений с помощью наборов состояний Kubernetes - когда их следует использовать, как развертывать MongoDB, ограничения и лучшие практики для реализации.

StatefulSet является API рабочей нагрузки Kubernetes, специально используемым для управления состояний приложений. Это исчерпывающее руководство по настройке и использованию StatefulSets, где мы рассмотрим следующие темы:

  1. Что такое StatefulSet и когда его следует использовать?
  2. Пример: Настройка и запуск MongoDB в качестве StatefulSet
  3. Ограничения StatefulSets и на что следует обратить внимание
  4. Лучшие практики при реализации StatefulSets

Безсостоятельные и состоятельные приложения

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

Кубернетес известен своей отличной работой с безсостоятельными сервисами. Для безсостоятельного приложения поды полностью взаимозаменяемы – масштабирование вверх и вниз не приведет к потере данных. В Kubernetes для управления подами безсостоятельных приложений используется развертывание (Deployment).

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

Итак, как мы управляем состоятельными приложениями в Kubernetes, если нам нельзя случайно перезапускать или выключать поды? Здесь и появляются StatefulSet.

Что такое StatefulSet?

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

Он обеспечивает определенные гарантии в отношении порядка и уникальности подов, их развертывания и масштабирования (см. ниже).

  • Гарантии порядка: При развертывании с использованием StatefulSet поды создаются последовательно и по порядку (в отличие от развертываний или ReplicaSets). Это важно для систем, где важен порядок запуска, таких как распределенные базы данных.
  • Постоянные идентификаторы: У каждого пода в StatefulSet есть стабильное и предсказуемое имя хоста, обычно в формате -. Даже если под переназначается, его идентификатор остается неизменным.
  • Стабильное хранилище: При использовании StatefulSet каждому поду сопоставляется постоянное хранилище. Это хранилище остается присоединенным к конкретному поду, даже если под перемещается на другой узел.
  • Грациозное масштабирование и обновление: StatefulSet позволяет контролируемо масштабировать приложения вверх или вниз, обеспечивая, что операции, такие как поэтапное обновление, не компрометируют целостность приложения.

Контроллер StatefulSet

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

Преимущества StatefulSets

  1. Предсказуемость: StatefulSet обеспечивает предсказуемый порядок развертывания, масштабирования и удаления подов, что крайне важно для приложений, таких как базы данных, где важен порядок операций.
  2. Стабильность: Даже если под в StatefulSet выключается или узел, на котором находится под, отказывает, то идентичность пода (имя, имя хоста и хранилище) остается неизменной.
  3. Безопасность данных: В сочетании с претензиями на постоянный объем, StatefulSet гарантирует, что данные каждого пода остаются в сохранности. Если под переназначается, его данные остаются нетронутыми.
  4. Простота обнаружения и общения: Каждый под получает свою DNS, что упрощает обнаружение сервиса и внутриподовое общение.
  5. Возможности для ручного вмешательства: Для тех случаев, когда вам нужно больше контроля, StatefulSet позволяет ручное вмешательство без попыток системы «автоисправления» немедленно.

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

Развертывание по сравнению с StatefulSet

Давайте посмотрим, в чем разница между StatefulSet и Deployment-

1. Имя пода и идентификация

Развертывание: Поды имеют идентификатор, содержащий имя развертывания и случайный хэш.

StatefulSet: Каждый под получает постоянный идентификатор с именем StatefulSet и порядковым номером.

2. Порядок создания подов

Развертывание: Поды создаются и удаляются случайным образом

StatefulSet: Поды, созданные последовательно, не могут быть удаляться случайным образом

3. Взаимозаменяемость

Развертывание: Все поды идентичны и могут быть взаимозаменяемы

StatefulSet: Поды не идентичны и не могут быть взаимозаменяемы

4. Перепланировка

Развертывание: Под может быть заменен новой репликой в любое время

StatefulSet: Поды сохраняют свою идентичность при перепланировке на другой узел

5. Запрос объема

Развертывание: Все реплики используют один и тот же постоянный объем и запрос объема

StatefulSet: Каждый под получает уникальный запрос объема и объем

6. Взаимодействие с подами

Развертывание: Требуется сервис для взаимодействия с подами

StatefulSet: Headless-сервис обрабатывает сетевые идентификаторы подов

Когда использовать StatefulSet

Используйте StatefulSet, когда ваше приложение имеет состояние. Спросите себя – требуются ли стабильные идентификаторы для подов вашего приложения? Будет ли ваша система нарушена, когда реплика пода будет заменена?

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

Что-то вроде:

  • mongodb-0 – Основной узел (чтение-запись).
  • mongodb-1 – Узел только для чтения.
  • mongodb-2 – Узел только для чтения.

Если уменьшить масштаб ReplicaSet или развертывание, произвольные поды будут удалены, включая основной узел в этой системе MongoDB.

Однако, когда мы используем StatefulSet, Kubernetes завершает поды в обратном порядке их создания, что обеспечивает уничтожение mongodb-2 первым в этом примере.

Пример StatefulSet: Запуск MongoDB в Kubernetes

Теперь давайте посмотрим на пример и запустим кластер MongoDB в Kubernetes с использованием StatefulSet.

Шаг 1: Настройка Headless-сервиса

Идентичность подов в StatefulSet тесно связана с его стабильной сетевой идентичностью, поэтому очень важно иметь Headless-сервис.

Headless-сервис определяется установкой его clusterIP в None, что гарантирует стабильные сетевые идентичности подов.

Вот YAML для нашего сервиса MongoDB:

    apiVersion: v1kind: Servicemetadata:  name: mongodb  labels:    app: mongodbspec:  ports:    - name: mongodb      port: 27017  clusterIP: None  selector:    app: mongodb

Шаг 2: Развертывание MongoDB StatefulSet

Следующий YAML представляет StatefulSet. В нем описывается запуск трех реплик образа MongoDB:

    apiVersion: apps/v1kind: StatefulSetmetadata:  name: mongodbspec:  selector:    matchLabels:      app: mongodb  serviceName: mongodb  replicas: 3  template:    metadata:      labels:        app: mongodb    spec:      containers:        - name: mongodb          image: mongo:latest          ports:          - name: mongodb            containerPort: 27017          volumeMounts:          - name: data            mountPath: /data/db  volumeClaimTemplates:  - metadata:      name: data    spec:      accessModes: ["ReadWriteOnce"]      resources:        requests:          storage: 1Gi

Теперь давайте применим конфигурацию StatefulSet:

$ kubectl apply -f mongodb-statefulset.yamlstatefulset.apps/mongodb created

Давайте проверим новые поды, чтобы увидеть их в действии:

Статус подов

Мы видим, что три пода создаются последовательно, обеспечивая инициализацию одного пода перед следующим.

Каждый новый под в этом StatefulSet MongoDB будет иметь свой собственный постоянный объем и запрос на постоянный объем. Эти запросы создаются из поля volumeClaimTemplates StatefulSet.

Persistent Volumes (Постоянные тома) предоставляют часть хранилища в кластере, независимо от любого отдельного пода, который его использует. Они являются ресурсами в кластере, так же как узлы – ресурсы кластера. PV имеют жизненный цикл, независимый от любого отдельного пода, который использует тома хранилища из PV.

Давайте посмотрим на PV.

$ kubectl get pv...

Результат показывает доступные Persistent Volumes в кластере. Для нашего MongoDB StatefulSet с тремя репликами, вот что мы видим:

$ kubectl get pvc...

Мы видим Persistent Volume Claims, сделанные тремя подами. Предоставление выделенного хранилища гарантирует, что наш экземпляр MongoDB сохраняет свои данные независимо от жизненного цикла пода, что является важным для любой базы данных.

Шаг 3: Масштабирование кластера MongoDB

Давайте посмотрим, как масштабировать наши экземпляры MongoDB:

$ kubectl scale sts mongodb --replicas=5statefulset.apps/mongodb scaled

Давайте убедимся, что поды создаются последовательно.

$ kubectl get pods...

Мы можем видеть здесь по возрасту, что поды создаются последовательно и когда именно.

Аналогично, давайте посмотрим, как уменьшить масштаб:

$ kubectl scale sts mongodb --replicas=2statefulset.apps/mongodb scaled

Kubernetes теперь будет завершать поды в том же хранилище в обратной последовательности создания.

Как видите, сначала завершаются последние поды.

Этот пример демонстрирует, как StatefulSet обеспечивает плавную работу MongoDB, приложения с сохранением состояния, масштабируемость при необходимости и сохранение важных данных с помощью Kubernetes.

Ограничения StatefulSets

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

1. Более медленное развертывание

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

2. Ручное вмешательство для очистки / восстановления состояния

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

3. Сложность изменения размера

StatefulSet тесно связан с ресурсами хранилища его Persistent Volume Claims (PVC). После создания PVC его нельзя легко изменить размер. Если нам нужно увеличить объем хранения, часто приходится пройти более сложный процесс в зависимости от используемого провайдера хранилища.

4. Сложность резервного копирования

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

5. Проблемы с настройкой сети

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

Лучшие практики использования StatefulSet

Исходя из наших знаний о StatefulSet, вот несколько лучших практик, о которых стоит помнить

1. Используйте уникальные и соответствующие имена для подов вашего StatefulSet

Это помогает легче идентифицировать и управлять конкретными подами StatefulSet и их ресурсами.

2. Управление инициализацией и порядком

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

spec:   template:     spec:       initContainers:       - name: init-container-1         image: init-image-1         # Добавьте здесь конфигурацию инициализационного контейнера       - name: init-container-2         image: init-image-2         # Добавьте здесь конфигурацию инициализационного контейнера       containers:       - name: main-container         image: main-image         # Добавьте здесь конфигурацию основного контейнера

Если ваш StatefulSet требует определенного порядка инициализации подов (например, основной узел базы данных должен запуститься перед репликами), вы можете реализовать специфичную логику в ваших Init контейнерах или использовать инструменты, такие как wait-for-it или wait-for, для управления готовностью пода.

3. Осмотритесь перед изменением масштабирования

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

4. Установите бюджеты нарушения работоспособности Pod’ов (PDB)

Бюджеты нарушения работоспособности Pod’ов позволяют вам установить политики, ограничивающие количество одновременно нарушаемых Pod’ов во время событий, таких как уменьшение масштаба или обслуживание. Чтобы установить бюджет нарушения работоспособности Pod’ов для вашего StatefulSet, создайте ресурс PodDisruptionBudget и укажите поле maxUnavailable, которое определяет максимальное количество недоступных Pod’ов в любой момент времени. Например, чтобы гарантировать, что во время масштабирования или обслуживания будет недоступен только один Pod, установите maxUnavailable: 1.

Вот быстрый инструктаж:

A. Создайте YAML-файл бюджета нарушения работоспособности Pod’ов (например, pdb.yaml) для вашего StatefulSet

apiVersion: policy/v1beta1
kind: PodDisruptionBudget
metadata:
  name: example-pdb
spec:
  maxUnavailable: 1  # Измените это значение в соответствии с вашими требованиями
  selector:
    matchLabels:
      app: ваш-лейбл-statefulset

B. Добавьте PDB на ваш кластер Kubernetes

kubectl apply -f pdb.yaml

5. Резервное копирование и восстановление данных

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

Обзор и устранение неполадок для StatefulSets

В целом, наблюдаемость для StatefulSet в Kubernetes во многом аналогична наблюдаемости для Deployment (оба могут быть инструментированы с использованием одних и тех же метрик и решений для логирования, таких как Prometheus и FluentD), но есть некоторые различия, которые следует учесть.

В некотором смысле отслеживать отдельные Pod’ы с помощью StatefulSet проще, так как StatefulSet назначает стабильные, предсказуемые имена своим Pod’ам, такие как pod-0, pod-1 и т.д. Это позволяет легче устранять неисправности и отлаживать. В отличие от этого, Deployment использует случайные имена Pod’ов, и нам приходится больше полагаться на метки и селекторы.

Однако для StatefulSets нам понадобятся некоторые дополнительные метрики и логи, такие как метрики, отображающие состояние отдельных Pod’ов, распределение данных, репликацию данных, синхронизацию и согласованность между Pod’ами. Мы также можем захотеть отслеживать различные состояния Pod’ов при масштабировании вверх или вниз, такие как “В ожидании”, “Запущен” или “Завершение работы”, чтобы убедиться, что данные правильно перемещаются или реплицируются во время этих переходов.

Также, для оповещений, мы обычно хотим добавить дополнительные оповещения, связанные с поведением или переходами в определенное состояние Pod’а, такие как изменения счетчика реплик, идентификатора или использования хранилища.

Чтобы узнать больше о том, как правильно настроить наблюдаемость, смотрите здесь.

Часто наиболее раздражающие проблемы возникают с StatefulSets и их труднее имитировать и отлаживать. Если у вас есть проблемы с состоянием приложения в стадии разработки и вы пытаетесь определить, вызваны ли они состоянием StatefulSet’а, вместо попыток имитирования состояния StatefulSet’а, вы можете использовать инструменты с открытым исходным кодом, например Klone, чтобы избежать имитации в целом и быстрее отлаживать. Также есть категория новых продуктов ИИ, таких как ZeroK.ai, которые автоматически помогают выявить вероятные причины с помощью ИИ, запуская автоматические исследования на ваших данных наблюдаемости, что может быть интересным.

Резюме

В этой статье мы рассмотрели, как работают StatefulSets и чем они отличаются от Deployment. Мы настроили и запустили MongoDB в качестве StatefulSet и рассмотрели ограничения и лучшие практики при использовании StatefulSets. StatefulSets значительно упрощают развертывание и управление приложениями с состоянием в Kubernetes.


Leave a Reply

Your email address will not be published. Required fields are marked *