Тома в Kubernetes — это ключевой механизм для управления данными в контейнерах. Они позволяют сохранять данные между перезапусками контейнеров, делиться файлами между подами и подключать внешние хранилища. Сегодня мы подробно разберем, как работают Volumes в Kubernetes, и на практике создадим несколько их типов, включая emptyDir, hostPath и PersistentVolume.
Что такое Kubernetes Volumes и зачем они нужны
Kubernetes Volumes — это объект в кластере Kubernetes, предназначенный для управления данными в контейнерах. Контейнеры по своей природе являются эфемерными, то есть их состояние не сохраняется после перезапуска или удаления. Это создает проблему для приложений, которым требуется постоянное хранение данных, таких как базы данных, файлы конфигурации или кэш. Kubernetes Volumes решают данную проблему, предоставляя способ хранения данных, доступных для контейнеров в поде, и управления ими на уровне кластера.
Основная задача томов — обеспечить постоянное хранение данных, их доступность между перезапусками контейнеров и возможность совместного использования данных между контейнерами в одном поде. Тома также позволяют подключать внешние хранилища, такие как облачные диски, NFS или локальные директории, к контейнерам. Без использования механизма volumes данные, записанные в контейнер, будут потеряны при его перезапуске, так как файловая система контейнера является временной.
Тома в Kubernetes также упрощают управление конфигурацией. Например, с помощью томов можно монтировать файлы конфигурации, таких объектов, как ConfigMap или Secret, что позволяет динамически обновлять настройки приложения без необходимости пересборки образа контейнера.
Kubernetes
приложениями: от развертывания
и масштабирования до мониторинга
и обработки ошибок.
Преимущества использования томов в Kubernetes
- Постоянное хранение данных: данные сохраняются даже после перезапуска пода или контейнера.
- Совместное использование данных: несколько контейнеров в одном поде могут использовать один и тот же том для доступа и обмена данными.
- Гибкость: поддержка множества типов хранилищ, от локальных директорий до облачных решений.
- Управление конфигурацией: интеграция с объектами
ConfigMapиSecretдля передачи конфиденциальных данных или настроек.
В Kubernetes тома связываются с подами через указание спецификации в YAML или JSON манифестах. Они определяют, где и как данные будут доступны контейнерам.
Предварительные требования
Далее мы будем рассматривать практическую часть для которой нам понадобится кластер Kubernetes. Арендовать готовый кластер можно с помощью сервиса Kubernetes в облаке. Для работы с сервисами достаточно одной master-ноды и одной worker-ноды с минимальной конфигурацией.
После заказа кластера он будет готов к использованию в течение нескольких минут. kubeconfig для подключения к кластеру будет сгенерирован и доступен в разделе «Дашборд».
Основные типы томов в Kubernetes
Kubernetes поддерживает различные типы томов, каждый из которых подходит для определенных сценариев использования. Рассмотрим наиболее распространенные типы томов и их особенности на практике.
emptyDir
emptyDir — это временный том в Kubernetes, который создается при запуске пода и существует только в течение его жизненного цикла. Данные в emptyDir хранятся на узле кластера, где выполняется под, и удаляются при завершении работы пода (например, при его перезапуске или удалении). Этот тип тома подходит для временных данных, таких как кэш, промежуточные результаты обработки или для обмена данными между контейнерами внутри одного пода.
Пример конфигурации emptyDir приведен ниже:
Мы выбрали образ веб-сервера Nginx, для которого emptyDir используется как временное хранилище. Оно подходит для кэширования данных или хранения лог-файлов, которые не требуют долговременного сохранения.
Сохраняем конфигурацию выше в файл с именем nginx-emptydir.yaml и применяем:

Проверим что под был успешно запущен:

Как можно увидеть на скриншоте выше, под был успешно запущен и его статус отображается как Running.
Далее подключаемся к контейнеру при помощи команды:
Где nginx-deployment-b8789c9cb-9xnv4 это имя пода. Не забудьте заменить на нужное — у вас будет свое уникальное имя.
Внутри контейнера проверяем наличие директории /cache:

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

Файл был успешно создан и запись успешно проходит.
Далее выходим из контейнера при помощи команды:
Как мы уже подчеркивали ранее, том emptyDir удаляется при удалении пода, но сохраняется при перезапуске контейнера внутри пода (если под не удаляется). Чтобы проверить это, сымитируем сбой, завершив основной процесс в контейнере при помощи команды:
Далее снова подключаемся к контейнеру:
Где nginx-deployment-b8789c9cb-9xnv4 это имя пода. Не забудьте заменить на нужное — у вас будет свое уникальное имя. Чтобы узнать имя пода можно выполнить команду:

Проверяем что ранее созданная директория осталась на месте:

Также проверим, что ранее созданный файл new-test-file.txt остался:

Файл testfile.txt остался на месте, так как emptyDir сохраняется на уровне пода.
hostPath
hostPath позволяет монтировать директорию или файл с узла кластера в контейнер. Этот тип тома полезен для доступа к системным файлам узла, например, логам или конфигурациям. Однако использование hostPath требует осторожности, так как оно привязывает под к конкретному узлу.
Рассмотрим работу hostPath на практике. Для этого создадим два пода. В первом поде с именем writer мы создадим файл demo.txt, который будет храниться в директории /host. В файл будет записана строка «Hello from writer». С помощью второго пода с именем reader мы прочитаем файл demo.txt, который был создан в первом поде. Опция DirectoryOrCreate означает, что заданный путь для директории должен существовать либо, если он отсутствует, должна быть создана новая директория. Конфигурация подов приведена ниже:
Сохраняем конфигурацию выше в файл с именем hostpath-testing.yaml и применяем:

Проверим что поды были успешно запущены:

Как можно увидеть на скриншоте выше, поды были успешно запущены и их статусы отображается как Running.
Далее подключаемся ко второму поду с именем reader и выводим содержимое файла demo.txt:

Как можно заметить на скриншоте выше, содержимое файла было успешно выведено.
ConfigMap
ConfigMap — это объект, используемый для хранения неконфиденциальных данных в формате ключ-значение. Он предназначен для передачи конфигурационных параметров в поды, таких как настройки приложения, переменные окружения или конфигурационные файлы, без необходимости встраивать их в образ контейнера.
Рассмотрим использование ConfigMap на практике. В конфигурации ниже задействован образ с веб-сервером Nginx, для которого будет использован файл nginx.conf (основной конфигурационный файл Nginx). ConfigMap используется как том (config-volume), монтируя файл nginx.conf в директорию /etc/nginx/conf.d контейнера в режиме только для чтения:
Сохраняем конфигурацию выше в файл с именем nginx-configmap.yaml и применяем:

Проверим что поды были успешно запущены:

Как можно увидеть на скриншоте выше, поды были успешно запущены и их статусы отображается как Running.
Далее подключаемся к контейнеру при помощи команды:
Где nginx-app-687d4c5ddf-2pfjz это имя пода. Не забудьте заменить на нужное — у вас будет свое уникальное имя.
Внутри контейнера отобразим файл nginx.conf для которого мы поменяли конфигурацию:

Как можно увидеть на скриншоте выше, ранее проброшенная конфигурация была успешно применена.
Работа с PersistentVolume (PV) и PersistentVolumeClaim (PVC)
Для приложений, требующих постоянного хранения, Kubernetes предоставляет механизмы PersistentVolume (PV) и PersistentVolumeClaim (PVC).
PersistentVolume — это объект, представляющий ресурс хранения в кластере Kubernetes. Он может быть как физическим, так и логическим ресурсом, например, NFS, блоком в облачном хранилище или локальным диском.
PersistentVolumeClaim — это запрос от пользователя или приложения на использование хранилища. PVC запрашивает определенный объем хранилища и режим доступа. Kubernetes связывает PVC с подходящим PV, если он доступен, или динамически создает PV при помощи StorageClass.
Создание PV
В качестве ресурса для PV мы воспользуемся дополнением CSI S3 от хостинг-провайдера Timeweb Cloud.
CSI S3 — это плагин для Kubernetes, который позволяет монтировать S3-бакеты как тома хранения для контейнеров. Он поддерживает динамическое выделение бакетов и их монтирование через FUSE (например, с использованием GeeseFS или rclone). Более подробно с CSI S3 можно ознакомиться перейдя по ссылке.
Для начала необходимо установить плагин CSI S3. Для этого переходим в раздел «Дополнения» на странице управления кластером и находим плагин с именем «CSI S3»:

На странице плагина создаем новый бакет или используем существующий (если он был арендован ранее):

После этого нажимаем на кнопку «Установить» и дожидаемся установки плагина.
Для проверки установки выполним команду ниже:
В ответ должна отобразиться информация о подключенном бакете:

Создание PVC
После того мы создали объект типа PV, создадим PVC. Пример конфигурации приведен ниже:
Манифест выше определяет PersistentVolumeClaim с именем csi-s3-pvc и запрашивает 5 ГБ хранилища с режимом доступа ReadWriteMany, который разрешает множественным подам читать и записывать данные одновременно используя класс хранения csi-s3.
Сохраняем конфигурацию выше в файл с именем pvc-testing.yaml и применяем:

Далее проверяем что объект PersistentVolumeClaim был успешно создан:

Подключение PVC в Deployment
Чтобы приложение могло использовать PVC, его необходимо подключить в манифесте Deployment. Пример ниже демонстрирует, как контейнер с образом Nginx использует подключенный PVC:
Контейнер монтирует том s3-storage по пути /usr/share/nginx/html, который связан с PersistentVolumeClaim под названием csi-s3-pvc.
Сохраняем конфигурацию выше в файл с именем pvc-deployment-connect.yaml и применяем:

Проверяем что все объекты были успешно созданы и под запущен:

Далее проверим что ранее примонтированный том доступен в контейнере. Для этого подключаемся к контейнеру при помощи команды:
Где test-pvc-nginx-deployment-5fd656dd6d-5r6sr это имя пода. Не забудьте поменять на свое. Имя пода можно узнать при помощи команды:
Внутри контейнера выполняем команду:

Директория /usr/share/nginx/html была успешно примонтирована.
Теперь возвращаемся в веб-интерфейс хранилище S3 в панели управления:

Далее переходим в раздел «Объекты»:

Открываем корневую директорию хранилища и нажимаем на кнопку «Загрузить файл»:

В качестве примера загрузим какой-нибудь файл. Например, картинку в формате SVG:

Подключаемся к контейнеру еще раз:
Где test-pvc-nginx-deployment-5fd656dd6d-5r6sr это имя пода. Не забудьте поменять на свое.
Переходим в директорию usr/share/nginx/html:
и проверяем наличие ранее загруженного файла:

Файл успешно отобразился.
Подготовили для вас выгодные тарифы на облачные серверы
477 ₽/мес
657 ₽/мес
Лучшие практики при работе с томами в Kubernetes
- Используйте PVC для постоянного хранения данных: Даже если вы работаете с локальным хранилищем, использование PVC упрощает управление и делает конфигурацию переносимой.
- Ограничивайте доступ с помощью accessModes: Выбирайте подходящий режим доступа (
ReadWriteOnce,ReadOnlyMany,ReadWriteMany) в зависимости от потребностей приложения. - Избегайте hostPath для production-систем:
hostPathпривязывает под к конкретному узлу, что может нарушить переносимость и отказоустойчивость. - Используйте ConfigMap для конфигурации: Это позволяет отделить конфигурацию от кода.
- Мониторьте использование хранилища: Убедитесь, что тома не переполняются, особенно для
emptyDir, который ограничен ресурсами узла. - Используйте StorageClass для автоматизации: Это упрощает масштабирование и управление хранилищем в больших кластерах.
Частые ошибки при работе с томами в Kubernetes
- Неправильно назначенные права доступа: Если контейнер не имеет прав на запись в том, это может привести к ошибкам. Например, при использовании
hostPathубедитесь, что директория на узле доступна для записи. - Отсутствие StorageClass: Без
StorageClassдинамическое выделение PV невозможно, что приводит к ручному управлению хранилищем. - Переполнение диска при использовании типа emptyDir: Так как
emptyDirиспользует диск узла, его переполнение может повлиять на стабильность кластера. - Игнорирование ресурса cleanup PV: После удаления PVC соответствующий PV может остаться в кластере, если не настроена политика регенерации (
reclaimPolicy).
Заключение
Kubernetes Volumes — это мощный инструмент для работы с данными в кластере, обеспечивающий гибкость и удобство управления конфигурацией. Знание типов томов, их принципов работы и лучших практик упрощает взаимодействие приложений с файлами. Чтобы обеспечить стабильность и высокую производительность системы, важно учитывать особенности каждого типа тома и избегать типичных ошибок.
