-
Notifications
You must be signed in to change notification settings - Fork 0
EN_Linux_Kernel
somaz edited this page Jul 13, 2026
·
3 revisions
Question: Explain the kernel parameters (sysctl) commonly used in Linux, and present the key settings for network performance optimization and improved system stability.
Answer:
# Check all kernel parameters
sysctl -a
# Check a specific parameter
sysctl net.ipv4.ip_forward
sysctl vm.swappiness
# Change a parameter (temporary)
sudo sysctl -w net.ipv4.ip_forward=1
sudo sysctl -w vm.swappiness=10
# Change a parameter (permanent)
sudo vi /etc/sysctl.conf
sudo sysctl -p # apply# /etc/sysctl.conf or /etc/sysctl.d/99-network.conf
# ===== TCP/IP stack optimization =====
# net.core.rmem_max: maximum size of the TCP receive buffer
# - Default: 212992 (about 208KB)
# - Recommended: 134217728 (128MB) - 10Gbps high-speed network environment
# - Description: maximum size of the kernel buffer that stores packets received from the network card
# - Effect: improved throughput for large file transfers and streaming services
# - Caution: possibility of OOM under low memory, must consider system RAM
net.core.rmem_max = 134217728
# net.core.wmem_max: maximum size of the TCP send buffer
# - Default: 212992 (about 208KB)
# - Recommended: 134217728 (128MB)
# - Description: temporarily stores data sent by the application before transmitting it to the network card
# - Effect: improved send performance in high-bandwidth environments
# - Use cases: CDN servers, video streaming, large file servers
net.core.wmem_max = 134217728
# net.core.rmem_default / wmem_default: default buffer size when a socket is created
# - Description: used when the application does not explicitly specify a buffer size
# - Recommended: 16MB (suitable for typical web traffic)
net.core.rmem_default = 16777216
net.core.wmem_default = 16777216
# net.ipv4.tcp_rmem / tcp_wmem: per-socket TCP buffer auto-tuning (min, default, max)
# - Format: min default max
# - tcp_rmem = 4096 87380 134217728
# * 4096 (4KB): minimum buffer - guaranteed even under low memory
# * 87380 (85KB): default buffer - used for typical connections
# * 134217728 (128MB): maximum buffer - auto-expands on high-speed networks
# - Description: the kernel dynamically adjusts buffer size according to network conditions
# - Effect: Bandwidth-Delay Product (BDP) optimization
net.ipv4.tcp_rmem = 4096 87380 134217728
net.ipv4.tcp_wmem = 4096 65536 134217728
# ===== Connection queue management =====
# net.core.somaxconn: maximum value for the backlog parameter of the listen() system call
# - Default: 128 (very small!)
# - Recommended: 65535 (high-load web servers)
# - Description: size of the queue of fully connected (ESTABLISHED) sockets waiting before accept()
# - Problem: a small value causes "connection refused" errors
# - Effect: prevents connection loss even during traffic spikes
# - Example: works together with Nginx's listen 80 backlog=65535;
net.core.somaxconn = 65535
# net.core.netdev_max_backlog: size of the network device input queue
# - Default: 1000
# - Recommended: 100000 (10Gbps environment)
# - Description: queue where packets forwarded from the NIC to the kernel wait before being processed
# - Problem: a small value causes packet drops (RX dropped increases in ifconfig)
# - Check: netstat -s | grep "dropped"
# - Use cases: DDoS defense, high PPS (Packets Per Second) environments
net.core.netdev_max_backlog = 100000
# net.ipv4.tcp_max_syn_backlog: size of the SYN_RECV state socket queue
# - Default: 128-1024 (varies by distribution)
# - Recommended: 8192
# - Description: queue of half-open sockets that received a SYN but not yet an ACK
# - Problem: a small value is vulnerable to SYN Flood attacks
# - Effect: handles a large number of concurrent connection requests (traffic surge right after a web server boots)
# - Security: use together with tcp_syncookies
net.ipv4.tcp_max_syn_backlog = 8192
# ===== TIME_WAIT socket optimization =====
# net.ipv4.tcp_tw_reuse: reuse TIME_WAIT sockets for new connections
# - Default: 0 (disabled)
# - Recommended: 1 (enable on the client side)
# - Description: immediately reuse TIME_WAIT sockets for outbound connections to external servers
# - Fixes: prevents "Cannot assign requested address" errors
# - Scenario: API Gateway or Reverse Proxy sending many requests to backend servers
# - Caution: no effect on the server side (inbound); may cause problems in NAT environments
# - Check: ss -tan | grep TIME_WAIT | wc -l
net.ipv4.tcp_tw_reuse = 1
# net.ipv4.tcp_fin_timeout: how long to hold the FIN-WAIT-2 state
# - Default: 60 seconds
# - Recommended: 30 seconds
# - Description: the time to wait in the FIN-WAIT-2 state when closing a TCP connection
# - Effect: quickly reclaims resources from abnormally terminated connections
# - Caution: if too short (e.g., 5 seconds), slow-client problems may occur
net.ipv4.tcp_fin_timeout = 30
# ===== TCP Keepalive settings =====
# net.ipv4.tcp_keepalive_time: time before sending a keepalive probe on an idle connection
# - Default: 7200 seconds (2 hours)
# - Recommended: 600 seconds (10 minutes)
# - Description: the time before checking whether the connection is alive after the last data transmission
# - Effect: early detection of zombie connections
# - Use cases: load balancers, database connection pools, keeping SSH sessions alive
net.ipv4.tcp_keepalive_time = 600
# net.ipv4.tcp_keepalive_intvl: retransmission interval for keepalive probes
# - Default: 75 seconds
# - Recommended: 30 seconds
# - Description: the interval at which the next probe is sent when there is no response
net.ipv4.tcp_keepalive_intvl = 30
# net.ipv4.tcp_keepalive_probes: maximum number of keepalive probe retries
# - Default: 9 times
# - Recommended: 3 times
# - Description: number of attempts before dropping the connection when there is no response
# - Calculation: total wait time = keepalive_time + (keepalive_intvl * keepalive_probes)
# = 600 + (30 * 3) = the connection is closed after 690 seconds (about 11.5 minutes)
net.ipv4.tcp_keepalive_probes = 3
# ===== TCP Fast Open (TFO) =====
# net.ipv4.tcp_fastopen: TCP 3-way handshake optimization
# - Default: 0 (disabled)
# - Recommended: 3 (enable both client and server)
# - Meaning of the value:
# * 1: enable client only (when connecting to external servers)
# * 2: enable server only (accepting incoming connections)
# * 3: client + server (bitwise OR: 1 | 2 = 3)
# - Principle: include data in the SYN packet -> save 1 RTT (Round Trip Time)
# - Effect: reduced connection latency (noticeable improvement in environments with many HTTP requests)
# - Requirement: both client and server must support it (kernel 3.7+)
# - Security: SYN Flood defense via the TFO Cookie
net.ipv4.tcp_fastopen = 3
# ===== IP forwarding =====
# net.ipv4.ip_forward: enable IPv4 packet forwarding
# - Default: 0 (disabled)
# - Recommended: 1 (routers, NAT, Kubernetes nodes)
# - Description: allows packets to be forwarded to other networks
# - Required scenarios:
# * Kubernetes worker nodes (Pod-to-Pod communication)
# * Docker bridge networks
# * VPN gateways
# * NAT routers
# - Check: cat /proc/sys/net/ipv4/ip_forward
net.ipv4.ip_forward = 1
net.ipv6.conf.all.forwarding = 1
# ===== Local port range =====
# net.ipv4.ip_local_port_range: range of ephemeral ports used for outbound connections
# - Default: 32768 60999 (about 28,000 ports)
# - Recommended: 10000 65535 (about 55,000 ports)
# - Description: source ports automatically assigned when a client connects to an external server
# - Problem: a narrow range causes "Cannot assign requested address" errors
# - Scenario: Reverse Proxy or API Gateway making many connections to backends
# - Calculation: concurrent connections = (port range) / (TIME_WAIT time / connection duration)
# - Example: 1000 requests per second, TIME_WAIT 30 seconds -> at least 30,000 ports needed
# - Check: ss -tan | awk '{print $4}' | grep -oP ':\d+$' | sort | uniq -c
net.ipv4.ip_local_port_range = 10000 65535# ===== SYN Flood attack defense =====
# net.ipv4.tcp_syncookies: enable the SYN Cookie mechanism
# - Default: 1 (enabled by default on most distributions)
# - Recommended: 1 (mandatory)
# - Principle:
# 1. Normal: client SYN -> server SYN-ACK (stored in queue) -> client ACK
# 2. Attack: thousands of SYNs -> queue full -> normal connections refused
# 3. SYN Cookie: encode connection info into the SYN-ACK sequence number -> no queue needed
# - Effect: connections can still be accepted even when tcp_max_syn_backlog is exceeded
# - Downside: some TCP options (Window Scaling, etc.) may be lost
# - Check: netstat -s | grep "SYNs to LISTEN sockets dropped"
net.ipv4.tcp_syncookies = 1
# net.ipv4.tcp_max_syn_backlog: backup queue for SYN Flood defense
# - Use together with tcp_syncookies to strengthen attack defense
net.ipv4.tcp_max_syn_backlog = 8192
# ===== ICMP Redirect attack prevention =====
# net.ipv4.conf.*.accept_redirects: whether to accept ICMP Redirect messages
# - Default: 1 (accept)
# - Recommended: 0 (reject)
# - Attack scenario:
# 1. The attacker sends a forged ICMP Redirect message
# 2. The victim's routing table is altered
# 3. Traffic passes through the attacker -> MitM (Man-in-the-Middle) attack
# - Example: trick the victim into changing the gateway with a "there is a better route" message
# - Mandatory application: production servers, routers
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv6.conf.default.accept_redirects = 0
# ===== Source Routing attack prevention =====
# net.ipv4.conf.*.accept_source_route: whether to accept Source Routing packets
# - Default: 0 (disabled on most distributions)
# - Recommended: 0 (reject)
# - Attack principle:
# * Source Routing: the sender specifies the packet's route (normally decided by routers)
# * an attacker specifies an arbitrary route -> firewall bypass, spoofing
# - Effect: blocks IP spoofing attacks
net.ipv4.conf.all.accept_source_route = 0
net.ipv4.conf.default.accept_source_route = 0
# ===== ICMP Echo (Ping) response =====
# net.ipv4.icmp_echo_ignore_all: ignore Ping requests
# - Default: 0 (responds)
# - Recommended: 0 (general servers), 1 (high-security servers)
# - Advantage: evades network scans (Nmap, etc.)
# - Disadvantage: network debugging is harder (traceroute, ping unavailable)
# - Recommendation: it is better to control ICMP at the firewall
net.ipv4.icmp_echo_ignore_all = 0
# net.ipv4.icmp_echo_ignore_broadcasts: ignore broadcast Pings
# - Default: 1 (ignore)
# - Recommended: 1 (mandatory)
# - Attack: Smurf Attack (DDoS amplification via broadcast Ping)
net.ipv4.icmp_echo_ignore_broadcasts = 1
# ===== IP spoofing prevention (Reverse Path Filtering) =====
# net.ipv4.conf.*.rp_filter: reverse path filtering
# - Default: 0 (disabled) or 1
# - Recommended: 1 (Strict Mode)
# - Meaning of the value:
# * 0: disabled (dangerous!)
# * 1: Strict Mode - verify the reply packet would also go out through the interface it came in on
# * 2: Loose Mode - only verify that the reply route exists in the routing table
# - Principle: verify against the routing table whether the packet's source IP is forged
# - Example:
# * receive a packet on eth0 from 10.0.0.5
# * check the routing table: is the route to 10.0.0.5 via eth0?
# * if not -> judged as a spoofed packet and dropped
# - Effect: blocks source-IP forgery in DDoS attacks
# - Caution: use 2 (Loose Mode) in asymmetric routing environments
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
# ===== Security logging =====
# net.ipv4.conf.*.log_martians: log abnormal packets
# - Default: 0 (no logging)
# - Recommended: 1 (log)
# - Martian Packets:
# * reserved IP addresses (0.0.0.0, 127.0.0.0/8, 224.0.0.0/4)
# * broadcast addresses
# * multicast addresses
# * invalid source IPs
# - Log location: /var/log/kern.log or dmesg
# - Example: "martian source 192.168.1.1 from 10.0.0.5"
# - Purpose: network attack detection, configuration error debugging
# - Caution: heavy logging increases disk I/O
net.ipv4.conf.all.log_martians = 1
# ===== SYN/ACK retransmission =====
# net.ipv4.tcp_synack_retries: number of SYN-ACK retransmissions
# - Default: 5 times (about 180 seconds of waiting)
# - Recommended: 2 times (about 7 seconds of waiting)
# - Description: number of SYN-ACK retransmissions when the client does not send an ACK
# - Effect: quickly reclaims resources during a SYN Flood attack
# - Retransmission intervals: 1s, 2s, 4s, 8s, 16s (exponential backoff)
net.ipv4.tcp_synack_retries = 2
# net.ipv4.tcp_syn_retries: number of SYN retransmissions (client side)
# - Default: 6 times (about 127 seconds)
# - Recommended: 3 times (about 7 seconds)
# - Description: number of SYN packet retransmissions when connecting to an external server
net.ipv4.tcp_syn_retries = 3# ===== Swappiness =====
# vm.swappiness: aggressiveness of Swap usage (0-100)
# - Default: 60
# - Recommended:
# * 0: minimize Swap (database servers, Redis, Elasticsearch)
# * 10: performance-focused (web servers, application servers)
# * 60: default (desktops, general servers)
# * 100: aggressive Swap (low-memory environments)
# - Principle:
# * higher value -> the kernel more aggressively moves memory to Swap
# * lower value -> use RAM as much as possible, Swap is a last resort
# - Effect:
# * 0: increased chance of the OOM Killer triggering but best performance
# * 10: balance of performance and stability (recommended for production)
# * 60: possible performance degradation from increased disk I/O
# - Check:
# * cat /proc/sys/vm/swappiness
# * free -h (check Swap usage)
# * vmstat 1 (monitor Swap In/Out via the si/so columns)
# - Caution:
# * setting it to 0 does not completely disable Swap
# * fully disable with swapoff -a (recommended for Kubernetes)
vm.swappiness = 10
# ===== Dirty Page management =====
# vm.dirty_ratio: dirty page ratio threshold relative to total memory (%)
# - Default: 20 (20%)
# - Recommended: 15
# - Description:
# * Dirty Page: page cache that has been modified but not yet written to disk
# * when the threshold is reached -> processes block and are forced to start writing to disk
# - Problem: if too large (e.g., 40%) -> disk is written all at once -> system response lag
# - Example: 32GB RAM, dirty_ratio=15 -> forced write when 4.8GB of dirty pages accumulate
# - Effect: balance of write performance and system responsiveness
# - Check:
# * cat /proc/meminfo | grep Dirty
# * watch -n 1 'cat /proc/meminfo | grep -E "Dirty|Writeback"'
vm.dirty_ratio = 15
# vm.dirty_background_ratio: ratio at which background writing starts (%)
# - Default: 10 (10%)
# - Recommended: 5
# - Description:
# * when this value is reached -> the pdflush/flush kernel threads start writing to disk in the background
# * processes are not blocked (they keep running)
# - Principle:
# 1. dirty pages reach 5% -> background writing starts (smoothly)
# 2. dirty pages reach 15% -> forced writing (processes block)
# - Effect: spreads disk I/O out ahead of time to prevent response lag
vm.dirty_background_ratio = 5
# vm.dirty_expire_centisecs: dirty page expiration time (centiseconds, 1/100 second)
# - Default: 3000 (30 seconds)
# - Recommended: 3000
# - Description: dirty pages older than this time are written to disk with priority
# - Effect: prevents data loss (at most 30 seconds of data lost on power failure)
# - Scenario: file write -> power failure within 30 seconds -> data loss
vm.dirty_expire_centisecs = 3000
# vm.dirty_writeback_centisecs: pdflush thread execution interval (centiseconds)
# - Default: 500 (5 seconds)
# - Recommended: 500
# - Description: the cycle at which the pdflush kernel thread wakes up to check for dirty pages
# - Effect: controls the frequency of disk writes
# - Caution: setting the value to 0 disables background writing (dangerous!)
vm.dirty_writeback_centisecs = 500
# ===== OOM (Out Of Memory) Killer =====
# vm.overcommit_memory: memory overcommit policy
# - Default: 0 (heuristic)
# - Meaning of the value:
# * 0: heuristic - the kernel evaluates and judges each request (default)
# * 1: always allow - allows allocation beyond physical memory (dangerous!)
# * 2: strict limit - allows only up to Swap + RAM * overcommit_ratio
# - Description:
# * a process requests memory via malloc() -> physical memory is not allocated until actual use
# * overcommit: total allocation requested > actual physical memory
# - Scenario:
# * Mode 0: general servers (balanced)
# * Mode 1: scientific computing (allocates a lot of memory but uses little)
# * Mode 2: databases (predictable memory usage)
# - Check: cat /proc/meminfo | grep Committed
vm.overcommit_memory = 0
# vm.overcommit_ratio: allowed ratio when overcommit_memory=2 (%)
# - Default: 50 (50%)
# - Description: max allocation = Swap + (RAM * overcommit_ratio / 100)
# - Example: 32GB RAM, 8GB Swap, ratio=50 -> max 24GB (8 + 32*0.5)
vm.overcommit_ratio = 50
# vm.panic_on_oom: whether to kernel panic when OOM occurs
# - Default: 0 (run the OOM Killer)
# - Recommended: 0 (general servers), 1 (cluster nodes)
# - Description:
# * 0: the OOM Killer terminates a process that uses a lot of memory
# * 1: immediate kernel panic -> system reboot
# - Use cases:
# * 0: single server (kill just one process and keep the system up)
# * 1: HA cluster (restart the whole node to fail over)
vm.panic_on_oom = 0
# vm.oom_kill_allocating_task: terminate the process requesting memory when OOM occurs
# - Default: 0 (terminate the largest process)
# - Description:
# * 0: terminate the process with the highest OOM Score
# * 1: immediately terminate the process that requested memory
vm.oom_kill_allocating_task = 0
# ===== Huge Pages (large-memory applications) =====
# vm.nr_hugepages: number of Huge Pages
# - Default: 0 (disabled)
# - Recommended: calculation needed (application memory / 2MB)
# - Description:
# * regular page: 4KB
# * Huge Page: 2MB (x86_64)
# * reduces TLB (Translation Lookaside Buffer) misses -> improved performance
# - Calculation:
# * Oracle DB needs 10GB SGA -> 10240 MB / 2 MB = 5120 Huge Pages
# - Check:
# * cat /proc/meminfo | grep -i huge
# * hugeadm --pool-list
# - Use cases:
# * Oracle Database (SGA)
# * PostgreSQL (shared_buffers)
# * Redis (large instances)
# * SAP HANA
# - Caution:
# * pre-allocated at system boot (cannot be swapped)
# * setting too many starves regular applications of memory
vm.nr_hugepages = 0
# vm.hugetlb_shm_group: GID of the group allowed to use Huge Pages
# - Description: only users in this group can use Huge Pages
# - Example: oracle group GID=1001
vm.hugetlb_shm_group = 0
# ===== Transparent Huge Pages (THP) =====
# Note: THP is configured under /sys/kernel/mm/transparent_hugepage/, not via sysctl
# - Check: cat /sys/kernel/mm/transparent_hugepage/enabled
# - Disable (recommended for Redis, MongoDB, Oracle):
# echo never > /sys/kernel/mm/transparent_hugepage/enabled
# echo never > /sys/kernel/mm/transparent_hugepage/defrag
# - Reason: THP can cause latency due to dynamic allocation# File descriptor limits
fs.file-max = 2097152 # system-wide maximum FDs
fs.nr_open = 1048576 # maximum FDs per process
# inotify limits (file watching)
fs.inotify.max_user_watches = 524288 # maximum watches per user
fs.inotify.max_user_instances = 512 # number of instances
# AIO (asynchronous I/O)
fs.aio-max-nr = 1048576
# Kernel message buffer
kernel.printk = 4 4 1 7 # console log level
# Core dump settings
kernel.core_uses_pid = 1 # include PID in core dumps
kernel.core_pattern = /var/crash/core.%e.%p.%h.%t# ===== Bridge network settings (mandatory!) =====
# net.bridge.bridge-nf-call-iptables: process bridge traffic through iptables
# - Default: 0 (disabled) or 1
# - Recommended: 1 (mandatory for Kubernetes)
# - Description:
# * whether iptables rules are applied when Pod-to-Pod communication packets pass through the Linux bridge
# * Kubernetes Service (kube-proxy) implements load balancing with iptables
# - Problem: Service Discovery does not work when disabled
# - Required scenarios:
# * all Kubernetes nodes (master + worker)
# * Docker Swarm
# * Calico, Flannel, Weave network plugins
# - Check:
# * lsmod | grep br_netfilter (check module is loaded)
# * modprobe br_netfilter (load the module)
# - Caution: the br_netfilter kernel module must be loaded first
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
# ===== IP forwarding (mandatory!) =====
# net.ipv4.ip_forward: routing of Pod-to-Pod packets
# - Mandatory in Kubernetes (Pod-to-Pod, Pod-to-Service communication)
# - Check: sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
# ===== Conntrack (connection tracking) table =====
# net.netfilter.nf_conntrack_max: maximum number of entries in the Conntrack table
# - Default: 65536 (too small!)
# - Recommended: 1048576 (1 million, large clusters)
# - Description:
# * Conntrack: iptables tracks connections for its stateful firewall
# * an entry is created for each TCP/UDP connection (5-tuple: src IP, src port, dst IP, dst port, protocol)
# - Kubernetes scenario:
# * 100 Pods x 10 Services x 100 connections = 100,000+ entries
# * even more entries when using NodePort, LoadBalancer
# - Problem: exceeding it causes "nf_conntrack: table full, dropping packet" errors
# - Check:
# * cat /proc/sys/net/netfilter/nf_conntrack_count (current usage)
# * cat /proc/sys/net/netfilter/nf_conntrack_max (maximum)
# * conntrack -L | wc -l (actual number of connections)
# - Log: dmesg | grep conntrack
# - Calculation: roughly 25,000 entries possible per 1GB of memory
net.netfilter.nf_conntrack_max = 1048576
net.nf_conntrack_max = 1048576
# net.netfilter.nf_conntrack_tcp_timeout_established: TCP connection timeout
# - Default: 432000 (5 days!)
# - Recommended: 86400 (1 day) or 3600 (1 hour)
# - Description: how long an ESTABLISHED TCP connection is kept in the Conntrack table
# - Effect: quickly removes old connections to free up table space
# - Caution: if too short (e.g., 300 seconds), long-lived connections get dropped
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
# net.netfilter.nf_conntrack_tcp_timeout_time_wait: TIME_WAIT timeout
# - Default: 120 seconds
# - Recommended: 30 seconds
# - Description: how long a TIME_WAIT connection is kept in Conntrack
net.netfilter.nf_conntrack_tcp_timeout_time_wait = 30
# ===== ARP (Address Resolution Protocol) table =====
# net.ipv4.neigh.default.gc_thresh1: ARP table soft minimum
# - Default: 128 (too small!)
# - Recommended: 8192
# - Description: garbage collection is not run below this value
# - Problem: a small value causes "Neighbour table overflow" errors
# - Kubernetes: an IP address per Pod -> ARP entries surge
net.ipv4.neigh.default.gc_thresh1 = 8192
# net.ipv4.neigh.default.gc_thresh2: ARP garbage collection start
# - Default: 512
# - Recommended: 32768
# - Description: garbage collection starts when this value is exceeded (removes old entries)
net.ipv4.neigh.default.gc_thresh2 = 32768
# net.ipv4.neigh.default.gc_thresh3: ARP table hard maximum
# - Default: 1024
# - Recommended: 65536
# - Description: can never be exceeded; new entries are rejected once exceeded
# - Check:
# * ip -s neigh show (check the ARP table)
# * arp -an | wc -l (number of entries)
net.ipv4.neigh.default.gc_thresh3 = 65536
# ===== File descriptors =====
# fs.file-max: system-wide maximum file descriptors
# - Default: hundreds of thousands (varies by system)
# - Recommended: 2097152 (2 million)
# - Kubernetes: each Pod uses many FDs (sockets, files)
# - Check:
# * cat /proc/sys/fs/file-nr (in use / available / maximum)
# * lsof | wc -l (number of open files)
fs.file-max = 2097152
# fs.inotify.max_user_watches: number of files inotify watches
# - Default: 8192 (very small!)
# - Recommended: 524288
# - Description: detects file changes (kubectl logs -f, ConfigMap auto-reload)
# - Problem: exceeding it causes "too many open files" or "no space left on device" (even though disk is plentiful)
# - Use cases:
# * kubectl logs -f (real-time logs)
# * Prometheus file watching
# * IDEs (VS Code, IntelliJ)
# - Check:
# * cat /proc/sys/fs/inotify/max_user_watches
# * find /proc/*/fd -lname anon_inode:inotify | wc -l (in use)
fs.inotify.max_user_watches = 524288
fs.inotify.max_user_instances = 512
# ===== Disabling Swap (recommended for Kubernetes) =====
# vm.swappiness: 0 is recommended in Kubernetes
# - Description:
# * Kubernetes needs to accurately track memory resource limits
# * memory usage becomes unpredictable when Swap is used -> Pod Eviction malfunctions
# - Official recommendation: completely disable Swap (swapoff -a)
# - Alternative: vm.swappiness=0 (some Swap may still be used depending on the kernel)
vm.swappiness = 0
# ===== PID limit =====
# kernel.pid_max: maximum process ID for the system
# - Default: 32768
# - Recommended: 4194304 (large clusters)
# - Kubernetes: many Pods + Containers -> many processes
# - Check: cat /proc/sys/kernel/pid_max
kernel.pid_max = 4194304
# ===== Network performance =====
# net.core.somaxconn: throughput for Ingress Controllers and Services
# - Kubernetes Ingress (Nginx, Traefik) needs a high backlog
net.core.somaxconn = 65535
# net.ipv4.tcp_max_syn_backlog: NodePort, LoadBalancer traffic
net.ipv4.tcp_max_syn_backlog = 8192
# ===== Security (optional) =====
# net.ipv4.conf.all.rp_filter: may cause problems with Calico, Flannel
# - Loose Mode (2) recommended (allows asymmetric routing)
net.ipv4.conf.all.rp_filter = 2
net.ipv4.conf.default.rp_filter = 2Kubernetes node application example:
# /etc/sysctl.d/99-kubernetes.conf
# Bridge network (mandatory)
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
# IP forwarding (mandatory)
net.ipv4.ip_forward = 1
# Conntrack (large clusters)
net.netfilter.nf_conntrack_max = 1048576
net.netfilter.nf_conntrack_tcp_timeout_established = 86400
# ARP table
net.ipv4.neigh.default.gc_thresh1 = 8192
net.ipv4.neigh.default.gc_thresh2 = 32768
net.ipv4.neigh.default.gc_thresh3 = 65536
# File system
fs.file-max = 2097152
fs.inotify.max_user_watches = 524288
# Memory
vm.swappiness = 0
vm.overcommit_memory = 1
# Process
kernel.pid_max = 4194304
# Network
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 8192
# Apply
sudo modprobe br_netfilter
sudo sysctl --systemVerification script:
#!/bin/bash
echo "=== Kubernetes kernel parameter check ==="
echo "1. Bridge settings:"
sysctl net.bridge.bridge-nf-call-iptables
sysctl net.bridge.bridge-nf-call-ip6tables
echo "2. IP forwarding:"
sysctl net.ipv4.ip_forward
echo "3. Conntrack:"
echo " current: $(cat /proc/sys/net/netfilter/nf_conntrack_count)"
echo " maximum: $(cat /proc/sys/net/netfilter/nf_conntrack_max)"
echo "4. ARP table:"
echo " entries: $(ip neigh show | wc -l)"
sysctl net.ipv4.neigh.default.gc_thresh3
echo "5. File descriptors:"
cat /proc/sys/fs/file-nr
sysctl fs.inotify.max_user_watches
echo "6. Swap:"
sysctl vm.swappiness
free -h | grep SwapHigh-performance web server (Nginx/Apache):
# /etc/sysctl.d/99-web-server.conf
net.core.somaxconn = 65535
net.core.netdev_max_backlog = 100000
net.ipv4.tcp_max_syn_backlog = 8192
net.ipv4.tcp_tw_reuse = 1
net.ipv4.ip_local_port_range = 10000 65535
vm.swappiness = 10
fs.file-max = 2097152
# Apply
sudo sysctl -p /etc/sysctl.d/99-web-server.confDatabase server (MySQL/PostgreSQL):
# /etc/sysctl.d/99-database.conf
vm.swappiness = 1 # minimize Swap
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
kernel.shmmax = 68719476736 # maximum shared memory (64GB)
kernel.shmall = 4294967296
fs.file-max = 2097152
# Huge Pages (e.g., 10GB)
vm.nr_hugepages = 5120Kubernetes worker node:
# /etc/sysctl.d/99-kubernetes.conf
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
net.netfilter.nf_conntrack_max = 1048576
vm.swappiness = 0
fs.inotify.max_user_watches = 524288
fs.file-max = 2097152# Check current settings
sysctl -a | grep tcp_rmem
sysctl net.ipv4.tcp_tw_reuse
# Verify applied settings
cat /proc/sys/net/ipv4/tcp_tw_reuse
cat /proc/sys/vm/swappiness
# Verify automatic application at boot
sudo sysctl --system
# Configuration file locations
/etc/sysctl.conf # traditional location
/etc/sysctl.d/*.conf # applied with priority (recommended)
/run/sysctl.d/*.conf # runtime settings
/usr/lib/sysctl.d/*.conf # system defaults| Parameter | Default | Recommended | Purpose |
|---|---|---|---|
vm.swappiness |
60 | 10 | Web/DB servers |
net.core.somaxconn |
128 | 65535 | High-performance web servers |
net.ipv4.tcp_tw_reuse |
0 | 1 | TIME_WAIT reuse |
fs.file-max |
hundreds of thousands | 2097152 | File descriptors |
net.ipv4.ip_forward |
0 | 1 | Routers/Kubernetes |
net.netfilter.nf_conntrack_max |
65536 | 1048576 | Kubernetes |
fs.inotify.max_user_watches |
8192 | 524288 | IDEs/build tools |
Cautions:
- Always back up before making changes
- Test before applying in production environments
- Verify the settings persist across system reboots (
/etc/sysctl.confor/etc/sysctl.d/)
- What is Linux Kernel?
- Linux Documentation: https://www.kernel.org/doc/
- RedHat Documentation: https://access.redhat.com/documentation
- Ubuntu Server Guide: https://ubuntu.com/server/docs
- sysctl Documentation: https://www.kernel.org/doc/Documentation/sysctl/