«Too many open files» — одна з тих помилок, яка ображає. Linux робить саме те, що ви йому наказали: застосовує ліміти. Proxmox — це місце, де ви це помічаєте, зазвичай о 2:00 ночі, зазвичай під час якоїсь «безпечної» операції на кшталт резервного копіювання, міграції або відновлення, яке не може чекати.
Вирішення рідко виглядає як «встановити все на мільйон». Правильний підхід: знайти процес, який впирається в стелю, підвищити правильний ліміт (systemd unit, користувацький ліміт, ядровий ліміт або налаштування програми) та переконатися, що ви не приховали витік файлових дескрипторів, який повернеться з більшими проблемами наступного тижня.
Що насправді означає «too many open files» у Proxmox
У Linux «відкриті файли» насправді означають файлові дескриптори: невеликі цілі числа, які процес використовує для посилань на відкриті ресурси. Так — звичайні файли. Також сокети, пайпи, eventfd, inotify‑watch, вузли пристроїв і іноді навіть «анонімні» об’єкти ядра, які виставлені через файловий інтерфейс. Коли ви зустрічаєте:
EMFILE: процес досяг свого пер‑процесного ліміту файлових дескрипторівENFILE: система досягла глобального ліміту таблиці файлів (менш поширено на сучасних ядрах, але можливо)
У середовищах Proxmox зазвичай винен EMFILE. Це означає, що конкретний процес — демон, екземпляр QEMU, воркер бекапу, Ceph OSD — вичерпав дескриптори. Бездумне підвищення лімітів може приховати витік, але іноді це й правильний крок, якщо ваша навантаження справді потребує десятків тисяч fd (наприклад: Ceph, зайняті зворотні проксі, великі каталоги бекапів або одна VM з великою кількістю virtio‑scsi і мережевої активності).
Ліміти файлових дескрипторів існують на кількох рівнях:
- Глобальний максимум ядра (наприклад,
fs.file-max): скільки файлових дескрипторів може виділити вся система. - Рліміт процесу (ulimit /
RLIMIT_NOFILE): обмеження для конкретного процесу. - Ліміти unit у systemd (
LimitNOFILE=): що systemd встановлює для служби перед exec. - Ліміти на користувача (PAM /
/etc/security/limits.conf): впливають на сесії входу й сервіси, запущені від імені користувача, але не обов’язково на системні служби, керовані systemd, якщо PAM не задіяно. - Внутрішні ліміти додатків: іноді в самій службі є власний параметр (налаштування Ceph, PBS, тощо).
Proxmox додає особливість: багато важливих процесів керуються systemd (pvedaemon, pveproxy, pvestatd, pve-cluster), плюс екземпляри QEMU запускаються в systemd‑scopes (залежно від версії й конфігурації). Тому «правильне» виправлення часто — це systemd‑override для конкретного юніта, а не глобальна зміна ulimit, яка до служб може й не застосовуватися.
Швидкий план діагностики (перші/другі/треті перевірки)
Це частина, яку ви виконуєте, коли pager гучний, а терпіння — тихе.
Перше: ідентифікуйте, хто це повідомив
- Перевірте journald на наявність точного рядка помилки та імені процесу. Не вгадуйте.
- Підтвердіть, чи це
EMFILE(пер‑процесний) чиENFILE(системний). Це змінює рішення.
Друге: перевірте використання файлових дескрипторів у підозрілому процесі
- Отримайте PID(и) підозрілого демона або процесу QEMU.
- Порахуйте відкриті fd і порівняйте з лімітом процесу (у
/proc/<pid>/limits).
Третє: вирішіть, що підвищувати (і де)
- Якщо ліміт процесу низький і використання справді велике — підвищте
LimitNOFILEдля цього systemd‑unit (найкращий варіант). - Якщо вичерпано системну таблицю файлів — підвищте
fs.file-maxі розберіться, чому система утримує так багато дескрипторів (часто витік, неконтрольовані сервіси або масивний Ceph). - Якщо це одноразовий сплеск від бекапу чи відновлення, подумайте про перенесення/обмеження паралелізму замість лише підвищення лімітів.
Є цитата, яка болісно правдива в операціях: (парафраз) «Надія — це не стратегія.» — часто приписують у колах інженерного лідерства
. Для цієї помилки надія виглядає як «піднімемо все і перезавантажимо». Стратегія — це інструментування і цілеспрямовані ліміти.
Цікаві факти та історичний контекст (чому це повторюється)
- Факт 1: Ранні Unix‑системи часто мали крихітні пер‑процесні ліміти fd (іноді кілька десятків). Сучасні системи за замовчуванням мають 1024 або більше, але ці значення все ще відображають «загального призначення», а не хости віртуалізації.
- Факт 2: Поділ soft/hard існує, щоби процеси могли підвищувати власний soft до hard‑межі. systemd може задавати обидва значення.
- Факт 3: «Все — файл» включає сокети; зайнятий API‑проксі може витратити тисячі fd без доступу до диску.
- Факт 4: QEMU використовує кілька fd на диск, на NIC, на vhost‑потік, плюс eventfd. Одна VM може споживати сотні чи тисячі fd на навантаженому хості.
- Факт 5: inotify використовує fd і wаtcher‑и; деякі стекі моніторингу і лог‑шипери масштабують watcher‑и агресивно і можуть вдарити по лімітам несподівано.
- Факт 6: systemd ввів більш явний, на рівні юніта спосіб керування лімітами (
LimitNOFILE), зменшивши залежність від shell‑ультимативних хаків, які ніколи не застосовувалися до демонів. - Факт 7: Облік глобальних файлових дескрипторів у Linux покращився, але ви все ще можете виснажити таблиці файлів, якщо запускаєте багато сервісів або маєте витоки fd з часом.
- Факт 8: Ceph історично прагне вищих fd‑лімітів; OSD може легітимно потребувати великої кількості відкритих файлів і сокетів під навантаженням.
Жарт №1: Файлові дескриптори — як нарадні кімнати: якщо ніхто не виходить, згодом будівля «вичерпає» простір, а керівництво звинувачує календар.
Де це трапляється в Proxmox: яка служба зазвичай винна
На вузлі Proxmox фраза «too many open files» може з’являтися з кількох шарів. Ваше завдання — припинити трактувати Proxmox як моноліт і почати дивитися на нього як на Debian + systemd + стек демонів + робочі навантаження (VM/CT), які творять хаос.
Демони Proxmox (часто на завантажених кластерах)
- pveproxy: веб‑інтерфейс і API. Він може спалювати fd через багато одночасних HTTPS‑з’єднань, довготривалі сесії браузера, зворотні проксі і бекенди автентифікації.
- pvedaemon: фонова обробка задач та помічник API. Часто задіяний під час бекапів, відновлень, міграцій, сканувань сховищ.
- pvestatd: збирає статистику; у великих кластерах може навантажувати запити до сховища і мережеві з’єднання.
- pve-cluster / pmxcfs: демон кластерної файлової системи; проблеми тут проявляються як дивна поведінка кластера, а не лише очевидний EMFILE‑рядок.
Процеси QEMU/KVM (коли «одна VM сходить з розуму»)
Якщо VM виконує інтенсивну роботу з великою кількістю з’єднань (проксі, брокери повідомлень, websocket, NAT‑шлюзи), вона може змусити хост‑процес QEMU відкрити багато fd для vhost‑net, tap‑пристроїв та взаємодій io_uring/eventfd. Якщо ліміт QEMU низький, ви побачите збої в мережі, дисковому IO або при хотплаг‑пристроях.
Шари зберігання (ZFS, Ceph, PBS)
- ZFS зазвичай не є прямим джерелом EMFILE на хості, але юзерленд‑утиліти й процеси бекапу, що взаємодіють з багатьма файлами, можуть бути. Думайте про
zfs sendпайплайни і індексацію бекапів. - Ceph: OSD і монітори відомі тим, що потребують високих fd‑лімітів у реальних розгортаннях. «Too many open files» тут не дивина — це перевірка конфігурації, яку слід робити рано.
- Proxmox Backup Server (якщо розташований на тій самій машині або інтегрований): робочі задачі відкривають багато чанків, індексів і з’єднань. Низький fd‑ліміт може перетворити вікно бекапу на повільну катастрофу.
Контейнери (LXC)
LXC‑контейнери можуть стикатися зі своїми nofile‑лімітами в межах неймспейсу контейнера. Але не припускайте негайно, що контейнер винен; хостовий демон, який ним керує, може скаржитися. Завжди прив’язуйте помилку до PID, а потім до юніта.
Практичні завдання (команди, виводи, рішення) — робочий чекліст
Ви хочете реальні завдання, що знижують невизначеність. Ось більше ніж десяток. Виконуйте їх по черзі, поки не отримаєте ідентифікований вузький місце та обґрунтовану зміну.
Завдання 1: Знайдіть точний рядок помилки і службу‑відправника
cr0x@server:~$ journalctl -p err -S -2h | grep -iE "too many open files|EMFILE|ENFILE" | tail -n 20
Dec 26 09:31:12 pve1 pveproxy[1432]: error: accept4: Too many open files
Dec 26 09:31:12 pve1 pveproxy[1432]: failed to accept connection: EMFILE
Що це означає: Це EMFILE від pveproxy PID 1432. Не чіпайте ядрові глобальні налаштування ще; це пер‑процесна проблема.
Рішення: Проінспектуйте ліміти PID 1432 і кількість fd. Підготуйте systemd‑override для pveproxy.service, якщо потрібно.
Завдання 2: Підтвердіть, чи система близька до вичерпання глобальної таблиці файлових дескрипторів
cr0x@server:~$ cat /proc/sys/fs/file-nr
23872 0 9223372036854775807
Що це означає: Перше число — виділені файлові дескриптори; третє — системний максимум. На багатьох сучасних ядрах максимум фактично величезний (або динамічний). Якщо перше число близьке до максимуму — у вас системна проблема.
Рішення: Тут далеко не близько. Зосередьтеся на пер‑процесних лімітах.
Завдання 3: Перевірте ліміт fd для процесу та поточне використання
cr0x@server:~$ pid=1432; echo "FDs:"; ls -1 /proc/$pid/fd | wc -l; echo; echo "Limits:"; grep -i "open files" /proc/$pid/limits
FDs:
1024
Limits:
Max open files 1024 1048576 files
Що це означає: Процес сидить точно на своєму soft‑ліміті (1024). Hard‑ліміт вищий, отже сервіс теоретично може підняти soft, але не зробив цього.
Рішення: Підвищте LimitNOFILE для юніта, щоб systemd стартував його з більшим soft‑лімітом. Орієнтуйтеся на щось розумне (наприклад, 8192–65536 залежно від конкуренції).
Завдання 4: Визначте systemd‑unit для PID
cr0x@server:~$ systemctl status pveproxy --no-pager
● pveproxy.service - PVE API Proxy Server
Loaded: loaded (/lib/systemd/system/pveproxy.service; enabled)
Active: active (running) since Thu 2025-12-26 08:11:02 UTC; 1h 25min ago
Main PID: 1432 (pveproxy)
Tasks: 10 (limit: 154675)
Memory: 76.4M
CPU: 1min 52.123s
Що це означає: Це звичайний юніт, не якийсь таємничий процес. Добре: ми можемо зробити чистий override.
Рішення: Використайте systemctl edit pveproxy, щоб задати LimitNOFILE. Не редагуйте файли в /lib/systemd/system напряму.
Завдання 5: Перевірте поточні ліміти на рівні юніта (якщо є)
cr0x@server:~$ systemctl show pveproxy -p LimitNOFILE
LimitNOFILE=1024:1048576
Що це означає: systemd запустив його з soft=1024, hard=1048576.
Рішення: Виконайте override, щоб збільшити soft (і за потреби hard). Якщо потрібен лише більший soft — задайте одне значення; systemd приймає LimitNOFILE=65536 (застосовується до обох) або LimitNOFILE=65536:65536.
Завдання 6: Створіть systemd‑override для конкретної служби Proxmox
cr0x@server:~$ sudo systemctl edit pveproxy
# (editor opens)
Помістіть це у drop‑in:
cr0x@server:~$ cat /etc/systemd/system/pveproxy.service.d/override.conf
[Service]
LimitNOFILE=65536
Що це означає: Після наступного рестарту pveproxy отримає ліміт 65k fd. Це достатньо для більшості кластерів без ексцесу.
Рішення: Перезавантажте systemd і рестартуйте сервіс. Якщо це API‑проксі і ви в середині інциденту, робіть це у безпечне вікно або через консоль вузла.
Завдання 7: Застосуйте й перевірте, що нові ліміти набрали чинності
cr0x@server:~$ sudo systemctl daemon-reload
cr0x@server:~$ sudo systemctl restart pveproxy
cr0x@server:~$ systemctl show pveproxy -p LimitNOFILE
LimitNOFILE=65536:65536
Що це означає: Юніт тепер налаштовано правильно.
Рішення: Переконайтеся, що запущений PID теж має новий ліміт, а не тільки метадані юніта.
Завдання 8: Підтвердіть ефективний ліміт робочого PID
cr0x@server:~$ pid=$(pidof pveproxy); grep -i "open files" /proc/$pid/limits
Max open files 65536 65536 files
Що це означає: Процес реально працює з новим лімітом. Оце і є мета.
Рішення: Спостерігайте за повторенням. Якщо використання fd продовжує зростати, можливо, у вас витік або надмірне навантаження зверху.
Завдання 9: Подивіться, який тип fd споживається (сокети чи файли)
cr0x@server:~$ pid=$(pidof pveproxy); sudo ls -l /proc/$pid/fd | awk '{print $11}' | head
socket:[942113]
socket:[942115]
/dev/null
socket:[942118]
anon_inode:[eventfd]
Що це означає: Якщо список здебільшого socket:, ви маєте справу з конкуруючими з’єднаннями. Якщо це реальні шляхи, можливо, відбувається багато сканувань файлів або проблеми зі сховищем.
Рішення: Якщо це сокети — подумайте про фронт‑проксі, налаштування keepalive, бекенди автентифікації і поведінку клієнтів. Якщо це файлові шляхи — з’ясуйте, що їх відкриває і чому.
Завдання 10: Визначте топ‑споживачів fd на вузлі (швидка триаж)
cr0x@server:~$ for p in /proc/[0-9]*; do
pid=${p#/proc/}
comm=$(tr -d '\0' < $p/comm 2>/dev/null) || continue
fdc=$(ls -1 $p/fd 2>/dev/null | wc -l)
echo "$fdc $pid $comm"
done | sort -nr | head -n 10
18034 28741 ceph-osd
9123 1942 qemu-system-x86
5012 1432 pveproxy
2120 1567 pvedaemon
Що це означає: Ви вивели список «злодіїв» за кількістю fd.
Рішення: Якщо Ceph OSD домінує, можливо, треба налаштувати ліміти Ceph. Якщо великий QEMU — зосередьтесь на конкретній VM і її методом запуску.
Завдання 11: Для QEMU: зв’яжіть PID QEMU з VMID
cr0x@server:~$ pid=1942; tr '\0' ' ' < /proc/$pid/cmdline | sed -n 's/.*-id \([0-9]\+\).*/VMID=\1/p'
VMID=104
Що це означає: Цей процес QEMU — VM 104.
Рішення: Перевірте, чи він регулярно стрибає у використанні fd під час бекапів, під високим навантаженням з’єднань або через неправильну конфігурацію пристроїв.
Завдання 12: Перевірте ліміт для процесу QEMU і чи він занадто низький
cr0x@server:~$ pid=1942; grep -i "open files" /proc/$pid/limits
Max open files 4096 4096 files
Що це означає: QEMU обмежений 4096. Це може бути достатньо або зовсім недостатньо для зайнятого gateway‑VM.
Рішення: Якщо QEMU падає з EMFILE і використання fd підходить до 4096 — підвищуйте ліміт для scope/service, що стартує VMs (див. розділ «Правильне підвищення лімітів»).
Завдання 13: Знайдіть systemd‑unit/scope для PID QEMU
cr0x@server:~$ pid=1942; systemctl status $pid --no-pager
● 104.scope - qemu-kvm -id 104
Loaded: loaded
Active: active (running) since Thu 2025-12-26 08:22:51 UTC; 1h 13min ago
Main PID: 1942 (qemu-system-x86)
Що це означає: VM працює в systemd‑scope з іменем за VMID. Ліміти можуть походити від батьківського сервісу або дефолтів systemd.
Рішення: Налаштування лімітів на рівні окремих scope можливе, але зазвичай це не краща операційна модель. Краще виправляти батьківський юніт/шаблон або сервіс, що породжує QEMU, або використовувати дефолти manager‑а, якщо доречно.
Завдання 14: Перевірте дефолтні ліміти systemd (іноді прихований винуватець)
cr0x@server:~$ systemctl show --property DefaultLimitNOFILE
DefaultLimitNOFILE=1024:524288
Що це означає: Дефолти systemd можуть впливати на scope і служби, які явно не встановлюють свої ліміти.
Рішення: Не підвищуйте це легковажно. Це «кнопка великого впливу». Використовуйте її тільки якщо багато сервісів справді потребують вищих лімітів і ви перевірили вплив на пам’ять і моніторинг.
Завдання 15: Перевірте ліміти на користувача (корисно для інтерактивних інструментів і PAM‑сесій)
cr0x@server:~$ ulimit -n
1024
Що це означає: Ваша shell‑сесія має ліміт 1024. Це не застосовується автоматично до systemd‑сервісів.
Рішення: Якщо ваші оперативні інструменти (скрипти, rsync‑джоби, CLI‑бекапи) падають з EMFILE у інтерактивних сесіях — змініть PAM‑ліміти. Інакше пріоритет — systemd‑overrides.
Завдання 16: Якщо підозрюєте витік — спостерігайте зміну fd з часом
cr0x@server:~$ pid=$(pidof pvedaemon); for i in $(seq 1 10); do date; ls -1 /proc/$pid/fd | wc -l; sleep 30; done
Thu Dec 26 09:40:01 UTC 2025
812
Thu Dec 26 09:40:31 UTC 2025
829
Thu Dec 26 09:41:01 UTC 2025
846
Що це означає: Якщо значення тільки зростає і ніколи не падає під стабільного навантаження — можливо, є витік fd (або постійно зростає кількість довготривалих з’єднань).
Рішення: Підвищення ліміту може дати час, але вам слід шукати витік: журнали, останні оновлення, плагіни, бекенди автентифікації або балансувальник навантаження, що робить «креативні» речі.
Завдання 17: Визначте, які віддалені пір‑и утримують сокети відкритими (для проксі)
cr0x@server:~$ pid=$(pidof pveproxy); sudo lsof -nP -p $pid | awk '/TCP/ {print $9}' | head
10.20.5.18:8006->10.20.5.40:51522
10.20.5.18:8006->10.20.7.91:50944
Що це означає: Ви бачите IP клієнтів і порти. Якщо один клієнт відкриває величезну кількість з’єднань — ви знайшли проблемну поведінку.
Рішення: Виправте клієнта, додайте проксі з адекватними лімітами або налаштуйте keepalive. Підвищення fd без усунення зловживань — це як купити більший сміттєвий бак для єнота.
Правильне підвищення лімітів: ядро vs systemd vs додаток
Почніть з найбільш хірургічного виправлення
Якщо конкретна служба досягає EMFILE — встановіть LimitNOFILE для цієї служби. Це найчистіший підхід: вимірюваний, зворотний, з мінімальними побічними ефектами.
Systemd‑override: стандартний хід для служб Proxmox
Демони Proxmox — це systemd‑служби. Ви змінюєте ліміти через drop‑in у /etc/systemd/system/<unit>.service.d/override.conf. Цей файл переживе оновлення і пояснить майбутньому вам, що було зроблено.
Поширені служби Proxmox, які варто розглянути:
pveproxy.service(UI/API)pvedaemon.service(таски, помічник API)pvestatd.service(статистика)pve-cluster.service(кластерна файлова система)ceph-osd@<id>.service,ceph-mon@<name>.service(якщо ви запускаєте Ceph на вузлі)
Наскільки високо слід ставити LimitNOFILE?
Підіймайте значення відповідно до операційної реальності:
- 8192: гідне збільшення для легких демонів з випадковими сплесками.
- 16384–65536: звично для зайнятих проксі, демонів управління в великих кластерах та процесів, пов’язаних з бекапами.
- 131072+: для «важковаговиків» (Ceph OSD на масштабі, високопродуктивні мережеві сервіси). Не робіть цього лише тому, що побачили на форумі.
Ліміт не безкоштовний: кожен fd використовує ресурси ядра. На сучасних системах це зазвичай прийнятно, але «прийнятність» залежить від тиску пам’яті, кількості процесів і того, скільки fd вони реально використовують.
Коли важливі глобальні ліміти ядра
Глобальне вичерпання файлових дескрипторів трапляється рідше, але буває на:
- вузлах, де працює багато сервісів (моніторинг, лог‑шипінг, сховище, зворотні проксі)
- вузлах з інтенсивним Ceph
- системах з витоками fd у багатьох процесах
Перегляньте поточні установки:
cr0x@server:~$ sysctl fs.file-max
fs.file-max = 9223372036854775807
На багатьох сучасних ядрах це значення величезне або фактично необмежене. У такому випадку ENFILE менш імовірний, а EMFILE залишається основною проблемою. Все ж — вимірюйте, не припускайте.
Ліміти на користувача: корисні, але не основний важіль для демнів Proxmox
/etc/security/limits.conf і ulimit -n важливі для сесій користувачів, cron‑джобів і скриптів, які запускають люди. Вони не надійно керують службами systemd (systemd сам встановлює rlimits). Якщо ви «виправили» демон Proxmox, редагуючи limits.conf, ви або пощастили, або одночасно змінили щось інше.
Підвищення лімітів для QEMU: що варто і чого не варто робити
Якщо QEMU доходить до ліміту fd, у вас є два питання:
- Чи є робоче навантаження VM справді fd‑важким (багато з’єднань/пристроїв)?
- Чи запускаються процеси QEMU з сенсовим rlimit для вашого середовища?
Підвищення лімітів QEMU можна зробити, налаштувавши systemd‑оточення, яке їх породжує (залежно від версії Proxmox і того, як VM scoped). На практиці рекомендую:
- Спочатку підтвердити, що PID QEMU досяг ліміту (не гостьова ОС).
- Потім розглянути підвищення дефолту для сервісу‑спавнера тільки якщо кілька VM мають ту саму проблему.
- Для одного виняткового VM переважно виправляти на рівні навантаження: пулювання з’єднань, скорочення агресивних keepalive, виправлення витоків додатків або розподіл ролей між VM.
Жарт №2: «Просто встановимо LimitNOFILE в нескінченність» — це те, як ви вчитеся, що «пам’ять скінченна» в продакшені.
Три корпоративні міні‑історії з реального життя
Міні‑історія 1: Інцидент через неправильне припущення
Вони керували середнім кластером Proxmox для внутрішніх сервісів і кількох клієнтських додатків. Одного ранку веб‑інтерфейс почав таймити. Потім API‑запити впали. Потім бекапи стали чергуватися. Команда припустила, що вузол «впав» у класичному сенсі: CPU на максимумі, диск повний, мережа померла. Ніщо з цього не було правдою.
Підказка була в journald: pveproxy не міг прийняти нові з’єднання. «Too many open files.» Хтось нещодавно повісив внутрішню панель у kiosk‑режимі на стінному дисплеї. Вона оновлювалася агресивно, відкривала кілька паралельних API‑з’єднань і ніколи їх не закривала. Помножте це на кілька телевізорів і кілька розробників, які тримали вкладки відкритими днями, і отримаєте повільний DoS.
Неправильне припущення було в тому, що «too many open files» має значити «ZFS відкрив забагато файлів» або «сховище зламалося». Вони годинами шукали стан пулу і SMART‑дані. Тим часом проксі мав 1024 fd і відкидав саме той UI, який їм потрібен був для дебагу.
Виправлення було простим: підвищили LimitNOFILE для pveproxy до розумного значення і виправили проблемну поведінку клієнта. Урок цінніший: завжди пов’язуйте помилку з PID, потім з юнітом, потім з навантаженням. Вгадування дороге.
Міні‑історія 2: Оптимізація, яка повернулася боком
Інша організація захотіла швидших бекапів. Вони підняли паралелізм задач бекапу і скоротили цикли зберігання. На папері виглядало чудово: більше конкуренції, більша пропускна спроможність, менше часу у вікні. Також вони розгорнули додатковий моніторинг, який tail‑ив багато логів і слідкував за багатьма директоріями.
Потім бекапи почали інтермітентно падати. Іноді це був процес бекапу. Іноді демон управління. Іноді якась, здавалося б, не пов’язана служба як збирач метрик. Шаблон був «випадковий», що і є системним ресурсним лімітом, коли ви ще не признали проблему.
Повернення удару було в тому, що кожний паралельний воркер бекапу і кожний агент моніторингу множили використання fd. Окремо кожна служба виглядала нормально. Разом вузол проводив довгі періоди з багатьма процесами біля soft‑капу. Сплески іноді штовхали одного з них за край, і нещасний кидав EMFILE першим.
Одного разу вони «виправили» це, піднявши глобальний дефолт, і забули. Місяць потому шаблон повернувся, але вже з вищим тиском пам’яті і більшою кількістю процесів. Зрештою правильне виправлення було нудним: встановити явні LimitNOFILE для відомих важких сервісів, зменшити паралелізм бекапів під можливості сховища і виміряти використання fd під піковими навантаженнями. Продуктивність покращилася, збої зупинилися, і не довелося постійно підвищувати стелі.
Міні‑історія 3: Нудна, але правильна практика, що врятувала день
Команда, що запускала Ceph на Proxmox, мала звичку, яка здавалася нецікавою: вони вели runbook з трьома простими перевірками для будь‑якої помилки платформи. Одна з перевірок була «використання fd vs ліміти». Вони також зберігали у версіях свої systemd‑drop‑in для критичних сервісів (не Proxmox‑керовані файли, а override у /etc).
Під час розширення сховища нове розгортання OSD почало флапати. Симптоми виглядали як мережеві: пропущені heartbeats, повільні операції, випадкові рестарти демонів. Але runbook змусив їх перевірити базові речі. Процеси OSD досягали свого fd‑ліміту під новим макетом і навантаженням.
Оскільки у них уже була відома політика для Ceph‑лімітів, виправлення не вимагало панічного пошуку на форумах. Вони застосували існуючі overrides, перезапустили постраждалі сервіси в контрольованій послідовності і перевірили однією командою, що ліміти і використання тепер мають запас.
День врятувала нудна річ: повторювані перевірки і гігієна конфігурації. Без героїзму. Без «просто перезавантажити». Кластер продовжив обслуговувати IO, і вікно змін закінчилося вчасно. У операціях нудне — це перевага.
Поширені помилки: симптом → корінь → виправлення
Помилка 1: «Я підняв ulimit -n, а все одно падає»
Симптом: Ви виконуєте ulimit -n 65535 у shell, перезапускаєте сервіс Proxmox і все одно бачите EMFILE.
Корінь: Служби systemd не успадковують ваш shell‑ulimit. systemd сам встановлює rlimits.
Виправлення: Встановіть LimitNOFILE в systemd‑drop‑in для конкретного юніта, потім перезапустіть юніт і перевірте /proc/<pid>/limits.
Помилка 2: Підвищення глобального дефолту systemd через одну служби
Симптом: Ви змінили DefaultLimitNOFILE системно і все здається ок… поки несумісні сервіси не починають споживати більше ресурсів.
Корінь: Ви розширили радіус ураження. Тепер багато служб можуть відкривати більше fd, що може посилити витоки і збільшити навантаження на пам’ять ядра.
Виправлення: Тримайте дефолти консервативними. Підвищуйте ліміти тільки для юнітів, яким це потрібно. Використовуйте дефолт лише після перевірки, що багато сервісів мають справді обґрунтовану потребу.
Помилка 3: Трактування EMFILE як «проблема зі сховищем»
Симптом: Бекап падає з «too many open files», і команда кидається в тюнінг ZFS.
Корінь: Процес, що падає, часто — демон або воркер бекапу, що відкриває багато файлів/сокетів, а не ZFS сам по собі.
Виправлення: Ідентифікуйте PID, що видав помилку, і перевірте його ліміт і кількість fd. Потім підвищте ліміт цього юніта або зменшіть конкуренцію.
Помилка 4: Підвищення лімітів без перевірки на витоки
Симптом: Вузол працює тиждень після підвищення лімітів, а потім знову падає.
Корінь: Реальний витік (fd ніколи не звільняються) або неконтрольована поведінка з’єднань; вищий ліміт лише відтермінував крах.
Виправлення: Трендуйте кількість fd у часі для підозрілих процесів. Якщо вона монотонно зростає — розглядайте це як баг або проблему навантаження. Ескалюйте з доказами (графік fd, зразки lsof, рядки з journald).
Помилка 5: Плутанина між гостьовими і хостовими лімітами
Симптом: Додаток у контейнері кидає EMFILE, ви підвищуєте ліміти хоста, і нічого не змінюється.
Корінь: Ліміт знаходиться всередині контейнера або в runtime додатка, а не у хост‑процесі.
Виправлення: Перевірте в контейнері (ulimit -n) і перевірте хост‑процес. Виправляйте шар, який реально падає.
Помилка 6: Перезапуск випадкових сервісів до зникнення помилки
Симптом: Після рестартів знову «все працює», але ніхто не знає чому.
Корінь: Рестарт скидає відкриті fd, тимчасово маскуючи навантаження або витік.
Виправлення: Використовуйте рестарт як стабілізацію, а не діагностику. Перед рестартом захопіть: journald‑рядок помилки, PID‑ліміти, кількість fd і зразок lsof.
Чеклісти / покроковий план (безпечна послідовність змін)
Чекліст A: Ви побачили «too many open files» в Proxmox UI/API
- Витягніть помилки з journald за останні 1–2 години; знайдіть бінарник і PID, що випустив помилку.
- Перевірте, чи це EMFILE чи ENFILE.
- Порахуйте відкриті fd для PID і порівняйте з
/proc/<pid>/limits. - Якщо кількість fd близька до ліміту: встановіть
LimitNOFILEдля конкретного юніта і рестартуйте його. - Якщо кількість fd значно менша за ліміт: можливо, це транзиторний сплеск; розслідуйте конкуренцію, поведінку клієнтів і логи навколо таймстемпу.
- Після зміни перевірте нові ліміти на робочому PID і моніторте повторення.
Чекліст B: Підозрюєте, що QEMU процеси досягають лімитів
- Знайдіть PID QEMU за повідомленням помилки або серед топ‑споживачів fd.
- Зв’яжіть PID з VMID через cmdline (
-id). - Перевірте
/proc/<pid>/limitsі кількість fd. Якщо близько — проблема реальна. - Розв’яжіть: виправлення шаблону навантаження (переважно для однієї VM) або підвищення лімітів (якщо багато VM постраждали).
- Після змін проганяйте те саме навантаження і стежте за запасом fd.
Чекліст C: Ви запускаєте Ceph на Proxmox і бачите EMFILE
- Визначте, який демон Ceph (OSD/MON/MGR) логував EMFILE.
- Перевірте ліміти systemd‑unit цього демона і ліміти робочого PID.
- Застосуйте override для типу демона (часто шаблонні юніти на кшталт
ceph-osd@.service). - Рестартуйте в контрольованому порядку, стежачи за здоров’ям кластера.
- Підтвердіть використання fd під навантаженням і переконайтеся, що ви не відклали витік.
Покроково: «правильний» спосіб підвищити ліміт для демона Proxmox
- Виміряйте поточний ліміт і використання (
/proc/<pid>/limitsі кількість/proc/<pid>/fd). - Виберіть нове значення з запасом (зазвичай 8–64× від пікового використання, не 1000×).
- Створіть systemd‑drop‑in через
systemctl edit <unit>. systemctl daemon-reload.- Рестарт юніта у відповідне вікно.
- Перевірте через
systemctl showі/proc/<pid>/limits. - Моніторьте: кількість fd у часі, журнали помилок і поведінку клієнтів.
- Запишіть, чому ви це зробили. Майбутній ви — інша людина з меншим контекстом і більше кофеїну.
Питання та відповіді
1) Чи слід підвищувати fs.file-max, щоб виправити «too many open files» у Proxmox?
Зазвичай ні. Більшість інцидентів Proxmox — це пер‑процесні EMFILE. Спочатку підвищте LimitNOFILE для служби. Торкайтеся ядрових глобалів лише якщо можете довести глобальне вичерпання.
2) Який хороший дефолт LimitNOFILE для pveproxy?
Для невеликих установок 8192 достатньо. Для зайнятих кластерів з багатьма UI/API клієнтами або автоматизацією — 65536 є практичним максимумом. Якщо треба більше — ймовірно, треба виправляти поведінку клієнтів також.
3) Чому ulimit -n показує 1024, хоча я встановив вищі ліміти в systemd?
ulimit -n відображає вашу поточну shell‑сесію. systemd‑сервіси мають власні rlimits. Перевіряйте PID служби в /proc/<pid>/limits, щоб бачити справжній стан.
4) Чи може підвищення nofile спричинити нестабільність?
Косвено — так. Вищі ліміти дозволяють процесам виділяти більше ресурсів ядра. Якщо є витоки, ви просто дали витоку більше простору. Використовуйте підвищення з моніторингом і трендами fd.
5) У мого контейнера «too many open files». Чи змінювати хост?
Можливо, але почніть зсередини контейнера: перевірте ліміт додатка і ліміт контейнера. Якщо хост‑процес LXC/QEMU — той, що кидає EMFILE, то налаштовуйте хост‑сторону (сервіс або scope).
6) Як зрозуміти, витік це чи легітимна конкуренція?
Витоки виглядають як кількість fd, що стабільно зростає і не падає, навіть коли навантаження зменшується. Легітимна конкуренція зазвичай корелює з трафіком. Вимірюйте кількість fd у часі та інспектуйте типи fd (сокети vs файли).
7) Які служби Proxmox найбільш чутливі до fd‑лімітів?
pveproxy і pvedaemon — найпоширеніші. У більших кластерах pvestatd і компоненти кластеру можуть проявляти проблеми. Якщо є Ceph — демони Ceph часто винні.
8) Я підняв ліміти, але все одно бачу помилки. Що робити далі?
Переконайтеся, що робочий PID має новий ліміт (не довіряйте лише конфіг‑файлам). Потім перевірте, чи використання fd досягає нового капу. Якщо так — або підвищуйте далі, або маєте справжню проблему з runaway. Якщо ні — можливо, помилка генерується іншим процесом, ніж ви думаєте.
9) Чи існує «універсальне» число для вузлів Proxmox?
Ні, це пастка. Вузли віртуалізації містять дуже різні навантаження. Встановлюйте пер‑службові ліміти на основі виміряних піків і очікуваної конкуренції, а не віри в магічне число.
Висновок: практичні наступні кроки
Якщо запам’ятати одне: «too many open files» — це не емоція. Це вимірюваний ресурсний ліміт. Ваше перше завдання — атрибуція: який PID, який юніт, який ліміт. Друге завдання — обрати найменшу ефективну зміну: systemd LimitNOFILE override для конкретної служби, яка реально вичерпала EMFILE. Третє — переконатися, що ви не дали витоку довший запобіжник.
Наступні кроки, які можна зробити сьогодні:
- Додайте швидку команду triage fd у ваш runbook (PID → кількість fd → ліміти).
- Встановіть явні
LimitNOFILEoverrides для відомих важких служб Proxmox у вашому середовищі (pveproxy,pvedaemon, демони Ceph якщо застосовано). - Під час пікових операцій (вікна бекапів, міграцій) знімайте вибірки використання fd і зберігайте числа. Докази перемагають суперечки.