Storage

Хоть и kubernetes очень удобен для разворачивания и управления нагрузкой, которая не имеет состояния(stateless), он также предоставляет механизмы для хранения данных и работы приложений, которым необходимо хранить в себе некоторое состояние(stateful). Данные механизмы позволяют не терять данные между перезапусками контейнеров(Volumes), а также динамически выделять хранилище(StorageClass, PersistentVolumeClaim, PersistentVolume) и управлять снимками хранилища(VolumeSnapshotClass, VolumeSnapshot).

Volumes

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

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /my-nfs-data
      name: test-volume
  volumes:
  - name: test-volume
    nfs:
      server: my-nfs-server.example.com
      path: /my-nfs-volume
      readOnly: true

В данном примере показан volume типа nfs, который монтируется в конкретный контейнер через параметр volumeMounts. Связь между volume пода и volumeMounts контейнера производится через параметр name. Volume поддерживает множество различных типов томов: configMap, secret, emptyDir, fc, iscsi, nfs, cephfs, rbd и другие. Помимо встроенных типов есть возможность добавление в кластер дополнительных типов с помощью Container Storage Interface (CSI).

Ephemeral Volumes

Не всем приложениям нужно хранить данные между пересозданием пода, например данные временных файлов, кэша, логов и т.д. Также приложению могут потребоваться данные из api kubernetes, которые можно смонтировать внутрь пода. Для этого подойдут эфемерные тома, которые создаются только на время жизни пода.

EmptyDir

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

apiVersion: v1
kind: Pod
metadata:
  name: test-pd
spec:
  containers:
  - image: registry.k8s.io/test-webserver
    name: test-container
    volumeMounts:
    - mountPath: /cache
      name: cache-volume
  volumes:
  - name: cache-volume
    emptyDir:
      medium: Memory
      sizeLimit: 500Mi

По умолчанию размер тома не ограничивается(только размером файловой системы на ноде), но может быть ограничен дополнительным параметром sizeLimit и через resources. Через параметр medium: Memory можно указать хранение данных не на файловой системе, а в оперативной памяти.

ConfigMap

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

apiVersion: v1
kind: ConfigMap
metadata:
  name: log-config
data:
  log_level: debug

Затем можно создать Volume в поде, используя данные из ConfigMap.

apiVersion: v1
kind: Pod
metadata:
  name: configmap-pod
spec:
  containers:
    - name: test
      image: busybox:1.28
      volumeMounts:
        - name: config-vol
          mountPath: /etc/config
  volumes:
    - name: config-vol
      configMap:
        name: log-config
        items:
          - key: log_level
            path: log_level
        optional: false

Secret

Также в Kubernetes существует ресурс Secret, который используется для хранения конфиденциальных данных, таких как пароли, ключи API и сертификаты.

apiVersion: v1
kind: Secret
metadata:
  name: mysecret
data:
  key: dmFsdWU=
type: Opaque

Secret может быть использован в качестве тома в Pod.

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
  - name: mypod
    image: redis
    volumeMounts:
    - name: foo
      mountPath: "/etc/foo"
      readOnly: true
  volumes:
  - name: foo
    secret:
      secretName: mysecret
      optional: true

DownwardAPI

В Kubernetes существует возможность для контейнеров получать информацию об окружении, в котором они запущены, с помощью механизма Downward API. Downward API позволяет контейнерам получить информацию о:

  • лейблах пода

  • полях пода

  • имени и уникальном идентификаторе пода

  • имени и уникальном идентификаторе неймспейса

Для использования Downward API можно использовать volume типа downwardAPI, который включает в себя файлы, содержащие запрашиваемую информацию.

apiVersion: v1
kind: Pod
metadata:
  name: downwardapi-example
  labels:
    app: myapp
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: downwardapi
      mountPath: /etc/podinfo
      readOnly: true
  volumes:
  - name: downwardapi
    downwardAPI:
      items:
      - path: "metadata/labels"
        fieldRef:
          fieldPath: metadata.labels
      - path: "mem_limit"
        resourceFieldRef:
          containerName: client-container
          resource: limits.memory
          divisor: 1Mi

Projected

Projected volume в Kubernetes позволяет объединять в одном volume несколько источников данных, таких как ConfigMap, Secret, Downward API и ServiceAccountToken, и предоставлять их как один файловый системный раздел в контейнере. Это может быть полезно, если контейнеру требуется доступ к нескольким ресурсам конфигурации или сервисным данным.

apiVersion: v1
kind: Pod
metadata:
  name: projected-example
spec:
  containers:
  - name: nginx
    image: nginx
    volumeMounts:
    - name: config
      mountPath: /etc/config
      readOnly: true
  volumes:
  - name: config
    projected:
      sources:
      - configMap:
          name: myconfigmap
      - secret:
          name: mysecret

Persistent Volumes

Persistent Volumes (PV) в Kubernetes - это абстракция над физическим хранилищем данных, которая позволяет абстрагировать хранилище от приложений, которые его используют. PV - это ресурс Kubernetes, который описывает хранилище данных, такое как диск, NFS-шару или том в облаке, и его характеристики, такие как доступность, емкость и режим доступа. PV можно создать заранее, до того, как к нему обратится приложение, а потом использовать его как ресурс для подов. Когда приложение запрашивает PV, Kubernetes выбирает наиболее подходящее свободное хранилище на основе его параметров.

apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv0003
spec:
  capacity:
    storage: 5Gi
  volumeMode: Filesystem
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Recycle
  storageClassName: slow
  mountOptions:
    - hard
    - nfsvers=4.1
  nfs:
    path: /tmp
    server: 172.17.0.2

Persistent Volume Claim (PVC) - это способ запроса ресурса PV в Kubernetes. Когда PVC создается, Kubernetes выбирает PV, который соответствует критериям PVC (размер, доступность и т.д.), и резервирует его для использования.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: myclaim
spec:
  accessModes:
    - ReadWriteOnce
  volumeMode: Filesystem
  resources:
    requests:
      storage: 1Gi
  storageClassName: slow
  selector:
    matchLabels:
      release: "stable"
    matchExpressions:
      - {key: environment, operator: In, values: [dev]}

Поды могут использовать PVC, чтобы монтировать том в свои контейнеры.

apiVersion: v1
kind: Pod
metadata:
  name: mypod
spec:
  containers:
    - name: myfrontend
      image: nginx
      volumeMounts:
      - mountPath: "/var/www/html"
        name: mypd
  volumes:
    - name: mypd
      persistentVolumeClaim:
        claimName: myclaim

Storage Classes

StorageClass - это объект, который определяет класс хранилища для PersistentVolume (PV). StorageClass определяет способ, которым PV будет создан, конфигурирован и управляться. Он также определяет тип хранилища, такой как NFS, iSCSI, Ceph, AWS EBS, GCP PD и т.д., и параметры хранилища, такие как размер, скорость, доступность и т.д.

StorageClass может использоваться для динамического выделения PV. Это означает, что при создании пода, если нужный PV не существует, StorageClass может автоматически создать его для пода. Например, если поду требуется PersistentVolumeClaim (PVC) определенного размера, и нет доступного PV, StorageClass может создать новый PV нужного размера и назначить его PVC. Это может быть очень удобно для разработчиков, которые не хотят создавать и управлять PV вручную.

Кроме того, разные приложения могут использовать разные классы хранилищ, а StorageClass обеспечивает способ управления и мониторинга этих классов в едином месте.

apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: standard
provisioner: kubernetes.io/aws-ebs
parameters:
  type: gp2
reclaimPolicy: Retain
allowVolumeExpansion: true
mountOptions:
  - debug
volumeBindingMode: Immediate