Messa a punto del kernel nell'hosting Linux porta guadagni di prestazioni misurabili perché regolo in modo specifico i parametri sysctl per rete, memoria, CPU e sicurezza. Carico i profili senza riavviare e regolo i valori per i carichi di lavoro, la concomitanza e il comportamento dell'I/O in modo che il sistema di gestione della rete e della sicurezza Server reagisce rapidamente sotto carico e funziona in modo affidabile.
Punti centrali
- sysctl Controlla il comportamento del kernel in fase di esecuzione
- Rete ottimizzare: Arretrati, socket, TCP
- Memoria assetto: Scambio, Pagine sporche
- CPU regolazione fine: Schedulatore, PID
- Sicurezza tempra senza testa
Che cos'è sysctl nell'hosting Linux?
Con sysctl Leggo e modifico i parametri del kernel in fase di esecuzione senza compilare il kernel. I valori sono memorizzati come file nella directory /proc/sys, come net/ipv4/tcp_max_syn_backlog, e controllano la rete, la memoria e la sicurezza. Per l'hosting di carichi di lavoro con molte connessioni, la regolazione diretta riduce i picchi di latenza e i timeout. Apporto modifiche temporanee con sysctl -w e scrivo profili permanenti in /etc/sysctl.d/*.conf. Poi carico tutto con sysctl -system e controllo i log di dmesg e journal in modo da poter riconoscere rapidamente le configurazioni errate.
Come usare sysctl in modo sicuro
Prima di apportare modifiche Profili e documentare i valori effettivi con sysctl -a in modo da poter tornare indietro in qualsiasi momento. Per prima cosa, provo i nuovi valori su macchine virtuali di staging con un carico paragonabile. Poi aumento i parametri passo dopo passo, monitoro le metriche e aggiusto di nuovo. In questo modo evito uccisioni OOM, cadute di socket e ritrasmissioni sporadiche. Per configurazioni riproducibili, creo un file separato come /etc/sysctl.d/99-hosting.conf e lo carico in modo controllato.
Testare temporaneamente #
sudo sysctl -w net.core.somaxconn=65535
sudo sysctl -w net.ipv4.tcp_max_syn_backlog=4096
Impostare # in modo permanente
sudo tee /etc/sysctl.d/99-hosting.conf >/dev/null <<'EOF'
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 4096
vm.swappiness = 10
vm.dirty_ratio = 20
EOF
sudo sysctl --system
Parametri di rete che trasportano i server web
Per molte connessioni simultanee aumento somaxconn, in modo che il backlog della lista di Nginx o Apache non trabocchi. Uso net.ipv4.tcp_max_syn_backlog per aumentare la coda di connessioni semiaperte, il che aiuta durante i picchi di traffico. Nelle configurazioni solo web di solito lascio net.ipv4.ip_forward disattivato, mentre con i reverse proxy o i gateway lo attivo. Verifico le cadute del backlog con ss -s e netstat -s e controllo se le code di accettazione sono vuote. Se si vuole approfondire il controllo della congestione, si possono valutare anche algoritmi come CUBIC o BBR; il mio riferimento è a Controllo della congestione TCP.
# Valori esemplificativi per i server web più frequentati
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.ip_forward = 0
Messa a punto dello storage e delle macchine virtuali per i carichi di lavoro in hosting
Abbasso swappiness a 10, in modo che il kernel utilizzi la RAM più a lungo e faccia meno swap. Con vm.dirty_ratio del 15-20%, limito le pagine sporche in modo che il carico di scrittura non porti a lunghi flush burst. Per molti processi, imposto vm.overcommit_memory a 1 se conosco le applicazioni e ne capisco le riserve. Inoltre, monitoro gli hit della cache delle pagine e l'attesa dell'IO, in modo da poter interpretare correttamente gli effetti della cache. Ho approfondito il comportamento della cache con questa guida alla Cache di pagina.
# Profili di storage e VM
vm.swappiness = 10
vm.dirty_ratio = 20
vm.overcommit_memory = 1
Messa a punto della CPU e dello scheduler
Con un'alta concurrency sollevo kernel.pid_max in modo che molti processi worker ricevano gli ID. Per le quote CFS regolo kernel.sched_cfs_bandwidth_slice_us per evitare fette troppo corte per i servizi a raffica. Controllo le lunghezze delle code di esecuzione, i passaggi di contesto e i tempi di furto, soprattutto sugli host condivisi. Se ho bisogno di isolare la CPU, lego i servizi ai core tramite taskset o cgroup. Un'introduzione all'ottimizzazione del kernel più profonda è fornita da questo compact Prestazioni del kernel-Guida.
# Parametri del processo e dello schedulatore
kernel.pid_max = 4194304
# Esempio per fette di CFS più sottili
kernel.sched_cfs_bandwidth_slice_us = 5000
Parametri di sicurezza senza perdita di prestazioni
Attivo dmesg_restrict, per impedire agli utenti non privilegiati di leggere i log del kernel. Uso kernel.kptr_restrict per nascondere gli indirizzi che potrebbero aiutare gli aggressori con gli exploit. A livello di rete, attivo rp_filter per impostazione predefinita per prevenire lo spoofing IP. Queste impostazioni non costano quasi nulla in termini di prestazioni e rafforzano in modo significativo l'hardening dell'host. Le carico nello stesso file sysctl in modo controllato, in modo da rimanere rintracciabile.
# Irrigidimento tramite sysctl
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
Buffer di rete esteso per un'elevata produttività
Per gli host ad alto traffico mi adatto a Buffer TCP in modo che le connessioni veloci non si blocchino nel limite della finestra. Uso net.ipv4.tcp_rmem e tcp_wmem per definire le dimensioni minime, standard e massime. net.core.optmem_max e net.core.netdev_max_backlog aiutano ad assorbire in modo pulito le brevi raffiche. Controllo le ritrasmissioni, lo sviluppo del cwnd e i livelli di riempimento del buffer prima di aumentare ulteriormente i valori. Questi passaggi aumentano il throughput e riducono sensibilmente le fluttuazioni di latenza sui moderni collegamenti 10G.
Buffer di rete esteso #
net.core.optmem_max = 81920
net.core.netdev_max_backlog = 3000
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
Pratica: dalla linea di base al profitto misurabile
Inizio ogni accordatura con un Linea di base e documentare le cifre chiave come la latenza di P95, il throughput e il tasso di errore. Quindi modifico alcuni parametri, carico il profilo e lo misuro di nuovo con ab, wrk o sysbench. Se la latenza diminuisce, registro la variazione; se aumenta, la riduco. In questo modo costruisco un profilo di hosting che corrisponde alla mia applicazione. Infine, verifico nuovamente sotto carico di produzione prima di rendere permanenti i valori.
# Salva lo stato attuale
sysctl -a > /root/sysctl-baseline.txt
# Visualizzare i parametri di rete
sysctl -a | grep -E 'net\.core|net\\.ipv4'
# Ricaricare i profili
sysctl --sistema
Tabella di confronto: profilo standard vs. profilo hosting
Il seguente Tabella mostra i valori iniziali pratici che uso frequentemente. I valori dipendono dal carico di lavoro, dalla rete e dall'hardware. Inizio con questi valori, controllo le metriche e li aggiusto passo dopo passo. Se ci sono problemi, torno ai valori predefiniti e li aumento di nuovo a piccoli passi. In questo modo, riduco al minimo i rischi e ottengo risultati coerenti.
| Parametri | Standard | Profilo di hosting | Benefici |
|---|---|---|---|
| net.core.somaxconn | 128 | 65535 | Più connessioni accettate |
| net.ipv4.tcp_max_syn_backlog | 1024 | 4096 | Meno gocce con picchi |
| vm.swappiness | 60 | 10 | Meno scambi sotto carico |
| kernel.pid_max | 32768 | 4194304 | Possibilità di più processi/lavoratori |
| vm.dirty_ratio | 30 | 20 | Una scrittura più uniforme |
Evitare gli errori comuni e monitorare
Non uso Valori estremi, perché possono portare a timeout, uccisioni OOM o perdita di pacchetti. I cambiamenti vengono testati per fasi, ciascuna con una metrica chiara e una breve fase di osservazione. Gli indicatori critici sono la lunghezza della coda di accettazione, le ritrasmissioni TCP, la latenza P95, l'attesa IO e lo swap in/out. Per il monitoraggio utilizzo agenti e dashboard leggeri, in modo da poter riconoscere rapidamente le tendenze. Dopo gli aggiornamenti del kernel, controllo se i profili sysctl sono ancora validi e li ricarico se necessario.
Persistenza, sequenza e distribuzioni
Per garantire che i profili rimangano riproducibili, osservo la sequenza di caricamento in /etc/sysctl.d: I file vengono elaborati in modo lessicografico. Assegno deliberatamente prefissi come 60-... o 99-... per garantire che il mio profilo di hosting prevalga sugli altri predefiniti. Le differenze tra le distribuzioni (Debian/Ubuntu vs. RHEL/Alma) di solito riguardano solo i percorsi e i valori predefiniti; sysctl -system carica sempre /etc/sysctl.conf, /etc/sysctl.d/*.conf e i file del fornitore, se applicabile. Dopo i principali aggiornamenti del sistema, controllo con sysctl -system -o (dry run a seconda della versione) o confronto la configurazione effettiva caricata con il mio modello per evitare sorprese.
# Esempio: garantire una sequenza pulita
sudo ls -1 /etc/sysctl.d
10-vendor.conf
50-defaults.conf
99-hosting.conf # sovrascrive tutto ciò che lo precede
# diffonde efficacemente i valori caricati
sysctl -a > /root/sysctl-after.txt
diff -u /root/sysctl-baseline.txt /root/sysctl-after.txt | less
Ciclo di vita del TCP e gestione delle porte
In condizioni di carico elevato, vengono create molte connessioni di breve durata. Ho messo intervallo_porta_locale in modo che le connessioni in uscita (ad esempio dai proxy) non rimangano bloccate nel limite della porta effimera. tcp_fin_timeout controlla il tempo di permanenza dei socket in FIN-WAIT-2. Con un valore significativo Keepalive-Chiudo le sessioni morte più velocemente senza tagliare le connessioni in modo aggressivo. TIME_WAIT è normale e protegge dai pacchetti in ritardo; non lo riduco alla cieca. tcp_tw_reuse È utile soprattutto sugli host client, mentre sui server puri di solito rimane spento. Lascio attivi i timestamp e SACK, perché migliorano le prestazioni e la robustezza.
# Intervallo di porte e ciclo di vita TCP
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
# Attenzione a tcp_tw_reuse: è utile solo per il carico dei client in uscita.
# net.ipv4.tcp_tw_reuse = 1
Mantenere stabili le tabelle IPv6 e di vicinato
Molti host oggi trasportano traffico dual-stack. Ottimizzo le tabelle ARP/ND in modo che non ci siano messaggi di „overflow della tabella dei vicini“, soprattutto sui proxy o sui nodi con numerosi peer. Il gc_thresh-Definisco le soglie per adattarle alla matrice di connessione. Lascio le opzioni ICMPv6 e router add restrittive per i server, in modo da non includere rotte indesiderate. Per IPv4, faccio attenzione anche alla garbage collection di ARP, in modo che le voci invecchino per tempo ma non scompaiano troppo presto.
Tabelle di vicinato #: soglie più generose
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192
net.ipv6.neigh.default.gc_thresh1 = 1024
net.ipv6.neigh.default.gc_thresh2 = 4096
net.ipv6.neigh.default.gc_thresh3 = 8192
# Invecchiamento ARP/ND conservativo
net.ipv4.neigh.default.gc_stale_time = 60
Pensare ai descrittori di file e ai backlog insieme
Un collo di bottiglia frequente sono Descrittori di file. Se le applicazioni hanno migliaia di socket, fs.file-max (a livello di sistema) e ulimit/nofile (per servizio) si adattano. somaxconn aumenta la coda della lista, ma aiuta solo se il server web stesso è autorizzato ad aprire più FD e il tasso di accettazione è sufficientemente alto. Mi assicuro che i limiti di sistema e di servizio siano sincronizzati, altrimenti si verificano colli di bottiglia artificiali nonostante i „grandi“ arretrati del kernel.
# Consentire più FD a livello di sistema
fs.file-max = 2097152
# Lato servizio (esempio unità systemd)
# [Servizio]
# LimitNOFILE=1048576
Cuscinetto per carichi di lavoro UDP/QUIC
Utilizzo di DNS, syslog, telemetria e QUIC (HTTP/3) UDP. Qui scaliamo i buffer globali dei socket e i limiti di memoria specifici per UDP. Per grandi carichi UDP (come i gateway di telemetria), questo previene le cadute nel percorso di ricezione. Controllo i contatori di errori con ss -u -a e netstat -su e regolo gradualmente i massimi. Per QUIC, anche net.core.rmem_max/wmem_max è rilevante, poiché gli stack dello spazio utente spesso raggiungono questi limiti tramite setsockopt.
# Buffer e limiti UDP
net.core.rmem_max = 268435456
net.core.wmem_max = 268435456
net.ipv4.udp_mem = 98304 131072 262144
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
Specificare il writeback sporco: Byte invece di percentuali
Sui sistemi con molta RAM, i valori percentuali possono portare a grandi e improvvisi sprechi. Preferisco quindi usare vm.dirty_background_bytes e vm.dirty_bytes, per definire limiti massimi assoluti. In questo modo si stabilizza la velocità di scrittura e si attenuano le latenze, soprattutto con le unità disco o con carichi di lavoro misti. Considero anche vm.min_free_kbytes moderatamente, in modo che il kernel abbia abbastanza memoria libera per le allocazioni a raffica.
# Esempio: limiti assoluti di dirty (circa 1G di background, 4G di hard)
vm.dirty_background_bytes = 1073741824
vm.dirty_bytes = 4294967296
vm.min_free_kbytes = 65536
Distribuire il carico RPS/RFS e IRQ di rete
A velocità elevate di PPS, un singolo core della CPU può rimanere bloccato sull'IRQ della NIC. Uso il Receive Packet Steering (RPS) e, se necessario, il Receive Flow Steering (RFS) per distribuire l'elaborazione dei pacchetti su più core. A livello globale ho impostato net.core.rps_sock_flow_entries, L'allocazione effettiva avviene per coda tramite sysfs. Questo riduce gli hotspot della CPU, migliora la localizzazione della cache e riduce i picchi di latenza. In combinazione con net.core.netdev_max_backlog, si ottiene una pipeline più robusta.
# Voci di flusso globali per RPS
net.core.rps_sock_flow_entries = 32768
# Nota: la regolazione per coda avviene tramite /sys/class/net//queues/rx-*/rps_cpus
# e rps_flow_cnt, a seconda della NIC e del numero di code.
Contenitori, spazi dei nomi e macchine virtuali
I contenitori contengono molti rete.*-Valori namespaced e può essere applicato per ogni spazio dei nomi della rete. Per questo motivo, mi documento se sto personalizzando l'host o la rete di pod/container. Gli orchestratori spesso consentono solo un elenco sicuro di sysctl; valori come kernel.pid_max rimangono sul lato host. Sulle macchine virtuali, controllo quali NIC e offload virtuali sono attivi (virtio, ENA), perché offload e MTU hanno un forte impatto sui requisiti di buffer e sullo sviluppo di cwnd. Gli host bare-metal pesanti dal punto di vista di NUMA traggono vantaggio dalla disattivazione di vm.zone_reclaim_mode e la disposizione deliberata dell'affinità CPU/IRQ.
# Evitare l'effetto collaterale di NUMA
vm.zone_reclaim_mode = 0
Conntrack e i firewall stateful in sintesi
Se l'host funziona come NAT/firewall o ospita molti container con NAT in uscita, scalerei il nf_conntrack-tabella. Le tabelle Hash troppo piccole generano cadute e latenze elevate durante le scansioni delle tabelle. Misuro l'utilizzo con nstat e guardo a „previsto“ e „in uso“. Per i server web puri senza NAT, conntrack è spesso acritico o addirittura disattivato; sui gateway, deve essere incluso nel pacchetto di tuning.
Dimensione della traccia di connessione # (solo se utilizzata attivamente!)
net.netfilter.nf_conntrack_max = 1048576
Robustezza contro attacchi e anomalie
Aiuto per il traffico bot e le scansioni tcp_syncookies e le opzioni ICMP/redirect conservative. I Syncookies salvano l'handshake in caso di code SYN traboccanti, senza limitare eccessivamente il traffico legittimo. Disabilito i reindirizzamenti e i percorsi di origine sui server che non dovrebbero essere instradati. Queste misure di protezione sono leggere e integrano i meccanismi di protezione menzionati in precedenza.
# Difesa da SYN flood e comportamento di routing conservativo
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
Approfondire la pratica della misurazione: Cosa controllo regolarmente
Per ottenere risultati riproducibili, misuro costantemente prima e dopo le modifiche. Per quanto riguarda la rete, uso ss -s, ss -ti, nstat e netstat -s per vedere la lunghezza delle code, le ritrasmissioni e le statistiche sui sacchi. Per quanto riguarda la memoria I/O, vmstat, iostat e pidstat aiutano a classificare i flush sporchi, i context switch e i tempi di attesa della CPU. Esamino anche i test di carico:
- Coda di accettazione (LISTEN) e coda di SYN: cadute e overflow
- Sviluppo di pacing/throughput per connessione e cwnd
- Latenze P95/99 nel confronto A/B, invece della sola media
- Tasso di swap in/out e tasso di hit della cache di pagina
- Distribuzione del carico IRQ e lunghezza delle code di esecuzione per CPU
Controllo rapido dello stato dell'#
ss -s
netstat -s | egrep 'listen|SYN|retran|dropped'
vmstat 1 10
pidstat -w -u -r 1 5
Esempio: Profilo di hosting consolidato
Per iniziare, combino i valori di base e quelli estesi in un unico file. Poi aumento a piccoli passi, ciascuno con chiari punti di misurazione. I valori seguenti sono un punto di partenza conservativo ma performante per i server web e i proxy più impegnati.
sudo tee /etc/sysctl.d/99-hosting.conf >/dev/null <<'EOF'
Nozioni di base della rete #
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 4096
net.core.netdev_max_backlog = 3000
net.core.optmem_max = 81920
Buffer e porte TCP #
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.ip_local_port_range = 10240 65535
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 5
# UDP/QUIC
net.core.rmem_max = 268435456
net.core.wmem_max = 268435456
net.ipv4.udp_mem = 98304 131072 262144
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192
Tabelle dei vicini #
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 4096
net.ipv4.neigh.default.gc_thresh3 = 8192
net.ipv6.neigh.default.gc_thresh1 = 1024
net.ipv6.neigh.default.gc_thresh2 = 4096
net.ipv6.neigh.default.gc_thresh3 = 8192
net.ipv4.neigh.default.gc_stale_time = 60
Sicurezza #
kernel.dmesg_restrict = 1
kernel.kptr_restrict = 2
net.ipv4.conf.default.rp_filter = 1
net.ipv4.conf.all.rp_filter = 1
net.ipv4.tcp_syncookies = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# Memoria/VM
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_bytes = 1073741824
vm.dirty_bytes = 4294967296
vm.min_free_kbytes = 65536
vm.overcommit_memory = 1
vm.zone_reclaim_mode = 0
# CPU/Processi
kernel.pid_max = 4194304
kernel.sched_cfs_bandwidth_slice_us = 5000
# RPS
net.core.rps_sock_flow_entries = 32768
# FDs
fs.file-max = 2097152
EOF
sudo sysctl --system
Sommario: La messa a punto come processo ricorrente
Mirato Messa a punto del kernel con sysctl produce effetti chiari nell'hosting: tempi di risposta più brevi, valori di throughput più elevati e servizi costanti. Inizio con le basi della rete, come somaxconn e tcp_max_syn_backlog, poi mi occupo della memoria con swappiness e dirty_ratio. Ottimizzo poi i PID e gli scheduler e rendo più rigido l'host con dmesg_restrict, kptr_restrict e rp_filter. Misuro ogni modifica, la documento e tengo d'occhio le metriche. Passo dopo passo, creo un profilo che serve i miei carichi di lavoro in modo efficiente e che ha riserve per i picchi di traffico.


