Назад | Перейти на главную страницу

mkdir: «на устройстве не осталось места» в определенных папках после того, как Apache Tomcat достиг максимального значения ulimit

Вопрос:

У меня есть кот, запускающий java-приложение, которое иногда накапливает дескрипторы сокетов и достигает установленного нами ulimit (как мягкого, так и жесткого) для max-open-files, который составляет 100K. Когда это происходит, кажется, что Java все еще жива, но мы больше не можем получить к ней доступ.

Однако мой вопрос касается странного явления, которое сопровождает эту ситуацию: Я не могу mkdir внутри папки tomcat.

[root@server /opt/apache-tomcat-7.0.52]# mkdir some_folder
mkdir: cannot create directory `some_folder': No space left on device

Фактически, я получаю ту же ошибку в нескольких разных папках, которые находятся в /opt, но не под /opt прямо, а не - например - под /opt/apache-tomcat-7.0.52/logs.

Я не могу объяснить это хоть убей, и могу решить только с помощью init 6. Любые предложения о том, как решить проблему и иметь возможность mkdir опять без перезагрузки?


Некоторые подсказки и подсказки, которые я собрал:

Это CentOS 6.5, работающая под AWS, с указанным диском tomcat, смонтированным из тома EBS.

Бег df -h показывает, что диск явно не заполнен:

[root@server ~]# df -h
Filesystem            Size  Used Avail Use% Mounted on
/dev/xvda1            9.9G  3.6G  5.9G  38% /
none                  121G     0  121G   0% /dev/shm
/dev/xvdc            1008G  197G  760G  19% /mnt/eternal

Содержание /etc/fstab (которые по какой-то причине используют двойной монтаж - не знаю почему):

/dev/xvdc       /mnt/eternal    ext4    defaults        0 0
/mnt/eternal    /opt    ext4    defaults,bind   0 0

И соответствующие строки из mount:

/dev/xvdc on /mnt/eternal type ext4 (rw)
/mnt/eternal on /opt type none (rw,bind)

Бег df -i не намекает на что-то плохое (и похоже на здоровую систему):

[root@server ~]# df -i
Filesystem            Inodes   IUsed   IFree IUse% Mounted on
/dev/xvda1            655360   78245  577115   12% /
none                 31549847       1 31549846    1% /dev/shm
/dev/xvdc            67108864   12551 67096313    1% /mnt/eternal

Бег sysctl fs.file-nr дает этот результат, который явно высок, но кажется далеким от предела:

[root@server ~]# sysctl fs.file-nr
fs.file-nr = 101632     0       25087252

Бег find /proc | wc -l возвращается 62497876 (62M), что может достичь некоторого предела ОС; на аналогичной здоровой системе это больше похоже на 1800000 (1,8M).

Чрезвычайно занятая подпапка выглядит /proc/<my-java-pid>/task (~ 62 млн элементов по сравнению с ~ 1,7 млн ​​в исправной системе). Скорее всего, это просто отражение моих 100K fds (x2, для fds и fdinfos) более 300 отдельных папок "задач".

Это появляется в конце моего дампа dmesg (мой java pid в этом примере - 105940) - не уверен, как это может быть связано:

INFO: task java:105940 blocked for more than 120 seconds.
"echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
java          D 0000000000000008     0 105940      1 0x00000080
 ffff88161ab55c88 0000000000000082 ffff88161ab55c18 ffffffff8109be4f
 ffffffff81ed28f0 ffff881e66360ae0 ffffffff8100bb8e ffff88161ab55c88
 ffff881e66361098 ffff88161ab55fd8 000000000000fb88 ffff881e66361098
Call Trace:
 [<ffffffff8109be4f>] ? hrtimer_try_to_cancel+0x3f/0xd0
 [<ffffffff8100bb8e>] ? apic_timer_interrupt+0xe/0x20
 [<ffffffff810521c9>] ? mutex_spin_on_owner+0x99/0xc0
 [<ffffffff8151636e>] __mutex_lock_slowpath+0x13e/0x180
 [<ffffffff8151620b>] mutex_lock+0x2b/0x50
 [<ffffffff8111c461>] generic_file_aio_write+0x71/0x100
 [<ffffffffa0121fb1>] ext4_file_write+0x61/0x1e0 [ext4]
 [<ffffffff81180d7a>] do_sync_write+0xfa/0x140
 [<ffffffff81096ca0>] ? autoremove_wake_function+0x0/0x40
 [<ffffffff812292ab>] ? selinux_file_permission+0xfb/0x150
 [<ffffffff8121bd26>] ? security_file_permission+0x16/0x20
 [<ffffffff81181078>] vfs_write+0xb8/0x1a0
 [<ffffffff81181971>] sys_write+0x51/0x90
 [<ffffffff81517e2e>] ? do_device_not_available+0xe/0x10
 [<ffffffff8100b072>] system_call_fastpath+0x16/0x1b

Я был бы рад поделиться / предоставить любые другие предлагаемые выводы.

Втайне я надеюсь, что понимание этого странного поведения прольет свет на патологию, вызвавшую весь этот беспорядок. Но это только моя личная надежда :)

В большинстве случаев (очевидно, не в вашем случае) причина в том, что у вас заканчиваются iNodes.

Чтобы проверить это, запустите df -i:

Filesystem            Inodes   IUsed   IFree IUse% Mounted on
[...]
                       25600   25600       0  100% /foo

Здесь вы можете увидеть использование iNodes на 100%.

Плохие новости, по словам https://superuser.com/questions/585641/changing-max-inode-count-number-in-ext3-filesystem-in-cent-os вам нужно воссоздать файловую систему с параметром -i, чтобы увеличить количество inodes.

Я нашел ответ на свой вопрос «как исправить этот сценарий». Я не знаю всех подробностей того, как это произошло, но я знаю достаточно, чтобы дать ответ.

Краткий ответ: размонтирование диска, запуск chkdsk -f на нем, и установка обратно решает и предотвращает повторение проблемы. В качестве альтернативы можно создать новый диск (помните, что мы на AWS) и скопировать все данные на новый диск (rsync -a была моей командой выбора), и использование ее для замены исходного диска также решает и предотвращает.


Более длинный ответ: файловая система диска (ext4), похоже, достигла нестабильного состояния при первоначальном создании моментального снимка диска. Когда позже исходный снимок размером 200 ГБ был расширен (с использованием resize2fs) до 1 ТБ, похоже, что в каком-то смысле он продолжал внутренне запоминать исходный размер 200 ГБ, создавая всевозможные странные явления, в результате которых ОС не могла закрывать дескрипторы, что заставляло Tomcat достигать своего предела файла, таким образом получая весь ад вырваться.


Самый длинный ответ, с немного большим количеством деталей детективной работы: прорыв произошел, когда мы заставили эту патологию происходить параллельно в двух разных ситуациях. Проверив все параметры этих настроек и сравнив, мы поняли, что df -h на диске показывал такой результат:

/dev/xvdc            1008G  197G  760G  19% /mnt/eternal

Раньше это не привлекало нашего внимания, потому что на диске еще достаточно места. Но это было одно и то же использование диска (197 ГБ) в обеих конфигурациях, и для этого нет причин. Отсюда дела быстро развернулись. Как упоминалось ранее, наши экземпляры AWS были созданы из образа с моментальным снимком диска размером 200 ГБ, который расширяется на отдельные экземпляры с использованием resize2fs - обычно до максимального размера 1 ТБ. Мы наконец смогли воссоздать «плохое состояние», запустив новый экземпляр, изменив размер до 1 ТБ и создав большой файл размером 300 ГБ. Когда это было сделано, система не зависла, но показала такое же странное поведение:

/dev/xvdc            1008G  197G  760G  19% /mnt/eternal

И это когда на диске явно было больше 197 ГБ данных. Итак, мы опробовали два упомянутых выше метода (chkdsk и воссоздание диска) в двух индивидуальных настройках очистки, и в каждом из них странное поведение больше не появлялось.

Наше лучшее предположение состоит в том, что в какой-то момент при создании AMI что-то пошло не так в процессе создания моментального снимка - скорее всего, из-за того, что мы сделали «моментальный снимок без перезапуска» (хотя обычно мы этого не делаем, и у меня нет доказательств для подтверждения это вверх, так что я надеюсь, что наши DevOps не злятся на меня за то, что я обвиняю ее без причины!). В общем, интересный опыт.