Rsync ha attivato il killer OOM Linux su un singolo file da 50 GB


66

Ho un singolo file da 50 GB su server_A e lo sto copiando su server_B. io corro

server_A$ rsync --partial --progress --inplace --append-verify 50GB_file root@server_B:50GB_file

Server_B ha 32 GB di RAM con 2 GB di scambio. È principalmente inattivo e avrebbe dovuto avere molta RAM libera. Ha un sacco di spazio su disco. A circa 32 GB, il trasferimento si interrompe perché il lato remoto ha chiuso la connessione.

Server_B è ora uscito dalla rete. Chiediamo al data center di riavviarlo. Quando guardo il registro del kernel da prima che si arrestasse in modo anomalo, vedo che stava usando 0 byte di swap e l'elenco dei processi utilizzava pochissima memoria (il processo rsync era elencato come usando 600 KB di RAM), ma oom_killer era impazzendo, e l'ultima cosa nel registro è dove uccide il processo di lettura del kernel di metalog.

Questo è il kernel 3.2.59, 32 bit (quindi nessun processo può mappare più di 4 GB comunque).

È quasi come se Linux desse più priorità alla memorizzazione nella cache che ai demoni in esecuzione di lunga durata. Cosa dà ?? E come posso impedire che accada di nuovo?

Ecco l'output di oom_killer:

Sep 23 02:04:16 [kernel] [1772321.850644] clamd invoked oom-killer: gfp_mask=0x84d0, order=0, oom_adj=0, oom_score_adj=0
Sep 23 02:04:16 [kernel] [1772321.850649] Pid: 21832, comm: clamd Tainted: G         C   3.2.59 #21
Sep 23 02:04:16 [kernel] [1772321.850651] Call Trace:
Sep 23 02:04:16 [kernel] [1772321.850659]  [<c01739ac>] ? dump_header+0x4d/0x160
Sep 23 02:04:16 [kernel] [1772321.850662]  [<c0173bf3>] ? oom_kill_process+0x2e/0x20e
Sep 23 02:04:16 [kernel] [1772321.850665]  [<c0173ff8>] ? out_of_memory+0x225/0x283
Sep 23 02:04:16 [kernel] [1772321.850668]  [<c0176438>] ? __alloc_pages_nodemask+0x446/0x4f4
Sep 23 02:04:16 [kernel] [1772321.850672]  [<c0126525>] ? pte_alloc_one+0x14/0x2f
Sep 23 02:04:16 [kernel] [1772321.850675]  [<c0185578>] ? __pte_alloc+0x16/0xc0
Sep 23 02:04:16 [kernel] [1772321.850678]  [<c0189e74>] ? vma_merge+0x18d/0x1cc
Sep 23 02:04:16 [kernel] [1772321.850681]  [<c01856fa>] ? handle_mm_fault+0xd8/0x15d
Sep 23 02:04:16 [kernel] [1772321.850685]  [<c012305a>] ? do_page_fault+0x20e/0x361
Sep 23 02:04:16 [kernel] [1772321.850688]  [<c018a9c4>] ? sys_mmap_pgoff+0xa2/0xc9
Sep 23 02:04:16 [kernel] [1772321.850690]  [<c0122e4c>] ? vmalloc_fault+0x237/0x237
Sep 23 02:04:16 [kernel] [1772321.850694]  [<c08ba7e6>] ? error_code+0x5a/0x60
Sep 23 02:04:16 [kernel] [1772321.850697]  [<c08b0000>] ? cpuid4_cache_lookup_regs+0x372/0x3b2
Sep 23 02:04:16 [kernel] [1772321.850700]  [<c0122e4c>] ? vmalloc_fault+0x237/0x237
Sep 23 02:04:16 [kernel] [1772321.850701] Mem-Info:
Sep 23 02:04:16 [kernel] [1772321.850703] DMA per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850704] CPU    0: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850706] CPU    1: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850707] CPU    2: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850709] CPU    3: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850711] CPU    4: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850713] CPU    5: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850714] CPU    6: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850716] CPU    7: hi:    0, btch:   1 usd:   0
Sep 23 02:04:16 [kernel] [1772321.850718] Normal per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850719] CPU    0: hi:  186, btch:  31 usd:  70
Sep 23 02:04:16 [kernel] [1772321.850721] CPU    1: hi:  186, btch:  31 usd: 116
Sep 23 02:04:16 [kernel] [1772321.850723] CPU    2: hi:  186, btch:  31 usd: 131
Sep 23 02:04:16 [kernel] [1772321.850724] CPU    3: hi:  186, btch:  31 usd:  76
Sep 23 02:04:16 [kernel] [1772321.850726] CPU    4: hi:  186, btch:  31 usd:  29
Sep 23 02:04:16 [kernel] [1772321.850728] CPU    5: hi:  186, btch:  31 usd:  61
Sep 23 02:04:16 [kernel] [1772321.850731] CPU    7: hi:  186, btch:  31 usd:  17
Sep 23 02:04:16 [kernel] [1772321.850733] HighMem per-cpu:
Sep 23 02:04:16 [kernel] [1772321.850734] CPU    0: hi:  186, btch:  31 usd:   2
Sep 23 02:04:16 [kernel] [1772321.850736] CPU    1: hi:  186, btch:  31 usd:  69
Sep 23 02:04:16 [kernel] [1772321.850738] CPU    2: hi:  186, btch:  31 usd:  25
Sep 23 02:04:16 [kernel] [1772321.850739] CPU    3: hi:  186, btch:  31 usd:  27
Sep 23 02:04:16 [kernel] [1772321.850741] CPU    4: hi:  186, btch:  31 usd:   7
Sep 23 02:04:16 [kernel] [1772321.850743] CPU    5: hi:  186, btch:  31 usd: 188
Sep 23 02:04:16 [kernel] [1772321.850744] CPU    6: hi:  186, btch:  31 usd:  25
Sep 23 02:04:16 [kernel] [1772321.850746] CPU    7: hi:  186, btch:  31 usd: 158
Sep 23 02:04:16 [kernel] [1772321.850750] active_anon:117913 inactive_anon:9942 isolated_anon:0
Sep 23 02:04:16 [kernel] [1772321.850751]  active_file:106466 inactive_file:7784521 isolated_file:0
Sep 23 02:04:16 [kernel] [1772321.850752]  unevictable:40 dirty:0 writeback:61 unstable:0
Sep 23 02:04:16 [kernel] [1772321.850753]  free:143494 slab_reclaimable:128312 slab_unreclaimable:4089
Sep 23 02:04:16 [kernel] [1772321.850754]  mapped:6706 shmem:308 pagetables:915 bounce:0
Sep 23 02:04:16 [kernel] [1772321.850759] DMA free:3624kB min:140kB low:172kB high:208kB active_anon:0kB inactive_anon:0kB active_file:0kB inactive_file:0kB unevictable:0kB isolated(anon):0kB isolate
d(file):0kB present:15808kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:240kB slab_unreclaimable:0kB kernel_stack:0kB pagetables:0kB unstable:0kB bounce:0kB writeback_tm
p:0kB pages_scanned:0 all_unreclaimable? yes
Sep 23 02:04:16 [kernel] [1772321.850763] lowmem_reserve[]: 0 869 32487 32487
Sep 23 02:04:16 [kernel] [1772321.850770] Normal free:8056kB min:8048kB low:10060kB high:12072kB active_anon:0kB inactive_anon:0kB active_file:248kB inactive_file:388kB unevictable:0kB isolated(anon)
:0kB isolated(file):0kB present:890008kB mlocked:0kB dirty:0kB writeback:0kB mapped:0kB shmem:0kB slab_reclaimable:513008kB slab_unreclaimable:16356kB kernel_stack:1888kB pagetables:3660kB unstable:0
kB bounce:0kB writeback_tmp:0kB pages_scanned:1015 all_unreclaimable? yes
Sep 23 02:04:16 [kernel] [1772321.850774] lowmem_reserve[]: 0 0 252949 252949
Sep 23 02:04:16 [kernel] [1772321.850785] lowmem_reserve[]: 0 0 0 0
Sep 23 02:04:16 [kernel] [1772321.850788] DMA: 0*4kB 7*8kB 3*16kB 6*32kB 4*64kB 6*128kB 5*256kB 2*512kB 0*1024kB 0*2048kB 0*4096kB = 3624kB
Sep 23 02:04:16 [kernel] [1772321.850795] Normal: 830*4kB 80*8kB 0*16kB 0*32kB 0*64kB 0*128kB 0*256kB 0*512kB 0*1024kB 0*2048kB 1*4096kB = 8056kB
Sep 23 02:04:16 [kernel] [1772321.850802] HighMem: 13*4kB 14*8kB 2*16kB 2*32kB 0*64kB 0*128kB 2*256kB 2*512kB 3*1024kB 0*2048kB 136*4096kB = 561924kB
Sep 23 02:04:16 [kernel] [1772321.850809] 7891360 total pagecache pages
Sep 23 02:04:16 [kernel] [1772321.850811] 0 pages in swap cache
Sep 23 02:04:16 [kernel] [1772321.850812] Swap cache stats: add 0, delete 0, find 0/0
Sep 23 02:04:16 [kernel] [1772321.850814] Free swap  = 1959892kB
Sep 23 02:04:16 [kernel] [1772321.850815] Total swap = 1959892kB
Sep 23 02:04:16 [kernel] [1772321.949081] 8650736 pages RAM
Sep 23 02:04:16 [kernel] [1772321.949084] 8422402 pages HighMem
Sep 23 02:04:16 [kernel] [1772321.949085] 349626 pages reserved
Sep 23 02:04:16 [kernel] [1772321.949086] 7885006 pages shared
Sep 23 02:04:16 [kernel] [1772321.949087] 316864 pages non-shared
Sep 23 02:04:16 [kernel] [1772321.949089] [ pid ]   uid  tgid total_vm      rss cpu oom_adj oom_score_adj name
            (rest of process list omitted)
Sep 23 02:04:16 [kernel] [1772321.949656] [14579]     0 14579      579      171   5       0             0 rsync
Sep 23 02:04:16 [kernel] [1772321.949662] [14580]     0 14580      677      215   5       0             0 rsync
Sep 23 02:04:16 [kernel] [1772321.949669] [21832]   113 21832    42469    37403   0       0             0 clamd
Sep 23 02:04:16 [kernel] [1772321.949674] Out of memory: Kill process 21832 (clamd) score 4 or sacrifice child
Sep 23 02:04:16 [kernel] [1772321.949679] Killed process 21832 (clamd) total-vm:169876kB, anon-rss:146900kB, file-rss:2712kB

Ecco l'output "top" dopo aver ripetuto il mio comando rsync come utente non root:

top - 03:05:55 up  8:43,  2 users,  load average: 0.04, 0.08, 0.09
Tasks: 224 total,   1 running, 223 sleeping,   0 stopped,   0 zombie
Cpu(s):  0.0% us,  0.0% sy,  0.0% ni, 99.9% id,  0.0% wa,  0.0% hi,  0.0% si
Mem:  33204440k total, 32688600k used,   515840k free,   108124k buffers
Swap:  1959892k total,        0k used,  1959892k free, 31648080k cached

Ecco i parametri sysctl vm:

# sysctl -a | grep '^vm'
vm.overcommit_memory = 0
vm.panic_on_oom = 0
vm.oom_kill_allocating_task = 0
vm.oom_dump_tasks = 1
vm.overcommit_ratio = 50
vm.page-cluster = 3
vm.dirty_background_ratio = 1
vm.dirty_background_bytes = 0
vm.dirty_ratio = 0
vm.dirty_bytes = 15728640
vm.dirty_writeback_centisecs = 500
vm.dirty_expire_centisecs = 3000
vm.nr_pdflush_threads = 0
vm.swappiness = 60
vm.lowmem_reserve_ratio = 256   32      32
vm.drop_caches = 0
vm.min_free_kbytes = 8192
vm.percpu_pagelist_fraction = 0
vm.max_map_count = 65530
vm.laptop_mode = 0
vm.block_dump = 0
vm.vfs_cache_pressure = 100
vm.legacy_va_layout = 0
vm.stat_interval = 1
vm.mmap_min_addr = 4096
vm.vdso_enabled = 2
vm.highmem_is_dirtyable = 0
vm.scan_unevictable_pages = 0

2
Non sono esperto nella lettura dei messaggi di crash del kernel, ma non vedo alcuna indicazione che B stia usando 32 GB di core. Prima di procedere partendo dal presupposto che lo fosse, puoi confermare che lo è attualmente? Perché c'è una grande differenza tra l'esaurimento della memoria di una scatola con 32 GB di core e una con solo 4 GB.
MadHatter,

Aggiornato con l'output principale. Questo dopo aver eseguito lo stesso comando rsync di un utente non root. Praticamente tutti tranne 1 GB sono usati per la cache in questo momento.
dataless

Grazie. Come ho già detto, non sono un esperto - ma sembrava che valesse la pena controllarlo.
MadHatter,

dovresti anche verificare che il tuo kernel consenta lo swap (ovvero, lo swap non è disattivato) (e dovresti dedicare una porzione maggiore di spazio su disco, diciamo 16Gb o addirittura 32Gb). Alcune persone strane in rete raccomandano di disattivare lo scambio, il che è molto sbagliato.
Olivier Dulac,

@OlivierDulac a quale impostazione ti riferisci? Il supporto per lo swap è compilato o non saremo in grado di montare lo swap e la 'swappiness' è impostata su 60. Per quanto riguarda le dimensioni dello swap, ciò non peggiorerebbe il problema, su un kernel a 32 bit? La risposta sembra che le strutture di dati del kernel ci hanno ucciso. Non stiamo eseguendo 32 GB di processi utente, vogliamo solo quella RAM per la cache del disco, per le prestazioni.
dataless

Risposte:


178

Quindi leggiamo l'output di Oom-Killer e vediamo cosa si può imparare da lì.

Quando si analizzano i registri killer OOM, è importante guardare a cosa è stato attivato. La prima riga del tuo registro ci fornisce alcuni indizi:

[kernel] [1772321.850644] clamd ha invocato oom-killer: gfp_mask = 0x84d0, ordine = 0

order=0ci sta dicendo quanta memoria viene richiesta. La gestione della memoria del kernel è in grado di gestire solo i numeri di pagina con potenze di 2, quindi clamd ha richiesto 2 0 pagine di memoria o 4KB.

I due bit più bassi di GFP_MASK (ottieni la maschera di pagina libera) costituiscono la cosiddetta maschera di zona che indica all'allocatore da quale zona ottenere la memoria :

Flag            value      Description
                0x00u      0 implicitly means allocate from ZONE_NORMAL
__GFP_DMA       0x01u      Allocate from ZONE_DMA if possible
__GFP_HIGHMEM   0x02u      Allocate from ZONE_HIGHMEM if possible

Le zone di memoria sono un concetto creato principalmente per motivi di compatibilità. In una vista semplificata, ci sono tre zone per un kernel x86:

Memory range   Zone       Purpose 

0-16 MB        DMA        Hardware compatibility (devices)
16 - 896 MB    NORMAL     space directly addressable by the Kernel, userland 
> 896 MB       HIGHMEM    userland, space addressable by the Kernel via kmap() calls

Nel tuo caso, la zonemask è 0, il che significa che clamd richiede memoria ZONE_NORMAL.

Le altre bandiere si stanno risolvendo

/*
 * Action modifiers - doesn't change the zoning
 *
 * __GFP_REPEAT: Try hard to allocate the memory, but the allocation attempt
 * _might_ fail.  This depends upon the particular VM implementation.
 *
 * __GFP_NOFAIL: The VM implementation _must_ retry infinitely: the caller
 * cannot handle allocation failures.
 *
 * __GFP_NORETRY: The VM implementation must not retry indefinitely.
 */
#define __GFP_WAIT      0x10u   /* Can wait and reschedule? */
#define __GFP_HIGH      0x20u   /* Should access emergency pools? */
#define __GFP_IO        0x40u   /* Can start physical IO? */
#define __GFP_FS        0x80u   /* Can call down to low-level FS? */
#define __GFP_COLD      0x100u  /* Cache-cold page required */
#define __GFP_NOWARN    0x200u  /* Suppress page allocation failure warning */
#define __GFP_REPEAT    0x400u  /* Retry the allocation.  Might fail */
#define __GFP_NOFAIL    0x800u  /* Retry for ever.  Cannot fail */
#define __GFP_NORETRY   0x1000u /* Do not retry.  Might fail */
#define __GFP_NO_GROW   0x2000u /* Slab internal usage */
#define __GFP_COMP      0x4000u /* Add compound page metadata */
#define __GFP_ZERO      0x8000u /* Return zeroed page on success */
#define __GFP_NOMEMALLOC 0x10000u /* Don't use emergency reserves */
#define __GFP_NORECLAIM  0x20000u /* No realy zone reclaim during allocation */

secondo la documentazione di Linux MM , così il vostro requst ha le bandiere per GFP_ZERO, GFP_REPEAT, GFP_FS, GFP_IOe GFP_WAIT, essendo così non particolarmente esigente.

Allora, che succede ZONE_NORMAL? Alcune statistiche generiche sono disponibili più avanti nell'output OOM:

[kernel] [1772321.850770] Normale libero: 8056kB min: 8048kB basso: 10060kB alto: 12072kB active_anon: 0kB inactive_anon: 0kB active_file: 248kB inactive_file: 388kB inattivabile: 0kB isolato (anon): 0kB: isolato: 0: 89

Notabile qui è che freeè solo 8K da mine molto sotto low. Ciò significa che il gestore della memoria del tuo host è in qualche modo in difficoltà e kswapd dovrebbe scambiare le pagine già come è nella fase gialla del grafico qui sotto: Grafico del gestore di memoria Linux

Alcune ulteriori informazioni sulla frammentazione della memoria della zona sono fornite qui:

[kernel] [1772321.850795] Normale: 830 * 4kB 80 * 8kB 0 * 16kB 0 * 32kB 0 * 64kB 0 * 128kB 0 * 128kB 0 * 512kB 0 * 1024kB 0 * 2048kB 1 * 4096kB = 8056kB

in sostanza affermando che hai una singola pagina contigua di 4 MB con il resto fortemente frammentato in pagine principalmente 4KB.

Quindi ricapitoliamo:

  • hai un processo userland ( clamd) che recupera la memoria ZONE_NORMALmentre l'allocazione della memoria non privilegiata di solito viene eseguitaZONE_HIMEM
  • a questo punto il gestore della memoria avrebbe dovuto essere in grado di servire la pagina 4K richiesta, sebbene sembri avere una significativa pressione della memoria ZONE_NORMAL
  • il sistema, secondo kswapdle regole, avrebbe dovuto vedere prima alcune attività di paginazione, ma nulla è stato scambiato, anche sotto pressione della memoria ZONE_NORMAL, senza una causa apparente
  • Nessuna delle precedenti fornisce una ragione precisa per cui oom-killerè stato invocato

Tutto ciò sembra piuttosto strano, ma almeno deve essere correlato a quanto descritto nella sezione 2.5 dell'eccellente libro "Comprensione del Linux Virtual Memory Manager" di John O'Gorman :

Poiché lo spazio degli indirizzi utilizzabile dal kernel (ZONE_NORMAL) ha dimensioni limitate, il kernel ha il supporto per il concetto di memoria elevata. [...] Per accedere alla memoria tra 1GiB e 4GiB, il kernel mappa temporaneamente le pagine dalla memoria alta in ZONE_NORMAL con kmap (). [...]

Ciò significa che per descrivere 1GiB di memoria, sono necessari circa 11MiB di memoria del kernel. Pertanto, con 16GiB, vengono consumati 176MiB di memoria, esercitando una pressione significativa su ZONE_NORMAL. Questo non suona troppo male finché non vengono prese in considerazione altre strutture che usano ZONE_NORMAL. Anche strutture molto piccole come PTE (Page Table Entries) richiedono circa 16 MiB nel peggiore dei casi. Questo rende 16GiB circa il limite pratico per la memoria fisica disponibile Linux su un x86 .

(l'enfasi è mia)

Poiché 3.2 ha numerosi progressi nella gestione della memoria rispetto alla 2.6, questa non è una risposta definitiva, ma un suggerimento davvero forte che vorrei perseguire per primo. Ridurre la memoria utilizzabile dell'host a un massimo di 16 G utilizzando il mem=parametro kernel o estraendo metà dei moduli DIMM dal server.

In definitiva, usa un kernel a 64 bit .

Amico, è il 2015.


13
Quando ho detto sopra " Non sono un esperto ", questo è quello che speravo di leggere. +1000, se solo potessi; +1 di sicuro. Che grande risposta!
MadHatter,

18
Era bello. C'è ancora speranza per SF.
Roman

9
@dataless Sì. Sospetto che tutti i tuoi ZONE_NORMAL siano pieni di metadati relativi alle aree di memoria superiori. Quando un processo userland richiede pagine di memoria, molto probabilmente richiederà ZONE_HIGHMEM (che potrebbe essere aggiornato da MM a ZONE_NORMAL se HIGHMEM non ha più pagine libere per soddisfare la richiesta ma NORMAL ha), quindi a meno che ZONE_HIGHMEM sia sotto pressione di memoria (il tuo non lo è), ZONE_NORMAL non avrà pagine di processi spazio utente.
the-wabbit,

3
[sbatte i pugni sulla tastiera] Dai a questo wabbit la generosità
underscore_d

3
@ the-wabbit Domande sulla rete hot.
CodesInChaos,

4

Poche cose ...

La mia regola empirica per lo spazio di swap è stata quella di avere almeno il doppio della quantità di RAM fisica. Ciò consente al demone page / swap di reimpostare la memoria in modo efficiente.

Server_B ha 32 GB di RAM, quindi prova a configurarlo per 64 GB di swap. IMO, il 2 GB di spazio di swap il server dispone è modo troppo bassa, soprattutto per un server.

Se non hai una partizione aggiuntiva che puoi creare in una partizione di swap, puoi verificarla creando un file e montandolo come partizione di swap [sarà lento]. Vedi https://www.maketecheasier.com/swap-partitions-on-linux/

Poiché server_B ha molto spazio su disco, --inplace non è necessario e potrebbe essere indesiderato in quanto potrebbe essere ciò che sta causando l'utilizzo di 32 GB di rsync. --inplace è davvero utile solo se sei a corto di spazio sul filesystem [che non sei] o hai qualche requisito speciale in termini di prestazioni.

La mia ipotesi è che rsync vorrà usare 50 GB di RAM [la dimensione del file] con le opzioni attuali. Normalmente, rsync non ha bisogno di tanta memoria per fare il suo lavoro, quindi una o più delle tue opzioni potrebbero essere il problema. Trasferisco regolarmente file da 200 GB senza problemi.

Esegui alcune prove senza usare opzioni. Fallo con file più piccoli, diciamo 10 GB - questo dovrebbe prevenire il panico del kernel, ma permetterti comunque di monitorare il comportamento che sta causando il problema. Monitora l'utilizzo della memoria di rsync.

A poco a poco, aggiungi di nuovo le opzioni, una alla volta, per vedere quale opzione [o combinazione di opzioni] fa sì che rsync inizi a inserirsi nella RAM (ad es. Mentre si sta verificando il trasferimento, l'utilizzo della RAM di rsync cresce proporzionalmente alla quantità di dati trasferiti, eccetera.).

Se hai davvero bisogno delle opzioni che fanno sì che rsync mantenga un'immagine del file in-ram, avrai bisogno dello spazio di scambio extra e le dimensioni massime del file saranno limitate di conseguenza.

Alcune altre cose [AGGIORNATO]:

(1) Il traceback dello stack del kernel mostra che rsync stava verificando un errore di pagina su un'area di mmap. Probabilmente sta eseguendo il mmaping del file. mmap non offre alcuna garanzia che scaricherà sul disco fino a quando il file non verrà chiuso [diversamente dalla lettura / scrittura] che passa immediatamente alla cache del blocco FS [dove verrà scaricato]

(2) L'arresto anomalo / panico del kernel si verifica quando la dimensione del trasferimento raggiunge la dimensione della RAM. Chiaramente rsync sta acquisendo molta memoria senza fscache tramite malloc o mmap. Ancora una volta, con le opzioni che hai specificato, rsync assegnerà 50 GB di memoria per trasferire un file da 50 GB.

(3) Trasferisci un file da 24 GB. Probabilmente funzionerà. Quindi, avviare il kernel con mem = 16G ed eseguire nuovamente il test del file da 24 GB. Esploderà a 16 GB anziché 32 GB. Ciò confermerà che rsync ha davvero bisogno della memoria.

(4) Prima di dire che l'aggiunta di swap è ridicola, prova ad aggiungerne [tramite il metodo swap-to-file]. Questo è molto più facile da fare e testare rispetto a tutti gli argomenti accademici su come lo scambio non è richiesto. Anche se non è la soluzione, puoi imparare qualcosa da essa. Scommetto che il test mem = 16G avrà successo senza panico / crash.

(5) È probabile che rsync stia colpendo lo swap, ma succede troppo velocemente per vedere con il top prima che OOM entri e uccida rsync. Quando rsync arriva a 32 GB, altri processi sono già stati costretti a scambiarsi, in particolare se sono inattivi. Forse, una combinazione di "gratis" e "top" ti darà un'immagine migliore.

(6) Dopo che rsync viene ucciso, ci vuole tempo per scaricare mmap su FS. Non abbastanza veloce per OOM e inizia a uccidere altre cose [alcune sono ovviamente mission-critical]. Cioè, il mmap flush e OOM stanno correndo. O OOM ha un bug. Altrimenti, non ci sarebbe un incidente.

(7) Nella mia esperienza, una volta che un sistema "colpisce il muro di memoria", Linux impiega molto tempo a recuperare completamente. E a volte non ripristina mai veramente correttamente e l'unico modo per cancellarlo è un riavvio. Ad esempio, ho 12 GB di RAM. Quando eseguo un lavoro che utilizza 40 GB di memoria [ho 120 GB di swap per adattarsi a lavori di grandi dimensioni] e quindi lo interrompo, sono necessari circa 10 minuti affinché il sistema ritorni alla normale capacità di risposta [con la luce del disco sempre accesa] .

(8) Esegui rsync senza opzioni. Questo funzionerà. Ottieni un esempio di base su cui lavorare. Quindi aggiungere di nuovo --inplace e ripetere il test. Quindi esegui --append-confirm. Quindi, prova entrambi. Scopri quale opzione ottiene rsync facendo l'enorme mmap. Quindi decidi se puoi vivere senza di essa. Se --inplace è il colpevole, è un gioco da ragazzi, dato che hai un sacco di spazio su disco. Se è necessario disporre dell'opzione, sarà necessario ottenere lo spazio di swap per adattarsi al malloc / mmap che farà rsync.

SECONDO AGGIORNAMENTO:

Esegui test mem = e file più piccoli da quanto sopra.

Le domande centrali: perché rsync viene ucciso da OOM? Chi / Che cos'è la masticazione della memoria?

Ho letto [ma ho dimenticato] che il sistema era a 32 bit. Quindi, sono d'accordo, rsync potrebbe non essere direttamente responsabile (tramite malloc / mmap - glibc implementa malloc di grandi dimensioni tramite mmaps anonimi / privati) e l'errore di pagina mmap di rsync attiva semplicemente OOM per coincidenza. Quindi, OOM calcola la memoria totale consumata da rsync direttamente e indirettamente [cache FS, buffer socket, ecc.] E decide che è il candidato principale. Pertanto, il monitoraggio dell'utilizzo totale della memoria può essere utile. Sospetto che si insinui alla stessa velocità del trasferimento dei file. Ovviamente non dovrebbe.

Alcune cose che puoi monitorare in / proc o / proc / rsync_pid tramite uno script perl o python in un ciclo veloce [uno script bash probabilmente non sarà abbastanza veloce per l'evento di fine mondo] che può monitorare tutto le seguenti centinaia di volte / sec. Puoi eseguirlo con una priorità più alta rispetto a rsync in modo che rimanga nella RAM e funzioni in modo da poter monitorare le cose appena prima dello schianto e si spera durante OOM in modo da poter capire perché OOM impazzisce:

/ proc / meminfo - per ottenere una grana più fine sull'uso dello swap in "punto di impatto". In realtà, ottenere il numero finale su quanta RAM viene utilizzata in totale potrebbe essere più utile. Mentre top fornisce questo, potrebbe non essere abbastanza veloce per mostrare lo stato dell'universo appena prima del "big bang" (ad esempio gli ultimi 10 millisecondi)

/ proc / rsync_pid / directory fd. La lettura dei symlink ti permetterà di identificare quale fd è aperto sul file di destinazione (es. Readlink di / proc / rsync_pid / fd / 5 -> target_file). Questo probabilmente deve essere fatto solo una volta per ottenere il numero fd [dovrebbe rimanere fisso]

Conoscendo il numero fd, guarda / proc / rsync_pid / fdinfo / fd. È un file di testo che assomiglia a:

pos: <posizione_file>
bandiere: blah_blah
mnt_id: blah_blah

Il monitoraggio del valore "pos" può essere utile in quanto "l'ultima posizione del file" può essere utile. Se esegui diversi test con dimensioni e opzioni mem = diverse, l'ultima posizione del file tiene traccia di uno di questi [e come]? Il solito sospetto: posizione del file == RAM disponibile

Ma il modo più semplice è iniziare con "rsync local_file server: remote_file" e verificare che funzioni. Potresti essere in grado di ottenere risultati simili [ma più veloci] facendo "ssh server rsync file_a file_b" [dovresti prima creare un file_a da 50 GB]. Un modo semplice per creare file_a è scp local_system: server_file originale: file_a e questo potrebbe essere interessante per se stesso (ad esempio, questo funziona in caso di crash di rsync? Se scp funziona, ma rsync fallisce, questo indica rsync. Se scp fallisce, questo indica a qualcos'altro come il driver NIC). Fare ssh rsync elimina anche la NIC dall'equazione, il che può essere utile. Se il problema persiste, allora qualcosa non va. Se riesce, [come ho già detto] inizia ad aggiungere nuovamente le opzioni una per una.

Odio confermare il punto, ma l'aggiunta di alcuni swap tramite swap-to-file può modificare / ritardare il comportamento dell'arresto anomalo e può essere utile come strumento diagnostico. Se l'aggiunta, diciamo 16 GB, di swap ritarda l'arresto anomalo [misurato dall'uso della memoria o dalla posizione del file di destinazione] da 32 GB a 46 GB, allora ciò dirà qualcosa.

Potrebbe non essere un processo particolare, ma un driver del kernel errante che mastica memoria. Il vmalloc interno del kernel alloca roba e può essere scambiata. IIRC, non è vincolato dalla indirizzabilità in tutte le circostanze.

Chiaramente, OOM viene confuso / preso dal panico. Cioè, uccide rsync, ma non vede la memoria liberata in modo tempestivo e va alla ricerca di altre vittime. Alcuni di questi sono probabilmente fondamentali per il funzionamento del sistema.

malloc / mmap a parte, questo potrebbe essere causato da cache FS non svuotata che impiega molto tempo (ad es. con 30 GB di dati non svuotati, supponendo una velocità del disco di 300 MB / sec, potrebbero essere necessari 100 secondi per scaricarlo). Anche a quel ritmo, OOM potrebbe essere troppo impaziente. Oppure, OOM che uccide rsync non avvia il flush di FS abbastanza velocemente [o affatto]. O il flush di FS avviene abbastanza velocemente, ma ha una versione "pigra" delle pagine nel pool gratuito. Ci sono alcune opzioni / proc che puoi impostare per controllare il comportamento della cache di FS [Non ricordo cosa sono].

Prova ad avviare con mem = 4G o qualche altro numero piccolo. Ciò potrebbe ridurre la cache di FS e ridurre il tempo di scaricamento per impedire a OOM di cercare altre cose da eliminare (ad esempio, il tempo di scaricamento viene ridotto da 100 secondi a <1 secondo). Potrebbe anche smascherare un bug OOM che non è in grado di gestire ram fisici> 4 GB su un sistema a 32 bit o simili.

Inoltre, un punto importante: esegui come non root. Gli utenti root non sono mai tenuti a masticare risorse, quindi ricevono limiti più tolleranti (ad es. 99% di memoria vs 95% per utenti non root). Questo può spiegare perché OOM è in tale stato. Inoltre, questo dà OOM et. al. più spazio per fare il suo lavoro di recupero della memoria.


Vedi Quanto spazio SWAP su un sistema ad alta memoria? - e non vuoi vedere il tuo sistema usare 63 GB di swap. Non sarà utilizzabile.
Ripristina Monica - M. Schröder,

1
swap> RAM è davvero utile solo se si esegue senza il sovraccarico della VM, quindi il kernel deve riservare spazio di swap per le pagine allocate fino a quando non vengono sporcate e necessitano di pagine fisiche reali che le supportano. La pratica corrente è quella di consentire l'overcommit e l'esecuzione con una piccola quantità di spazio di swap per sfogliare le pagine che sono state toccate solo all'avvio e non sono necessarie nel normale funzionamento. overcommit = 0 con piccolo swap va bene se hai molta RAM, per la maggior parte dei sistemi.
Peter Cordes,

Sembra che rsync stia davvero cercando di usare> 32 GB, quindi lo swap è necessario per questo. Cioè, rsync utilizzerà 50 GB per questo file. Il 2x è una metrica provata e vera da 30 anni. Poiché un disco da 6 TB è ~ $ 300, non c'è motivo di non farlo. Cos'altro potrebbe essere in esecuzione su questo server che collettivamente supererà il limite di RAM?
Craig Estey,

1
@CraigEstey 64 GB di swap è completamente ridicolo poiché, come ho affermato in precedenza, non abbiamo processi utente di grandi dimensioni, vogliamo solo la cache del disco e, come dimostrato dal mio registro, stavamo usando lo scambio ZERO al momento del crash. ZERO. Inoltre rsync utilizza 600 KB di RAM anche su un file da 50 GB. La mia prima confusione era che forse Linux si aggrappava aggressivamente alla cache del disco. E infine, voglio vedere alcuni numeri o documentazione su quanta memoria usa il kernel per tracciare il suo spazio di swap prima di aggiungere altro a questa casella.
dataless,

@dataless Ho aggiunto ulteriori informazioni che spiegano completamente cosa sta succedendo e perché. rsync sta afferrando la memoria tramite malloc / mmap e andrà per 50 GB prima che sia fatto. Vedi la sezione aggiornata. Ha dei test che possono dimostrare / confutare ciò che sto dicendo e puoi saltare inizialmente lo scambio aggiunto per testare. A proposito, sto programmando kernel / driver da oltre 40 anni - potrei solo sapere qualcosa che non conosci, quindi per favore modera il tono - Sto cercando di aiutare.
Craig Estey,

2

clamd? Sembra che tu stia usando ClamAV e che la scansione in accesso sia abilitata laddove il motore antivirus tenta di scansionare i file aperti alla ricerca di virus, caricando nella memoria l'intero contenuto di ogni file aperto da qualsiasi altro processo .

A seconda della posizione di sicurezza e della necessità di questo trasferimento, è necessario valutare la disabilitazione della scansione in accesso ClamAV durante l'esecuzione del trasferimento.


Non sapevo che fosse una cosa che Clamav poteva fare ... ma no, scansioniamo solo file specifici inviati ad esso da Clamc. Inoltre, a 32 bit, quindi nessun pericolo di clamav che registra tutta la memoria del sistema. (capisci perché pensavamo che 32 bit fosse ancora una buona idea?)
dataless

1
Il kernel Linux riporta che clamd è il processo le cui richieste di allocazione della memoria invocano il killer OOM - ClamAV è quasi sicuramente la causa secondaria (la causa primaria non è sufficiente memoria). Che si tratti di scansione in accesso o di qualche altra configurazione, tutti i segni indicano ClamAV.
oo.

La prossima volta che avvii rsync, esegui top e monitora la dimensione residente del processo clamd.
oo.

clamd è stato il primo processo a invocare l'assassino di Oom, ma anche il primo a morire perché pesa quasi 42 MB (uno dei processi più grandi sul server). Oom_killer viene eseguito più volte fino a quando non viene ucciso anche Metalog.
dataless
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.