Această pagină poate fi doar citită. Poți vedea sursa, dar nu poți modifica pagina. Consultă administratorul dacă ești de părere că ceva este în neregulă. ====== Optimizarea parametrilor kernel Linux pentru performanță mai bună ====== Majoritatea serverelor Linux rulează cu parametrii kernel impliciți. Este în regulă pentru sarcini generale, dar odată ce începi să încarci mai serios un server, acele valori implicite lasă performanță reală pe masă. ''sysctl'' este utilitarul care permite citirea și scrierea parametrilor kernel în timp ce sistemul rulează, iar ''/proc/sys'' este locul unde acești parametri există efectiv. Acest ghid acoperă cei mai utili parametri de ajustat pentru throughput de rețea, gestionarea memoriei, I/O pe fișiere și performanță generală a serverului - cum să aplici modificările în siguranță, să le faci permanente și să verifici că fac ce te aștepți. ===== Ce este sysctl? ===== ''sysctl'' este un utilitar pentru examinarea și modificarea parametrilor kernel în timp ce sistemul rulează, fără repornire. Parametrii sunt expuși ca fișiere sub ''/proc/sys/'', organizați în subdirectoare pe categorii. Listarea tuturor parametrilor curenți: <code bash> sysctl -a </code> Citirea unui parametru specific: <code bash> sysctl net.ipv4.tcp_syncookies </code> Setarea unui parametru temporar (nu supraviețuiește unui reboot): <code bash> sudo sysctl -w net.ipv4.tcp_syncookies=1 </code> Pentru a face modificările permanente, adaugă-le în ''/etc/sysctl.conf'' sau într-un fișier din ''/etc/sysctl.d/''. Abordarea preferată pe sistemele moderne este un fișier separat: <code bash> sudo nano /etc/sysctl.d/99-tuning.conf </code> Aplicarea modificărilor fără reboot: <code bash> sudo sysctl --system </code> Sau reîncărcarea unui fișier specific: <code bash> sudo sysctl -p /etc/sysctl.d/99-tuning.conf </code> Parametrii pot fi citiți și direct din ''/proc/sys''. Slash-urile din cale înlocuiesc punctele din numele sysctl. Astfel, ''net.ipv4.tcp_syncookies'' se află la: <code bash> cat /proc/sys/net/ipv4/tcp_syncookies </code> Ambele abordări citesc aceleași valori kernel. ''sysctl'' este pur și simplu mai convenabil. ===== Tuning performanță rețea ===== Acesta este domeniul unde ajustarea atentă poate da rezultate, dar și unde oamenii copiază valori de care nu au nevoie. Kernel-urile moderne ajustează automat buffer-ele de recepție TCP în intervalul setat, deci creșterea plafonurilor ajută doar când conexiunea este efectiv limitată de bandă pe o cale cu latență mare. Dacă muți cantități mari de date pe distanțe lungi, aceste setări contează. Pentru un server web tipic pe o rețea cu latență redusă, valorile implicite sunt de obicei bune. ==== Dimensiuni buffer TCP ==== Kernel-ul folosește buffer-e de recepție și trimitere pentru conexiunile TCP. Valorile implicite sunt conservatoare (aproximativ 208 KB). Pentru transferuri cu bandă largă și latență mare, maxime mai mari permit autotuning-ului să extindă fereastra mai mult. Acestea sunt plafoane, nu ținte - kernel-ul nu va aloca 64 MB per socket decât dacă o conexiune chiar are nevoie: <code> # Buffer recepție socket TCP (min, implicit, max) în octeți net.ipv4.tcp_rmem = 4096 87380 67108864 # Buffer trimitere socket TCP (min, implicit, max) în octeți net.ipv4.tcp_wmem = 4096 65536 67108864 # Maxime buffer recepție/trimitere socket core net.core.rmem_max = 67108864 net.core.wmem_max = 67108864 net.core.rmem_default = 262144 net.core.wmem_default = 262144 </code> ==== Controlul congestiei TCP ==== BBR (Bottleneck Bandwidth and Round-trip propagation time) este algoritmul de control al congestiei TCP de la [[https://github.com/google/bbr|Google]]. Poate depăși implicit ''cubic'' pe legături cu latență mare sau pierderi, deși nu este universal mai rapid. Benchmarkează-l față de algoritmul existent înainte să-l adopți. Verifică ce este disponibil pe sistem: <code bash> sysctl net.ipv4.tcp_available_congestion_control </code> BBR poate veni ca modul și să nu apară în acea listă până nu îl încarci. Dacă nu vezi ''bbr'': <code bash> sudo modprobe tcp_bbr </code> Pentru încărcare automată la boot: <code bash> echo tcp_bbr | sudo tee /etc/modules-load.d/tcp-bbr.conf </code> Odată disponibil BBR, activează-l (necesită kernel 4.9+): <code> net.ipv4.tcp_congestion_control = bbr net.core.default_qdisc = fq </code> ''fq'' (fair queuing) este scheduler-ul de pachete recomandat când folosești BBR, deoarece BBR se bazează pe pacing. ==== SYN Backlog și gestionarea conexiunilor ==== Sub trafic intens, cozile de conexiuni implicite se umplu rapid, cauzând refuzuri de conexiuni înainte ca aplicația să vadă cererea: <code> # Numărul maxim de conexiuni half-open în coada SYN net.ipv4.tcp_max_syn_backlog = 8192 # Numărul maxim de cereri de conexiune în coadă înainte ca aplicația să le accepte net.core.somaxconn = 65535 # Numărul maxim de pachete în coadă pe partea INPUT net.core.netdev_max_backlog = 16384 </code> Activează SYN cookies pentru protecție împotriva atacurilor SYN flood: <code> net.ipv4.tcp_syncookies = 1 </code> ==== TIME_WAIT și reciclarea conexiunilor ==== Serverele care gestionează multe conexiuni de scurtă durată (API-uri HTTP, de exemplu) pot acumula mii de socket-uri în starea ''TIME_WAIT''. Verifică contorul curent: <code bash> ss -s | grep TIME-WAIT </code> **''tcp_tw_reuse''** permite kernel-ului să reutilizeze un socket ''TIME_WAIT'' pentru o conexiune nouă. Important: se aplică **doar conexiunilor ieșitoare**, deci ajută un server care face multe conexiuni în exterior (un reverse proxy care vorbește cu backend-uri, de exemplu) și nu face nimic pentru conexiunile client entrante. Valoarea implicită este ''2'' (loopback only): <code> # Avansat: reutilizează socket-uri TIME_WAIT doar pentru conexiuni ieșitoare # Implicit este 2 (loopback). Setează deliberat, nu din obișnuință. net.ipv4.tcp_tw_reuse = 1 </code> ''tcp_max_tw_buckets'' limitează numărul de socket-uri ''TIME_WAIT''. Această limită există ca protecție DoS de bază, deci reducerea ei este instinctul greșit: <code> net.ipv4.tcp_max_tw_buckets = 262144 </code> ==== Tuning Keepalive ==== Keepalive este detectarea peer-urilor moarte, nu o optimizare de performanță, și se activează doar pentru aplicațiile care activează ''SO_KEEPALIVE'' pe socket-urile lor. Valorile implicite ale kernel-ului sunt 2 ore idle, 75 secunde între sonde și 9 sonde. Scurtarea lor detectează mai rapid conexiunile moarte, eliberând descriptorii de fișiere și memoria: <code> # Începe trimiterea keepalive după 60 secunde de idle (implicit: 7200) net.ipv4.tcp_keepalive_time = 60 # Intervalul dintre sondele keepalive net.ipv4.tcp_keepalive_intvl = 10 # Numărul de sonde înainte de a declara conexiunea moartă net.ipv4.tcp_keepalive_probes = 6 </code> ===== Gestionarea memoriei ===== ==== Swappiness ==== Controlează cât de agresiv mută kernel-ul paginile de memorie anonimă în swap. Valoarea implicită este 60, intervalul este 0 la 200. Verifică valoarea curentă: <code bash> cat /proc/sys/vm/swappiness </code> Pentru un server sensibil la latență unde preferi să păstrezi paginile în RAM: <code> vm.swappiness = 10 </code> Valoarea 1 este cea mai mică setare utilă fără a dezactiva complet swap-ul. Testează cu sarcina ta reală înainte să stabilești un număr. ==== VFS Cache Pressure ==== Controlează cât de agresiv recuperează kernel-ul memoria folosită pentru cache-urile inode și dentry (cache-ul de metadate director/fișier). Valorile mai mici păstrează mai mult din acest cache în memorie, ceea ce accelerează operațiunile de sistem de fișiere: <code> vm.vfs_cache_pressure = 50 </code> Valoarea implicită este 100. Pe un server cu multă RAM și o sarcină de lucru care accesează frecvent multe fișiere, reducerea la 50 menține mai multe metadate în cache. Nu merge prea jos pe sisteme cu memorie limitată și nu seta niciodată la 0. ==== Dirty Page Writeback ==== Controlează cât de agresiv scrie kernel-ul paginile murdare (date modificate în așteptare pentru a fi scrise pe disc) pe stocare. Relevant pe servere cu sarcini de scriere intense: <code> # Procentul din RAM murdar înainte ca kernel-ul să blocheze scrierile pentru flush (limita hard) vm.dirty_ratio = 10 # Procentul din RAM care poate fi murdar înainte să înceapă writeback în fundal vm.dirty_background_ratio = 5 # Cât timp rămân datele murdare înainte să fie scrise (în centisecunde, implicit 3000 = 30s) vm.dirty_expire_centisecs = 1500 # Cât de des se trezește daemon-ul writeback (centisecunde, implicit 500 = 5s) vm.dirty_writeback_centisecs = 250 </code> > **Atenție:** Timing-ul writeback **nu este o garanție de durabilitate** și nu protejează împotriva pierderii bruște de curent. Durabilitatea vine din ''fsync()'' / ''fdatasync()'' în aplicație, journaling, cache-uri de scriere cu baterie și UPS. Pe mașini cu memorie mare există o capcană de scalare: pe un server cu 256 GB RAM, ''dirty_ratio = 10'' înseamnă ~25 GB, iar flush-ul dintr-o dată poate bloca sistemul cu un spike masiv de I/O. Pe sisteme cu memorie mare, setează limite absolute: <code> # Limite absolute în octeți în loc de procente (mai bine pentru sisteme cu RAM mare) vm.dirty_bytes = 536870912 # 512 MB limita hard vm.dirty_background_bytes = 268435456 # 256 MB pragul pentru background </code> Setarea formei ''_bytes'' la o valoare nenulă dezactivează forma corespunzătoare ''_ratio''. Folosește una sau cealaltă pereche, nu ambele. ==== Comportament Overcommit ==== <code> # 0 = heuristic (implicit) # 1 = permite întotdeauna overcommit (util pentru unele sarcini HPC/științifice) # 2 = niciodată overcommit peste RAM fizic + swap vm.overcommit_memory = 0 </code> [[https://redis.io/docs/latest/operate/oss_and_stack/management/admin/|Documentația Redis]] recomandă setarea la 1 pentru a evita eșecurile la salvarea în fundal. Lasă la 0 dacă nu ai un motiv specific. ===== Limite pentru descriptori de fișiere și procese ===== Serverele cu trafic intens pot atinge limita descriptorilor de fișiere mult înainte să atingă limitele CPU sau memorie. Nginx, Node.js și bazele de date deschid mulți descriptori de fișiere per conexiune. ==== Numărul maxim de fișiere deschise ==== <code> # Limita de descriptori de fișiere la nivel de sistem fs.file-max = 2097152 </code> Înainte de a modifica, verifică dacă ești cu adevărat aproape de plafon: <code bash> cat /proc/sys/fs/file-nr </code> Cele trei valori sunt: handle-uri alocate, handle-uri alocate nefolosite și maximul. Dacă prima valoare este departe de a treia, ridicarea ''fs.file-max'' nu îți folosește la nimic. > **Notă:** Limita kernel setată aici este plafonul. Trebuie să setezi și ''LimitNOFILE'' în unitățile de serviciu systemd, sau să folosești ''ulimit -n'' pentru procesele non-systemd. Limita kernel singură nu este suficientă. ==== Limite Inotify ==== Dacă rulezi aplicații care monitorizează fișiere (unelte de build, IDE-uri pe un server remote, sau agenți de monitorizare), poți atinge limitele inotify: <code> fs.inotify.max_user_watches = 524288 fs.inotify.max_user_instances = 512 </code> Simptomul când atingi aceste limite este de obicei o eroare de tipul "too many open files" sau "inotify watch limit reached" în logurile aplicației. ===== Parametri de securitate ===== Unii parametri sysctl privesc atât securitatea cât și performanța. Merită incluși în configurația de bază standard: <code> # Ignorarea cererilor ICMP broadcast (protecție atac Smurf) net.ipv4.icmp_echo_ignore_broadcasts = 1 # Ignorarea răspunsurilor ICMP de eroare false net.ipv4.icmp_ignore_bogus_error_responses = 1 # Filtrare reverse path (ajută la prevenirea IP spoofing) # 1 = strict, 2 = loose. Folosește 2 pentru rutare asimetrică/multihomed. net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 # Dezactivarea IP source routing net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.default.accept_source_route = 0 # Dezactivarea acceptării redirect-urilor ICMP net.ipv4.conf.all.accept_redirects = 0 net.ipv4.conf.default.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 # Nu trimite redirect-uri ICMP (nu este router) net.ipv4.conf.all.send_redirects = 0 # Logarea pachetelor martian (pachete cu adrese sursă imposibile) net.ipv4.conf.all.log_martians = 1 </code> > **Atenție:** Filtrarea reverse path strictă (''1'') poate strica rutarea asimetrică, policy routing, VPN-urile și unele configurații multihomed. Dacă traficul poate ajunge legitim pe o interfață diferită față de cea pe care pleacă, folosește modul loose (''2''). Dacă serverul nu acționează ca router: <code> net.ipv4.ip_forward = 0 </code> Schimbarea ''ip_forward'' resetează mai mulți parametri de configurare IPv4, deci setează deliberat. Dacă mașina este router sau rulează Docker, vei vrea valoarea 1. ===== O configurație de bază completă ===== Aceasta este un punct de **pornire**, nu o configurație de copiat orb. Dimensiunile buffer-elor de rețea, swappiness, cache pressure și setările dirty-page depind de sarcina de lucru. Salvează în ''/etc/sysctl.d/99-tuning.conf'': <code> # /etc/sysctl.d/99-tuning.conf # Punct de pornire sysctl - citește secțiunile de mai sus înainte să aplici ## Rețea: dimensiuni buffer TCP net.ipv4.tcp_rmem = 4096 87380 67108864 net.ipv4.tcp_wmem = 4096 65536 67108864 net.core.rmem_max = 67108864 net.core.wmem_max = 67108864 net.core.rmem_default = 262144 net.core.wmem_default = 262144 ## Rețea: control congestie (necesită kernel 4.9+ pentru BBR) net.ipv4.tcp_congestion_control = bbr net.core.default_qdisc = fq ## Rețea: gestionare conexiuni net.ipv4.tcp_max_syn_backlog = 8192 net.core.somaxconn = 65535 net.core.netdev_max_backlog = 16384 net.ipv4.tcp_syncookies = 1 ## Rețea: TIME_WAIT # tcp_tw_reuse omis - este doar pentru ieșiri, implicit 2. Setează per sarcină de lucru. net.ipv4.tcp_max_tw_buckets = 262144 ## Rețea: Keepalive net.ipv4.tcp_keepalive_time = 60 net.ipv4.tcp_keepalive_intvl = 10 net.ipv4.tcp_keepalive_probes = 6 ## Memorie vm.swappiness = 10 vm.vfs_cache_pressure = 50 vm.dirty_ratio = 10 vm.dirty_background_ratio = 5 vm.dirty_expire_centisecs = 1500 vm.dirty_writeback_centisecs = 250 ## Descriptori de fișiere (ridică doar dacă file-nr arată că ești aproape de plafon) fs.file-max = 2097152 fs.inotify.max_user_watches = 524288 ## Securitate net.ipv4.icmp_echo_ignore_broadcasts = 1 net.ipv4.icmp_ignore_bogus_error_responses = 1 # rp_filter: folosește 2 (loose) dacă ai rutare asimetrică/multihomed net.ipv4.conf.all.rp_filter = 1 net.ipv4.conf.default.rp_filter = 1 net.ipv4.conf.all.accept_source_route = 0 net.ipv4.conf.all.accept_redirects = 0 net.ipv6.conf.all.accept_redirects = 0 net.ipv4.conf.all.send_redirects = 0 net.ipv4.conf.all.log_martians = 1 </code> Aplică imediat: <code bash> sudo sysctl -p /etc/sysctl.d/99-tuning.conf </code> ===== Cum verifici că modificările funcționează ===== Nu presupune niciodată că o modificare a făcut ce te așteptai. Verifică fiecare parametru după aplicare: <code bash> sysctl net.ipv4.tcp_congestion_control </code> Confirmă că BBR este activ pe conexiunile stabilite: <code bash> ss -tin | grep bbr | head -5 </code> Verifică situația descriptorilor de fișiere sub sarcină: <code bash> cat /proc/sys/fs/file-nr </code> Monitorizează activitatea paginilor murdare: <code bash> cat /proc/meminfo | grep -i dirty </code> Dacă ceva se comportă greșit după aplicarea modificărilor, ''dmesg'' este un check util de depanare: <code bash> sudo dmesg | tail -20 </code> Potrivește utilitarul cu ce testezi: [[https://iperf.fr/|iperf3]] pentru throughput brut de rețea, ''ss -s'' și ''ss -tin'' pentru starea TCP, ''vmstat'' / ''iostat'' / ''sar'' pentru comportamentul sistem în timp. Pentru orice contează cu adevărat, folosește un benchmark specific aplicației - [[https://github.com/wg/wrk|wrk]] sau ''ab'' (Apache Bench) pentru un server web, uneltele proprii ale bazei de date pentru o bază de date. ===== Considerații pentru medii speciale ===== În containere, anumiți parametri (mai ales cei de rețea) pot fi setați la nivel de host și să nu poată fi scriși din interior. Parametrii kernel ai hostului se aplică tuturor containerelor care rulează pe el. În mașini virtuale, ai control complet atâta timp cât hypervisor-ul nu restricționează accesul. > **Notă:** Unele imagini pre-configurate (cloud sau altele) pot avea deja ajustați anumiți parametri. Rulează ''sysctl -a'' pe un sistem proaspăt și compară cu valorile implicite înainte să aplici un fișier de tuning, ca să nu duplici sau să suprascrii setări deja existente. ===== Ce să nu atingi ===== Câțiva parametri par tentanți, dar cauzează mai multe probleme decât rezolvă: * **''net.ipv4.tcp_tw_recycle''** a fost eliminat complet în kernel 4.12. Pe kernel-uri mai vechi cauza conexiuni abandonate pentru clienții din spatele NAT. Nu îl folosi. * **''vm.overcommit_memory = 1''** poate masca scurgeri de memorie și face kill-urile OOM mai greu de prezis. Setează-l doar dacă știi exact de ce ai nevoie. * **Huge pages** (''vm.nr_hugepages'') pot ajuta semnificativ serverele de baze de date ca MySQL și PostgreSQL, dar configurarea greșită poate împiedica pornirea serviciilor. Este un subiect separat care merită propriul ghid. ===== Concluzie ===== Configurația implicită a kernel-ului Linux este conservatoare prin design - trebuie să funcționeze rezonabil pe orice, de la un Raspberry Pi la un server cu 256 de nuclee. Pentru orice sarcină specifică, poți face mai bine. Începe cu setările de buffer de rețea și control al congestiei dacă rulezi orice cu față la internet. Adaugă ajustările de swappiness și cache pressure pentru orice server care rulează pe termen lung. Adaugă setările de hardening de securitate ca bază peste tot. Fă modificările o secțiune pe rând. Măsoară înainte și după. Păstrează o copie a valorilor implicite originale pentru a putea reveni. Și pune fișierul final de tuning în control de versiuni sau sistemul tău de configuration management, astfel încât să urmeze automat fiecare server nou provizionat. ===== Referințe ===== * [[https://docs.kernel.org/admin-guide/sysctl/index.html|Documentația sysctl kernel Linux]] * [[https://github.com/google/bbr|BBR TCP Congestion Control (Google)]] * [[https://redis.io/docs/latest/operate/oss_and_stack/management/admin/|Redis Administration]] * [[https://linuxblog.io/linux-performance-no-swap-space/|Linux swap space guide (LinuxBlog.io)]] * [[https://linuxblog.io/linux-server-after-installation/|Linux Server Setup guide]] {{tag>linux kernel sysctl performanta retea securitate server}}