40 votes

Docker sur Ubuntu ne peut pas saturer le CPU

J'ai une application Ruby simple, qui reçoit des données via un point d'accès HTTP, les traite un peu, les regroupe et les envoie par lots à un point d'accès HTTP distant.

Lorsque je l'exécute sur une machine nue, je sature 4 CPU à 100% et j'obtiens environ 3000reqs/s (selon ab l'application est un peu gourmande en ressources informatiques) ;

mais lorsque je l'exécute dans Docker, j'obtiens seulement 1700reqs/s - Les processeurs semblent atteindre un pic à environ 55-65%. La même application, les mêmes paramètres.

CPUs

J'ai essayé d'augmenter la concurrence d'ab. L'application elle-même est hébergée dans Passenger, j'ai essayé de l'exécuter dans 20 processus, dans 40 processus (Passenger exécute l'application). Dans Docker, il ne semble pas vouloir aller plus loin.

Je l'exécute via docker-compose l'hôte est Ubuntu 14.04

$ docker -v
Docker version 1.10.0, build 590d5108

$ docker-compose -v
docker-compose version 1.5.2, build 7240ff3

La moyenne de charge est élevée dans les deux cas (environ 20), mais elle n'est pas liée au disque.

$ vmstat 1
procs -----------memory---------- ---swap-- -----io---- ---system---  ------cpu-----
 r  b   swpd   free   buff  cache   si   so    bi    bo   in      cs  us sy id wa st
22  0      0 8630704  71160 257040    0    0    29     6  177    614   3  1 94  1  0
 7  0      0 8623252  71160 257084    0    0     0    16  9982 83401  46 12 43  0  0
43  0      0 8618844  71160 257088    0    0     0     0  9951 74056  52 10 38  0  0
17  0      0 8612796  71160 257088    0    0     0     0 10143 70098  52 14 34  0  0
17  0      0 8606756  71160 257092    0    0     0     0 11324 70113  48 15 37  0  0
31  0      0 8603748  71168 257104    0    0     0    32  9907 85295  44 12 41  3  0
21  0      0 8598708  71168 257104    0    0     0     0  9895 69090  52 11 36  0  0
22  0      0 8594316  71168 257108    0    0     0     0  9885 68336  53 12 35  0  0
31  0      0 8589564  71168 257124    0    0     0     0 10355 82218  44 13 43  0  0

Il n'est pas non plus lié au réseau. Même si je désactive l'envoi de données à l'hôte distant et que toutes les communications se font à l'intérieur de la machine, je vois toujours 55-65%.

La configuration pour docker et compose sont par défaut, rien n'a été modifié.

Pourquoi ne puis-je pas saturer les processeurs lorsqu'il est exécuté dans Docker ? Y a-t-il une limite cachée dans Docker ? Comment puis-je découvrir cette limite ?

EDIT1 CPU set, CPU shares

cpuset_cpus:0,1,2,3,4,5,6,7 et/ou cpu_shares: 102400 (100 fois la valeur par défaut) ne semble pas changer la situation.

Il n'y a rien d'intéressant non plus concernant les limitations dans /var/log/*

EDIT2 pont/réseau hôte

Ce n'est pas non plus le docker bridge réseau. L'effet est le même lorsque j'utilise net: host dans Docker Compose

Échelle EDIT3

Si j'exécute un deuxième conteneur avec le même code mais avec un port différent exposé, je peux faire monter la charge du processeur à 77 %, mais pas encore à 100 % comme sur une machine nue. Notez que chacun de ces conteneurs exécute 20-40 processus équilibrés en charge avec Passenger à l'intérieur.

EDIT4 Le problème d'Ubuntu ?

Ok, ça semble avoir quelque chose à voir avec Ubuntu. Le même conteneur a été exécuté sur CoreOS - je suis capable de saturer tous les cœurs.

htop core os

Mais je ne comprends toujours pas la limitation.

EDIT5 Test de DigitalOcean

Pour être tout à fait juste, j'ai pris 2 instances identiques de 16GB 8CPU sur DigitalOcean, toutes deux dans le centre de données de Francfort. J'ai installé l'application sur la version la plus récente d'Ubuntu et la plus récente de CoreOS alpha.

CoreOS 949.0.0: Docker version 1.10.0, build e21da33
Ubuntu 14.04.3: Docker version 1.10.0, build 590d5108

Je ne suis pas sûr de savoir comment obtenir exactement les mêmes builds - il semble que CoreOS ait Docker intégré et FS en lecture seule et avec Ubuntu - je n'ai aucune idée de comment obtenir exactement le build e21da33. Mais la version générale est la même 1.10.0

Je cours ab à partir d'une machine externe sur DigitalOcean également dans le centre de données de Francfort pour s'assurer que ab n'est pas une variation. J'ai touché l'IP externe dans les deux cas. Les paramètres de ab sont les mêmes ( ab -n 40000 -c 1000 -k ), le code est le même.

Les résultats :

 Ubuntu:   58-60% CPU    1162.22 [#/sec] (mean)
 CoreOS:     100% CPU    4440.45 [#/sec] (mean)

Ça commence à devenir vraiment bizarre. htop comparison

Pour donner une chance à Ubuntu, j'ai aussi essayé d'ajouter :

  security_opt:
     - apparmor:unconfined

Mais cela n'a pas changé grand-chose.

EDIT6 Testé le conteneur sous d'autres OS :

Ubuntu 14.04.3   NOT OK (50-60% CPU)
Ubuntu 15.10     NOT OK (50-60% CPU)
Debian 8.3       NOT OK (50-60% CPU)
CentOS 7.2.1511      OK   (100% CPU)
CoreOS 949.0.0       OK   (100% CPU)

Je n'ai toujours aucune idée de la limitation. Il semble que ce soit lié à Debian.

0 votes

Comme vous avez 4 Cpus, je suppose que vous lancez votre conteneur docker avec docker run --cpu 4 n'est-ce pas ?

0 votes

Je le lance avec docker-compose up -d - Je ne suis pas sûr de ce qu'il fait à l'intérieur. Je vais essayer de le vérifier. Merci.

0 votes

Il semble qu'il n'y ait pas de telle option dans docker run seulement ceux-là : --cpu-shares , --cpu-period , --cpu-quota , --cpuset-cpus , --cpuset-mems

8voto

PaulG Points 303

S'il vous plaît, ne vous excitez pas (ou ne m'envoyez pas de flammes) - ce n'est pas le site réponse - J'ai juste besoin de plus d'espace qu'un commentaire ne le permet ! Je ne suis pas un expert de Linux ou de Docker mais j'aime vraiment ce genre de problème et j'ai fait quelques recherches pendant le week-end et j'ai quelques pistes à explorer qui pourraient m'aider. Je n'ai pas de banc d'essai et je suis donc dans une impasse.

Théories jusqu'à présent "Pour Debian et Ubuntu..." :

  1. Docker place les conteneurs et les sous-processus dans un cgroup qui est qui est étranglé d'une certaine façon.

  2. Le planificateur pour le système d'exploitation et le planificateur au sein de Docker Docker (systemd ?) sont en quelque sorte en train de se " battre " pour le CPU et et se déplacent constamment l'un l'autre.

  3. L'ordonnanceur du système d'exploitation traite (a) le conteneur Docker et (b) le système de gestion de l'information. l'application à l'intérieur comme des demandes de ressources concurrentes et donc donne à chacun environ 50% de

  4. Il me semble que les versions RedHat de Linux ont en quelque sorte intégré " Docker (lire " regardé ce qu'il fait et modifié la configuration de leur configuration du système d'exploitation ou de Docker pour être compatible"). Qu'ont-ils changé pour faire ça ? - C'est peut-être ce qui fait la différence.

  5. Il y a une forte tendance à ne pas utiliser Docker sous RHEL 6 mais plutôt à utiliser RHEL 7+. RHEL 7+ - Qu'ont-ils changé dans RH entre ces versions ? Qu'ont-ils changé dans RH entre ces versions en ce qui concerne l'ordonnancement du CPU qui les rend si désireux d'utiliser 7+ ?

Ce que je regarderais ensuite :

  • cgroup setup en cours d'exécution.
  • Contenu de tout fichier limits.conf
  • Différences dans les fichiers de configuration de Docker entre la version sur RH et Ubuntu.
  • (Si j'avais le temps) voir si Docker sur RHEL 6 avait le problème (comme RHEL 7 n'en a pas)

Recherche : https://goldmann.pl/blog/2014/09/11/resource-management-in-docker/
http://www.janoszen.com/2013/02/06/limiting-linux-processes-cgroups-explained/
https://github.com/docker/docker/issues/6791
https://github.com/ibuildthecloud/systemd-docker/issues/15
https://unix.stackexchange.com/questions/151883/limiting-processes-to-not-exceed-more-than-10-of-cpu-usage
http://linux.die.net/man/5/limits.conf
https://marketplace.automic.com/details/centos-official-docker-image
https://www.datadoghq.com/blog/how-to-monitor-docker-resource-metrics/
https://libraries.io/go/github.com%2Fintelsdi-x%2Fsnap-plugin-collector-docker%2Fdocker
https://serverfault.com/questions/356962/where-are-the-default-ulimit-values-set-linux-centos
https://www.centos.org/forums/viewtopic.php?t=8956
https://docs.mongodb.org/manual/reference/ulimit/
http://www.unixarena.com/2013/12/how-to-increase-ulimit-values-in-redhat.html

Si rien de tout cela ne vous aide, je m'excuse !

0 votes

C'est au moins un bon domaine de recherche :) Merci, je vais essayer d'y jeter un œil :)

0 votes

Merci pour les représentants. J'espère que quelque chose là-dedans aidera. J'ai oublié de dire que j'aime ce genre de problème. sauf quand j'ai ce genre de problème et une date limite ! Bonne chance.

2voto

gnou Points 561

Démarrer Docker avec systemd a réglé ce problème pour moi (Unbuntu 16.04). Mes 12 threads sont tous utilisés à 100% dans un seul conteneur lors de l'évaluation.

Arrêtez le service Docker :

sudo service docker stop

Et le démarrer avec systemctl :

sudo systemctl start docker

Pour démarrer Docker au démarrage :

sudo systemctl enable docker

0voto

p7r Points 237

Nous avons eu le même problème, nous avons commencé à plonger et avons trouvé ceci : https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt

Vous pouvez spécifier --cpu-quota à Docker, et vous voulez qu'il corresponde au nombre de processeurs que vous souhaitez utiliser.

Par exemple, si vous souhaitez que le conteneur puisse utiliser 4 processeurs, vous devez le définir comme suit 400000 ; si vous voulez qu'il soit complètement libéré, spécifiez -1 .

Ça a marché pour nous.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X