mkdir: “nenhum espaço deixado no dispositivo” em pastas específicas depois que o Apache Tomcat atingiu o ulimit de arquivo máximo

6

A questão:

Eu tenho um tomcat executando um aplicativo java que ocasionalmente acumula handles de soquete e atinge o ulimit que configuramos (tanto soft quanto hard) para max-open-files, que é 100K. Quando isso acontece, o java parece ainda estar ativo, mas não podemos mais acessá-lo.

No entanto, minha pergunta é sobre um fenômeno bizarro que acompanha esta situação: Não consigo mkdir dentro da pasta tomcat.

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

Na verdade, recebo o mesmo erro em várias pastas diferentes que residem em /opt , mas não em /opt diretamente, e não - por exemplo - em /opt/apache-tomcat-7.0.52/logs .

Eu não posso explicar isso por minha vida e só posso resolver usando init 6 . Alguma sugestão sobre como corrigir o problema e poder mkdir novamente sem reiniciar?

Alguns ponteiros e pistas que eu recolhi:

A configuração é o CentOS 6.5 em execução no AWS com o referido disco do tomcat montado a partir de um volume do EBS.

A execução de df -h mostra que o disco evidentemente não está cheio:

[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

Conteúdo de /etc/fstab (que, por algum motivo, usa montagem dupla - não sei por que):

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

E linhas apropriadas de mount :

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

A execução de df -i não indica algo ruim (e é semelhante a um sistema saudável):

[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

A execução de sysctl fs.file-nr fornece esse resultado, que é evidentemente alto, mas parece muito distante do limite:

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

Executando find /proc | wc -l retornando 62497876 (62M), o que poderia atingir algum limite de SO; em um sistema semelhante saudável é mais como 1800000 (1,8 M).

A subpasta extremamente ocupada parece ser /proc/<my-java-pid>/task (~ 62M itens comparados a ~ 1,7M no sistema saudável). Este é provavelmente apenas um reflexo dos meus 100K fds (x2, para ambos os fds e fdinfos) mais de 300 pastas individuais de "tarefas".

Isso aparece no final do meu dmesg dump (meu java pid neste exemplo é 105940) - não tenho certeza de como isso pode estar relacionado:

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

Eu ficaria feliz em compartilhar / fornecer quaisquer outras descobertas sugeridas.

Secretamente, espero que a compreensão desse comportamento estranho possa esclarecer a patologia que está causando toda essa bagunça. Mas essa é apenas minha esperança pessoal:)

    
por Yonatan 16.02.2015 / 01:43

2 respostas

4

Eu encontrei a resposta para a minha pergunta de "como corrigir esse cenário". Não conheço todos os detalhes de como isso aconteceu, mas sei o suficiente para dar uma resposta.

Resposta curta: desmontando o disco, executando chkdsk -f sobre ele e a montagem de volta resolve e evita que o problema ocorra novamente. Como alternativa, criar um novo disco (lembre-se de que estamos na AWS) e copiar todos os dados para o novo disco ( rsync -a foi o meu comando de escolha) e usá-lo para substituir o disco original também resolve & impede.

Resposta mais longa: o sistema de arquivos do disco (ext4) parece ter atingido algum estado instável quando o instantâneo do disco foi originalmente criado. Quando mais tarde o instantâneo original de 200GB foi estendido (usando resize2fs ) para 1TB, parece que em certo sentido ele manteve lembrando internamente o tamanho original de 200GB, criando todos os tipos de fenômenos estranhos que acabaram com o OS incapaz de fechar manipula, fazendo com que o Tomcat atinja seu limite de arquivos, tendo assim todo o inferno solto.

Resposta mais longa, com um pouco mais dos detalhes do trabalho de detetive: a descoberta aconteceu quando tivemos essa patologia ocorrendo em paralelo em duas configurações separadas. Verificando todos os parâmetros nessas configurações e comparando, percebemos que df -h na unidade estava mostrando esse resultado:

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

Agora, isso não chamou nossa atenção antes, porque o disco ainda tem muito espaço sobrando. Mas foi exatamente o mesmo uso de disco (197G) em ambas as configurações, e isso não tem motivos para acontecer. Daqui as coisas rapidamente se desdobraram. Como mencionado anteriormente, nossas instâncias do AWS foram criadas a partir de uma imagem que tem um instantâneo de disco de 200 GB, que é estendido em instâncias individuais usando resize2fs - geralmente para o tamanho máximo de 1 TB. Finalmente conseguimos recriar um "mau estado", lançando uma nova instância, redimensionando para 1 TB e criando um grande arquivo de 300 GB. Quando isso foi feito, o sistema não congelou, mas mostrou o mesmo comportamento estranho:

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

E quando havia claramente mais de 197 GB de dados no disco. Então, tentamos os dois métodos mencionados acima (chkdsk e recriando o disco) em duas configurações limpas individuais, e em cada uma delas o comportamento estranho não apareceria mais.

Nosso melhor palpite é que em algum momento, quando a AMI foi criada, algo deu errado no processo de snapshots - muito provavelmente porque tínhamos tirado um "snapshot sem reiniciar" (embora não usualmente, e eu não tenho evidência para sustentar isso, então espero que nossos DevOps não fiquem bravos comigo por culpá-la sem motivo!). Tudo somado, uma experiência interessante.

    
por 10.03.2015 / 21:57
5

Na maioria dos casos (obviamente, não no seu caso) a razão é que você está ficando sem o iNodes.

Para verificar esta corrida, df -i:

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

Aqui você pode ver que o uso do iNodes é 100%.

As más notícias são, de acordo com o link você precisa recriar seu sistema de arquivos com a opção -i para aumentar o número de inodes.

    
por 13.11.2015 / 16:08