📝 Kubernetes

Volumes и Persistent Storage в Kubernetes

P
Автор
Pyland
📅
Опубликовано
30.06.2026
⏱️
Время чтения
3 мин
👁️
Просмотров
78
🌳
Уровень
Продвинутый
🐦 💼 ✈️

По умолчанию данные внутри контейнера исчезают вместе с его смертью. Kubernetes предлагает несколько уровней абстракции для хранения данных — от временных до постоянных.

Проблема: Pod умер → данные потеряны

Файловая система контейнера эфемерна. Если Pod перезапустился — база данных пуста, загруженные файлы исчезли, логи пропали. Для stateful-приложений это неприемлемо.

Решение — Volumes: внешнее хранилище, которое живёт дольше пода.

emptyDir: временное хранилище

Создаётся вместе с Pod, уничтожается вместе с Pod. Полезен для временных файлов и обмена данными между контейнерами в одном Pod.

apiVersion: v1
kind: Pod
metadata:
  name: app-with-temp-storage
spec:
  containers:
    - name: app
      image: my-app:1.0
      volumeMounts:
        - name: temp-data
          mountPath: /tmp/cache
    - name: sidecar
      image: busybox
      volumeMounts:
        - name: temp-data
          mountPath: /shared
  volumes:
    - name: temp-data
      emptyDir: {}

Оба контейнера видят одни и те же файлы. Данные живут пока жив Pod.

hostPath: монтирование директории с узла

Монтирует директорию с хост-машины (Worker Node) в Pod. Данные переживают перезапуск пода, но привязаны к конкретному узлу.

volumes:
  - name: host-logs
    hostPath:
      path: /var/log/myapp
      type: DirectoryOrCreate

Использование: доступ к устройствам хоста, специфические dev-сценарии. В production не рекомендуется — Pod привязан к узлу.

PersistentVolume и PersistentVolumeClaim

Полноценное постоянное хранилище. Состоит из двух объектов:

  • PersistentVolume (PV) — реальный ресурс хранения. Создаётся администратором или автоматически (StorageClass). Описывает ёмкость, тип, параметры доступа.
  • PersistentVolumeClaim (PVC) — запрос на хранилище от приложения. Разработчик описывает, сколько места и какой тип нужен. K8s найдёт подходящий PV.
# persistent-volume.yaml (обычно создаёт администратор)
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-pv
spec:
  capacity:
    storage: 10Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce      # один Pod в режиме чтение/запись
  persistentVolumeReclaimPolicy: Retain
  storageClassName: standard
  hostPath:
    path: /data/postgres  # для minikube/dev; в prod — NFS, cloud disk, etc.
# persistent-volume-claim.yaml (создаёт разработчик)
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: standard
  resources:
    requests:
      storage: 5Gi
# Использование PVC в Pod/Deployment
spec:
  containers:
    - name: postgres
      image: postgres:15
      env:
        - name: PGDATA
          value: /var/lib/postgresql/data/pgdata
      volumeMounts:
        - name: postgres-storage
          mountPath: /var/lib/postgresql/data
  volumes:
    - name: postgres-storage
      persistentVolumeClaim:
        claimName: postgres-pvc
kubectl apply -f persistent-volume.yaml
kubectl apply -f persistent-volume-claim.yaml

kubectl get pv
# NAME          CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   STORAGECLASS
# postgres-pv   10Gi       RWO            Retain           Bound    standard

kubectl get pvc
# NAME           STATUS   VOLUME        CAPACITY   ACCESS MODES   STORAGECLASS
# postgres-pvc   Bound    postgres-pv   10Gi       RWO            standard

Режимы доступа (AccessModes)

Режим Описание
ReadWriteOnce (RWO) Один узел, чтение+запись
ReadOnlyMany (ROX) Много узлов, только чтение
ReadWriteMany (RWX) Много узлов, чтение+запись (NFS, CephFS)

StorageClass: динамический provisioning

Вручную создавать PV для каждого PVC — неудобно. StorageClass автоматизирует создание хранилища.

# storageclass.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: fast-ssd
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp3
  iopsPerGB: "10"
  encrypted: "true"
reclaimPolicy: Delete
allowVolumeExpansion: true

Теперь PVC с storageClassName: fast-ssd автоматически создаст EBS-диск в AWS:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: app-data
spec:
  accessModes:
    - ReadWriteOnce
  storageClassName: fast-ssd
  resources:
    requests:
      storage: 20Gi
# Доступные StorageClass в кластере
kubectl get storageclass
# NAME                 PROVISIONER             AGE
# standard (default)   docker.io/hostpath      10d
# fast-ssd             kubernetes.io/aws-ebs   5d

StatefulSet для stateful-приложений

Обычный Deployment не подходит для баз данных: поды взаимозаменяемы, не имеют стабильных имён и отдельных PVC.

StatefulSet решает это:

  • Стабильные имена подов: postgres-0, postgres-1, postgres-2
  • Гарантированный порядок запуска и остановки
  • Каждый Pod получает собственный PVC (VolumeClaimTemplate)
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
spec:
  serviceName: postgres-headless
  replicas: 3
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:15
          env:
            - name: PGDATA
              value: /var/lib/postgresql/data/pgdata
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
  volumeClaimTemplates:
    - metadata:
        name: data
      spec:
        accessModes: [ReadWriteOnce]
        storageClassName: fast-ssd
        resources:
          requests:
            storage: 10Gi

Каждый из трёх подов получит свой PVC: data-postgres-0, data-postgres-1, data-postgres-2. При удалении пода PVC сохраняется — данные не теряются.

kubectl get statefulset
# NAME       READY   AGE
# postgres   3/3     5m

kubectl get pvc
# NAME             STATUS   VOLUME          CAPACITY
# data-postgres-0  Bound    pvc-abc...      10Gi
# data-postgres-1  Bound    pvc-def...      10Gi
# data-postgres-2  Bound    pvc-ghi...      10Gi

Ваша реакция на статью

💬 Комментарии (0)

🔐 Войдите в систему, чтобы оставить комментарий
🚪 Войти
💭

Комментариев пока нет

Станьте первым, кто поделится мнением об этой статье!

🔗 Похожие

Похожие статьи

Продолжите изучение с этими материалами

📝

Health Checks: liveness и readiness в Kubernetes

Контейнер запущен — не значит, что приложение работает. Может быть дедлок, переполнение памяти или медленная...

📅 30.06.2026 👁️ 93
📝

Resource Limits и Requests в Kubernetes

Без ограничений ресурсов один «жадный» контейнер может съесть всю память узла и убить остальные поды....

📅 30.06.2026 👁️ 83
📝

Что такое Kubernetes и зачем он нужен

Docker упакует приложение в контейнер. Но что делать, когда контейнеров сотни, они падают, нагрузка скачет,...

📅 30.06.2026 👁️ 86

Понравилась статья?

Подпишитесь на наши обновления и получайте новые статьи первыми. Развивайтесь вместе с PyLand!