Ремонт файловых систем в контейнерах: практическое восстановление persistent storage в Docker и Kubernetes | AdminWiki
Timeweb Cloud — сервера, Kubernetes, S3, Terraform. Лучшие цены IaaS.
Попробовать

Ремонт файловых систем в контейнерах: практическое восстановление persistent storage в Docker и Kubernetes

18 мая 2026 12 мин. чтения
Содержание статьи

Повреждение файловой системы в persistent storage контейнера - критический инцидент, который останавливает stateful-приложения: базы данных, очереди сообщений, хранилища. В отличие от виртуальных машин, восстановление данных в средах Docker и Kubernetes требует понимания многоуровневой архитектуры хранения и точных, безопасных действий. Эта статья - практическое руководство, которое позволит вам диагностировать сбой, изолировать проблемный том, выполнить ремонт файловой системы и вернуть сервис в работу с минимальным простоем. Мы разберем конкретные команды для типовых ошибок, таких как Read-only file system, и стратегии работы с разными бэкендами: от локальных дисков до облачных EBS и сетевых NFS.

Архитектура persistent storage: где искать слабые места

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

Docker: Volumes vs Bind Mounts - разные риски потери данных

В Docker есть два основных типа постоянного хранения, и методы их восстановления различаются кардинально.

Docker Volume - сущность, управляемая демоном Docker. Данные хранятся в директории хоста, обычно /var/lib/docker/volumes/<volume_name>/_data. Риски связаны со сбоем самого демона Docker, повреждением этой директории или проблемами с драйвером тома. Восстановление часто требует доступа к этой служебной папке и проверки файловой системы на хосте.

Bind Mount - прямое монтирование директории с хоста в контейнер. Риск потери данных здесь выше, так как он напрямую зависит от состояния файловой системы хоста, прав доступа и действий администратора на самой ноде. Повреждение данных в bind mount означает повреждение данных в смонтированной директории хоста. Перед любыми операциями fsck критически важно определить тип используемого хранилища: для volume нужно найти его физическое расположение, для bind mount - путь на хосте.

Определить тип можно командой docker inspect <container_id>, изучив секцию Mounts.

Kubernetes: от StorageClass до физического диска - цепочка зависимостей

В Kubernetes цепочка доступа к данным длиннее: Pod -> PersistentVolumeClaim (PVC) -> PersistentVolume (PV) -> StorageClass -> CSI Driver/In-tree Plugin -> физический бэкенд (диск, NFS-сервер, облачный том).

Типичные точки отказа:

  • Узел (Node): физический сбой сервера, где размещен PV.
  • Присоединение тома (Volume Attach/Detach): сбой операции подключения диска к виртуальной машине в облаке или к ноде.
  • CSI-драйвер: ошибка в работе драйвера хранилища (например, для Ceph, AWS EBS).
  • Файловая система бэкенда: повреждение данных на самом диске, NFS-шаре или в объектном хранилище.
  • Сеть: разрыв соединения с сетевым хранилищем (NFS, iSCSI).

Для диагностики пройдите по цепочке:
1. kubectl get pod <pod_name> -o yaml - проверьте статус пода и условия (Conditions).
2. kubectl describe pvc <pvc_name> - убедитесь, что PVC связан с PV (поле VolumeName).
3. kubectl describe pv <pv_name> - ключевой шаг. В статусе (Status) проверьте, Bound ли том. В спецификации найдите nodeAffinity или nodeName, чтобы понять, на какой ноде том примонтирован. Поле Source укажет на бэкенд (например, volumeHandle: vol-0ab1c3def456789ab для AWS EBS).

Ошибка Read-only file system в логах пода - это симптом. Причина может быть на любом из этих уровней.

Экстренный ответ: что делать при первых признаках проблем

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

Создание диагностического пода: безопасный доступ к поврежденному тому

Не запускайте утилиты проверки файловой системы на работающем production-поде. Создайте изолированную среду. Самый безопасный способ - подключить проблемный PVC к специальному отладочному поду в режиме только для чтения.

Создайте манифест debug-pod.yaml:

apiVersion: v1
kind: Pod
metadata:
  name: volume-debugger
spec:
  volumes:
    - name: damaged-volume
      persistentVolumeClaim:
        claimName: your-damaged-pvc-claim # Замените на имя вашего PVC
        readOnly: true # Критически важный параметр!
  containers:
  - name: debugger
    image: alpine:latest
    command: [ "sleep", "3600" ]
    volumeMounts:
    - name: damaged-volume
      mountPath: /data

Примените его: kubectl apply -f debug-pod.yaml. После запуска пода вы можете подключиться к нему и провести первичный осмотр: kubectl exec -it volume-debugger -- /bin/sh. Проверьте, смонтирован ли том (mount | grep /data), попробуйте прочитать файлы. Режим readOnly: true предотвратит случайную запись и дальнейшую порчу.

Альтернативный метод для случаев, когда нужно работать с файловой системой ноды напрямую - kubectl debug node/<node_name> -it --image=alpine. Этот способ дает доступ к хостовой системе, но требует больше прав и осторожности.

Фиксация состояния: VolumeSnapshot и другие методы резервирования

Перед любыми деструктивными операциями (такими как fsck -y) необходимо зафиксировать текущее состояние тома. Идеальный вариант - создать снапшот средствами Kubernetes, если ваш StorageClass и CSI-драйвер это поддерживают.

Пример манифеста для VolumeSnapshot:

apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
  name: rescue-snapshot-before-repair
spec:
  volumeSnapshotClassName: csi-aws-vsc # Укажите ваш класс снапшотов
  source:
    persistentVolumeClaimName: your-damaged-pvc-claim

Если снапшоты не поддерживаются (например, для некоторых NFS-бэкендов), создайте резервную копию данных с смонтированного в read-only режиме тома внутри диагностического пода. Используйте tar или dd для копирования на другой, заведомо исправный том или в объектное хранилище.

Пример команды внутри отладочного пода:
tar czf /backup/volume-backup-$(date +%Y%m%d-%H%M).tar.gz -C /data .

Только после создания резервной копии или снапшота можно переходить к активным действиям по восстановлению.

Практикум: команды восстановления для типовых сценариев

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

Ошибка 'Read-only file system': снятие флагов и принудительная проверка

Эта ошибка означает, что файловая система смонтирована в режиме только для чтения. Это может быть как следствие ошибок ввода-вывода на диске (тогда ядро переводит ФС в readonly для безопасности), так и проблема с монтированием в Kubernetes.

Алгоритм действий внутри диагностического пода или на ноде, где физически находится диск:

  1. Определите устройство: Найдите, какое блочное устройство соответствует вашему тому. Внутри пода выполните df -h /data. На хосте найдите устройство по точке монтирования или через lsblk.
  2. Проверьте журналы ядра: Выполните dmesg | grep -i error или dmesg | grep -i <device_name> (например, xvdf1). Ищите ошибки диска типа I/O error, buffer I/O error.
  3. Принудительно размонтируйте: Если ФС смонтирована в read-only, её нужно размонтировать для проверки. Убедитесь, что никакие процессы не используют том. lsof /data или fuser -vm /data. Затем размонтируйте: umount -f /data (флаг -f для принудительного размонтирования).
  4. Запустите проверку ФС: Определите тип файловой системы: blkid /dev/<device_name> или lsblk -f /dev/<device_name>.
    • Для ext2/ext3/ext4: fsck -y /dev/<device_name>. Ключ -y автоматически отвечает «yes» на все запросы исправления.
    • Для XFS: xfs_repair /dev/<device_name>. XFS не имеет аналога fsck -y, но для принудительного размонтирования может потребоваться ключ -L (сбрасывает журнал, используйте с крайней осторожностью).
  5. Перемонтируйте в режиме read-write: mount -o rw /dev/<device_name> /data.

Восстановление после внезапной перезагрузки ноды: проверка целостности ФС

Внезапное отключение питания ноды Kubernetes может привести к повреждению файловых систем на persistent volumes. После перезагрузки ноды и перед запуском подов рекомендуется провести проверку.

На самой ноде выполните:

  1. Определите тома, которые были примонтированы на этой ноде: cat /proc/mounts | grep /var/lib/kubelet/pods или проанализируйте вывод mount.
  2. Для каждого устройства, связанного с PV, выполните проверку в режиме «только проверка» сначала: fsck -n /dev/<device>. Это покажет ошибки без внесения изменений.
  3. Если ошибки найдены, и вы уверены, что на томах нет активных процессов, выполните полный ремонт: fsck -y /dev/<device> или xfs_repair /dev/<device>.

Особое внимание для StatefulSet с базами данных: Простая проверка fsck может привести к логической несогласованности данных СУБД. Для таких случаев предпочтительнее восстановление из снапшота тома, созданного до инцидента, или использование встроенных механизмов восстановления СУБД (например, pg_resetwal для PostgreSQL).

Повреждение метаданных (inode, superblock): продвинутое восстановление

Если стандартный fsck не может исправить ошибки или сообщает о повреждении суперблока, требуются продвинутые методы.

Для ext4:
1. Найдите резервные копии суперблока: mkfs.ext4 -n /dev/<device> (ключ -n не форматирует, а только показывает информацию). В выводе найдите строку «Backup superblocks at...». 2. Попробуйте восстановить файловую систему, используя один из backup superblock: fsck -b 32768 /dev/<device> (где 32768 - номер backup superblock).

Для XFS:
Инструмент xfs_repair обычно справляется с большинством повреждений. В крайнем случае, если он не работает, можно попробовать ключ -L для сброса журнала: xfs_repair -L /dev/<device>. Внимание: Эта операция может привести к потере последних изменений и увеличивает риск потери данных. Всегда предварительно создавайте полную побитовую копию диска с помощью dd if=/dev/<device> of=/backup/disk.img bs=1M status=progress.

Для комплексного управления томами Docker, включая их визуальный осмотр и мониторинг, может быть полезен графический интерфейс. В статье «Управление томами Docker в Portainer: полный визуальный гайд для DevOps и сисадминов» подробно разбираются практические сценарии работы с хранилищем через Portainer.

Восстановление работы с разными бэкендами: NFS, iSCSI, облачные диски

Процедура восстановления сильно зависит от типа используемого хранилища. Для сетевых и облачных решений фокус смещается с локальной проверки ФС на диагностику сервера или провайдера.

NFS тома: проверка сервера и обработка stale file handle

Если ваш PersistentVolume использует бэкенд NFS, ошибки чаще всего возникают на стороне сервера или сети.

Диагностика на стороне клиента (ноды Kubernetes):

  1. Проверьте доступность NFS-сервера: showmount -e <nfs_server_ip>.
  2. Убедитесь, что открыты необходимые порты (обычно 2049): nc -zv <nfs_server_ip> 2049.
  3. Проверьте текущие NFS-монтирования на ноде: mount | grep nfs.

Ошибка «Stale NFS file handle» означает, что клиент пытается получить доступ к файлу или директории, которые были удалены или изменены на сервере. Решение на клиенте:

# Принудительное ленивое размонтирование (lazy unmount)
umount -f -l /path/to/nfs/mount
# Затем повторное монтирование
mount -t nfs <nfs_server_ip>:/export/path /path/to/nfs/mount

Основные действия для устранения причины - на стороне NFS-сервера: перезапуск служб nfs-server, проверка целостности экспортируемой файловой системы, анализ логов /var/log/messages или journalctl.

Облачные диски (AWS EBS, GCP PD, Azure Disk): снапшоты и переподключение

Прямой запуск fsck на облачном диске, подключенном к виртуальной машине, возможен, но стандартный flow восстановления в облаке завязан на снапшоты.

Алгоритм для AWS EBS (аналогичен для GCP Persistent Disk и Azure Disk):

  1. Создайте снапшот поврежденного тома. Сделайте это через AWS Console, CLI (aws ec2 create-snapshot --volume-id vol-12345) или, если настроено, через Kubernetes VolumeSnapshot.
  2. Создайте новый том из этого снапшота. В консоли AWS это действие «Create Volume from Snapshot». Задайте тот же тип и размер (или больше).
  3. Обновите PersistentVolume в Kubernetes. Нужно изменить PV так, чтобы он ссылался на новый volumeID. Если PV создавался динамически через StorageClass, проще удалить старый PVC/PV и создать новые, указав в PVC volumeName нового PV. Для StatefulSet с автоматическим созданием томов это может быть сложнее - может потребоваться ручное редактирование PV или использование операторов, таких как специализированных для резервного копирования.

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

Плановые операции: миграция и вывод нод из эксплуатации без потерь

Многие аварийные ситуации можно предотвратить, правильно выполняя плановые работы, такие как обновление кластера или замена оборудования.

Drain ноды Kubernetes с PersistentVolumes: пошаговый алгоритм

Безопасный вывод ноды из эксплуатации при наличии stateful-подов с локальными томами (с volumeMode: Filesystem и привязкой к ноде через nodeAffinity) требует осторожности.

  1. Установите кордон (cordon) на ноду: Это предотвратит планирование новых подов на эту ноду.
    kubectl cordon <node_name>
  2. Используйте drain с учетом DaemonSet и локальных данных:
    kubectl drain <node_name> --ignore-daemonsets --delete-emptydir-data
    Флаг --delete-emptydir-data удалит данные из временных томов EmptyDir. Для persistent volumes он безопасен - данные останутся на диске.
  3. Если под с PVC завис в статусе Terminating, это часто связано с проблемой окончательного отсоединения тома (finalizer). Можно попробовать принудительно удалить под:
    kubectl delete pod <pod_name> --grace-period=0 --force --namespace <namespace>
    После этого проверьте, что том освободился: kubectl describe pv <pv_name>. Статус должен смениться с Released на Available.
  4. Для переноса тома на другую ноду (если используется локальное хранилище и это допустимо) необходимо вручную обновить nodeAffinity в спецификации PV, указав новую целевую ноду, а затем пересоздать Pod (или StatefulSet), который будет использовать этот PVC.

Для глубокого понимания различий в управлении данными между оркестраторами изучите сравнительное руководство по persistent данным в Docker Swarm и Kubernetes.

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

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

Ключевые метрики Prometheus для мониторинга хранилища на нодах:

  • node_filesystem_avail_bytes / node_filesystem_size_bytes - процент свободного места на файловой системе. Настройте алерт при заполнении более чем на 85%.
  • node_filesystem_readonly - метрика, принимающая значение 1, если ФС смонтирована в режиме только для чтения. Это прямой предвестник серьезных проблем с диском.
  • node_disk_io_time_seconds_total - время, затраченное на ввод/вывод. Резкий рост может указывать на проблемы с диском.
  • node_disk_io_error_total - счетчик ошибок ввода-вывода.

Пример правила Alertmanager для алерта на read-only ФС:

- alert: FilesystemReadOnly
  expr: node_filesystem_readonly{mountpoint!~"^/(sys|proc|run|dev).*"} == 1
  for: 2m
  labels:
    severity: critical
  annotations:
    summary: "Файловая система в read-only режиме на {{ $labels.instance }}"
    description: "Монтирование {{ $labels.mountpoint }} переведено в режим только для чтения. Требуется немедленная проверка диска."

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

Чек-лист и готовые решения для production

Чек-лист действий при обнаружении повреждения данных в томе:

  1. Изолировать. Остановить Pod (StatefulSet) или выставить replicas=0. Не пытаться рестартовать приложение.
  2. Зафиксировать. Создать снапшот тома (VolumeSnapshot) или полную файловую копию (tar/dd) в режиме read-only.
  3. Диагностировать. Подключить том в режиме read-only к диагностическому поду. Определить тип сбоя (ошибка ФС, сеть, бэкенд) с помощью dmesg, kubectl describe pv/pvc, проверки доступности бэкенда.
  4. Восстановить. В зависимости от диагноза: запустить fsck/xfs_repair, переподключить сетевой ресурс, восстановить из снапшота или резервной копии.
  5. Протестировать. Развернуть тестовый под с восстановленным томом, проверить целостность данных и работу приложения.
  6. Вернуть в работу. Запустить production-под.

Рекомендации по архитектуре для минимизации рисков:

  • Выбор StorageClass: Для production-нагрузок избегайте тома hostPath. Используйте реплицируемые решения (Ceph Rook, Longhorn, облачные managed-диски с автоматическими снапшотами) или, как минимум, Network-Attached Storage (NFS от надежного сервера).
  • Резервное копирование: Настройте регулярное создание снапшотов томов через Velero в сочетании с снапшотами хранилища. Имейте оттестированный план восстановления.
  • Отказоустойчивые файловые системы: Рассмотрите использование томов с ФС, поддерживающими снапшоты и самовосстановление, таких как ZFS или btrfs, поверх базовых блочных устройств.

Восстановление поврежденного persistent storage - сложная, но решаемая задача. Ключ к успеху - методичный подход: изоляция, резервирование, точная диагностика и применение правильного инструмента для конкретного бэкенда. Интеграция процедур мониторинга и создания снапшотов в ваши runbooks превратит экстренный ремонт в управляемый операционный процесс.

Для автоматизации рутинных задач обслуживания Docker, включая освобождение места, которое может косвенно влиять на работу storage, используйте готовые скрипты для безопасной очистки. А для построения отказоустойчивой production-среды ознакомьтесь с полным руководством по Docker в production.

Поделиться:
Сохранить гайд? В закладки браузера