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.
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:
sysctl -a
Citirea unui parametru specific:
sysctl net.ipv4.tcp_syncookies
Setarea unui parametru temporar (nu supraviețuiește unui reboot):
sudo sysctl -w net.ipv4.tcp_syncookies=1
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:
sudo nano /etc/sysctl.d/99-tuning.conf
Aplicarea modificărilor fără reboot:
sudo sysctl --system
Sau reîncărcarea unui fișier specific:
sudo sysctl -p /etc/sysctl.d/99-tuning.conf
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:
cat /proc/sys/net/ipv4/tcp_syncookies
Ambele abordări citesc aceleași valori kernel. sysctl este pur și simplu mai convenabil.
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.
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:
# 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
BBR (Bottleneck Bandwidth and Round-trip propagation time) este algoritmul de control al congestiei TCP de la 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:
sysctl net.ipv4.tcp_available_congestion_control
BBR poate veni ca modul și să nu apară în acea listă până nu îl încarci. Dacă nu vezi bbr:
sudo modprobe tcp_bbr
Pentru încărcare automată la boot:
echo tcp_bbr | sudo tee /etc/modules-load.d/tcp-bbr.conf
Odată disponibil BBR, activează-l (necesită kernel 4.9+):
net.ipv4.tcp_congestion_control = bbr net.core.default_qdisc = fq
fq (fair queuing) este scheduler-ul de pachete recomandat când folosești BBR, deoarece BBR se bazează pe pacing.
Sub trafic intens, cozile de conexiuni implicite se umplu rapid, cauzând refuzuri de conexiuni înainte ca aplicația să vadă cererea:
# 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
Activează SYN cookies pentru protecție împotriva atacurilor SYN flood:
net.ipv4.tcp_syncookies = 1
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:
ss -s | grep TIME-WAIT
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):
# 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
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:
net.ipv4.tcp_max_tw_buckets = 262144
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:
# Î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
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ă:
cat /proc/sys/vm/swappiness
Pentru un server sensibil la latență unde preferi să păstrezi paginile în RAM:
vm.swappiness = 10
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.
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:
vm.vfs_cache_pressure = 50
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.
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:
# 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
Atenție: Timing-ul writeback nu este o garanție de durabilitate și nu protejează împotriva pierderii bruște de curent. Durabilitatea vine dinfsync()/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:
# 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
Setarea formei _bytes la o valoare nenulă dezactivează forma corespunzătoare _ratio. Folosește una sau cealaltă pereche, nu ambele.
# 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
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.
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.
# Limita de descriptori de fișiere la nivel de sistem fs.file-max = 2097152
Înainte de a modifica, verifică dacă ești cu adevărat aproape de plafon:
cat /proc/sys/fs/file-nr
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 șiLimitNOFILEîn unitățile de serviciu systemd, sau să foloseștiulimit -npentru procesele non-systemd. Limita kernel singură nu este suficientă.
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:
fs.inotify.max_user_watches = 524288 fs.inotify.max_user_instances = 512
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.
Unii parametri sysctl privesc atât securitatea cât și performanța. Merită incluși în configurația de bază standard:
# 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
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:
net.ipv4.ip_forward = 0
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.
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:
# /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
Aplică imediat:
sudo sysctl -p /etc/sysctl.d/99-tuning.conf
Nu presupune niciodată că o modificare a făcut ce te așteptai. Verifică fiecare parametru după aplicare:
sysctl net.ipv4.tcp_congestion_control
Confirmă că BBR este activ pe conexiunile stabilite:
ss -tin | grep bbr | head -5
Verifică situația descriptorilor de fișiere sub sarcină:
cat /proc/sys/fs/file-nr
Monitorizează activitatea paginilor murdare:
cat /proc/meminfo | grep -i dirty
Dacă ceva se comportă greșit după aplicarea modificărilor, dmesg este un check util de depanare:
sudo dmesg | tail -20
Potrivește utilitarul cu ce testezi: 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 - wrk sau ab (Apache Bench) pentru un server web, uneltele proprii ale bazei de date pentru o bază de date.
Î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 -ape 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.
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.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.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.