Learning Platform
Глоссарий Troubleshooting
Урок 15.04 · 22 мин
Начальный
emergencydisk fullcleanupjournalctldocker pruneaptproduction

Сценарий: 3 часа ночи, телефон звонит

PagerDuty присылает: «Airflow scheduler down». Заходишь по SSH:

$ ssh airflow-prod
$ touch /tmp/test
touch: cannot touch '/tmp/test': No space left on device

Диск 100%. Половина сервисов уже легла, потому что не могут писать логи. У тебя есть 15 минут до того, как менеджер начнёт писать в чат «Что происходит?». Этот урок — playbook для такой ситуации.

Главный принцип: диагностируй до того, как что-то удалять. Импульсивное rm -rf /var/log/* может всё сломать ещё больше — например, оставить systemd без места под socket-файлы или сломать privacy logs, которые нужны для audit.

Step 1: подтвердить, что диск действительно полный

$ df -h
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p3  466G  466G   30M 100% /
tmpfs           7.8G  4.0K  7.8G   1% /dev/shm
/dev/sdb1       1.8T  240G  1.6T  14% /data

Корневой раздел / забит. /data (где DE-данные) — в порядке.

Внимание: проверь inodes тоже. Возможно, место есть, но кончились inodes:

$ df -i
Filesystem        Inodes    IUsed     IFree IUse% Mounted on
/dev/nvme0n1p3  30924800 30924800         0  100% /
/dev/sdb1      121634816  4892341 116742475    5% /data

Если inodes 100% — стратегия другая: искать миллионы мелких файлов, не гигабайты больших. Подробнее в уроке 01-df-du.

Step 2: найти, какой mountpoint виноват

В нашем случае / забит. Дальше — раскладка по каталогам верхнего уровня:

$ sudo du -hd 1 / 2>/dev/null | sort -hr | head -10
466G    /
245G    /var
120G    /home
45G     /usr
12G     /opt
8.4G    /tmp
1.2G    /boot
512M    /etc
240M    /root

/var лидирует с большим отрывом — типичный паттерн. Идём глубже:

$ sudo du -hd 1 /var 2>/dev/null | sort -hr | head -10
245G    /var
198G    /var/lib/docker
24G     /var/log
8.4G    /var/cache
6.1G    /var/lib/postgresql
4.2G    /var/lib/apt

/var/lib/docker — 198 ГБ. Это классика: Docker image cache + container logs. Обычно его и можно безопасно чистить (см. Step 5).

/var/log — 24 ГБ. Тоже подозрительно много. Идём в обе папки параллельно.

DE-playbook: диагностика забитого диска

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

1. df -h && df -iбьём диагноз
2. du -hd 1 / | sort -hrгде живёт проблема
3. du -hd 1 /var | sort -hrуточняем подкаталог
4. lsof | grep deletedghost-файлы держат место
5. cleanup конкретного виновникаjournal/docker/apt
6. df -h — verifyместо свободно?

Step 3: ghost-файлы (deleted-but-open)

До того как удалять что-то, проверь, не держит ли кто-то «удалённый» файл открытым. Это типичный сценарий: logrotate переименовал файл и сделал rm, но Java/Python пишет в старый дескриптор.

$ sudo lsof 2>/dev/null | grep '(deleted)' | awk '{print $1, $7, $9, $10}'
java       4.5G /var/log/tomcat/catalina.out (deleted)
python     892M /var/log/airflow/scheduler.log.1 (deleted)

Это значит: 4.5 ГБ + 892 МБ = ~5.4 ГБ занято призраками. Никакой find -delete это не уберёт — нужно либо рестартнуть процесс, либо попросить его reopen логи.

Для большинства сервисов работает:

$ sudo systemctl restart tomcat
$ sudo systemctl restart airflow-scheduler

Или (если рестарт нельзя):

# Послать SIGHUP — большинство демонов на него закрывают и открывают логи заново:
$ sudo kill -HUP $(pgrep tomcat)

После рестарта df -h должна показать освобождённое место.

Step 4: цели чистки — типичные виновники

Перечисление по убыванию частоты в production:

Топ виновников 'диск 100%' на production VM

Эти пять директорий покрывают 95% случаев. Знаешь их — знаешь disk emergency.

/var/lib/dockerimages, containers, volumes, cache
/var/log/journalsystemd journal без retention
/var/log/{airflow,postgres,...}приложения без ротации
/var/cache/apt/archivesapt download cache
/tmptmp-файлы (если не tmpfs)
/var/lib/systemd/coredumpcore dumps
/var/lib/{apt,dpkg}package metadata

Step 5: cleanup-команды по виновникам

5.1 systemd journal

# Сколько занимает journal:
$ journalctl --disk-usage
Archived and active journals take up 14.3G in the file system.

# Удалить логи старше 7 дней:
$ sudo journalctl --vacuum-time=7d
Deleted archived journal /var/log/journal/.../[email protected] (1.2G).
...
Vacuuming done, freed 11.4G of archived journals from /var/log/journal/.

# Или ограничить размер до 2 ГБ:
$ sudo journalctl --vacuum-size=2G

# Или оставить только последние 50 файлов:
$ sudo journalctl --vacuum-files=50

Чтобы это не повторилось — настроить retention в /etc/systemd/journald.conf:

[Journal]
SystemMaxUse=2G
SystemMaxFileSize=128M
MaxRetentionSec=2week

После правки: sudo systemctl restart systemd-journald. Подробнее про journald — модуль 14-systemd-services.

5.2 Docker

Docker volumes и управление жизненным циклом данных
# Сколько занимает Docker:
$ docker system df
TYPE            TOTAL     ACTIVE    SIZE      RECLAIMABLE
Images          84        12        145.2GB   124.8GB (85%)
Containers      45        3         8.4GB     8.1GB (96%)
Local Volumes   23        8         32.4GB    22.1GB (68%)
Build Cache     0         0         12.1GB    12.1GB

# Безопасная чистка: остановленные containers + dangling images + unused networks + build cache:
$ docker system prune
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all dangling images
  - all dangling build cache
Are you sure you want to continue? [y/N] y

# Агрессивная чистка: ВСЁ неиспользуемое + неиспользуемые images (не только dangling):
$ docker system prune -a
WARNING! This will remove:
  - all stopped containers
  - all networks not used by at least one container
  - all images without at least one container associated to them
  - all dangling build cache
Are you sure you want to continue? [y/N] y

# С volumes (вне docker system prune по умолчанию):
$ docker system prune -a --volumes
WARNING

docker system prune -a --volumes удалит все volumes, не используемые в данный момент контейнером. Если у тебя есть persistent data в volume (например, Postgres-данные), но контейнер сейчас остановлен — данные исчезнут. Прежде чем --volumes, проверь docker volume ls и убедись, что важных volumes нет.

5.3 apt cache (Debian/Ubuntu)

# Сколько занимает apt cache:
$ du -sh /var/cache/apt
4.2G    /var/cache/apt

# Удалить кэш скачанных .deb:
$ sudo apt clean

# Удалить только .deb, которых уже нет в репозиториях:
$ sudo apt autoclean

# Удалить пакеты, установленные как deps и больше не нужные:
$ sudo apt autoremove

apt clean обычно высвобождает 1-10 ГБ на активной системе.

5.4 Логи приложений (Airflow, Postgres, кастомные)

Если у Airflow логи в /var/log/airflow:

# Проверить, что найдём:
$ sudo find /var/log/airflow -type f -name '*.log' -mtime +7

# Сжать старые:
$ sudo find /var/log/airflow -type f -name '*.log' -mtime +7 -exec gzip {} +

# Удалить совсем старые архивы:
$ sudo find /var/log/airflow -type f -name '*.log.gz' -mtime +90 -delete

См. урок 03-find-by-size-and-cleanup для полного паттерна.

5.5 Core dumps

$ du -sh /var/lib/systemd/coredump
8.4G    /var/lib/systemd/coredump

# Удалить старые:
$ sudo journalctl --vacuum-time=1d  # это и coredumps зацепит, если systemd-coredump
$ sudo rm /var/lib/systemd/coredump/*.zst   # явно

5.6 Старые kernels (Ubuntu/Debian)

# Сколько kernels установлено:
$ dpkg -l linux-image-* | grep '^ii'

# Удалить все, кроме текущего и одного запасного:
$ sudo apt autoremove --purge

Каждый kernel занимает 100-300 МБ в /boot + initramfs. На VM с 500 МБ /boot третий kernel = «No space left on /boot».

Чего НИКОГДА не делать

Опасные команды при disk emergency

Эти действия могут сломать систему гораздо сильнее, чем 100% disk.

rm -rf /var/log/*break logging, ghost-files грow
rm -rf /tmp/*break running sessions
rm -rf /boot/*система не загрузится
rm -rf /var/lib/dockerзависит docker daemon
rm -rf /var/lib/dpkgломает package manager
dd if=/dev/zero of=ANYdata corruption

Резерв: 5% root reserve в ext4

По умолчанию ext4 резервирует 5% места под пользователя root. Это означает: когда обычный юзер видит 100% — у root всё ещё есть запас, чтобы сделать sudo операции (без этого admin не смог бы залогиниться и почистить диск).

Это можно проверить:

$ sudo tune2fs -l /dev/nvme0n1p3 | grep -i reserved
Reserved block count:     5817958
Reserved GID:             0
Reserved UID:             0

5817958 блоков по 4 KB = ~23 ГБ зарезервировано для root.

В extreme cases можно временно уменьшить резерв, чтобы выиграть пространство:

# Установить резерв в 1%:
$ sudo tune2fs -m 1 /dev/nvme0n1p3

5% -> 1% освободит около 4% от размера ФС. На 466 ГБ — это ~18 ГБ. Это «emergency lever»: после чистки верни обратно (tune2fs -m 5).

Real-world recovery: пошаговый сценарий

Реальный кейс из production: VM с Airflow, 100% диска, нужно поднять.

# 1) Проверка
$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p3  100G  100G    0  100% /

# 2) Раскладка
$ sudo du -hd 1 / 2>/dev/null | sort -hr | head -5
100G    /
56G     /var
30G     /home
8G      /usr
4G      /opt

# 3) /var дальше
$ sudo du -hd 1 /var 2>/dev/null | sort -hr | head -5
56G     /var
34G     /var/lib/docker
18G     /var/log
2G      /var/cache
1.5G    /var/lib/postgresql

# 4) Чистим docker (часто самый большой выигрыш)
$ docker system prune -a -f
Total reclaimed space: 28.4GB

# 5) Чистим journal
$ sudo journalctl --vacuum-time=2d
Vacuuming done, freed 12.1G of archived journals.

# 6) Проверка
$ df -h /
Filesystem      Size  Used Avail Use% Mounted on
/dev/nvme0n1p3  100G   59G   41G  60% /

# 7) Поднимаем сервисы
$ sudo systemctl start airflow-scheduler airflow-webserver
$ systemctl is-active airflow-scheduler
active

41 ГБ выиграли за 5 минут. Сервисы поднялись.

Prevention: чтобы не повторилось

После recovery — настроить, чтобы такое не происходило снова:

  1. Monitoring и alerts: Prometheus node-exporter + alert на disk usage > 80%. Узнаёшь за неделю до problem, не за 15 минут.
  2. Log rotation: настроить logrotate или скрипт find -delete в cron (модуль 15-cron-scheduling).
  3. systemd journal retention: SystemMaxUse=2G в /etc/systemd/journald.conf.
  4. Docker pruning по расписанию: docker system prune -af --volumes=false раз в неделю в cron.
  5. Apt cleanup: apt-get autoclean в /etc/apt/apt.conf.d/20auto-upgrades (на Ubuntu обычно уже настроено).
  6. /var/log на отдельном разделе: если приложение бесконтрольно пишет логи, оно сожрёт /var/log, но не корневую /. Корень останется работоспособным.

Попробуй сам

  1. Сколько занимает journal на твоей системе:
    journalctl --disk-usage
  2. Сколько занимает Docker (если он у тебя установлен):
    docker system df 2>/dev/null
  3. Сколько занимает apt cache:
    du -sh /var/cache/apt
  4. Топ-5 жирных подкаталогов в /:
    sudo du -hd 1 / 2>/dev/null | sort -hr | head -5
  5. Ghost-файлы (deleted-but-open):
    sudo lsof 2>/dev/null | grep '(deleted)' | head

macOS-различия

  • macOS не использует systemd -> нет journalctl. Логи через log show, log stream (Apple Unified Logging).
  • Docker Desktop на macOS использует виртуальную машину (Linux под HyperKit/Virtualization.framework). /var/lib/docker находится внутри VM, не на host. docker system prune работает так же.
  • apt clean -> на macOS используется brew cleanup.
  • /var/log на macOS заметно меньше, чем на Linux production servers, потому что многие сервисы пишут в Apple Unified Log, не в файлы.

Главное

  • Playbook при «диск 100%»: df -h -> df -i -> du -hd 1 / | sort -hr -> идти вглубь -> cleanup.
  • Проверь ghost-файлы: lsof | grep deleteddu их не видит, df считает.
  • Топ виновников: Docker (/var/lib/docker), systemd journal (/var/log/journal), app logs (/var/log/*), apt cache (/var/cache/apt), core dumps.
  • Безопасные cleanup-команды:
    • journalctl --vacuum-time=7d / --vacuum-size=2G
    • docker system prune -a (--volumes — с осторожностью!)
    • apt clean && apt autoremove
    • find /var/log/APP -name '*.log' -mtime +14 -delete
  • НИКОГДА: rm -rf /var/log/*, rm -rf /tmp/*, rm -rf /var/lib/docker (без stop daemon).
  • 5% root reserve в ext4 — emergency lever: tune2fs -m 1 временно.
  • Prevention: monitoring, retention config, scheduled cleanup, отдельные разделы.

Проверьте понимание

Результат: 0 из 0
Прикладной
Вопрос 1 из 5. Production VM, /var/lib/docker занимает 198 ГБ. Какая команда — безопасная чистка?

Закончили урок?

Отметьте его как пройденный, чтобы отслеживать свой прогресс

Войдите чтобы оценить урок

Прогресс модуля
0 из 4