TLDR
Ao ativar vários contêineres do docker nos quais executo npm ci
, começo a receber pthread_create: Resource temporariamente indisponível erros (menos de 5 contêineres do docker podem funcionar bem). Deduzo que há algum tipo de limite de thread em algum lugar, mas não consigo encontrar qual está bloqueando aqui.
configuração
- uma instância do Jenkins ativa contêineres do docker para cada compilação (conexão por meio de ssh nesse contêiner do docker).
- em cada container são executados alguns comandos de construção; Eu vejo o erro com frequência ao usar
npm ci
, pois isso parece criar alguns tópicos; mas não acho que o problema esteja relacionado anpm
si mesmo. - todos os contêineres docker são executados em um único docker-host . É especificações:
docker-host
- CPU Intel(R) Xeon(R) Gold 5118 @ 2,30 GHz com 12 núcleos, 220 GB de RAM
- Centos 7
- Versão do Docker 18.06.1-ce, compilação e68fc7a
- versão do sistema 219
- kernel 3.10.0-957.5.1.el7.x86_64
erros
Eu posso ver o erro em diferentes formas:
- jenkins não conseguindo entrar em contato com o contêiner docker; erros como: java.lang.OutOfMemoryError: incapaz de criar novo thread nativo
git clone
falhando dentro do contêiner com ERRO: Erro ao clonar o repositório remoto 'origin'... Causado por: java.lang.OutOfMemoryError: impossível criar novo thread nativonpm ci
falhando dentro do contêiner com node[1296]: pthread_create: Recurso temporariamente indisponível
Coisas que investiguei ou tentei
Eu olhei bastante essa pergunta .
- docker-host tem a
systemd
versão 219 e, portanto, não possui oTasksMax
atributo. /proc/sys/kernel/threads-max
= 1798308kernel.pid_max
= 49152- O número de threads (
ps -elfT | wc -l
) normalmente é 700, mas com vários contêineres em execução, vi subir para 4500. - todas as compilações são executadas como algum usuário com pid 1001 dentro do contêiner docker; no entanto, não há usuário com pid 1001 no docker-host, então não sei quais limites se aplicam a esse usuário.
- Já aumentei vários limites para todos os usuários em
/etc/security/limits.conf
(veja abaixo) - Eu criei um usuário fictício com uid 1001 no docker-host e verifiquei se ele também tinha
nproc
limite definido como ilimitado. Fazer login nesse usuárioulimit -u
= ilimitado. Isso ainda não resolveu o problema
/etc/security/limits.conf :
* soft nproc unlimited
* soft stack 65536
* soft nofile 2097152
saída de ulimit -a
como root:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 899154
max locked memory (kbytes, -l) 1048576
max memory size (kbytes, -m) unlimited
open files (-n) 1048576
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 65536
cpu time (seconds, -t) unlimited
max user processes (-u) 899154
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
limites do meu processo dockerd (cat /proc/16087/limits
onde 16087 é pid do dockerd)
Limit Soft Limit Hard Limit Units
Max cpu time unlimited unlimited seconds
Max file size unlimited unlimited bytes
Max data size unlimited unlimited bytes
Max stack size unlimited unlimited bytes
Max core file size unlimited unlimited bytes
Max resident set unlimited unlimited bytes
Max processes unlimited unlimited processes
Max open files 65536 65536 files
Max locked memory 65536 65536 bytes
Max address space unlimited unlimited bytes
Max file locks unlimited unlimited locks
Max pending signals 899154 899154 signals
Max msgqueue size 819200 819200 bytes
Max nice priority 0 0
Max realtime priority 0 0
Max realtime timeout unlimited unlimited us
Eu encontrei uma maneira de obter acesso a mais de 4096 tópicos.
Meu contêiner docker é uma imagem centos7; que tem por padrão um limite de usuários definido para 4096 processos; conforme definido em
/etc/security/limits.d/20-nproc.conf
:ao fazer login no meu contêiner docker; Eu adicionei ao
~/.bashrc
comando paraulimit -u unlimited
que esse limite seja removido para esse usuário. Agora posso romper este teto 4096.Não estou totalmente satisfeito com esta solução; já que isso significa que eu preciso adaptar todos os containers que seriam executados no docker-host , pois cada um tem seu próprio limite; e como eu executo todos os comandos de compilação como usuário
1001
, parece que quando um contêiner pergunta quantos threads ele está executando; ele "vê" todos os encadeamentos de todos os contêineres juntos; não apenas os de sua própria instância.Eu criei um problema no github do docker-for-linux para isso: https://github.com/docker/for-linux/issues/654