100% використання диска: справжні причини (та реальні виправлення)

Було корисно?

Це завжди відбувається в найгірший момент: вікно розгортання, дзвінок on-call, табло кричить, і хтось каже: «Диск заповнений на 100%». Це висловлення одночасно корисне й дуже неповне. Який диск? Яка файлова система? Справжній обсяг, зарезервований простір, іноди, тонке провізіювання (thin provisioning) чи монтування-брехун, яке навіть не там, де пише ваш додаток?

Неправильна діагностика витрачає час і створює нові інциденти: видалення не тих файлів, пошкодження баз даних або «виправлення», яке знову подзвонить через годину. Зробімо по-діловому: визначимо, що реально заповнено, чому так сталося, і як виправити без ризику для даних.

Коли «100% диска» не означає те, що ви думаєте

«Використання диска 100%» може означати принаймні вісім різних речей. Деякі з них очевидні («файлова система не має вільних блоків»). Інші підступні («вільні блоки є, але ви не можете ними користуватися»). Ще інші хитрі («простір вільний, але kernel все ще утримує його, бо процес має відкритий файл»). Якщо не розрізняти ці випадки, ви зробите класичний хід: видалите файл, не отримаєте назад місця, злякаєтеся і видалите ще. Це не інженерія. Це метушня.

Почніть з одиниці істини: файлова система vs блочний пристрій vs пул

Як мінімум, треба знати, на якому шарі відбулося заповнення:

  • Файлова система (ext4/xfs/btrfs/zfs dataset): файли й каталоги, іноди, зарезервовані блоки, снапшоти, квоти.
  • Блочний пристрій (LVM LV, NVMe, EBS volume): базова ємність; може бути нормальною, поки файлова система — ні (або навпаки).
  • Пул сховища (ZFS pool, LVM thin pool, Ceph): тонке провізіювання, метадані, снапшоти й облік «логічне vs фізичне».
  • Шар контейнера/overlay: Docker overlay2, containerd snapshotters, Kubernetes ephemeral storage; запис може відбуватися не там, де ви чекаєте.

Три найпоширеніші невірні інтерпретації

  1. Простір vs іноди: «df каже, що повно» відрізняється від «df -i каже, що повно». Виправлення різні.
  2. Видалено, але файл відкритий: ви видалили файл, але місце не повертається, поки процес його не закриє.
  3. Снапшоти й copy-on-write: ви «видалили» дані, але снапшоти все ще посилаються на блоки, тому пул залишається заповненим.

Жарт №1: Диск — як готель. «У нас є вільні номери» не допоможе, якщо всі ключі досі видають постояльці.

Швидкий план діагностики (перший/другий/третій)

Це версія для on-call. Пріоритети: зупинити витік, визначити реальне обмеження, уникнути погіршення ситуації.

Перший крок: підтвердьте, що саме заповнено і на якому шарі

  1. Перевірте використання файлової системи на підозрюваних монтах: df -hT.
  2. Перевірте використання інодів: df -i.
  3. Перевірте базовий блочний пристрій: lsblk -f і pvs/vgs/lvs, якщо використовується LVM.
  4. Якщо ZFS: перевірте dataset і пул: zfs list, zpool list.
  5. Якщо контейнери: перевірте overlay/сховище контейнерів: docker system df або crictl df.

Другий крок: швидко знайдіть споживача (що саме виросло?)

  1. Розміри верхнього рівня каталогів: du -xhd1 /mount (залишайтеся в межах однієї файлової системи).
  2. Останній приріст: сортування за часом модифікації: find ... -printf '%T@ %s %p\n'.
  3. Логи: journalctl --disk-usage, перевірте /var/log і директорії з логами додатків.
  4. Витік через видалені, але відкриті файли: lsof +L1.

Третій крок: оберіть безпечне виправлення залежно від режиму відмови

  • Файли фактично займають місце: безпечно видаляйте/архівуйте/переміщуйте дані, потім додайте ємність або зменшіть ретеншн.
  • Іноди вичерпані: видаліть мільйони дрібних файлів (кеші, тимчасові файли), переробіть архітектуру або перебудуйте файлову систему з більшим числом інодів (неприємна операція).
  • Снапшоти: обрізайте снапшоти або змініть політику зберігання. Не видаляйте «випадкові файли» в надії на диво.
  • Thin pool заповнений: розширіть пул або видаліть снапшоти; це високоризикова подія.
  • Видалено, але файл відкритий: акуратно перезапустіть/перекрутить (rotate) відповідний сервіс (або вбивайте процес, якщо готові до постмортему).

Практичні завдання: команди, виводи, рішення

Це не «спробуй це» поради. Кожне завдання включає: команду, що можна виконати, що з неї видно і яке рішення прийняти. Припускаємо Linux, якщо не вказано інакше. Виконуйте від root лише коли потрібно — не перетворюйте кожну проблему на тренування з ескалації привілеїв.

Завдання 1: Визначте заповнену файлову систему (і її тип)

cr0x@server:~$ df -hT
Filesystem                        Type   Size  Used Avail Use% Mounted on
/dev/mapper/vg0-root              ext4    80G   79G  0.6G  99% /
/dev/nvme0n1p1                    vfat   511M  7.2M  504M   2% /boot/efi
tmpfs                            tmpfs   32G   96M   32G   1% /run
/dev/mapper/vg0-var               xfs    200G  200G   20M 100% /var

Що це означає: /var заповнений, і це XFS. Тут часто живуть журнали баз даних, шари контейнерів і журнали systemd.

Рішення: Зосередьте увагу на /var. Не видаляйте з / в надії, що це допоможе. Зверніть увагу на тип файлової системи: XFS поводиться інакше за ext4 (не можна зменшити, інша поведінка з резервними блоками).

Завдання 2: Перевірка вичерпання інодів (мовчазний вбивця)

cr0x@server:~$ df -i /var
Filesystem                 Inodes   IUsed   IFree IUse% Mounted on
/dev/mapper/vg0-var       13107200 13107190      10  100% /var

Що це означає: Майже немає вільних інодів. Ви можете мати вільні байти і бути приреченими. Це спричинено великою кількістю дрібних файлів.

Рішення: Перестаньте шукати «великі файли». Знайдіть каталоги з мільйонами записів (кеші, тимчасові, поштові черги, шари контейнерів) і безпечно їх видаліть.

Завдання 3: Знайти найбільші каталоги без перетину монтувань

cr0x@server:~$ sudo du -xhd1 /var | sort -h
12M	/var/tmp
220M	/var/lib
1.6G	/var/cache
48G	/var/log
150G	/var/lib/docker

Що це означає: /var/lib/docker величезний. Це не рідкість. Часто недооцінюють його вклад.

Рішення: Дослідіть сховище контейнерів перед видаленням логів. Логи можуть бути симптомом, Docker-shари — причиною, або навпаки.

Завдання 4: Отримати версію правди від Docker

cr0x@server:~$ sudo docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          47        12        62.3GB    44.8GB (71%)
Containers      36        8         9.1GB     7.9GB (86%)
Local Volumes   18        11        81.4GB    12.6GB (15%)
Build Cache     119       0         24.7GB    24.7GB (100%)

Що це означає: Build cache повністю підлягає очищенню. Образи й зупинені контейнери теж можна звільнити. Томи — там, де ховаються «важливі дані».

Рішення: Спочатку очистіть build cache (безпечно), потім неактивні образи/контейнери, і лише торкайтеся томів якщо ви впевнені, що їх можна видалити.

Завдання 5: Безпечно звільнити кеш і артефакти Docker

cr0x@server:~$ sudo docker builder prune -af
Deleted build cache objects:
m1r4nd4d1g3st:sha256:0c5b...  215.3MB
m1r4nd4d1g3st:sha256:8e21...  112.9MB
Total reclaimed space: 24.7GB

Що це означає: Ви отримали реальний вільний простір, не торкаючись персистентних томів.

Рішення: Повторно перевірте df. Якщо тісно, продовжуйте з docker image prune та docker container prune. Заплануйте політику збереження образів, щоб не повторювати це що тиждень.

Завдання 6: Знайти видалені, але відкриті файли (місце не повертається)

cr0x@server:~$ sudo lsof +L1 | head
COMMAND   PID  USER   FD   TYPE DEVICE   SIZE/OFF NLINK  NODE NAME
java     2214  app    12w  REG  253,1  4294967296     0 90122 /var/log/app/server.log (deleted)
rsyslogd  912  syslog  7w  REG  253,1   2147483648     0 72311 /var/log/syslog (deleted)

Що це означає: Процеси утримують видалені лог-файли. Файлова система не може звільнити блоки, поки ці дескриптори не закриються.

Рішення: Перезапустіть відповідні сервіси або налаштуйте коректну ротацію логів. Вбивати процеси — грубий інструмент; використовуйте його лише якщо приречені.

Завдання 7: Оцініть використання journald і провакуумуйте

cr0x@server:~$ sudo journalctl --disk-usage
Archived and active journals take up 18.0G in the file system.
cr0x@server:~$ sudo journalctl --vacuum-size=2G
Deleted archived journal /var/log/journal/4c.../system@0005b1d2....journal (8.0G).
Deleted archived journal /var/log/journal/4c.../system@0005b1d9....journal (6.0G).
Vacuuming done, freed 16.0G of archived journals.

Що це означає: Journald накопичував історію. Це трапляється на завантажених вузлах і не є ознакою морального провалу.

Рішення: Встановіть постійну політику (SystemMaxUse= у конфігу journald) після того, як пожежу загасили. Не робіть vacuum вручну постійно як стиль життя.

Завдання 8: Знайти найбільші файли швидко (за розміром)

cr0x@server:~$ sudo find /var -xdev -type f -size +1G -printf '%s %p\n' | sort -nr | head
8589934592 /var/lib/docker/containers/1b.../1b...-json.log
4294967296 /var/log/app/server.log
2147483648 /var/lib/postgresql/15/main/pg_wal/000000010000000A000000FE

Що це означає: JSON-логи контейнерів величезні, плюс директорія WAL PostgreSQL зростає. Кілька джерел одночасно.

Рішення: Додайте обмеження на логування для драйвера Docker; для PostgreSQL перевірте реплікацію/архівацію і ретеншн. Не видаляйте файли WAL просто так, якщо не хочете відновлювати з бекапів.

Завдання 9: Перевірити тиск на PostgreSQL WAL та архівацію

cr0x@server:~$ sudo -u postgres psql -c "select now(), pg_size_pretty(pg_wal_lsn_diff(pg_current_wal_lsn(),'0/0')) as wal_since_boot;"
              now              | wal_since_boot
------------------------------+---------------
 2026-02-05 12:44:19.121+00   | 87 GB
(1 row)

Що це означає: Було згенеровано багато WAL. Це не завжди погано, але дає підказку.

Рішення: Перевірте, чи не застрягла архівація або реплікація, і чи не утримує WAL. Якщо не впевнені — зупиніться і підключіть DBA. Диск-100% плюс «експерименти з WAL» — шлях до активного інциденту.

Завдання 10: Перевірити здоров’я LVM thin pool

cr0x@server:~$ sudo lvs -a -o +devices,seg_monitor,metadata_percent,data_percent
  LV              VG   Attr       LSize   Pool  Origin Data%  Meta%  Move Log Cpy%Sync Convert Devices
  thinpool        vg0  twi-aotz--  500.00g             99.80  92.10                            /dev/sdb(0)
  vm-01           vg0  Vwi-aotz--   80.00g thinpool     74.20                                  thinpool(0)
  vm-02           vg0  Vwi-aotz--  120.00g thinpool     68.15                                  thinpool(0)

Що це означає: Thin pool практично повний. Коли thin pool досягає 100%, запис провалюється в неочікувані способи.

Рішення: Негайно розширте thin pool або звільніть місце всередині нього (видаліть зайві thin снапшоти/томи). Це термінова подія; не ставте її в чек-лист «на потім».

Завдання 11: Підтвердити обмеження ZFS pool/dataset (квоти, снапшоти, резервації)

cr0x@server:~$ sudo zpool list
NAME   SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP  HEALTH  ALTROOT
tank   3.62T  3.55T  72.0G        -         -    39%    98%  1.00x  ONLINE  -

cr0x@server:~$ sudo zfs list -o name,used,avail,refer,mountpoint
NAME              USED  AVAIL  REFER  MOUNTPOINT
tank              3.55T  72.0G   128K  /tank
tank/app          2.40T  20.0G  2.10T  /tank/app
tank/app@daily-1   300G      -  2.10T  -

Що це означає: Пул зайнято на 98%. Dataset tank/app має лише 20G вільних. Існує снапшот, який може «прикривати» блоки.

Рішення: Оцініть політику ретеншну снапшотів і безпечно видаліть ті, що утримують простір. Також: не тримайте ZFS pool на 98% якщо не любите раптове падіння продуктивності.

Завдання 12: Перевірити зарезервовані блоки ext4 (root має простір, користувачі — ні)

cr0x@server:~$ sudo tune2fs -l /dev/mapper/vg0-root | egrep 'Block count|Reserved block count|Reserved block percentage'
Block count:              20971520
Reserved block count:     1048576
Reserved block percentage: 5%

Що це означає: 5% файлової системи зарезервовано (історично, щоб захистити root і зменшити фрагментацію). На великих томах це може означати кілька ГБ.

Рішення: Якщо це не системний кореневий том, подумайте про зменшення резерву блоків, але робіть це обдумано. Не «звільняйте місце», прибираючи захисні механізми на критичних томах без плану.

Завдання 13: Виявити неконтрольовану генерацію файлів (витрата інодів) по каталогах

cr0x@server:~$ sudo find /var -xdev -type d -printf '%p\n' | while read -r d; do echo "$(find "$d" -maxdepth 1 -type f 2>/dev/null | wc -l) $d"; done | sort -nr | head
1200345 /var/cache/myapp
410221 /var/lib/docker/overlay2
99521 /var/spool/postfix/maildrop

Що це означає: Директорія кешу генерує абсурдну кількість файлів. Це ваш інодовий винуватець.

Рішення: Очистіть кеш і виправте політику кешування додатку (TTL, макс. кількість, хешування директорій). Також розгляньте перенос кешів у tmpfs (якщо безпечно) або на окрему файлову систему з плануванням інодів.

Завдання 14: Перевірити точки монтування (щоб не чистити не там)

cr0x@server:~$ mount | egrep ' /var | /var/lib/docker | / '
/dev/mapper/vg0-root on / type ext4 (rw,relatime)
/dev/mapper/vg0-var on /var type xfs (rw,relatime,attr2,inode64,logbufs=8,logbsize=32k,noquota)

Що це означає: Docker знаходиться під /var на цьому хості. Якби ви думали, що він живе на іншому LV, ви б почали чистити невірну файлову систему і нічого б не змінили.

Рішення: Підтверджуйте монтування перед діями. Це допомагає уникнути «видалив 20G і нічого не змінилося», бо ви чистили не там.

Завдання 15: Відстежувати, що росте прямо зараз (коли диск заповнюється в реальному часі)

cr0x@server:~$ sudo bash -lc 'while true; do date; df -h /var; du -xhd1 /var/log | sort -h | tail -n 5; sleep 10; done'
Thu Feb  5 12:46:00 UTC 2026
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/vg0-var       200G  199G  380M 100% /var
1.3G	/var/log/apt
4.8G	/var/log/nginx
16G	/var/log/journal
48G	/var/log
Thu Feb  5 12:46:10 UTC 2026
Filesystem                Size  Used Avail Use% Mounted on
/dev/mapper/vg0-var       200G  200G  120M 100% /var

Що це означає: Використання ще росте. Це не «почистили і все гаразд». Хтось активно пише.

Рішення: Знайдіть процес, що пише (логи, БД, завантаження). Розгляньте тимчасову зупинку сервісу або обмеження швидкості прийому. Чистка без зупинки джерела — це як мітла проти повені.

Справжні причини (з довготривалими виправленнями)

Причина 1: Логи виросли, бо система достатньо здорова, щоб працювати

Логи — класичний «пожирач» диска, бо вони проектуються так, щоб не блокувати основну роботу. Це добре… поки не стає погано. Поширені тригери:

  • Увімкнено debug-логування після інциденту та забули вимкнути.
  • Access-логи на публічному ендпоінті під час сканування/шторму.
  • Додатки логують повні тіла запитів (так, таке в реальному проді трапляється).
  • Systemd journal без обмежень на навантажених вузлах.

Реальні виправлення:

  • Налаштуйте ретеншн і обмеження розміру (logrotate, journald SystemMaxUse).
  • Відправляйте логи поза хост (ship logs), але не використовуйте це як привід тримати нескінченні локальні логи.
  • Зробіть рівні логування конфігуруваними в рантаймі й встановіть розумну вербозність за замовчуванням.

Причина 2: Видалені файли не звільнили місце (відкриті дескриптори)

Unix-семантика елегантна: видалення імені не видаляє файл, поки хтось ним користується. На завантажених хостах «ніхто» може означати довгий час.

Реальні виправлення:

  • Використовуйте lsof +L1 для виявлення видалених, але відкритих файлів.
  • Перезапустіть процес акуратно (або примусово, якщо треба).
  • Налаштуйте ротацію логів так, щоб сервіс перезапускав/перевідкривав логи (наприклад, SIGHUP).

Причина 3: Іноди вичерпано (байти є, але не можна створити файли)

Іноди — це «слоти для файлів» файлової системи. Якщо ви створюєте мільйони дрібних файлів — шардовані кеші, тимчасові артефакти, шари образів, поштові черги — ви можете вичерпати іноди, поки df -h показує нормальні байти. Симптом зазвичай: «No space left on device» при смішно низькій зайнятості байтів.

Реальні виправлення:

  • Видаліть каталоги з великою кількістю файлів (кеш, tmp) і виправте продуцента.
  • Зменшіть кількість файлів: пакуйте об’єкти, використовуйте SQLite/LMDB або переробіть структуру кешу.
  • У крайніх випадках: перебудуйте файлову систему з іншим параметром інодів (ext4 -N) або оберіть файлову систему, кращу для вашого навантаження.

Причина 4: Снапшоти прикріплюють блоки (особливо в CoW ФС)

На ZFS і btrfs снапшоти не «безкоштовні». Вони дешеві, але не безкоштовні. Видалення файлу не обов’язково звільняє блоки, якщо на них посилається снапшот. Це коректна поведінка. Але о 3 ранку це дуже заплутано.

Реальні виправлення:

  • Перегляньте політику снапшотів: частота, ретеншн і які dataset-и включені.
  • Обрізайте снапшоти, щоб звільнити місце.
  • Тримайте запас вільного місця; CoW ФС вередливі при майже повному диску (тиск метаданих, фрагментація).

Причина 5: Тонке провізіювання вичерпало реальний простір

LVM thin pools, сховища VM і багато SAN-ів дозволяють виділяти більше «віртуального» простору, ніж фізично є. Це працює — поки не перестає. Коли пул доходить до межі, записи падають у дивні способи, які додатки інтерпретують як корупцію, таймаути або «disk full» в неочікуваних місцях.

Реальні виправлення:

  • Моніторьте використання даних і метаданих thin pool і повідомляйте завчасно.
  • Розширюйте пул до того, як він досягне 100%. На 99% ви вже запізнилися.
  • Обмежуйте спалах снапшотів. Снапшоти — це борг із складними відсотками.

Причина 6: Overlay/сховище контейнерів тихо зростало

Контейнери роблять використання диска абстрактним. Образи, шари, build cache і JSON-логи накопичуються. Kubernetes ускладнює це, розподіляючи відповідальність по нодах, неймспейсах і «це не моя проблема».

Реальні виправлення:

  • Встановіть обмеження на розмір логів для драйверів логування контейнерів.
  • Регулярно збирайте сміття образів і build cache.
  • Використовуйте виділені розділи для сховища контейнерів, щоб воно не задушило ОС.
  • Встановіть запити/ліміти ephemeral storage у Kubernetes і забезпечте їх дотримання.

Причина 7: Резервований простір і квоти (для вас повно, для root — ні)

На ext4 існують зарезервовані блоки з хороших причин. У ZFS квоти й резервації можуть робити dataset повним, тоді як пул має місце, або навпаки. На XFS проєктні квоти можуть мовчки обмежувати директорії. Це не баг. Це політика.

Реальні виправлення:

  • Перевірте налаштування квот і зарезервованого простору перед тим, як щось видаляти.
  • Змінюйте політику усвідомлено: хто може заповнювати диск, а хто має бути захищеним?

Причина 8: «df каже повно», але «du не знаходить» (незбіг обліку)

Це складний випадок: df показує зайняті блоки, але du не бачить відповідних файлів. Поширені причини:

  • Знову видалені, але відкриті файли.
  • Зростання метаданих і журналу файлової системи.
  • Снапшоти (ZFS/btrfs).
  • Виділення блоків у sparse-файлах або попередньо алокованих файлах БД.

Реальне виправлення: Використовуйте правильний інструмент для правильного шару. Якщо ви трактуєте весь диск як «файли в директоріях», ви сліпі до половини системи.

Цитата, бо вона тут доречна: Усе ламається, весь час. — Werner Vogels

Три корпоративні історії з передової

Міні-історія 1: Інцидент через хибне припущення

У них була ферма аплікаційних серверів з підключеним «великим диском для даних». Всі знали правило: логи йдуть на цей великий диск. У рукбуці навіть було записано це. Команда зробила логічну річ під час інциденту: пагала логи, бачила потік помилок і повернула величезний лог. Диск залишився на 100%.

Хтось ескалував до storage. Storage подивився на df -hT і зітхнув. Великий диск був змонтований на /data, але файл-сервіс додатку місяцями тому змінився. Шлях для логів тихцем змінився на /var/log/app — на root-файловій системі. «Великий диск» був спокійний і ні в чому не винен.

Неправильне припущення було соціальним, а не технічним: «конфіг гарантує, що не буде дрейфу, бо є рукбук». Він все одно дрейфнув. Виправлення не сталося через геройський скрипт очищення. Воно полягало в: корекції конфігу сервісу, акуратному рестарті і додаванні перевірки на старті, яка відмовляє запуск якщо очікуваний монт не присутній.

Також вони змінили рукбук: першим кроком стало «перевірити монтування і шляхи», а не «робити ротацію логів». Наступного разу діагностика зайняла хвилини, а не весь день впевнених здогадок.

Міні-історія 2: Оптимізація, що відпалилася боком

Інженер, що думав про продуктивність, вирішив пришвидшити збірки, кешуючи все на CI-ранах. Docker build cache, кеші пакетів, артефакти тестів — якщо це можна кешувати, воно кешувалося. Збірки стали швидшими. Всім сподобалось. Потім ранери почали падати хвилями.

Не CPU. Не пам’ять. Диск. Але не «великі файли». Іноди. Мільйони дрібних кеш-об’єктів, розкиданих по каталогах, створених людьми, які ніколи не керували спільним раннер-фармом.

Першою реакцією було передбачувано: «Додайте більші диски». Це допомогло тиждень. Потім іноди знову вичерпалися, бо число інодів не масштабується автоматично з просто «додати більший том», як люди думають. Вони апгрейдили ємність, а слоти для файлів все одно закінчувалися.

Оптимізація дала урок: кешування потребує бюджетів. Остаточне рішення було нудним, але дієвим — обмеження розмірів кешу, періодичне очищення і зберігання деяких кешів у tar-архівах замість тисяч файлів. Збірки залишились достатньо швидкими, а ранери перестали помирати від тисяч дрібних порізів.

Міні-історія 3: Нудна, але правильна практика, що врятувала ситуацію

Інша організація керувала кластером баз даних, де диски були розмірені консервативно, а алерти встановлені на 70%, 80% і 85%. Люди скаржилися на шум алертів. Керівництво хотіло зробити їх «менш чутливими». Команда SRE не поступилась.

Однієї вихідної, downstream-клієнт сповільнився і відставання реплікації зросло. Згенерувався WAL. Оповіщення на 70% спрацювало. On-call побачив тренд і відкрив інцидент до того, як клієнти помітили щось.

У команди було достатньо часу зробити безпечні дії: з’ясувати, чому клієнт застряг, тимчасово збільшити ємність і підправити налаштування ретеншну без імпровізацій. Ніхто не видаляв випадкові файли бази даних. Ніхто не «звільняв місце», видаляючи єдину копію чогось важливого.

Коли б диск досяг 100%, система вже була стабільною. Політика алертів виглядала нудною на дашборді. На практиці вона відрізнила контрольовану відповідь від нічного семінару з відновлення даних.

Типові помилки: симптом → корінь → вирішення

1) «Я видалив 20 GB, але df не змінився»

Симптом: du показує менше, але df досі показує повно.

Корінь: Видалені, але відкриті файли (або снапшоти на CoW системах).

Вирішення: lsof +L1, перезапустіть процес, що утримує файли; для снапшотів — prune і перевірка звільнення простору на рівні пула/dataset.

2) «No space left on device», але df показує багато вільного місця

Симптом: Записи відмовляються; df -h показує вільні ГБ.

Корінь: Вичерпані іноди або перевищені квоти.

Вирішення: df -i; знайдіть каталоги з великою кількістю файлів; очистіть кеші; перевірте та відкоригуйте квоти.

3) «Тільки / заповнений, а диск для даних порожній»

Симптом: Root-файлова система досягла 100%; приєднаний зовнішній диск має місце.

Корінь: Неправильний шлях, відсутнє монтування або додаток пише в дефолтне місце після падіння монтування.

Вирішення: Перевірте монтування (mount, findmnt), вимагайте монтування перед стартом сервісу, використовуйте абсолютні шляхи і тестуйте поведінку після перезавантаження.

4) «Використання диска зростає під час бекапів/снапшотів і не повертається»

Симптом: Після снапшотних бекапів використання зростає.

Корінь: Занадто довгий ретеншн снапшотів або бекапи утримують снапшоти; CoW блочне утримання.

Вирішення: Аудит розкладу і ретеншну снапшотів, переконайтесь, що бекапи видаляють непотрібні снапшоти, тримайте запас і моніторте referenced vs used (властивості ZFS допомагають).

5) «Після увімкнення debug, диски почали заповнюватись кожен день»

Симптом: Стабільне зростання логів; сам додаток стабільний.

Корінь: Неврегульований обсяг логування; відсутня або неправильна ротація логів.

Вирішення: Обмежте логи, налаштуйте ротацію і централізоване відправлення логів з розумним локальним ретеншном.

6) «Ми розширили том, але він все ще 100%»

Симптом: В облаку збільшили обсяг; df не змінилося.

Корінь: Блочний пристрій виріс, але файлова система не була розширена, або було розширено неправильний шар (наприклад, PV, а не LV; LV, але не FS).

Вирішення: Перевірте lsblk; поширюйте PV/LV/FS відповідно (наприклад, pvresize, lvextend, xfs_growfs / resize2fs).

7) «Thin-provisioned пул досяг 100% і все стало дивно»

Симптом: Випадкові помилки запису, помилки файлової системи, паузи VM.

Корінь: Thin pool вичерпався по даним або метаданим.

Вирішення: Розширте thin pool негайно; зменшіть кількість снапшотів; запровадьте алерти значно раніше 90%.

Жарт №2: Якщо ви тримаєте файлову систему на 100% і вона «в порядку», це лише тому, що вона ще не перевірила пошту.

Чек-листи / покроковий план

Чек-лист A: Живий інцидент (диск зараз на 100%)

  1. Зупиніть витік: Якщо один сервіс неконтрольовано записує, обмежте швидкість або зупиніть його. Тримайте хост живим.
  2. Підтвердіть ціль заповнення: df -hT і df -i на відповідному монті.
  3. Визначте шар: файлова система vs thin pool vs ZFS pool vs overlay контейнерів.
  4. Знайдіть топ-споживачів: du -xhd1 і таргетовані find для великих файлів.
  5. Перевірте видалені, але відкриті: lsof +L1.
  6. Застосуйте найменш ризикове звільнення:
    • Vacuum journal-ів
    • Prune build cache
    • Ротація/стиск логів коректно
    • Видалення відомих безпечних кешів
  7. Перевірте знову: df і стан сервісів після кожної зміни.
  8. Лише потім розгляньте розширення ємності або переміщення даних.

Чек-лист B: Після інциденту (щоб не було рецидиву)

  1. Запишіть, що заповнило диск одним реченням (приклад: «Docker build cache і JSON-логи, без обмежень»).
  2. Додайте моніторинг і алерти для:
    • простору файлової системи та інодів
    • даних і метаданих thin pool
    • ємності та фрагментації ZFS pool
    • використання сховища контейнерів
  3. Встановіть бюджети ретеншну: логи, артефакти, бекапи, снапшоти, кеші.
  4. Зробіть монтування обов’язковим: сервіс відмовляє старт, якщо потрібна ФС не змонтована.
  5. Проведіть game day: симулюйте дисковий тиск і перевірте рукбук.

Чек-лист C: Архітектурні рішення для зменшення інцидентів

  • Розміщуйте /var, сховище контейнерів і бази даних на окремих файлових системах де можливо. Радіус ураження важливий.
  • Віддавайте перевагу передбачуваним шляхам зростання: планування місткості краще за екстрене прибирання.
  • Тримайте запас: ціль — 20–30% вільного на завантажених файлових системах; більше для CoW і робіт з метаданими.
  • Вважайте снапшоти виробничими даними. Ставайте до них з тією ж серйозністю, що й до бекапів.
  • Не використовуйте thin-provisioning без першокласного моніторингу і протестованих процедур розширення.

Цікаві факти та історичний контекст

  • Зарезервовані блоки на ext були введені, щоб система залишалась придатною для root і щоб зменшити фрагментацію при заповненні диска.
  • Іноди передалокуються у багатьох традиційних файлових системах (наприклад, ext4). Ви можете вичерпати записи файлів незалежно від байтів.
  • Поведение «видалено, але відкрито» — базовий дизайн Unix: імена файлів — це записи в каталогах; файл живе, доки існує останнє посилання.
  • XFS створювався для великих систем (висока пропускна здатність, великі файлові системи). Він швидкий, але зменшувати його — не те, що роблять на вівторок.
  • Copy-on-write снапшоти (ZFS/btrfs) дають легкість знімання, але ускладнюють облік простору під тиском.
  • Ротація логів існує, бо диски кінцеві, і це було істинно на 40 MB дисках так само, як і на багатотерабайтних томах.
  • Thin provisioning став масовим, бо покращив використання, але перетворив «ємність» на проблему моніторингу і керування.
  • Поведінка при заповненні файлової системи нелінійна: продуктивність і відмови різко погіршуються поблизу повного стану, особливо при фрагментації і метаданому навантаженні.

ЧаПи

Чому система сповільнюється, коли диск майже повний?

Вільний простір фрагментується, операції з метаданими ускладнюються, а CoW файлові системи можуть посилювати записи. Поблизу повного стану «середній випадок» перестає працювати.

Чому du не сходиться з тим, що показує df?

du обходить дерево каталогів і підсумовує файли, які бачить. df показує виділені блоки. Видалені, але відкриті файли, снапшоти і метадані можуть викликати розбіжності.

Чи безпечно видаляти файли в /var/log?

Іноді. Віддавайте перевагу ротації й стисканню через системні інструменти логування. Якщо видалити лог, який відкритий процесом, простір може не звільнитися до моменту, коли процес перевідкриє лог.

Чи можна просто видалити PostgreSQL WAL-файли, щоб звільнити місце?

Ні, не як нормальна оперативна тактика. WAL — частина цілісності й реплікації. Безпечний підхід — виправити архівацію/реплікацію, налаштувати ретеншн або додати ємність. Якщо ви вже в катастрофічному стані, залучіть експерта з БД.

Який найшвидший і безпечний спосіб звільнити місце на Docker-хості?

Почніть з build cache: docker builder prune -af. Потім prune непотрібні образи і зупинені контейнери. Будьте обережні з томами; вони часто містять реальні дані.

Як зрозуміти, чи проблема в інодах?

Запустіть df -i на ураженому монті. Якщо IUse% близький до 100%, вам треба видаляти багато дрібних файлів або переробити навантаження, а не шукати великі файли.

Чому ZFS показує використання навіть після видалення великих директорій?

Снапшоти можуть все ще посилатися на ці блоки, тому пул не може їх звільнити. Перевірте список снапшотів і ретеншн. Також тримайте запас; ZFS погано поводиться при дуже повному пулі.

Які пороги алертів для дискового простору варто використовувати?

Залежить від швидкості зростання і часу відновлення. Практична база: попередження при 70–80%, пейджинг при 85–90% для критичних систем. CoW і thin-provisioned пули заслуговують на більш ранні алерти.

Чи варто відокремлювати /var від /?

Так, для більшості production-хостів. /var — місце зростання (логи, кеші, дані контейнерів). Відокремлення зменшує шанс, що галасливе навантаження виведе з ладу ОС.

Яка «найбезпечніша» ціль для екстреного видалення?

Відновлювані кеші: build cache, кеші пакетів, тимчасові файли, ротаційні логи, старі journal-архіви. Уникайте торкання живих файлів баз даних або невідомих директорій під тиском.

Наступні кроки, щоб інцидент не повторився

Виправлення 100% використання диска — це не героїзм. Це визначення шару, що заповнився, використання правильних інструментів для виявлення реального споживача і застосування змін, які не повернуться бумерангом.

  1. Опануйте швидкий план діагностики і відпрацюйте його в пам’яті: df -hT, df -i, du -x, lsof +L1, потім шарово-специфічні перевірки (Docker/ZFS/LVM thin).
  2. Встановіть бюджети усюди: ретеншн логів, caps для journal, ретеншн снапшотів, розміри кешів, політики життєвого циклу образів.
  3. Дизайн з урахуванням радіусу ураження: окремі файлові системи для ОС, логів, контейнерів і баз даних; вимагайте монтування на старті сервісів.
  4. Моніторьте важливе заздалегідь: простір, іноди, дані/метадані thin pool, зростання снапшотів і топ-директорії за використанням.
  5. Тримайте запас спеціально: «Ми працюємо на 95% весь час» — це не ощадливість; це відкладена реакція на інциденти.

Інциденти з переповненням диска рідко містять таємницю. Зазвичай це невиплачений операційний борг, який прийшов з відсотками і вимагає негайного платежу.

← Попередня
OOBE-цикл / «Щось пішло не так»: швидкі виправлення для катастроф під час налаштування
Наступна →
Виправлення DNS у Windows: перестаньте використовувати «flushdns» як ритуал

Залишити коментар