Causa da fragmentação da página no servidor “grande” com xfs, 20 discos e Ceph

18

Qualquer visão de alguém com um pouco de experiência no sistema Linux IO seria útil. Aqui está a minha história:

Recentemente, criou um cluster de seis Dell PowerEdge rx720xds para servir arquivos via Ceph. Essas máquinas têm 24 núcleos em dois soquetes com duas zonas numa e 70 gigabytes ímpares de memória. Os discos são formatados como invasões de um disco cada (não foi possível ver uma maneira de expô-los diretamente caso contrário). A rede é fornecida pelo mellanox infiniband IP over IB (os pacotes IP são transformados em IB no país do kernel, não no hardware).

Cada uma de nossas unidades SAS é montada da seguinte maneira:

# 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

O IO passando por essas máquinas explode a algumas centenas de MB / s, mas na maioria das vezes é bastante inativo com muitos pequenos 'puxões':

# 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

O problema:

Após cerca de 48 horas depois, as páginas contíguas ficam tão fragmentadas que as alocações magnéticas de quatro (16 páginas, 65536 bytes) começam a falhar e começamos a soltar pacotes (devido à falha do kalloc quando um SLAB é aumentado).

É assim que um servidor relativamente "íntegro" se parece:

# 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 

Quando a fragmentação fica consideravelmente pior, o sistema parece começar a girar no espaço do kernel e tudo simplesmente desmorona. Uma anomalia durante essa falha é que o xfsaild parece usar muita CPU e fica preso no estado de suspensão ininterrupta. Eu não quero tirar conclusões precipitadas durante a falha total do sistema.

Solução alternativa até o momento.

Para garantir que essas alocações não falhem, mesmo sob fragmentação, defino:

vm.min_free_kbytes = 16777216

Depois de ver milhões de blkdev_requests em caches SLAB, tentei reduzir páginas sujas via:

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

Possivelmente alterando muitas variáveis ​​de uma só vez, mas, caso os inodes e dentries estivessem causando fragmentação, decidi mantê-las no mínimo:

vm.vfs_cache_pressure = 10000

E isso pareceu ajudar. A fragmentação ainda é alta, e os problemas reduzidos de inode e dentaria significavam que eu notei algo estranho que me leva a ...

Minha pergunta:

Por que tenho tantos blkdev_requests (ativos menos) que desaparecem quando eu solto caches?

Aqui está o que eu quero dizer:

# 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           

Isso me diz que o acúmulo de blkdev_request não está de fato relacionado a páginas sujas e, além disso, que os objetos ativos não estão realmente ativos? Como esses objetos podem ser liberados se não estão de fato em uso? O que está acontecendo aqui?

Para alguns antecedentes, aqui está o que o drop_caches está fazendo:

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

Atualizar:

Descobriu que eles podem não ser blkdev_requests, mas podem ser entradas xfs_buf aparecendo sob esse 'cabeçalho'? Não sabe ao certo como isso funciona:

/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/

Ainda não sei por que eles são limpos pelo 'drop_slabs' ou como descobrir o que está causando essa fragmentação.

Pergunta de bônus: Qual é a melhor maneira de chegar à fonte dessa fragmentação?

Se você leu até aqui, obrigado por sua atenção!

Informações adicionais solicitadas:

Informações sobre memória e xfs: https://gist.github.com/christian-marie/f417cc3134544544a8d1

Falha na alocação de página: https://gist.github.com/christian-marie/7bc845d2da7847534104

Acompanhamento: informações sobre perf e coisas relacionadas à compactação

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

Código de compactação parece um pouco ineficiente, hein? Reuni alguns códigos juntos para tentar replicar as compacações com falha: https://gist.github.com/christian-marie/cde7e80c5edb889da541

Isso parece reproduzir o problema.

Também observarei que um rastreamento de evento me diz que há muitas recuperações com falha, repetidas vezes:

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

A saída Vmstat também é preocupante. Enquanto o sistema está nesse estado de alta carga, as compactação estão passando pelo telhado (e principalmente falhando):

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

De fato, há algo errado com a recuperação / compactação.

No momento, pretendo reduzir as alocações de pedidos altos, adicionando suporte SG à nossa configuração ipoib. O problema real parece provável relacionado ao vmscan.

Isso é interessante e faz referência a esta pergunta: http://marc.info/?l=linux-mm&m=141607142529562&w=2

pingu
fonte
2
Heck yeah !! Não recebemos muitas dessas boas perguntas. Vou ver o que podemos fazer, no entanto.
ewwhite
11
Por favor, você pode fornecer a saída /proc/buddyinfoe os resultados de free -m? As solicitações blockdev provavelmente são representadas como buffers em free. Ah, e a distribuição que você está usando também seria boa. Além disso, você tem alguma page allocation failuremensagem aparecendo dmesg? Se sim, forneça a saída mais qualquer contexto relevante.
Matthew Ife
11
Além disso, você usou uma mkfs.xfslinha de comando específica ? Páginas enormes ativadas?
ewwhite
Também a saída de/proc/meminfo
Matthew Ife
Tentando desativar grandes páginas transparentes por conta própria (configurando-as para nunca), a falha ainda ocorreu. Não tentei isso em conjunto com outras 'correções'.
pingu

Respostas:

4

Pensei em responder às minhas observações porque há muitos comentários.

Baseado em sua saída em https://gist.github.com/christian-marie/7bc845d2da7847534104

Podemos determinar o seguinte:

  1. O GFP_MASK da alocação de memória tentada pode fazer o seguinte.
    • Pode acessar pools de emergência ( acho que isso significa acessar dados abaixo da marca d'água alta para uma zona)
    • Não use reservas de emergência ( acho que isso significa não permitir acesso a memroy abaixo da marca d'água mínima)
    • Aloque de uma das zonas normais.
    • Pode trocar para dar espaço.
    • Pode soltar caches para liberar espaço.

A fragmentação da zona está localizada aqui:

[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

E a utilização da memória no momento está aqui:

[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

A fragmentação de cada zona é ruim na saída da falha de alocação de página. Existem muitas páginas gratuitas para pedidos 0 e muito menos para páginas de pedidos superiores. Um resultado "bom" será o número de páginas gratuitas abundantes em cada pedido, diminuindo gradualmente o tamanho, quanto maior o pedido. Ter 0 páginas de ordem alta 5 e acima indica fragmentação e falta de fome para alocações de ordem alta.

Atualmente, não estou vendo um grau convincente de evidência para sugerir que a fragmentação durante esse período tenha algo a ver com caches de laje. Nas estatísticas de memória resultantes, podemos ver o seguinte

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

Não há páginas enormes atribuídas no espaço do usuário, e o espaço do usuário sempre reivindicará a memória da ordem 0. Portanto, em ambas as zonas, há mais de 22 GiB de memória desfragmentável.

Comportamentos que não posso explicar

Quando as alocações de alta ordem falham, entendo que a compactação de memória é sempre tentada para permitir que regiões de alocação de memória de alta ordem ocorram e sejam bem-sucedidas. Por que isso não acontece? Se isso acontecer, por que não consegue encontrar nenhuma memória para desfragmentar quando há 22GiB dela pronta para reordenar?

Comportamentos que eu acho que posso explicar

Isso precisa de mais pesquisas para entender corretamente, mas acredito que a capacidade da alocação de trocar / descartar automaticamente alguns pagecache para obter êxito provavelmente não se aplica aqui, porque ainda há muita memória livre disponível, portanto, nenhuma recuperação ocorre. Apenas não é suficiente nas ordens mais altas.

Embora exista muita memória livre e poucas solicitações de pedidos em cada zona, o problema "total de memória livre total para cada pedido e deduzido da memória livre real" resulta em uma 'memória livre' abaixo da marca d'água 'min', que é o que leva à falha de alocação real.

Matthew Ife
fonte
Parece estranho que um cache SLAB pequeno (relativamente à memória livre total) fragmente todas as memórias. Eu esperava que, com todas aquelas páginas gratuitas e evitáveis, ela simplesmente expulsasse algumas e acabasse com ela. Suspeito que a NUMA possa ter algo a ver com essa estranheza.
Pinguim8
Está numadsendo executado neste sistema?
ewwhite
@ewwhite numad não está funcionando, não.
pingu
@pingu Se esse comportamento for reprodutível, tente ativar o numadserviço e tome nota das ações em /var/log/numad.log. Você também pode precisar do libcgroup instalado.
ewwhite
@whwhite Ok, eu tenho um funcionando agora. Não sei ao certo o que espero que faça ou que informações possamos obter dele. O que você espera que aconteça?
pingu