Контейнер теряет загруженные файлы после пересоздания. Какой механизм объясняет это поведение?
Файлы были записаны в изменяемый слой файловой системы контейнера, который существует только вместе с конкретным экземпляром контейнера. При пересоздании создаётся новый экземпляр из образа, поэтому этот слой и его содержимое исчезают. Для сохранения данных используют том, подключаемое внешнее хранилище или объектное хранилище.
Контейнеры создавались как способ упаковать приложение вместе с его окружением и запускать его воспроизводимо на разных узлах. Для этого образ должен оставаться неизменяемым, а изменения во время работы контейнера отделяются в дополнительный записываемый слой.
Такой подход упрощает замену экземпляров, откат версий и масштабирование. Однако он намеренно отделяет жизненный цикл приложения от жизненного цикла данных.
Если приложение сохраняет пользовательские файлы только внутри контейнера, данные могут исчезнуть при пересоздании после обновления, сбоя узла или перемещения нагрузки на другой узел. Перезапуск процесса внутри того же контейнера обычно не удаляет записываемый слой, но удаление и создание нового контейнера уже создают другой слой.
Неверное решение приводит к потере данных, рассинхронизации реплик и невозможности гарантировать восстановление после сбоя. Особенно опасно хранить так файлы, которые должны переживать обновление приложения или обслуживаться несколькими экземплярами.
Образ контейнера состоит из неизменяемых слоёв. При запуске контейнер получает собственный записываемый слой поверх этих слоёв; конкретная реализация зависит от драйвера хранения, но концепция остаётся той же: изменения контейнера не изменяют исходный образ.
При пересоздании старый контейнер и его записываемый слой удаляются, а новый контейнер получает чистый слой из образа. Поэтому файл, созданный только внутри старого контейнера, недоступен новому экземпляру.
Для постоянных данных применяют разные варианты:
В оркестраторе важно различать жизненный цикл контейнера, пода или другой единицы размещения и внешнего хранилища. Например, временный каталог может пережить перезапуск контейнера, но исчезнуть вместе с подом, тогда как постоянный том имеет отдельный жизненный цикл. Точные гарантии нужно проверять в используемой платформе и классе хранилища.
Практическое правило: локальный записываемый слой использовать для временного кэша и промежуточных файлов, а бизнес-данные размещать во внешнем хранилище. Одного подключения тома недостаточно: нужны резервное копирование, контроль доступа, мониторинг заполнения и проверка восстановления.
Сервис обработки изображений принимает загрузку, сохраняет исходный файл в каталог контейнера и помещает путь к нему в базу данных. После обновления число реплик увеличили с двух до пяти, а часть заданий начала выполняться на новых узлах. Файлы стали недоступны: путь существовал в базе, но соответствующего локального содержимого на новом экземпляре не было.
Рассматривались три варианта. Общий том упростил бы работу с каталогами, но добавил зависимость от производительности и доступности сетевой файловой системы. Локальный том был бы быстрее, однако не решал перенос задачи между узлами без дополнительной репликации. Объектное хранилище потребовало изменить логику доступа, зато отделило файлы от контейнеров и позволило всем репликам обращаться к одному источнику.
Выбрали объектное хранилище для исходных и обработанных изображений, а в базе оставили идентификаторы объектов и метаданные. Локальная файловая система используется только для временных промежуточных результатов. После этого пересоздание контейнеров и перенос заданий между узлами перестали влиять на доступность файлов; отдельно добавили политики удаления, резервирование метаданных и контроль неуспешных загрузок.
Обычно да, если речь идёт именно о перезапуске того же контейнера: его записываемый слой не создаётся заново. Но это не является гарантией долговечности данных: контейнер могут удалить, узел может выйти из строя, а оркестратор может создать новый экземпляр. Поэтому перезапуск и пересоздание нужно различать явно.
Образ предназначен для доставки версии приложения и его исходных статических файлов. Рабочие данные, записанные после запуска, автоматически не попадают в образ. Теоретически состояние можно специально превратить в новый образ, но это плохо подходит для пользовательских данных: процесс непрактичен, нарушает разделение приложения и состояния, усложняет параллельную работу и не заменяет резервное копирование.
Нет, нужно проверить режим доступа и семантику самого хранилища. Блочное хранилище часто рассчитано на подключение к одному узлу или одному потребителю, тогда как общий файловый ресурс поддерживает совместный доступ с другими ограничениями. Даже при технической возможности общего монтирования приложение может некорректно работать без безопасных блокировок, согласованности и защиты от одновременной записи; для независимых реплик часто надёжнее использовать объектное хранилище или специализированное внешнее хранилище состояния.