web-dev-qa-db-fra.com

Bibliothèque partagée dans des conteneurs

Pour deux processus A et B, les deux utilisent la bibliothèque libc.so, libc.so n'est chargée en mémoire qu'une seule fois. Il s'agit d'une situation normale lorsque A et B s'exécutent tous les deux sur le même hôte et les mêmes rootfs.

En ce qui concerne le conteneur, si A et B s'exécutent dans des conteneurs différents, A et B partagent-ils la même zone de mémoire?

par exemple

imageA

--libc.so

--programA

imageB

--libc.so

--programB

nous utilisons chroot pour exécuter A et B dans différents rootfs. Les deux libc.so sont identiques. Libc.so sera-t-il chargé en mémoire deux fois?

22
Xinli Niu

En fait, les processus A et B qui utilisent une bibliothèque partagée libc.so can partagent la même mémoire. De manière peu intuitive, cela dépend du pilote de stockage Docker que vous utilisez. Si vous utilisez un pilote de stockage qui peut exposer les fichiers de bibliothèque partagée comme provenant du même périphérique/inode lorsqu'ils résident dans la même couche Docker, ils partageront les mêmes pages de cache de mémoire virtuelle. Lorsque vous utilisez les pilotes de stockage aufs, overlay ou overlay2, vos bibliothèques partagées partageront la mémoire, mais lors de l'utilisation des autres pilotes de stockage, elles ne le feront pas.

Je ne sais pas pourquoi ce détail n'est pas rendu plus explicite dans la documentation Docker. Ou peut-être que c'est mais je l'ai juste raté. Cela semble être un facteur de différenciation clé si vous essayez d'exécuter des conteneurs denses.

17
Yeroc

Vous pouvez déterminer si les fichiers .so dans différents conteneurs partagent la même mémoire physique en comparant les adresses physiques des processus (/ proc/pid/pagemap) de deux conteneurs différents, comme indiqué sur l'hôte.

# ps -ef | grep Java | grep -v grep | awk '{ print $2 }'
3906
4018
# Sudo pmap -X 3906 | grep -e "Address" -e "libpthread"
     Address Perm   Offset Device     Inode    Size   Rss   Pss Referenced Anonymous LazyFree ShmemPmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked Mapping
7f97d9249000 r-xp 00000000  fd:00 135202206     104   104    52        104         0        0              0              0               0    0       0      0 libpthread-2.27.so
# Sudo pmap -X 4018 | grep -e "Address" -e "libpthread"
     Address Perm   Offset Device     Inode    Size   Rss   Pss Referenced Anonymous LazyFree ShmemPmdMapped Shared_Hugetlb Private_Hugetlb Swap SwapPss Locked Mapping
7fce739e1000 r-xp 00000000  fd:00 135202206     104   104    52        104         0        0              0              0               0    0       0      0 libpthread-2.27.so
# virt_to_phys_user 3906 0x7f97d9249000
0x59940000
# virt_to_phys_user 4018 0x7fce739e1000
0x59940000

Ici 3906 et 4018 sont des identifiants de processus sur l'hôte de deux instances d'une Java exécutée dans deux conteneurs différents. J'ai utilisé virt_to_phys_user qui est un simple programme 'c' pour vider la mémoire physique avec un pid et une mémoire virtuelle de cette lien . Notez que l'adresse physique est la même pour les deux processus ci-dessus. Notez également que les deux instances ont le même inode addr et Pss indique que ces pages sont partagées.

Cependant, comme indiqué dans la réponse précédente, ce comportement dépend du pilote de stockage utilisé. Je vois que cela fonctionne sur docker-ce sur Ubuntu 18.04 et podman sur RHEL8 (overlay2 et overlay fs respectivement), mais cela n'a pas fonctionné sur RHEL 7.5 avec devicemapper.

2
dino