В чем разница в работе с PersistentVolume (PV) между Deployment и StatefulSet?

«В чем разница в работе с PersistentVolume (PV) между Deployment и StatefulSet?» — вопрос из категории Kubernetes, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое отличие в том, что StatefulSet обеспечивает стабильную, уникальную привязку тома к конкретному поду, в то время как Deployment этого не гарантирует. Это фундаментально влияет на работу с состоянием (state).

Deployment (для stateless-приложений):

  • Нет гарантий уникальности тома. Поду назначается любой доступный PV, удовлетворяющий PersistentVolumeClaim (PVC). Если под пересоздается, он может получить другой том.
  • Все реплики используют один том (при ReadWriteMany) или независимые тома (при ReadWriteOnce), но без привязки к идентификатору пода.
  • Пример (опасный для stateful-данных):
    apiVersion: apps/v1
    kind: Deployment
    spec:
      replicas: 3
      template:
        spec:
          containers:
          - name: app
            volumeMounts:
            - mountPath: /data
              name: storage
          volumes:
          - name: storage
            persistentVolumeClaim:
              claimName: shared-pvc # Все 3 пода могут претендовать на один том

StatefulSet (для stateful-приложений: БД, очереди):

  • Уникальный том на под. Каждая реплика (app-0, app-1, app-2) получает свой собственный, уникальный PVC и PV.
  • Стабильная идентичность. Том следует за подом при ресхедулиннге. Если app-1 упадет и перезапустится на другом узле, он смонтирует тот же самый том data-app-1.
  • Порядок и предсказуемость. Развертывание, масштабирование и обновление происходят последовательно (по индексу), что критично для кластерных приложений.
  • Пример (корректный для stateful-данных):
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: postgres
    spec:
      serviceName: "postgres"
      replicas: 3
      volumeClaimTemplates: # Шаблон для создания УНИКАЛЬНОГО PVC для каждого пода
      - metadata:
          name: data
        spec:
          accessModes: ["ReadWriteOnce"]
          resources:
            requests:
              storage: 10Gi
      template:
        spec:
          containers:
          - name: postgres
            volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data

    В результате будут созданы PVC: data-postgres-0, data-postgres-1, data-postgres-2, каждый со своим PV.

Вывод: Используйте Deployment для веб-серверов, API, worker-ов. Используйте StatefulSet для PostgreSQL, Redis, Kafka, Elasticsearch и любых приложений, где данные привязаны к конкретной инстанции.