Работа с хранилищами в Kubernetes. Часть 1
При развёртывании масштабируемого веб-приложения, которое обрабатывает большие объёмы пользовательских данных и транзакций, хорошо настроенное управление хранилищем заметно повышает производительность и доступность данных. И тогда при увеличении нагрузки на приложение доступ к данным остаётся быстрым и надёжным, задержки уменьшаются, общее взаимодействие пользователя с приложением улучшается.
Например, у нас была задача обеспечить надёжное и масштабируемое хранение данных в веб-приложении для управления клиентскими заказами. Мы настроили в Kubernetes Storage Class на основе SSD для базы данных (что не является хорошей практикой): это помогло обеспечить быстрый доступ и обработку транзакций. А для логов и нечасто применяемых данных использовали отдельный Storage Class с HDD, и это позволило снизить затраты.
А главное, Storage в Kubernetes — это такая штука, которую ты сделал и забыл, дальше оно там само работает.
PersistentVolume (PV)
Подсистемы PV представляют собой абстракции реальных хранилищ данных, которые размещаются на физических или виртуальных дисках. PV предоставляют интерфейс для управления жизненным циклом данных независимо от того, на каком уровне инфраструктуры они фактически хранятся (например, NFS, iSCSI, cloudstorage и т. д.).
Путешествие данных: от пода — к PV
Когда вы работаете с подами в Kubernetes, одним из первых вопросов, который приходит в голову, является: «Куда деваются мои данные после завершения пода?»
Именно здесь на сцену выходят PV. Они как бы говорят вашим данным: «Не волнуйтесь, я сохраню вас». Это не просто хранилище — это хранилище, спроектированное так, чтобы выжить в условиях постоянных изменений, характерных для кластеров Kubernetes.
Статическое vs динамическое создание
Создание PV может быть статическим или динамическим, и это одна из его наиболее привлекательных особенностей. В статическом режиме администратор заранее создаёт ряд PV с различными характеристиками. Это как заранее приготовленный шкаф с разными ящиками для хранения. В динамическом режиме PV создаётся «на лету» на основе требований, указанных в PersistentVolumeClaim (PVC). Это как если бы у вас был магический шкаф, который сам создаёт нужный вам ящик, когда вы его запросите.
Жизненный цикл и политики восстановления
Один из наиболее интересных аспектов PV — это его жизненный цикл и политики восстановления. Когда PVC удаляется, что происходит с PV? Он может быть сохранён для будущего использования, может быть полностью удалён или даже «рециклирован» для очистки данных. Это даёт администраторам гибкость в управлении ресурсами и обеспечивает высокую степень контроля над данными.
Affinity узлов: почему это важно?
Affinity узлов в PV позволяет вам уточнить, на каких узлах этот конкретный PV может быть использован. Это особенно полезно в больших и разнородных кластерах, где у разных узлов могут быть разные характеристики хранилища. С помощью аффинности узлов вы можете гарантировать, что ваш PV будет размещён там, где это наиболее эффективно с точки зрения производительности и надёжности.
Схема работы PV
На этой схеме показан процесс работы с PV в Kubernetes:
- User: пользователь или приложение создаёт PVC.
- Persistent Volume Claim (PVC): запрос на выделение PV.
- API Server: обрабатывает запрос и передаёт его PV Controller.
- PV Controller: управляет жизненным циклом PV.
- PersistentVolume (PV): фактическое хранилище.
- Storage Backend: backend, который обеспечивает хранение данных (может быть локальным или облачным).
- Disk/Cloud Storage: физическое хранилище данных.
Примеры
YAML для Persistent Volume:
apiVersion: v1 kind: PersistentVolume metadata: name: my-local-pv spec: capacity: storage: 10Gi volumeMode: Filesystem accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Retain storageClassName: my-local-sc hostPath: path: "/mnt/local-storage" nodeAffinity: required: nodeSelectorTerms: - matchExpressions: - key: "kubernetes.io/hostname" operator: In values: - node1 - node2
В этом примере:
- `name: my-local-pv` — имя Persistent Volume.
- `storage: 10Gi` — размер хранилища в гигабайтах.
- `ReadWriteOnce` — режим доступа, позволяющий чтение и запись только одним пользователем.
- `storageClassName: my-local-sc` — имя Storage Class, к которому привязан этот PV.
- `path: /mnt/local-storage` — локальный путь на узле для хранилища.
- `nodeAffinity` — условия, определяющие, на каких узлах может быть размещён этот PV.
PersistentVolumes в Kubernetes — не просто механизм хранения данных. Это продуманный и гибкий инструмент, который позволяет администраторам и разработчикам сосредоточиться на своей основной работе, не беспокоясь о данных. Они обеспечивают уровень абстракции и управления, который делает работу с хранилищем не только возможной, но и эффективной.
Persistent Volume Claim (PVC) в Kubernetes
PersistentVolumeClaims (PVC) — это как заявки на аренду недвижимости в мире Kubernetes.
Если PersistentVolumes (PV) являются зданиями, готовыми к заселению, то PVC — это ваша анкета, в которой вы указываете, какие условия вам нужны: количество комнат, наличие балкона и так далее.
PVC — это запрос на выделение хранилища из общего пула PV. Когда приложение в кластере нуждается в постоянном хранилище, оно не обращается напрямую к PV. Вместо этого оно создаёт PVC, в котором описывает свои требования к хранилищу. Это абстракция, которая позволяет разработчикам фокусироваться на коде, не задумываясь о деталях инфраструктуры.
Как только PVC создан, Kubernetes начинает поиск подходящего PV. Этот процесс называется «связыванием». Если подходящий PV найден, то он «связывается» с PVC, и приложение может начать использовать этот том для хранения данных. Если подходящего PV нет, то PVC остаётся в состоянии Pending до тех пор, пока не появится соответствующий PV или пока не будет выполнено динамическое выделение хранилища.
Принципы работы PVC:
- Декларативность: PVC создаётся через YAML-файл, который описывает требуемые параметры хранилища, такие, как размер, тип и режимы доступа.
- Динамическое выделение: если в кластере настроены Storage Classes, то PVC может динамически создавать PersistentVolumes (PV) на основе этих классов.
- Привязка к PV: после создания PVC автоматически привязывается к соответствующему PV. Если подходящего PV нет, то PVC остаётся в состоянии Pending до тех пор, пока не будет найден или создан подходящий PV.
- Изоляция ресурсов: PVC обеспечивает изоляцию хранилища между различными приложениями и пользователями, позволяя каждому из них иметь свои собственные требования к хранилищу.
Ключевые концепции
Access Modes
В Kubernetes PersistentVolumeClaim (PVC) предоставляет различные режимы доступа к хранилищу. Эти режимы определяют, как поды могут взаимодействовать с соответствующим
PersistentVolume (PV). Вот подробное описание каждого режима:
- ReadWriteOnce (RWO). Этот режим позволяет одному поду читать и записывать данные на хранилище. Ни один другой под не может подключиться к этому же хранилищу для чтения или записи. Применение: идеально подходит для баз данных, где требуется эксклюзивный доступ к хранилищу для обеспечения целостности данных.
- ReadOnlyMany (ROX). Этот режим позволяет множеству подов подключаться к хранилищу только для чтения данных. Применение: подходит для сценариев, где множество подов должно читать общие данные, например, конфигурации или общие ресурсы.
- ReadWriteMany (RWX). Этот режим позволяет множеству подов читать и записывать данные на одно и то же хранилище. Применение: используется в сценариях, где несколько подов должно иметь возможность читать и записывать данные, например, в системах совместной работы.
Storage Class
Представляет собой способ описания классов хранилища, которые можно использовать для динамического выделения PersistentVolumes (PV) при создании PersistentVolumeClaims (PVC).
Storage Class определяет, какой провайдер хранилища будет использоваться, какие параметры будут применены и другие специфические для провайдера настройки.
Selector
Селекторы в PVC позволяют вам фильтровать и выбирать PersistentVolumes (PV) на основе меток. Это предоставляет дополнительный уровень контроля при привязке PVC к PV, позволяя вам удостовериться, что выбранный том соответствует определённым требованиям или политикам. Селекторы в PVC используют метки, которые были присвоены PV. Когда PVC создаётся с определённым селектором, он будет привязан только к тем PV, которые соответствуют меткам селектора.
Reclaim Policy
Определяет, что произойдёт с PersistentVolume (PV) после удаления соответствующего PersistentVolumeClaim (PVC). Это важный аспект управления жизненным циклом хранилища в Kubernetes.
Виды политик восстановления:
1. Retain (сохранить).
- Что происходит: после удаления PVC соответствующий PV не удаляется. Он остаётся в системе в состоянии Released.
- Применение: этот вариант полезен, если вы хотите вручную управлять данными на томе после удаления PVC.
2. Delete (удалить).
- Что происходит: после удаления PVC соответствующий PV также удаляется.
- Применение: полезно в динамических окружениях, где ресурсы хранилища должны быть освобождены как можно быстрее.
3. Recycle (переработать).
- Что происходит: после удаления PVC данные на PV удаляются, и он может быть автоматически перепривязан к новому PVC.
- Применение: этот метод устарел и обычно заменяется динамическим выделением хранилища.
Вот диаграмма, которая поможет понять ключевые компоненты и взаимодействия, связанные с PersistentVolumeClaim:
На диаграмме:
- PersistentVolume (PV): представляет собой фактический ресурс хранилища в кластере.
- Storage Backend: фактическая система хранения, где хранятся данные, такие, как NFS, iSCSI и т. д.
- Типы хранилищ: различные типы систем хранения, которые могут быть использованы.
- PersistentVolumeClaim (PVC): запрос на хранилище от пользователя.
- Поды: наименьшие развёртываемые единицы вычислений, которые могут быть созданы и управляемы в Kubernetes.
- Контейнеры: контейнеры, которые работают внутри подов и выполняют фактические вычисления.
Пример YAML для PVC:
apiVersion: v1 kind: PersistentVolumeClaim metadata: name: my-pvc spec: accessModes: - ReadWriteOnce resources: requests: storage: 1Gi storageClassName: standard
Использование PVC в Pod:
apiVersion: v1 kind: Pod metadata: name: "myapp" namespace: default labels: app: "myapp" spec: volumes: - name: my-storage persistentVolumeClaim: claimName: my-pvc containers: - name: myapp image: "debian-slim:latest" volumeMounts: - name: my-storage mountPath: "/data"
Управление жизненным циклом:
- Создание: как только PVC создан, Kubernetes автоматически ищет подходящий PV и привязывает его к PVC.
- Использование: поды могут использовать PVC для хранения данных.
- Удаление: при удалении PVC PV может быть либо удалён, либо сохранён (в зависимости от политики).
StorageClass (SC) в Kubernetes
Это нечто вроде каталога аренды жилья, где каждый класс представляет собой набор характеристик и условий для хранилища. Это ключевой элемент, который управляет динамическим выделением хранилища в кластере. Этот механизм описывает различные классы хранилища, которые предлагаются в кластере. Каждый класс имеет свои уникальные характеристики, такие, как тип диска, скорость IOPS и параметры шифрования.
SC определяет, как должны быть созданы PersistentVolumes (PV) при динамическом выделении хранилища на основе PersistentVolumeClaims (PVC). Возможность динамического выделения, когда приложение создаёт PVC и указывает в нём Storage Class, Kubernetes автоматически создаёт PV с нужными характеристиками.
Ключевые аспекты Storage Class:
- Provisioner: определяет, какой провайдер хранилища будет использоваться, например, для AWS это будет `kubernetes.io/aws-ebs`.
- Reclaim Policy: определяет, что произойдёт с PV после того, как PVC будет удалён. Обычно это Retain или Delete.
- Parameters: это дополнительные параметры, которые можно установить для хранилища, например, для AWS EBS это может быть тип диска (`io1`, `gp2` и т. д.).
- VolumeBinding Mode: этот параметр определяет, когда PV будет привязан к PVC. Он может быть либо Immediate, либо WaitForFirstConsumer.
- AllowedTopologies: это ограничения на топологию, в которой могут быть созданы PV.
Пример YAML для Storage Class:
apiVersion: v1 kind: StorageClass metadata: name: my-local-sc provisioner: kubernetes.io/no-provisioner volumeBindingMode: WaitForFirstConsumer
В этом примере:
- `name: my-local-sc` задаёт имя для StorageClass.
- `provisioner: kubernetes.io/no-provisioner` указывает, что хранилище не будет динамически выделяться. Вместо этого будет использоваться уже существующий PersistentVolume.
- `volumeBindingMode: WaitForFirstConsumer` означает, что фактическое привязывание PV к PVC произойдёт, только когда первый клиент (обычно под) будет готов его использовать.
Storage Class особенно полезен в многофункциональных и разнородных кластерах. Например, для базы данных вы можете создать класс с высокопроизводительным SSD, а для архива данных — класс с более дешёвым и медленным хранилищем. Это позволяет оптимизировать затраты и производительность.
Вот диаграмма, которая поможет вам понять ключевые компоненты и взаимодействия, связанные со Storage Class:
На диаграмме:
- Storage Class (SC): определяет класс хранилища в кластере.
- Provisioner: система, которая будет предоставлять хранилище (например, AWS, GCP и т. д.).
- Reclaim Policy: политика возврата ресурсов (Retain, Delete).
- Parameters: дополнительные параметры для хранилища, такие, как тип файловой системы или зона.
- PersistentVolumeClaim (PVC): запрос на хранилище от пользователя.
- PersistentVolume (PV): фактический ресурс хранилища.
В целом Storage Class в Kubernetes является инструментом, который добавляет дополнительный уровень абстракции и гибкости при работе с хранилищем данных. Он не только упрощает задачи управления, но и открывает новые возможности для оптимизации ресурсов и повышения эффективности. Эта функциональность становится особенно ценной в сложных и динамичных средах, где требования к хранилищу могут быстро меняться.