8 Ekim 2013 Salı

Linux kernelına ve tcp performansına ilişkin bazı ayarlar ve açıklamaları

Burada kendi sunucularımda kullandığım çeşitli kernel ayarlarını yazdım. Bu değerleri sysctl -a komutuyla görüntüleyebilir. /etc/sysctl.conf dosyasında gerekli gördüğünüz değişiklikleri yapabilir, bu değişiklikleri makinayı yeniden başlatmadan, anında uygulamak isterseniz sysctl -p /etc/sysctl.conf komutunu kullanabilirsiniz.

Default verilen ayarlar virtualbox'da 384mb alan ayırdığım Debian'a ait:
Linux debian-70rc1-x64-vbox4210 3.2.0-4-amd64 #1 SMP Debian 3.2.35-2 x86_64 GNU/Linux

Bu ayarların bazılarının sunucu olarak kullanılan Linux'larda düzenlenmesinin elzem olduğunu düşünüyorum. Öte yandan herhangi bir sorun ile karşılaşmadıysanız, ya da özel / deneysel bir kurulum yapma peşinde değilseniz bunlarla çok fazla oynamanızı tavsiye etmem. Bir büyüğümüzün de söylediği gibi: "Premature optimization is the root of all evil." ve "Çalışıyorsa, siktir edin- dokunmayın."

Bir çok blog sitesinde çeşit çeşit sysctl performans ayarlarıyla karşılaşabilirsiniz, bu ayarların tek tek ne olduğunu araştırmadan ve bilmeden bunları uygularsanız %90 ihtimalle verimsiz bir sunucu performansıyla karşı karşıya kalırsınız.

Burada belirtilen değerler en çok karşılaşılan (out of socket memory error, possible syn flood vb.) hata mesajlarıyla ilgili. Bu değerler kernelda tweak edebileceğiniz ayarların çok çok ufak bir kısmı, ama genel olarak yüksek trafikli sunucularda ilk el atılması gereken seçenekler. Gözünüz kapalı bu değerleri uygulamadan önce /var/log klasörüne ve /var/log/syslog dosyalarına sıklıkla göz atın ve sisteminizin arızalı ya da sistem performansınızın düşük olmasının altında yatan asıl sebebe odaklanın.


kernel.panic = 1 (default: 0)
kernel.panic_on_oops = 1 (default: 0)


Kernel panic ve oops durumlarında kaç sn. sonra sistemin yeniden başlatılması gerektiğini belirliyor.



kernel.sysrq = 0 (default: 438)


SysRq tuşu kullanıldığında verilen erişim izinlerini belirliyor.



kernel.core_uses_pid = 1 (default: 0)


Core dump dosyalarına PID eklenip eklenmeyeceğini belirliyor.



kernel.pid_max = 65536 (default: 32768)


Verilebilecek maksimum PID pid_max-1’dir. 32-bit sistemlerde bu sayı 32768’in üzerine çıkamaz, 64-bit sistemler 2^22’nin üzerine çıkamaz.



kernel.msgmax = 32768 (default: 8192)


Her bir System V message’ın byte cinsinden maksimum boyutu.



kernel.msgmnb = 65536 (default: 16384)


Mesaj queueların byte cinsinden maksimum boyutu.



kernel.msgmni = 738 (default: 738)


Toplam mesaj queue identifier sayısı.



kernel.shmmax = (Toplam ram * 1024 * 1024 * 1024)


Olusturulabilecek maksimum shared memory segment boyutunu belirler. 16 gb ram icin: (16 * 1024 * 1024 * 1024)



kernel.shmall = (Toplam ram * 1024 * 1024 * 1024) / Page size


Shared memory toplam page sayısını belirler. 16 gb ram, PAGE_SIZE = 4096 icin: (16 * 1024 * 1024 * 1024) / 4096 (getconf PAGE_SIZE)



fs.file-max


Tüm processler tarafından açılabilecek toplam açık dosya sayısı belirler. Kernel constant NR_OPEN üst limittir. Bu değeri değiştirirseniz inode-max değerini de bu değerin en az 3-4 katına çıkardığınıza emin olun. Bazı sitelerde her 4mb ram için 256 değeri önerilmiş, buna göre 2 gb ram için: (2048/4) = 512 _ 512 x 256 = 131072. Bununla beraber her kullanıcı için limitleri (ulimit -n) /etc/security/limits.conf dosyasından değiştirmek gerekiyor.



fs.inode-max = fs.file-max değeri * 4


Hafızada tutulabilecek en fazla inode sayısını belirliyor. file-max değerinin en az 3-4 katı olmalı.



vm.swappiness = 20 (default: 60)


Bu değer memory pagelerin ne kadar sıkışıklık durumunda swaplenmesi gerektiğini belirliyor. Eğer buna 0 değeri verilirse, swapleme işlemi yapılmıyor. 100 değeri verilirse her fırsatta swap yapılıyor.



vm.mmap_min_addr = 65536 (default: 65536)


Processlerin mmap edebileceği min. sanal adres. Bazı uygulamaların düzgün çalışabilmesi için azaltılması gerekebilir.


vm.min_free_kbytes = 65536


Bu değer kernela hafızada en az burada belirtilen değer (bu örnekde 64mb) kadar alanı boş bırakması gerektiğini belirtiyor.



net.ipv4.tcp_moderate_rcvbuf = 1 (default: 1)


Eğer aktif edilirse, tcp_rmem değerleri limit olarak alınıp receive bufferlar otomarik olarak boyutlandırılır.



net.ipv4.tcp_rmem = 4096 87380 ((bandwidth / 8) * latency) + 65536


TCP receive bufferların boyutlarını belirleyen, 3 integerdan oluşan vektör. Alıcı tarafta olunan her soketin byte cinsinden hafızada ne kadar alan işgal edebileceğini belirler. İlk değer minimum, ikinci değer default, üçüncü değer maksimum limitler. Alıcı olarak kullanılan her soket burada belirtilen default değeri boyutunda hafızada yer ayırır. Bu tampon bölgenin boyutu her tcp aktarımı esnasında alabileceğimiz maksimum veri boyutudur. Bu değer ortalama window boyutundan biraz daha fazla olmalı. Uygulamalar setsockopt ile default değerden farklı boyutlarda receive buffer boyutu belirleyebilirler. Maksimum boyut: örneğin 200mbit/s ve ortalama 70ms latency gören bir birim için: (200,000,000 / 8) * 0.07 = 1750000 + 64kb kernel payload = 1815536 olarak düşünülebilir. (Max hesaplarken ram boyutunu da hesaba katmak gerekiyor.) Minimum boyut page boyutundan az olmamalı.



net.ipv4.tcp_wmem = 4096 16384 ((bandwidth / 8) * latency) + 65536


tcp_rmem’den farklı olarak bu değerler göndericinin bu makine olduğu durumlar için geçerlidir.



net.core.rmem_max


Tüm protokoller tarafından riayet edilmesi gereken receive buffer maksimum limiti. Bu değerin tcp_rmem maksimum değeriyle eşitlenmesi gerekiyor.



net.core.wmem_max


Tüm protokoller tarafından riayet edilmesi gereken send buffer maksimum limiti. Bu değerin tcp_wmem maksimum değeriyle eşitlenmesi gerekiyor.



net.ipv4.tcp_congestion_control = cubic (default: cubic)


Yeni bağlantılar için kullanılacak tcp congestion control algoritmasını belirler.



net.ipv4.tcp_window_scaling = 1 (default: 1)


TCP window scaling özelliğinin aktif olup olmadığını belirler.



net.core.somaxconn = 4096 (default: 128)


Default listen() backlog (accept() bekleyen bağlantı sayısı) limitini belirler.



net.ipv4.tcp_max_syn_backlog = net.core.somaxconn (default: 128)


Hatırlanabilecek maksimum ACK bekleyen bağlantı sayısını belirler.



net.core.netdev_max_backlog = 30000 (default: 1000)


Interface tarafında maksimum backlog sayısı, interface büyük ihtimalle kerneldan daha hızlı olacağı için bu değer tcp_max_syn_backlog ve somaxconn’dan yüksek olmalı.



net.ipv4.tcp_syncookies = 0 (default: 1)


Soket backlog queue dolu olduğu zaman syncookie gönderir. Bu özellik yalnızca Syn flood tehlikesi durumunda, /var/log/syslog dosyasında syn flood uyarıları görüldüğü (ve bu uyarıların sebebinin legal connection rate olmadığının anlaşıldığı vakit) aktif edilmeli.


net.ipv4.tcp_syn_retries = 5 (default: 5)


Bağlantıyı kapatmadan önce kaç defa başlangıç SYN gönderileceğini belirler.



net.ipv4.tcp_synack_retries = 3 (default: 5)


Bağlantıyı kapatmadan önce kaç defa SYN-ACK yanıtı gönderileceğini belirler.



net.ipv4.ip_local_port_range = 10200 61000 (default: 32768 61000)


İlk değer minimum, ikinci değer maksimum. Herhangi bir uygulamanın bu min. değerin üstünde port kullanmadığına emin olunmalı.



net.ipv4.tcp_fin_timeout = 24 (default: 60)


Orphan bağlantıların bağlantı kesilmeden önce kaç sn. FIN-WAIT-2 durumunda tutulacağını belirliyor. (netstat -an|grep TIME_WAIT)



net.ipv4.tcp_keepalive_time = 1800 (default: 7200)


Ne sıklıkla keepalive mesajları gönderileceğini belirliyor.



net.ipv4.tcp_keepalive_probes = 5 (default: 9)


Bağlantıyı kesmeden önce kaç defa keepalive probe yapılacağını belirliyor.



net.ipv4.tcp_keepalive_intvl = 15 (default: 75)


Keepalive probeların ne aralıklarla gönderileceğini bekliyor. Pasif bağlantılar (tcp_keepalive_intl * tcp_keepalive_probes) süre içinde yanıt vermiyorsa kapatılır.



net.ipv4.tcp_rw_reuse = 1 (default: 0)


TIME-WAIT durumundaki soketlerin yeni bağlantılar için kullanılabilmesini sağlar.



net.ipv4.tcp_rw_recycle = 0 (default: 0)


TIME-WAIT durumundaki soketlerin yeni bağlantılar için hızlı-recycle edilmesini sağlar.



net.ipv4.tcp_orphan_retries = 0 (default: 0)


Orphan bağlantıların kaç saniye sonra kesileceğini belirler.



net.ipv4.tcp_retries2 = 10 (default: 15)


ACK alınamayan açık bağlantıların ne kadar süre sonunda kesileceğini belirler. Verilen değer saniye cinsinden olmayıp, default 15 değeri 925 saniyeye tekabül eder. Bu değerin 8’in altında olması tavsiye edilmez.



net.ipv4.tcp_max_orphans = 8192 (default: 8192)


(Orphan) Herhangi bir file-handle’a bağlı olmayan kaç adet soketin hafızada tutulacağını belirler. Bu değer basit DoS saldırılarına karşı güvenlik anlamında bulunmaktadır. DoS saldırıları durumunda bu değer alçaltılmamalı, aksine (fiziksel ram arttırıldıktan sonra) bu değer de arttırılmalıdır. Her orphan hafızada -swap edilemeyen- 64kb alan işgal eder.



net.ipv4.tcp_max_tw_buckets = 8192 (default: 8192)


Aynı anda hafızada tutulabilecek maksimum timewait  tcp_max_orphans ile ilgili uyarılar bu seçenek için de geçerlidir.



net.ipv4.conf.all.rp_filter = 1 (default: 0)


IP spoofinge karşı güvenlik.



net.ipv4.tcp_rfc1337 = 1 (default: 0)


RFC 1337’de adı geçen güvenlik zafiyetlerine karşı önlemleri uygula.



net.ipv4.tcp_slow_start_after_idle = 0 (default: 1)


RFC 2861’de bahsi geçen TCP congestion window validation özelliği.




Linkler




TCP






Faydalı komutlar ve araçlar



cat /proc/net/sockstat
Soket durumu bilgileri, page sayıları.


netstat -an|grep -c SYN_RECV / netstat -s
SYN_RECV durumunda olan bağlantı sayısı. (somaxconn, tcp_max_syn_backlog, netdev_max_backlog)


cat /proc/sys/fs/file-nr
Açık dosya sayısı (allocated free maximum) (file-max, inode-max, limits.conf)


cat /proc/net/tcp


ethtool


netstat -tan|awk ‘{print $6}’|sort|uniq -c / ss -s
Bağlantı durumları


ulimit -n / lsof
file-max


ipcs -l
System V IPC


getconf PAGE_SIZE


awk '{ print $4 }' /var/log/nginx/localhost.access.log |awk -F: '{ print $2 ":" $3 ":" $4 }'|sort|uniq -c
Concurrent bağlantı sayısı


ifconfig ethN txqueuelen 10000
Bu komutla 10G kartlar için txqueuelen arttırılabilir.


dtrace




---

Benim 384mb makinede nihai sysctl.conf dosyam:

kernel.panic = 1
kernel.panic_on_oops = 1
kernel.sysrq = 0
kernel.core_uses_pid = 1
kernel.pid_max = 65536
kernel.msgmax = 32768
kernel.msgmnb = 65536
kernel.msgmni = 738
kernel.shmmax = 402653184
kernel.shmall = 98304

fs.file-max = 24576
fs.inode-max = 98304

vm.mmap_min_addr = 65536
vm.swappiness = 20
vm.min_free_kbytes = 65536

net.core.rmem_max = 6315536
net.core.wmem_max = 6315536
net.core.somaxconn = 4096
net.core.netdev_max_backlog = 30000

net.ipv4.tcp_moderate_rcvbuf = 1
net.ipv4.tcp_rmem = 4096 87380 6315536
net.ipv4.tcp_wmem = 4096 65536 6315536
net.ipv4.tcp_congestion_control = cubic
net.ipv4.tcp_window_scaling = 1 
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_syncookies = 0
net.ipv4.tcp_syn_retries = 5
net.ipv4.tcp_synack_retries = 3
net.ipv4.ip_local_port_range = 10200 61000
net.ipv4.tcp_fin_timeout = 24 
net.ipv4.tcp_keepalive_time = 1800 
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_rw_reuse = 1
net.ipv4.tcp_rw_recycle = 0
net.ipv4.tcp_orphan_retries = 0
net.ipv4.tcp_retries2 = 10
net.ipv4.tcp_max_orphans = 8192
net.ipv4.tcp_max_tw_buckets = 8192
net.ipv4.conf.all.rp_filter = 1
net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_rfc1337 = 1
net.ipv4.tcp_slow_start_after_idle = 0
net.ipv4.ip_forward = 0
net.ipv6.conf.all.forwarding = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv6.conf.all.accept_redirects = 0
net.ipv4.conf.all.secure_redirects = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_source_route = 0
net.ipv6.conf.all.accept_source_route = 0

net.ipv4.conf.all.log_martians = 1