Przyczyna fragmentacji strony na „dużym” serwerze z XFS, 20 dyskami i Ceph

18

Pomocny byłby wgląd kogoś, kto ma trochę doświadczenia w systemie Linux IO. Oto moja historia:

Niedawno pojawił się klaster sześciu Dell PowerEdge rx720xds do obsługi plików przez Ceph. Te maszyny mają 24 rdzenie na dwóch gniazdach z dwiema strefami num i 70 nieparzystymi gigabajtami pamięci. Dyski są formatowane jako rajdy na jeden dysk każdy (inaczej nie moglibyśmy znaleźć sposobu na ich bezpośrednie ujawnienie). Sieć zapewnia mellanox infiniband IP przez IB (pakiety IP zamieniane są w IB na ziemi jądra, a nie sprzętowo).

Każdy z naszych dysków SAS jest zamontowany w następujący sposób:

# 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

IO przechodzące przez te maszyny pęka z szybkością kilkuset MB / s, ale przez większość czasu jest dość bezczynne z wieloma małymi „zaczepkami”:

# 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

Problem:

Po około 48 godzinach później ciągłe strony są tak rozdrobnione, że powiększenie czterech (16 stron, 65536 bajtów) przydziałów zaczyna się nie powieść i zaczynamy upuszczać pakiety (z powodu awarii kalloc, gdy rośnie SLAB).

Tak wygląda względnie „zdrowy” serwer:

# 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 

Kiedy fragmentacja staje się znacznie gorsza, system zaczyna wirować w przestrzeni jądra i wszystko po prostu się rozpada. Jedną z anomalii podczas tej awarii jest to, że xfsaild wydaje się używać dużo procesora i utknie w nieprzerwanym stanie uśpienia. Nie chcę jednak wyciągać żadnych dziwnych wniosków podczas całkowitej awarii systemu.

Obejście do tej pory.

Aby zapewnić, że alokacje te nie zawiodą, nawet przy fragmentacji, ustawiam:

vm.min_free_kbytes = 16777216

Po obejrzeniu milionów buforów blkdev_requests w pamięciach podręcznych SLAB, próbowałem zmniejszyć liczbę brudnych stron poprzez:

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

Możliwe, że jednocześnie zmieniam zbyt wiele zmiennych, ale na wypadek, gdyby inody i dentraty powodowały fragmentację, postanowiłem ograniczyć je do minimum:

vm.vfs_cache_pressure = 10000

I to chyba pomogło. Fragmentacja jest jednak wciąż wysoka, a zredukowane problemy z igłami i zębami spowodowały, że zauważyłem coś dziwnego, co prowadzi mnie ...

Moje pytanie:

Dlaczego mam tak wiele żądań blkdev_request (które są nie mniej aktywne), które po prostu znikają po upuszczeniu pamięci podręcznej?

Oto co mam na myśli:

# 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           

To mówi mi, że tworzenie blkdev_request nie jest w rzeczywistości powiązane z brudnymi stronami, a ponadto, że aktywne obiekty nie są tak naprawdę aktywne? Jak można uwolnić te obiekty, jeśli w rzeczywistości nie są używane? Co tu się dzieje?

Na tle, oto co robi drop_caches:

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

Aktualizacja:

Przekonali się, że mogą to nie być blkdev_requests, ale mogą to być wpisy xfs_buf wyświetlane pod tym „nagłówkiem”? Nie jestem pewien, jak to działa:

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

Nadal nie wiem, dlaczego są one usuwane przez „drop_slabs”, ani jak dowiedzieć się, co powoduje tę fragmentację.

Pytanie dodatkowe: Jaki jest lepszy sposób na uzyskanie źródła tej fragmentacji?

Jeśli czytasz tak daleko, dziękuję za uwagę!

Dodatkowe wymagane informacje:

Informacje o pamięci i xfs: https://gist.github.com/christian-marie/f417cc3134544544a8d1

Błąd przydziału strony: https://gist.github.com/christian-marie/7bc845d2da7847534104

Kontynuacja: informacje o perf i rzeczy związane z zagęszczaniem

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

Kod zagęszczania wydaje się trochę nieefektywny, co? Zebrałem trochę kodu, aby spróbować zreplikować nieudane zagęszczenia: https://gist.github.com/christian-marie/cde7e80c5edb889da541

To wydaje się odtwarzać problem.

Zauważę również, że śledzenie zdarzeń mówi mi, że istnieje wiele nieudanych reklamacji, w kółko:

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

Dotyczy również wyjścia Vmstat. Podczas gdy system znajduje się w stanie wysokiego obciążenia, zagęszczania przechodzą przez dach (i w większości nie działają):

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

Naprawdę jest coś nie tak z odzyskiwaniem / zagęszczaniem.

W tej chwili zamierzam zmniejszyć alokacje wysokich zamówień poprzez dodanie obsługi SG do naszej konfiguracji ipoib. Wydaje się, że prawdziwy problem dotyczy vmscan.

Jest to interesujące i odnosi się do tego pytania: http://marc.info/?l=linux-mm&m=141607142529562&w=2

pingu
źródło
2
Cholera, tak !! Nie otrzymujemy wielu z tych dobrych pytań. Zobaczę jednak, co możemy zrobić.
ewwhite
1
Czy możesz podać dane wyjściowe /proc/buddyinfoi wyniki free -m? Żądania blockdev są prawdopodobnie reprezentowane jako bufory w free. Aha, a dystrybucja, której używasz, też byłaby dobra. Dodatkowo, czy masz jakieś page allocation failurewiadomości dmesg? Jeśli tak, proszę podać wynik oraz odpowiedni kontekst.
Matthew Ife
1
Czy używałeś też konkretnego mkfs.xfswiersza poleceń? Włączone strony informacyjne?
ewwhite
Również wyniki/proc/meminfo
Matthew Ife
Próbowałem samodzielnie wyłączyć przezroczyste fragmenty strony (ustawiając je na nigdy), błąd nadal występował. Nie próbowałem tego w połączeniu z innymi „poprawkami”.
pingu

Odpowiedzi:

4

Myślałem, że odpowiem swoimi spostrzeżeniami, ponieważ jest wiele komentarzy.

Na podstawie wyników uzyskanych na https://gist.github.com/christian-marie/7bc845d2da7847534104

Możemy ustalić, co następuje:

  1. GFP_MASK dla wypróbowanej alokacji pamięci może wykonać następujące czynności.
    • Może uzyskać dostęp do basenów awaryjnych (myślę, że oznacza to dostęp do danych poniżej wysokiego znaku wodnego dla strefy)
    • Nie używaj rezerw awaryjnych (myślę, że to oznacza, że ​​nie zezwalaj na dostęp do memroy poniżej minimalnego znaku wodnego)
    • Przydziel z jednej ze zwykłych stref.
    • Można zamienić, aby zrobić miejsce.
    • Może upuścić skrzynki, aby zrobić miejsce.

Fragmentacja strefy to lokalizacja tutaj:

[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

Wykorzystanie pamięci w tym momencie jest tutaj:

[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

Fragmentacja każdej strefy jest niepoprawna w wyniku niepowodzenia alokacji strony. Istnieje wiele stron z bezpłatnym zamówieniem 0, ze znacznie mniejszą liczbą stron o wyższym zamówieniu. „Dobry” wynik to obfite bezpłatne strony wzdłuż każdego zamówienia, stopniowo zmniejszające się wraz ze wzrostem kolejności. Posiadanie 0 stron wysokiego rzędu 5 i wyższych wskazuje na fragmentację i głód przydziałów wysokiego rzędu.

Obecnie nie widzę przekonujących dowodów na to, że fragmentacja w tym okresie ma cokolwiek wspólnego z buforami płyt. W wynikowych statystykach pamięci możemy zobaczyć następujące

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

Nie ma żadnych dużych stron przypisanych z przestrzeni użytkownika, a zatem przestrzeń użytkownika zawsze będzie żądać pamięci rzędu 0. Zatem w obu strefach jest ponad 22 GB pamięci defragmentowalnej.

Zachowania, których nie potrafię wyjaśnić

Kiedy przydziały wysokiego rzędu kończą się niepowodzeniem, rozumiem, że zawsze próbuje się zagęścić pamięć , aby umożliwić regionom przydziału pamięci wysokiego rzędu, aby odniosła sukces. Dlaczego tak się nie dzieje? Jeśli tak się stanie, dlaczego nie może znaleźć żadnej pamięci do defragmentacji, gdy 22GiB jest gotowe do zmiany kolejności?

Zachowania, które myślę, że potrafię wyjaśnić

Aby poprawnie zrozumieć, potrzeba więcej badań, ale uważam, że możliwość automatycznego zamiany / upuszczenia części pamięci podręcznej na sukces prawdopodobnie nie ma tutaj zastosowania, ponieważ wciąż jest dużo wolnej pamięci, więc nie ma możliwości odzyskania. Po prostu za mało w wyższych rzędach.

Chociaż w każdej strefie pozostało dużo wolnej pamięci i kilka żądań 4 zamówień w każdej strefie, problem „suma całej wolnej pamięci dla każdego zamówienia i odliczenia od rzeczywistej wolnej pamięci” powoduje „wolną pamięć” poniżej znaku wodnego „min”, który jest co prowadzi do faktycznego niepowodzenia alokacji.

Matthew Ife
źródło
Wydaje się dziwne, że względnie (do całkowitej wolnej pamięci) mała pamięć podręczna SLAB podzieliłaby wszystkie wspomnienia. Spodziewałbym się, że w przypadku wszystkich tych darmowych stron, które można eksmitować, po prostu eksmitują niektóre z nich i są gotowe. Podejrzewam, że NUMA może mieć coś wspólnego z tą dziwnością.
pingu
Czy numaddziała w tym systemie?
ewwhite
@ewwhite numad nie działa, nie.
pingu
@pingu Jeśli to zachowanie jest powtarzalne, spróbuj włączyć numadusługę i zanotuj działania w /var/log/numad.log. Może być także konieczne zainstalowanie libcgroup.
ewwhite
@ewwhite Dobra, mam już jeden uruchomiony. Nie jestem pewien, czego się od tego oczekuję ani jakie informacje możemy z tego uzyskać. Co masz nadzieję, że może się stać?
pingu