Cause de la fragmentation des pages sur un «grand» serveur avec xfs, 20 disques et Ceph

18

Toute idée de quelqu'un ayant un peu d'expérience dans le système Linux IO serait utile. Voici mon histoire:

Récemment mis en place un cluster de six Dell PowerEdge rx720xds pour servir des fichiers via Ceph. Ces machines ont 24 cœurs sur deux sockets avec deux zones numa et 70 gigaoctets impairs de mémoire. Les disques sont formatés comme des raids d'un disque chacun (nous ne pouvions pas voir un moyen de les exposer directement autrement). La mise en réseau est assurée par mellanox infiniband IP sur IB (les paquets IP sont transformés en IB dans le noyau, pas en matériel).

Nous avons chacun de nos disques SAS montés comme suit:

# cat /proc/mounts | grep osd
/dev/sdm1 /var/lib/ceph/osd/ceph-90 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdj1 /var/lib/ceph/osd/ceph-87 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdu1 /var/lib/ceph/osd/ceph-99 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdd1 /var/lib/ceph/osd/ceph-82 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdk1 /var/lib/ceph/osd/ceph-88 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdl1 /var/lib/ceph/osd/ceph-89 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdh1 /var/lib/ceph/osd/ceph-86 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdo1 /var/lib/ceph/osd/ceph-97 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdc1 /var/lib/ceph/osd/ceph-81 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdb1 /var/lib/ceph/osd/ceph-80 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sds1 /var/lib/ceph/osd/ceph-98 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdn1 /var/lib/ceph/osd/ceph-91 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sde1 /var/lib/ceph/osd/ceph-83 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdq1 /var/lib/ceph/osd/ceph-93 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdg1 /var/lib/ceph/osd/ceph-85 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdt1 /var/lib/ceph/osd/ceph-95 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdf1 /var/lib/ceph/osd/ceph-84 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdr1 /var/lib/ceph/osd/ceph-94 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdi1 /var/lib/ceph/osd/ceph-96 xfs rw,noatime,attr2,inode64,noquota 0 0
/dev/sdp1 /var/lib/ceph/osd/ceph-92 xfs rw,noatime,attr2,inode64,noquota 0 0

L'IO passant par ces machines éclate à quelques centaines de Mo / s, mais la plupart du temps est assez inactif avec beaucoup de petits `` pokes '':

# iostat -x -m
Linux 3.10.0-123.el7.x86_64 (xxx)   07/11/14    _x86_64_    (24 CPU)

avg-cpu:  %user   %nice %system %iowait  %steal   %idle
       1.82    0.00    1.05    0.11    0.00   97.02
Device:         rrqm/s   wrqm/s     r/s     w/s    rMB/s    wMB/s avgrq-sz avgqu-sz   await r_await w_await  svctm  %util
sda               0.00     0.11    0.25    0.23     0.00     0.00    27.00     0.00    2.07    3.84    0.12   0.61   0.03
sdb               0.02     0.57    3.49    2.28     0.08     0.14    77.18     0.01    2.27    2.99    1.18   1.75   1.01
sdd               0.03     0.65    3.93    3.39     0.10     0.16    70.39     0.01    1.97    2.99    0.79   1.57   1.15
sdc               0.03     0.60    3.76    2.86     0.09     0.13    65.57     0.01    2.10    3.02    0.88   1.68   1.11
sdf               0.03     0.63    4.19    2.96     0.10     0.15    73.51     0.02    2.16    3.03    0.94   1.73   1.24
sdg               0.03     0.62    3.93    3.01     0.09     0.15    70.44     0.01    2.06    3.01    0.81   1.66   1.15
sde               0.03     0.56    4.35    2.61     0.10     0.14    69.53     0.02    2.26    3.00    1.02   1.82   1.26
sdj               0.02     0.73    3.67    4.74     0.10     0.37   116.06     0.02    1.84    3.01    0.93   1.31   1.10
sdh               0.03     0.62    4.31    3.04     0.10     0.15    67.83     0.02    2.15    3.04    0.89   1.75   1.29
sdi               0.02     0.59    3.82    2.47     0.09     0.13    74.35     0.01    2.20    2.96    1.03   1.76   1.10
sdl               0.03     0.59    4.75    2.46     0.11     0.14    70.19     0.02    2.33    3.02    1.00   1.93   1.39
sdk               0.02     0.57    3.66    2.41     0.09     0.13    73.57     0.01    2.20    3.00    0.97   1.76   1.07
sdm               0.03     0.66    4.03    3.17     0.09     0.14    66.13     0.01    2.02    3.00    0.78   1.64   1.18
sdn               0.03     0.62    4.70    3.00     0.11     0.16    71.63     0.02    2.25    3.01    1.05   1.79   1.38
sdo               0.02     0.62    3.75    2.48     0.10     0.13    76.01     0.01    2.16    2.94    0.99   1.70   1.06
sdp               0.03     0.62    5.03    2.50     0.11     0.15    68.65     0.02    2.39    3.08    0.99   1.99   1.50
sdq               0.03     0.53    4.46    2.08     0.09     0.12    67.74     0.02    2.42    3.04    1.09   2.01   1.32
sdr               0.03     0.57    4.21    2.31     0.09     0.14    72.05     0.02    2.35    3.00    1.16   1.89   1.23
sdt               0.03     0.66    4.78    5.13     0.10     0.20    61.78     0.02    1.90    3.10    0.79   1.49   1.47
sdu               0.03     0.55    3.93    2.42     0.09     0.13    70.77     0.01    2.17    2.97    0.85   1.79   1.14
sds               0.03     0.60    4.11    2.70     0.10     0.15    74.77     0.02    2.25    3.01    1.10   1.76   1.20
sdw               1.53     0.00    0.23   38.90     0.00     1.66    87.01     0.01    0.22    0.11    0.22   0.05   0.20
sdv               0.88     0.00    0.16   28.75     0.00     1.19    84.55     0.01    0.24    0.10    0.24   0.05   0.14
dm-0              0.00     0.00    0.00    0.00     0.00     0.00     8.00     0.00    1.84    1.84    0.00   1.15   0.00
dm-1              0.00     0.00    0.23    0.29     0.00     0.00    23.78     0.00    1.87    4.06    0.12   0.55   0.03
dm-2              0.00     0.00    0.01    0.00     0.00     0.00     8.00     0.00    0.47    0.47    0.00   0.45   0.00

Le problème:

Après environ 48 heures plus tard, les pages contiguës sont si fragmentées que quatre allocations (16 pages, 65536 octets) commencent à échouer et nous commençons à supprimer des paquets (en raison de l'échec de kalloc lors de la croissance d'une SLAB).

Voici à quoi ressemble un serveur relativement "sain":

# cat /sys/kernel/debug/extfrag/unusable_index
Node 0, zone      DMA 0.000 0.000 0.000 0.001 0.003 0.007 0.015 0.031 0.031 0.096 0.225 
Node 0, zone    DMA32 0.000 0.009 0.015 0.296 0.733 0.996 0.997 0.998 0.998 1.000 1.000 
Node 0, zone   Normal 0.000 0.000 0.019 0.212 0.454 0.667 0.804 0.903 0.986 1.000 1.000 
Node 1, zone   Normal 0.000 0.027 0.040 0.044 0.071 0.270 0.506 0.772 1.000 1.000 1.000 

Lorsque la fragmentation s'aggrave considérablement, le système semble commencer à tourner dans l'espace du noyau et tout s'écroule. Une anomalie lors de cet échec est que xfsaild semble utiliser beaucoup de CPU et reste bloqué dans l'état de veille sans interruption. Cependant, je ne veux pas tirer de conclusions étranges lors d'une panne totale du système.

Solution de contournement jusqu'à présent.

Afin de garantir que ces allocations n'échouent pas, même en cas de fragmentation, j'ai défini:

vm.min_free_kbytes = 16777216

Après avoir vu des millions de blkdev_requests dans les caches SLAB, j'ai essayé de réduire les pages sales via:

vm.dirty_ratio = 1
vm.dirty_background_ratio = 1
vm.min_slab_ratio = 1
vm.zone_reclaim_mode = 3

Peut-être en changeant trop de variables à la fois, mais juste au cas où les inodes et les dentiers provoquaient une fragmentation, j'ai décidé de les garder au minimum:

vm.vfs_cache_pressure = 10000

Et cela semblait aider. Cependant, la fragmentation est toujours élevée, et la réduction des problèmes d'inode et de dentisterie a fait que j'ai remarqué quelque chose de bizarre qui m'amène à ...

Ma question:

Pourquoi est-ce que j'ai autant de blkdev_requests (qui ne sont pas moins actifs), qui disparaissent juste quand je laisse des caches?

Voici ce que je veux dire:

# slabtop -o -s c | head -20
 Active / Total Objects (% used)    : 19362505 / 19431176 (99.6%)
 Active / Total Slabs (% used)      : 452161 / 452161 (100.0%)
 Active / Total Caches (% used)     : 72 / 100 (72.0%)
 Active / Total Size (% used)       : 5897855.81K / 5925572.61K (99.5%)
 Minimum / Average / Maximum Object : 0.01K / 0.30K / 15.69K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
2565024 2565017  99%    1.00K  80157       32   2565024K xfs_inode              
3295194 3295194 100%    0.38K  78457       42   1255312K blkdev_requests        
3428838 3399527  99%    0.19K  81639       42    653112K dentry                 
5681088 5680492  99%    0.06K  88767       64    355068K kmalloc-64             
2901366 2897861  99%    0.10K  74394       39    297576K buffer_head            
 34148  34111  99%    8.00K   8537        4    273184K kmalloc-8192           
334768 334711  99%    0.57K  11956       28    191296K radix_tree_node        
614959 614959 100%    0.15K  11603       53     92824K xfs_ili                
 21263  19538  91%    2.84K   1933       11     61856K task_struct            
 18720  18636  99%    2.00K   1170       16     37440K kmalloc-2048           
 32032  25326  79%    1.00K   1001       32     32032K kmalloc-1024           
 10234   9202  89%    1.88K    602       17     19264K TCP                    
 22152  19765  89%    0.81K    568       39     18176K task_xstate

# echo 2 > /proc/sys/vm/drop_caches                                                                                                                                                   :(
# slabtop -o -s c | head -20       
 Active / Total Objects (% used)    : 965742 / 2593182 (37.2%)
 Active / Total Slabs (% used)      : 69451 / 69451 (100.0%)
 Active / Total Caches (% used)     : 72 / 100 (72.0%)
 Active / Total Size (% used)       : 551271.96K / 855029.41K (64.5%)
 Minimum / Average / Maximum Object : 0.01K / 0.33K / 15.69K

  OBJS ACTIVE  USE OBJ SIZE  SLABS OBJ/SLAB CACHE SIZE NAME                   
 34140  34115  99%    8.00K   8535        4    273120K kmalloc-8192           
143444  20166  14%    0.57K   5123       28     81968K radix_tree_node        
768729 224574  29%    0.10K  19711       39     78844K buffer_head            
 73280   8287  11%    1.00K   2290       32     73280K xfs_inode              
 21263  19529  91%    2.84K   1933       11     61856K task_struct            
686848  97798  14%    0.06K  10732       64     42928K kmalloc-64             
223902  41010  18%    0.19K   5331       42     42648K dentry                 
 32032  23282  72%    1.00K   1001       32     32032K kmalloc-1024           
 10234   9211  90%    1.88K    602       17     19264K TCP                    
 22152  19924  89%    0.81K    568       39     18176K task_xstate            
 69216  59714  86%    0.25K   2163       32     17304K kmalloc-256            
 98421  23541  23%    0.15K   1857       53     14856K xfs_ili                
  5600   2915  52%    2.00K    350       16     11200K kmalloc-2048           

Cela me dit que l'accumulation blkdev_request est pas en fait liées aux pages sales, et en outre que les objets actifs ne sont pas vraiment actifs? Comment libérer ces objets s'ils ne sont pas réellement utilisés? Qu'est-ce qui se passe ici?

Pour quelques informations, voici ce que font les drop_caches:

http://lxr.free-electrons.com/source/fs/drop_caches.c

Mise à jour:

Vous avez compris qu'il ne s'agissait peut-être pas de blkdev_requests, mais qu'il pouvait s'agir d'entrées xfs_buf apparaissant sous cette «rubrique»? Je ne suis pas sûr de comment cela fonctionne:

/sys/kernel/slab # ls -l blkdev_requests(
lrwxrwxrwx 1 root root 0 Nov  7 23:18 blkdev_requests -> :t-0000384/

/sys/kernel/slab # ls -l | grep 384
lrwxrwxrwx 1 root root 0 Nov  7 23:18 blkdev_requests -> :t-0000384/
lrwxrwxrwx 1 root root 0 Nov  7 23:19 ip6_dst_cache -> :t-0000384/
drwxr-xr-x 2 root root 0 Nov  7 23:18 :t-0000384/
lrwxrwxrwx 1 root root 0 Nov  7 23:19 xfs_buf -> :t-0000384/

Je ne sais toujours pas pourquoi ceux-ci sont effacés par les «drop_slabs», ni comment déterminer la cause de cette fragmentation.

Question bonus: Quelle est la meilleure façon de trouver la source de cette fragmentation?

Si vous lisez jusqu'ici, merci de votre attention!

Informations supplémentaires demandées:

Informations sur la mémoire et xfs: https://gist.github.com/christian-marie/f417cc3134544544a8d1

Échec d'allocation de page: https://gist.github.com/christian-marie/7bc845d2da7847534104

Suivi: informations sur la perf et choses liées au compactage

http://ponies.io/raw/compaction.png

Le code de compactage semble un peu inefficace hein? J'ai bricolé du code ensemble pour tenter de répliquer les compactions ayant échoué: https://gist.github.com/christian-marie/cde7e80c5edb889da541

Cela semble reproduire le problème.

Je noterai également qu'une trace d'événement me dit qu'il y a beaucoup de récupérations échouées, encore et encore:

<...>-322 [023] .... 19509.445609: mm_vmscan_direct_reclaim_end: nr_reclaimed=1

La sortie Vmstat est également préoccupante. Alors que le système est dans cet état de charge élevée, les compactages passent par le toit (et échouent principalement):

pgmigrate_success 38760827 pgmigrate_fail 350700119 compact_migrate_scanned 301784730 compact_free_scanned 204838172846 compact_isolated 18711615 compact_stall 270115 compact_fail 244488 compact_success 25212

Il y a en effet quelque chose de mal avec la récupération / le compactage.

En ce moment, je cherche à réduire les allocations de commandes élevées en ajoutant la prise en charge SG à notre configuration ipoib. Le vrai problème semble probablement lié à vmscan.

Ceci est intéressant et fait référence à cette question: http://marc.info/?l=linux-mm&m=141607142529562&w=2

pingu
la source
2
Zut ouais !! Nous ne recevons pas beaucoup de ces bonnes questions. Je verrai cependant ce que nous pouvons faire.
ewwhite
1
Pouvez-vous fournir la sortie /proc/buddyinfoet les résultats de free -m? Les requêtes blockdev sont probablement représentées comme des tampons dans free. Oh, et la distribution que vous utilisez serait bien aussi. De plus, des page allocation failuremessages apparaissent-ils dans dmesg? Dans l'affirmative, veuillez fournir la sortie ainsi que tout contexte pertinent.
Matthew Ife
1
De plus, avez-vous utilisé une mkfs.xfsligne de commande spécifique ? Hugepages activé?
ewwhite
Aussi la sortie de/proc/meminfo
Matthew Ife
J'ai essayé de désactiver les pages géantes transparentes par elles-mêmes (en les réglant sur jamais), l'échec s'est toujours produit. N'a pas essayé cela en conjonction avec d'autres «correctifs».
pingu

Réponses:

4

J'ai pensé mettre une réponse avec mes observations car il y a beaucoup de commentaires.

Basé sur votre sortie sur https://gist.github.com/christian-marie/7bc845d2da7847534104

Nous pouvons déterminer les éléments suivants:

  1. Le GFP_MASK pour l'allocation de mémoire essayée est autorisé à effectuer les opérations suivantes.
    • Peut accéder aux piscines d'urgence (je pense que cela signifie accéder aux données en dessous du filigrane élevé pour une zone)
    • Ne pas utiliser les réserves d'urgence (je pense que cela signifie ne pas autoriser l'accès à memroy en dessous du filigrane min)
    • Attribuer à partir d'une des zones normales.
    • Peut échanger pour faire de la place.
    • Peut déposer des caches pour faire de la place.

La fragmentation de zone se trouve ici:

[3443189.780792] Node 0 Normal: 3300*4kB (UEM) 8396*8kB (UEM) 4218*16kB (UEM) 76*32kB (UEM) 12*64kB (M) 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 151056kB
[3443189.780801] Node 1 Normal: 26667*4kB (UEM) 6084*8kB (UEM) 2040*16kB (UEM) 96*32kB (UEM) 22*64kB (UEM) 4*128kB (U) 0*256kB 0*512kB 0*1024kB 0*2048kB 0*4096kB = 192972kB

Et l'utilisation de la mémoire à l'époque est ici:

[3443189.780759] Node 0 Normal free:149520kB min:40952kB low:51188kB high:61428kB active_anon:9694208kB inactive_anon:1054236kB active_file:7065912kB inactive_file:7172412kB unevictable:0kB isolated(anon):5452kB isolated(file):3616kB present:30408704kB managed:29881160kB mlocked:0kB dirty:0kB writeback:0kB mapped:25440kB shmem:743788kB slab_reclaimable:1362240kB slab_unreclaimable:783096kB kernel_stack:29488kB pagetables:43748kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no
[3443189.780766] Node 1 Normal free:191444kB min:45264kB low:56580kB high:67896kB active_anon:11371988kB inactive_anon:1172444kB active_file:8084140kB inactive_file:8556980kB unevictable:0kB isolated(anon):4388kB isolated(file):4676kB present:33554432kB managed:33026648kB mlocked:0kB dirty:0kB writeback:0kB mapped:45400kB shmem:2263296kB slab_reclaimable:1606604kB slab_unreclaimable:438220kB kernel_stack:55936kB pagetables:44944kB unstable:0kB bounce:0kB free_cma:0kB writeback_tmp:0kB pages_scanned:0 all_unreclaimable? no

La fragmentation de chaque zone est mauvaise dans la sortie d'échec d'allocation de page. Il y a beaucoup de pages de commande gratuite 0 avec beaucoup moins de pages d'ordre nul. Un «bon» résultat sera de nombreuses pages gratuites le long de chaque commande, diminuant progressivement en taille à mesure que vous augmentez la commande. Le fait d'avoir 0 pages de haut niveau 5 et plus indique la fragmentation et la famine pour les allocations de haut niveau.

Je ne vois actuellement pas de degré de preuve convaincant suggérant que la fragmentation au cours de cette période est liée aux caches de dalles. Dans les statistiques de mémoire résultantes, nous pouvons voir ce qui suit

Node 0 = active_anon:9694208kB inactive_anon:1054236kB
Node 1 = active anon:11371988kB inactive_anon:1172444kB

Il n'y a pas d'énormes pages attribuées à partir de l'espace utilisateur, et l'espace utilisateur réclamera donc toujours la mémoire d'ordre 0. Ainsi, dans les deux zones, il y a plus de 22 Go de mémoire défragmentable.

Comportements que je ne peux expliquer

Lorsque les allocations d'ordre élevé échouent, je crois comprendre que le compactage de la mémoire est toujours tenté afin de permettre aux régions d'allocation de mémoire d'ordre élevé d'avoir lieu et de réussir. Pourquoi cela ne se produit-il pas? Si cela se produit, pourquoi ne peut-il pas trouver de mémoire à défragmenter alors qu'il y en a 22 Go mûrs pour une réorganisation?

Comportements que je pense pouvoir expliquer

Cela nécessite plus de recherches pour bien comprendre, mais je pense que la capacité de l'allocation de permuter / supprimer automatiquement un cache de page pour réussir ne s'applique probablement pas ici car il y a beaucoup de mémoire libre encore disponible, donc aucune récupération ne se produit. Pas assez dans les ordres supérieurs.

Bien qu'il y ait beaucoup de mémoire libre et quelques commandes d'ordre 4 restantes dans chaque zone, le problème "total de toute la mémoire libre pour chaque commande et déduire de la mémoire réelle réelle" entraîne une "mémoire libre" sous le filigrane "min" qui est ce qui conduit à l'échec réel de l'allocation.

Matthew Ife
la source
Il semble étrange qu'un petit cache SLAB relativement (à la mémoire totale libre) fragmente toutes les mémoires. Je m'attendais à ce qu'avec toutes ces pages évictibles gratuites, il en expulse simplement certaines et soit terminé. Je soupçonne que NUMA pourrait avoir quelque chose à voir avec cette bizarrerie.
pingu
Est en numadcours d' exécution sur ce système?
ewwhite
@ewwhite numad n'est pas en cours d'exécution, non.
pingu
@pingu Si ce comportement est reproductible, essayez d'activer le numadservice et notez les actions dans /var/log/numad.log. Vous devrez peut-être également installer libcgroup.
ewwhite
@ewwhite D'accord, j'en ai un en cours d'exécution maintenant. Je ne sais pas ce que j'attends de lui ou quelles informations nous pourrions en tirer. Qu'espérez-vous qu'il puisse arriver?
pingu