АрхитектураОблако и инфраструктураИнженер по эксплуатации и надёжности платформ

Контейнер теряет загруженные файлы после пересоздания. Какой механизм объясняет это поведение?

Контейнер теряет загруженные файлы после пересоздания. Какой механизм объясняет это поведение?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

Файлы были записаны в изменяемый слой файловой системы контейнера, который существует только вместе с конкретным экземпляром контейнера. При пересоздании создаётся новый экземпляр из образа, поэтому этот слой и его содержимое исчезают. Для сохранения данных используют том, подключаемое внешнее хранилище или объектное хранилище.

Исторический контекст

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

Такой подход упрощает замену экземпляров, откат версий и масштабирование. Однако он намеренно отделяет жизненный цикл приложения от жизненного цикла данных.

Постановка проблемы

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

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

Подробное решение

Образ контейнера состоит из неизменяемых слоёв. При запуске контейнер получает собственный записываемый слой поверх этих слоёв; конкретная реализация зависит от драйвера хранения, но концепция остаётся той же: изменения контейнера не изменяют исходный образ.

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

Для постоянных данных применяют разные варианты:

  • Именованный том управляется контейнерной платформой и обычно переживает удаление контейнера. Он подходит для данных, размещённых рядом с приложением, но его доступность и переносимость зависят от инфраструктуры.
  • Монтирование каталога узла даёт прямую связь с файловой системой конкретной машины. Это просто, но создаёт зависимость от узла, его структуры каталогов и прав доступа.
  • Распределённая файловая система может предоставлять общий каталог нескольким экземплярам, но требует отдельного управления производительностью, блокировками и доступностью.
  • Объектное хранилище хорошо подходит для пользовательских файлов: данные адресуются как объекты и не привязаны к конкретному контейнеру или узлу. Цена этой независимости — другая модель доступа и необходимость учитывать задержки, права и согласованность.

В оркестраторе важно различать жизненный цикл контейнера, пода или другой единицы размещения и внешнего хранилища. Например, временный каталог может пережить перезапуск контейнера, но исчезнуть вместе с подом, тогда как постоянный том имеет отдельный жизненный цикл. Точные гарантии нужно проверять в используемой платформе и классе хранилища.

Практическое правило: локальный записываемый слой использовать для временного кэша и промежуточных файлов, а бизнес-данные размещать во внешнем хранилище. Одного подключения тома недостаточно: нужны резервное копирование, контроль доступа, мониторинг заполнения и проверка восстановления.

Ситуация из практики

Сервис обработки изображений принимает загрузку, сохраняет исходный файл в каталог контейнера и помещает путь к нему в базу данных. После обновления число реплик увеличили с двух до пяти, а часть заданий начала выполняться на новых узлах. Файлы стали недоступны: путь существовал в базе, но соответствующего локального содержимого на новом экземпляре не было.

Рассматривались три варианта. Общий том упростил бы работу с каталогами, но добавил зависимость от производительности и доступности сетевой файловой системы. Локальный том был бы быстрее, однако не решал перенос задачи между узлами без дополнительной репликации. Объектное хранилище потребовало изменить логику доступа, зато отделило файлы от контейнеров и позволило всем репликам обращаться к одному источнику.

Выбрали объектное хранилище для исходных и обработанных изображений, а в базе оставили идентификаторы объектов и метаданные. Локальная файловая система используется только для временных промежуточных результатов. После этого пересоздание контейнеров и перенос заданий между узлами перестали влиять на доступность файлов; отдельно добавили политики удаления, резервирование метаданных и контроль неуспешных загрузок.

Что кандидаты часто упускают

  1. Сохранятся ли файлы после перезапуска контейнера?

Обычно да, если речь идёт именно о перезапуске того же контейнера: его записываемый слой не создаётся заново. Но это не является гарантией долговечности данных: контейнер могут удалить, узел может выйти из строя, а оркестратор может создать новый экземпляр. Поэтому перезапуск и пересоздание нужно различать явно.

  1. Почему нельзя считать образ способом сохранения данных?

Образ предназначен для доставки версии приложения и его исходных статических файлов. Рабочие данные, записанные после запуска, автоматически не попадают в образ. Теоретически состояние можно специально превратить в новый образ, но это плохо подходит для пользовательских данных: процесс непрактичен, нарушает разделение приложения и состояния, усложняет параллельную работу и не заменяет резервное копирование.

  1. Достаточно ли подключить один том к нескольким репликам?

Нет, нужно проверить режим доступа и семантику самого хранилища. Блочное хранилище часто рассчитано на подключение к одному узлу или одному потребителю, тогда как общий файловый ресурс поддерживает совместный доступ с другими ограничениями. Даже при технической возможности общего монтирования приложение может некорректно работать без безопасных блокировок, согласованности и защиты от одновременной записи; для независимых реплик часто надёжнее использовать объектное хранилище или специализированное внешнее хранилище состояния.