Все уроки
Linux и серверыСредний12 мин чтенияВ моём стеке

Пакеты, логи, cron и диски

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

  • apt
  • Logs
  • cron
  • Disks & df / du
  • logrotate
Шаг 1/5
Приложение пишет логи. И пишет. И пишет. Никто их не ротирует, и диск тихо ползёт от 60% к 100%.

За 30 секунд

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

Почему я это использую

  • unattended-upgrades входит в мой базовый набор для каждого сервера, потому что непропатченные пакеты — один из самых простых способов проникнуть внутрь.
  • Я очистил один продакшен-сервер с 91% до 66% заполненности диска, отыскав старые логи, старые сборки и раздутые node_modules.
  • Мониторинг диска, нагрузки и аптайма — в моём стандартном списке, потому что заполненный диск — тихий сбой, пока в один момент не ломается всё сразу.

Как это работает

01apt: установка и обновление ПО

В Debian и Ubuntu apt устанавливает ПО из доверенных репозиториев, разрешает зависимости и проверяет подписи пакетов. apt update обновляет список доступных версий, но ничего не устанавливает. apt upgrade ставит новые версии того, что у вас уже есть, а apt full-upgrade может также добавлять или удалять пакеты при изменении зависимостей, что нужно для обновлений ядра. В системах семейства RHEL то же самое делает dnf (dnf check-update, dnf upgrade). Предпочитайте пакеты из репозиториев дистрибутива; сторонние репозитории добавляйте только от вендоров, которым доверяете, с их ключами signed-by. После обновления ядра или базовых библиотек проверьте, не требуется ли перезагрузка.

bash
sudo apt update                    # refresh package lists
apt list --upgradable              # what would change
sudo apt upgrade                   # install updates
sudo apt full-upgrade              # also handle changed dependencies
sudo apt install nginx htop        # install packages
sudo apt remove --purge apache2    # remove, including config
sudo apt autoremove                # remove unused dependencies
apt show nginx; apt policy nginx   # details and versions
[ -f /var/run/reboot-required ] && cat /var/run/reboot-required

02Автоматические обновления безопасности

unattended-upgrades автоматически ставит обновления безопасности каждый день, так что известные дыры закрываются, даже если никто не заходит на сервер. В Ubuntu Server он установлен по умолчанию; проверить и включить его можно через dpkg-reconfigure. По умолчанию он применяет только обновления из security-репозитория, что является разумным балансом между безопасностью и стабильностью. Можно настроить автоматическую перезагрузку в тихий час, когда её требует обновление ядра, и очистку старых ядер. В RHEL аналог — dnf-automatic. Его лог в /var/log/unattended-upgrades/ показывает, что и когда было установлено. Автоматические обновления не заменяют плановые апгрейды между мажорными версиями, которые стоит сначала протестировать.

bash
sudo apt install unattended-upgrades
sudo dpkg-reconfigure -plow unattended-upgrades   # enable
cat /etc/apt/apt.conf.d/20auto-upgrades
# In /etc/apt/apt.conf.d/50unattended-upgrades you can set:
#   Unattended-Upgrade::Automatic-Reboot "true";
#   Unattended-Upgrade::Automatic-Reboot-Time "04:00";
#   Unattended-Upgrade::Remove-Unused-Kernel-Packages "true";
sudo unattended-upgrade --dry-run --debug         # test it

03Логи: /var/log, journald и logrotate

На современном сервере две системы логов. Журнал systemd собирает вывод сервисов и ядра; читается он через journalctl. Классические текстовые файлы в /var/log пишут rsyslog и приложения вроде nginx. Полезные файлы в Ubuntu: /var/log/syslog для общих сообщений, /var/log/auth.log для входов и sudo и /var/log/nginx/ для веб-трафика и ошибок (в RHEL — /var/log/messages и /var/log/secure). Логи растут бесконечно, если их ничто не обрезает. Для текстовых файлов этим занимается logrotate: он переименовывает текущий файл, сжимает старые и хранит только заданное количество. Для журнала задайте ограничение размера в конфиге journald или чистите его через vacuum.

bash
# /etc/logrotate.d/myapp
/var/log/myapp/*.log {
    daily
    rotate 14
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
}
# Test without changing anything:  sudo logrotate -d /etc/logrotate.d/myapp
# Journal size:  journalctl --disk-usage
#                sudo journalctl --vacuum-size=500M
# Permanent cap: SystemMaxUse=500M in /etc/systemd/journald.conf

04Планирование через cron

cron запускает команды по расписанию. У каждого пользователя есть crontab (редактируется через crontab -e), а системные задачи лежат в /etc/crontab и /etc/cron.d. Строка состоит из пяти полей времени — минута, час, день месяца, месяц и день недели, — за которыми следует команда. Звёздочка означает «каждый», */5 — «каждые пять», а диапазоны вроде 1-5 — с понедельника по пятницу. cron работает с минимальным окружением: PATH короткий, профиль shell не загружается, поэтому используйте абсолютные пути и перенаправляйте вывод в лог, иначе ошибки просто исчезнут. cron использует часовой пояс сервера, а на облачных серверах это часто UTC. Проверить выражение помогает сайт вроде crontab.guru.

bash
# m  h  dom mon dow  command
*/5  *  *   *   *    /usr/local/bin/healthcheck.sh >> /var/log/healthcheck.log 2>&1
0    3  *   *   *    /usr/local/bin/backup.sh >> /var/log/backup.log 2>&1
30   2  *   *   1    /usr/local/bin/weekly-report.sh
# Laravel scheduler: run every minute as the app user
*    *  *   *   *    cd /var/www/app && php artisan schedule:run >> /dev/null 2>&1
# Prevent overlapping runs with flock
0    *  *   *   *    flock -n /tmp/sync.lock /usr/local/bin/sync.sh

05Диски: df, du, lsblk и mount

df показывает, насколько заполнена каждая смонтированная файловая система; du — сколько места занимают файлы и каталоги. lsblk выводит блочные устройства, так что видно диски и разделы, включая только что подключённый новый том. Чтобы использовать новый том, один раз создайте на нём файловую систему (ext4 — безопасный выбор по умолчанию), смонтируйте её и добавьте в /etc/fstab по UUID, чтобы она подключалась после перезагрузки. Проверьте fstab через mount -a до перезагрузки, потому что сломанная запись может не дать серверу загрузиться. Следите и за inode через df -i: диск может оказаться «заполненным» при наличии свободного места, если миллионы мелких файлов (сессии, кэш) исчерпали все inode.

bash
df -h                        # space per filesystem
df -i                        # inodes per filesystem
lsblk -f                     # disks, partitions, filesystems, UUIDs
sudo mkfs.ext4 /dev/sdb      # format a NEW empty volume (destroys data!)
sudo mkdir -p /mnt/data
sudo mount /dev/sdb /mnt/data
# /etc/fstab line (use the UUID from lsblk -f):
# UUID=your-uuid  /mnt/data  ext4  defaults,nofail  0  2
sudo mount -a                # test fstab before rebooting

06Ищем, что забивает диск

Когда df показывает диск заполненным на 90% и больше, двигайтесь сверху вниз. du с ограничением глубины показывает самые большие каталоги; повторяйте внутри самого крупного. ncdu — интерактивная версия, которая делает это быстро. Обычные подозреваемые — старые логи и архивы после ротации, журнал systemd, образы Docker и кэш сборки, старые папки релизов от деплоев, каталоги node_modules и vendor, забытые в домашних каталогах дампы БД и кэш пакетов apt. Одна ловушка: если удалить лог-файл, который процесс всё ещё держит открытым, место не освободится, пока процесс не перезапустится или не откроет файл заново. lsof +L1 показывает такие удалённые, но открытые файлы. Обнулить живой лог безопаснее, чем удалить его.

bash
sudo du -xh --max-depth=1 / | sort -h | tail
sudo du -xh --max-depth=1 /var | sort -h | tail
sudo ncdu -x /                         # interactive (apt install ncdu)
sudo find / -xdev -type f -size +500M -exec ls -lh {} + 2>/dev/null
journalctl --disk-usage
docker system df                       # images, containers, cache
sudo apt clean                         # apt package cache
sudo lsof +L1                          # deleted files still held open
sudo truncate -s 0 /var/log/myapp/huge.log   # empty a live log safely

07Память и swap

free -h показывает память. Не паникуйте из-за маленького значения «free»: Linux использует свободную память как дисковый кэш и отдаёт её, когда она нужна приложениям. Смотреть нужно на колонку available. Когда доступная память заканчивается, OOM killer ядра (out of memory) завершает процесс, часто самый крупный, и нередко это ваша база данных. Swap — это место на диске, используемое как переполнение памяти. Он гораздо медленнее RAM, но на небольшом VPS скромный swap-файл (от 1 до 2 GB) превращает внезапное падение в замедление, которое можно заметить и исправить. Если сервер постоянно свапится, нужно больше RAM или менее прожорливое приложение, а не больше swap.

bash
free -h                          # read the "available" column
sudo journalctl -k | grep -i "out of memory"   # OOM kills
# Create a 2 GB swap file
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile && sudo swapon /swapfile
echo "/swapfile none swap sw 0 0" | sudo tee -a /etc/fstab
swapon --show

Когда применять

  • Любой сервер, который вы ведёте: обновления, ротация логов и мониторинг диска — базовая гигиена.
  • Инциденты с заполненным диском, падающие деплои или базы данных, отказывающиеся записывать.
  • Регулярные задачи: бэкапы, отчёты, очистка и планировщики фреймворков.
  • Небольшие VPS, где swap-файл и лимиты журнала предотвращают падения, которых можно избежать.

Когда не стоит

  • Не запускайте apt full-upgrade или обновление до нового мажорного релиза на продакшене без снапшота и окна обслуживания.
  • Не используйте swap как замену достаточному объёму RAM на нагруженном сервере базы данных.
  • Не удаляйте непонятные файлы только ради освобождения места; сначала выясните, что их пишет.

Альтернативы

  • dnf / dnf-automatic

    Аналоги apt и unattended-upgrades в RHEL, Rocky и Alma.

  • Таймеры systemd

    Более наблюдаемая альтернатива cron с логами в журнале и догоняющими запусками.

  • Централизованное логирование (Loki, ELK, облачные сервисы)

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

  • Объектное хранилище

    Перенесите пользовательские загрузки и бэкапы в S3-совместимое хранилище, чтобы диск сервера оставался маленьким, а сам сервер — заменяемым.

Лучшие практики

  1. Включите unattended-upgrades для обновлений безопасности и проверяйте, не требуется ли перезагрузка.
  2. Делайте снапшот перед крупными обновлениями и сначала обновляйте staging.
  3. Задайте правило logrotate для каждого лога приложения и ограничьте размер журнала.
  4. Настройте алерт по заполненности диска задолго до того, как он заполнится, например на 80%.
  5. В cron используйте абсолютные пути, перенаправляйте вывод в лог и предотвращайте наложение запусков через flock.
  6. Монтируйте дополнительные тома по UUID с опцией nofail и проверяйте fstab через mount -a.
  7. Регулярно чистите старые релизы, образы Docker и кэши сборки как часть процесса деплоя.

Частые ошибки

  • Запуск apt upgrade без предварительного apt update, из-за чего ничего нового не ставится.
  • Удаление живого лога через rm, после которого место не освобождается, потому что процесс всё ещё держит файл открытым.
  • cron-задачи, которые работают в терминале, но молча падают из-за PATH или отсутствующего перенаправления вывода.
  • Опечатка в /etc/fstab, из-за которой сервер не загружается.
  • Смотрят на «free» вместо «available» и добавляют RAM, которая была не нужна.

Глубже

08Под капотом apt: dpkg, источники, pinning и phased updates

apt — планировщик, а устанавливает dpkg. dpkg распаковывает архивы .deb, запускает их maintainer-скрипты и записывает состояние в /var/lib/dpkg. Если обновление прервано, пакеты остаются наполовину настроенными, пока вы не выполните dpkg --configure -a. Начиная с Ubuntu 24.04 репозитории описываются в формате deb822, в файлах вроде /etc/apt/sources.list.d/ubuntu.sources, а сторонние репозитории должны указывать свой ключ через Signed-By, чтобы этот ключ не мог ручаться за другие репозитории. Pinning в /etc/apt/preferences.d задаёт приоритеты между репозиториями, а apt-mark hold замораживает версию пакета, когда с обновлением нужно подождать. Ubuntu также использует phased updates: обновления, не связанные с безопасностью, в течение нескольких дней раскатываются на растущий процент машин, поэтому apt может показывать часть обновлений как «deferred due to phasing». Это ожидаемое поведение, а не сломанное зеркало.

bash
# /etc/apt/sources.list.d/vendor.sources (deb822 format)
Types: deb
URIs: https://packages.example.com/apt
Suites: stable
Components: main
Signed-By: /etc/apt/keyrings/vendor.gpg
 
# Useful commands:
#   sudo dpkg --configure -a        # finish interrupted installs
#   sudo apt-mark hold nginx        # freeze a version (unhold to undo)
#   apt-cache policy nginx          # which repo and priority wins
#   dpkg -S /usr/sbin/nginx         # which package owns a file
#   zgrep ' install ' /var/log/dpkg.log*   # install history

09Файловые системы: зарезервированные блоки, расширение томов и LVM

ext4 по умолчанию резервирует 5% блоков для root, чтобы сервисы, работающие от root, продолжали работать, когда пользователи заполнят диск. На томе данных в 500 GB это 25 GB; tune2fs -m 1 уменьшает резерв, но на корневой файловой системе оставьте значение по умолчанию. ext4 можно расширять онлайн, а уменьшать только офлайн; XFS, файловую систему по умолчанию в RHEL, можно расширять онлайн, но никогда нельзя уменьшить. Когда вы увеличиваете диск у провайдера, файловая система сама не растёт: если на диске есть разделы, сначала расширьте раздел через growpart, затем файловую систему через resize2fs (ext4) или xfs_growfs (XFS). Многие облачные образы делают это автоматически для корневого диска при загрузке через cloud-init, но для подключённых томов обычно нужно делать это вручную. LVM добавляет слой, позволяющий объединять диски, расширять логические тома и делать снапшоты, ценой большего числа движущихся частей.

bash
lsblk                                  # disk vs partition sizes
sudo growpart /dev/vda 1               # grow partition 1 to fill the disk
sudo resize2fs /dev/vda1               # grow ext4 online
sudo xfs_growfs /                      # grow XFS (by mount point)
sudo resize2fs /dev/sdb                # unpartitioned volume: grow directly
sudo tune2fs -l /dev/sdb | grep -i 'reserved block count'
sudo tune2fs -m 1 /dev/sdb             # 1% reserved on a data volume
sudo lvextend -r -l +100%FREE /dev/vg0/data   # LVM: grow LV and filesystem

10Диагностика нагрузки на I/O и память

Когда сервер тормозит, а CPU простаивает, измерьте диск. vmstat 1 каждую секунду показывает процессы, заблокированные на I/O (b), swap-in и swap-out (si, so) и время CPU в ожидании I/O (wa). iostat -x 1 (пакет sysstat) показывает задержки по устройствам в r_await и w_await и загрузку; на SSD и сетевых томах задержка и лимит IOPS провайдера важнее, чем %util. iotop или pidstat -d 1 показывают, какой процесс выполняет I/O. Запись сначала попадает в page cache и сбрасывается позже, поэтому большая запись может выглядеть быстрой, а затем всё застопорить во время writeback. Pressure Stall Information в /proc/pressure/io и /proc/pressure/memory показывает долю времени, когда задачи простаивали, и это гораздо лучший сигнал, чем свободная память. vm.swappiness определяет, насколько охотно ядро использует swap; значение по умолчанию 60 подходит большинству серверов.

bash
vmstat 1 5                     # b, si/so, wa columns
iostat -x 1 3                  # r_await, w_await, %util per device
sudo iotop -oPa                # processes doing I/O (accumulated)
pidstat -d 1 5                 # per-process disk reads/writes
cat /proc/pressure/io          # some/full stall percentages
grep -E 'Dirty|Writeback' /proc/meminfo
sysctl vm.swappiness

11Проектирование конвейера логов

На одном сервере достаточно journald вместе с logrotate, если ограничить размеры. journald хранит логи в /var/log/journal, если этот каталог существует или задано Storage=persistent; иначе только в памяти в /run, и они исчезают при перезагрузке. Он также ограничивает частоту сообщений от шумных сервисов (RateLimitIntervalSec и RateLimitBurst), так что зациклившаяся ошибка может скрыть собственные повторы; журнал фиксирует, сколько сообщений было подавлено. Когда серверов больше одного, логи должны покидать машину: агент вроде Grafana Alloy (преемник Promtail), Vector или Fluent Bit читает журнал и файлы и отправляет их в Loki, Elasticsearch или облачный сервис. Предпочитайте структурированные JSON-логи с единообразными полями, такими как level, request ID и user ID, чтобы фильтровать, а не грепать. Срок хранения задавайте по типам: отладочные логи — дни, access-логи — недели, audit-логи — столько, сколько требует политика.

ini
# /etc/systemd/journald.conf.d/size.conf
[Journal]
Storage=persistent
SystemMaxUse=500M
SystemKeepFree=2G
MaxRetentionSec=30day
RateLimitIntervalSec=30s
RateLimitBurst=10000
 
# Apply: sudo systemctl restart systemd-journald
# Check: journalctl --disk-usage; journalctl --verify

Реальные ситуации

01

apt заблокирован или не завершил работу

Проблема

apt install падает с «Could not get lock /var/lib/dpkg/lock-frontend», а после обрыва SSH-сессии во время обновления apt жалуется, что dpkg был прерван.

Как решить

Сначала проверьте, действительно ли работает другой apt: ps aux | grep -E 'apt|dpkg|unattended' и systemctl status unattended-upgrades apt-daily-upgrade.service. На свежих серверах unattended-upgrades часто запускается сразу после загрузки, поэтому дождитесь его, а не удаляйте lock-файлы — это может повредить базу dpkg. Если ничего не запущено, а предыдущее обновление было прервано, выполните sudo dpkg --configure -a, затем sudo apt -f install, чтобы исправить сломанные зависимости, и снова apt update и upgrade. Прочитайте /var/log/apt/term.log, чтобы найти упавший maintainer-скрипт. В будущем запускайте долгие обновления внутри tmux, чтобы обрыв соединения их не убивал.

02

Диск у провайдера увеличен, а df показывает старый размер

Проблема

Вы увеличили подключённый том со 100 GB до 200 GB в панели провайдера. lsblk показывает 200 GB, но df -h всё ещё сообщает 100 GB, и диск по-прежнему почти заполнен.

Как решить

Блочное устройство выросло, а раздел и файловая система — нет. Запустите lsblk -f, чтобы увидеть разметку и тип файловой системы. Если файловая система лежит прямо на устройстве (без раздела, что типично для томов), расширьте её онлайн: sudo resize2fs /dev/sdb для ext4 или sudo xfs_growfs /mnt/data для XFS. Если есть раздел, сначала sudo growpart /dev/sdb 1, затем расширьте файловую систему раздела. С LVM используйте pvresize, а затем lvextend -r. Перед началом сделайте снапшот. Затем устраните и первопричину роста, потому что больший диск лишь выигрывает время, если логи или загрузки растут без ограничений.

03

«No space left on device» при гигабайтах свободного места

Проблема

Загрузки и PHP-сессии падают с «No space left on device», хотя df -h показывает, что диск заполнен на 60%. Перезапуск сервисов не помогает.

Как решить

Проверьте inode через df -i: если IUse% равен 100%, в файловой системе закончились записи для файлов — обычно из-за миллионов крошечных файлов. Найдите каталог с наибольшим числом файлов: sudo find / -xdev -type f | cut -d/ -f2-4 | sort | uniq -c | sort -rn | head. Типичные виновники — файлы PHP-сессий без сборки мусора, каталоги кэша или почтовые очереди. Удалите старые через find -mtime +2 -delete в нужном каталоге. Затем устраните причину: включите сборку мусора для сессий или перенесите сессии в Redis, добавьте таймер очистки и настройте алерты на использование inode наряду с местом. Для новых файловых систем, которые будут хранить огромное число мелких файлов, выбирайте соотношение inode при mkfs.

Шпаргалка

Завершить прерванную установку пакетов
sudo dpkg --configure -a && sudo apt -f install
Какому пакету принадлежит файл
dpkg -S /usr/bin/curl
Заморозить / разморозить версию пакета
sudo apt-mark hold nginx / sudo apt-mark unhold nginx
Расширить раздел и файловую систему ext4
sudo growpart /dev/vda 1 && sudo resize2fs /dev/vda1
Каталоги с наибольшим числом файлов (inode)
sudo du --inodes -x -d 2 / | sort -n | tail
Задержка диска по устройствам
iostat -x 1 3
Процессы, выполняющие I/O
sudo iotop -oPa
Логи предыдущей загрузки
journalctl -b -1 -p warning
Сжать журнал прямо сейчас
sudo journalctl --vacuum-time=14d
Принудительно запустить logrotate для проверки правила
sudo logrotate -vf /etc/logrotate.d/myapp

В моих реальных проектах

  • На одном сервере я снизил заполненность диска с 91% до 66%, очистив старые логи, старые сборки и раздутые node_modules, а затем проверил его бэкапы.
  • unattended-upgrades и мониторинг диска, нагрузки и аптайма входят в базовый набор, который я применяю к каждому серверу.
  • На своих серверах я использую cron для запуска планировщика Laravel.
  • На сервере POS SaaS логи централизованно собираются в Loki и визуализируются в Grafana рядом с метриками Prometheus.

Вопросы и ответы

Q1Чем apt update отличается от apt upgrade?

apt update только скачивает свежие списки пакетов из настроенных репозиториев, чтобы apt знал, какие версии существуют. Никакое ПО он не меняет. Затем apt upgrade устанавливает новые версии уже установленных пакетов, ничего не удаляя. apt full-upgrade идёт дальше и может установить новые зависимости или удалить пакеты, чтобы завершить обновление, — это нужно для ядра и некоторых библиотек. Поэтому нормальная последовательность — update, затем upgrade. На продакшене я сначала просматриваю apt list --upgradable, делаю снапшот перед крупными изменениями, а рутинные исправления безопасности ежедневно ставит unattended-upgrades. Переход между релизами Ubuntu — это отдельный запланированный do-release-upgrade.

Q2На продакшен-сервере закончился диск. Что вы делаете?

Сначала стабилизирую: df -h, чтобы увидеть, какая файловая система заполнена, и df -i, чтобы исключить исчерпание inode. Затем ищу причину через du -xh --max-depth=1 с сортировкой по размеру, углубляясь в самые большие каталоги, или через ncdu. Частые виновники — логи без ротации, журнал, образы Docker и кэш сборки, старые каталоги релизов и забытые дампы БД. Освобождаю место безопасно: обнуляю живые логи вместо удаления, чищу журнал через vacuum, делаю prune в Docker, удаляю старые релизы. Если место не возвращается, lsof +L1 покажет удалённые файлы, которые процесс всё ещё держит открытыми. После этого устраняю первопричину: правила logrotate, лимиты журнала и алерт по диску.

Q3Почему cron-задача работает в терминале, но не из cron?

cron запускает команды с минимальным окружением. В PATH всего несколько системных каталогов, ваш .bashrc или .profile не загружается, рабочий каталог — домашний каталог пользователя, и используется /bin/sh, а не bash, если не указано иное. Поэтому команды вроде node или php, установленные в другие места, не находятся, относительные пути ломаются, а переменных окружения нет. Исправляется это абсолютными путями к бинарникам и файлам, cd в нужный каталог, заданием нужных переменных в crontab или в скрипте-обёртке и обязательным перенаправлением вывода в лог через >> file 2>&1, чтобы видеть ошибки. Проверьте также часовой пояс.

Q4Как не дать логам забить диск?

Для текстовых лог-файлов я добавляю правило logrotate на каждое приложение: ротация ежедневно или еженедельно, фиксированное число хранимых файлов, сжатие старых и copytruncate или сигнал в postrotate, чтобы приложение продолжало писать в новый файл. Для журнала systemd задаю SystemMaxUse в journald.conf, чтобы он не выходил за лимит размера. Приложениям стоит избегать debug-уровня логирования в продакшене. Всё, что важно в долгосрочной перспективе, нужно отправлять в централизованную систему, например Loki или облачный сервис, чтобы на сервере хранилось только короткое локальное окно. А алерт по заполненности диска ловит всё, что пропустили правила.

Q5free показывает почти ноль свободной памяти. У сервера проблемы?

Обычно нет. Linux использует простаивающую RAM как страничный кэш для файлов, что ускоряет чтение с диска, и сразу освобождает её, когда память нужна приложениям. Этот кэш отображается как занятый, поэтому на здоровой машине колонка free выглядит маленькой. Смотреть нужно на available — оценку того, сколько памяти можно отдать новой работе без свопинга. Настоящие проблемы выглядят так: мало доступной памяти, постоянная активность swap, растущая нагрузка с высоким I/O wait или сообщения OOM killer в journalctl -k. Тогда я ищу разросшийся процесс, например утечку или ненастроенную базу данных, прежде чем просто докупать RAM.

Q6Нужен ли серверу swap?

На большинстве небольших и средних VPS — да, в скромном объёме, обычно около 1–2 GB. Он работает как страховочный буфер: кратковременный всплеск потребления памяти делает сервер медленнее вместо срабатывания OOM killer, который может убить базу данных. Он также позволяет ядру выгружать из RAM редко используемые страницы. Но swap — это не дополнительная память: диск гораздо медленнее RAM. Если сервер постоянно свапится, ему не хватает ресурсов или приложение течёт, и решение — больше RAM или тюнинг. Некоторые конфигурации, например узлы Kubernetes или критичные к задержкам базы данных, сознательно работают без swap или с очень низким swappiness.

Вопросы уровня senior

S1Как вы балансируете автоматические обновления и стабильность на продакшен-серверах?

Я разделяю уровни риска. Обновления безопасности из security-репозитория дистрибутива применяются автоматически каждый день через unattended-upgrades, потому что оставленная открытой известная уязвимость — больший риск, чем хорошо протестированный патч безопасности. Функциональные и минорные обновления, сторонние репозитории, например баз данных или рантаймов, и всё, что требует рестарта критичного сервиса, проходят через запланированное окно: сначала staging, снапшот, затем продакшен. Пакеты, которые должны обновляться синхронно с приложением, например мажорная версия базы данных, закрепляются через pin или hold. Для обновлений ядра я либо разрешаю автоматическую перезагрузку в тихий час, если приложение переносит короткий рестарт, либо отслеживаю /var/run/reboot-required и перезагружаю осознанно. В масштабе парка я разношу обновления по серверам во времени, чтобы неудачное обновление никогда не задело всё сразу.

S2Сервер базы данных тормозит, и iowait высокий. Как выяснить, является ли узким местом хранилище?

Прежде чем что-то тюнить, я подтверждаю это цифрами. vmstat показывает заблокированные процессы и wa; iostat -x — задержки чтения и записи и размер очереди по устройствам. На сетевых облачных томах сравните наблюдаемые IOPS и пропускную способность с задокументированными лимитами тарифа, потому что упор в лимит провайдера выглядит в точности как медленный диск. pidstat -d или iotop подтверждают, что I/O выполняет именно база данных, а /proc/pressure/io показывает, сколько времени задачи простаивают. Затем я ищу причину на стороне базы: отсутствующие индексы, вызывающие полные сканирования, слишком маленький buffer pool для рабочего набора, из-за чего чтения идут на диск, или задачу checkpoint либо бэкапа, насыщающую запись. Решения — от тюнинга запросов и памяти до локального NVMe или тарифа с более высоким IOPS.

S3Что бы вы хранили на диске сервера, а что вынесли бы с него?

Я считаю диск сервера заменяемым. На нём лежат операционная система, релиз приложения, короткоживущие кэши, небольшое окно локальных логов и файлы базы данных, если она self-hosted. Всё, потеря чего была бы болезненной, уходит в другое место: пользовательские загрузки — в S3-совместимое объектное хранилище, бэкапы базы данных — в объектное хранилище у другого провайдера или в другом регионе, а логи отправляются в центральную систему. Это делает диск небольшим и предсказуемым, так что он редко заполняется, а пересборка сервера превращается в провижининг плюс восстановление данных, а не в спасение «питомца». Цена — дополнительные задержки и egress для объектного хранилища, больше движущихся частей и необходимость безопасно управлять учётными данными этих сервисов.

Глоссарий

dpkg
Низкоуровневый пакетный инструмент Debian, который устанавливает файлы .deb и отслеживает их состояние. apt вызывает его.
Источники deb822
Структурированный формат «ключ-значение» для файлов репозиториев apt (.sources); по умолчанию в Ubuntu начиная с 24.04.
Pinning
Настройки apt preferences, задающие приоритеты репозиториям или версиям и определяющие, какая версия будет установлена.
Phased updates
Постепенная раскатка в Ubuntu обновлений, не связанных с безопасностью, на растущую долю машин, чтобы рано ловить регрессии.
Зарезервированные блоки
Место на ext4, по умолчанию 5%, которым может пользоваться только root; сохраняет работоспособность системы при заполнении диска.
Исчерпание inode
Ситуация, когда в файловой системе закончились записи для файлов, хотя свободное место ещё есть; обычно из-за миллионов крошечных файлов.
LVM
Logical Volume Manager: слой, объединяющий диски в тома, которые можно менять в размере, растягивать на несколько дисков и снимать снапшоты.
Page cache
RAM, которую ядро использует для кэширования данных файлов и буферизации записи; освобождается, когда памяти не хватает приложениям.
I/O wait
Время простоя CPU, пока процессы ждут диск. Высокие значения указывают на хранилище, а не на CPU как на узкое место.
Доставка логов
Отправка логов с серверов в центральное хранилище агентом, чтобы их можно было искать и они переживали потерю сервера.

Есть идея продукта?Давайте создадим его.

Расскажите о своей идее, продукте или команде. Обычно отвечаю в течение одного рабочего дня.