студия открытых решений о-никс
<< Skype в Centos yum в CentOS >>

NAT на CentOS под высокой нагрузкой

Рассмотрим живой пример организации высоконагруженного NAT-сервера на CentOS, не вдаваясь в детали оборудования (сервер имеет 4 процессора с 4-мя ядрами, т.е. по-сути, 16 процессоров, две сетевых 10-Гбитных карты от Intel с SFP-модулями, с 8-ю Гб памяти на борту).

Поскольку сервис irqbalance под высокой нагрузкой и огромном трафике будет только мешать наши карты, отключаем его, т.к. мы будем распределять прерывания потоков сетевых карт так, как нужно это нам. Можно вручную, можно автоматически скриптом.

service irqbalance stop
chkconfig irqbalance off

Также нужно отключить Hyper-threading. Сделать это можно, например, через строку загрузчика grub, заодно "для надежности" там и отключение irqbalance продублируем:

    kernel /vmlinuz-3.0.78-1.el5.elrepo ro root=/dev/VolGroup00/LogVol00 noht noirqbalance

А вот и скрипт, привязывающий номера прерываний сетевых карт к ядрам процессоров irq-smp-balance.sh:

#!/bin/sh
#
#  irq2smp -- distribute hardware interrupts from Ethernet devices by CPU cores.
#
#  Should be called from /etc/rc.local.
#

ncpus=`grep -ciw ^processor /proc/cpuinfo`
test "$ncpus" -gt 1 || exit 1

n=0
for irq in `cat /proc/interrupts | grep eth | awk '{print $1}' | sed s/\://g`
do
    f="/proc/irq/$irq/smp_affinity"
    test -r "$f" || continue
    cpu=$[$ncpus - ($n % $ncpus) - 1]
    if [ $cpu -ge 0 ]
            then
                mask=`printf %x $[2 ** $cpu]`
                echo "Assign SMP affinity: eth$n, irq $irq, cpu $cpu, mask 0x$mask"
                echo "$mask" > "$f"
                let n+=1
    fi
done

Разместим его, к примеру, в каталоге

/etc/rc.d/irq-smp-balance.sh

и не забудем прописать его запуск в /etc/rc.local

Вообще, rc.local для высоконагруженного NAT-сервера может выглядеть примерно так (поясняющие комментарии собственно в нём):

cat /etc/rc.local
#!/bin/sh
#
# This script will be executed *after* all the other init scripts.
# You can put your own initialization stuff in here if you don't
# want to do the full Sys V style init stuff.


# Можно увеличить MTU, не забываем делать его таким же на портах свичей: system mtu jumbo 9000 (если позволяет инфраструктура)
# /sbin/ifconfig eth2 mtu 9000
# /sbin/ifconfig eth3 mtu 9000

# Увеличиваем очередь передачи на Intel-овских сетевых картах. Для 10-гигабитных линков рекомендуется ставить 10000
/sbin/ifconfig eth2 txqueuelen 10000
/sbin/ifconfig eth3 txqueuelen 10000

# /sbin/ethtool
# изменение размеров буферов
/sbin/ethtool -G eth2 rx 2048
/sbin/ethtool -G eth2 tx 2048
/sbin/ethtool -G eth3 rx 2048
/sbin/ethtool -G eth3 tx 2048

# отключение flow control
# отключил 2 апреля 2012 16:05
/sbin/ethtool -A eth2 autoneg off rx off tx off
/sbin/ethtool -A eth3 autoneg off rx off tx off

# Правило для hashsize = nf_conntrack_max / 8
# Посмотреть текущее значение можно так: sysctl net.netfilter.nf_conntrack_max
# Посмотреть, насколько уже заполнена таблица отслеживания соединений: sysctl net.netfilter.nf_conntrack_count
# НЕ рекомендуется ставить большое значение nf_conntrack_max, если на NAT-e мало оперативы

# 2^20
# echo 1048576 > /sys/module/nf_conntrack/parameters/hashsize
# CentALT пишет, что hashsize должен быть равен nf_conntrack_max на больших объемах трафика
# http://habrahabr.ru/post/108763/
echo 9437184 > /sys/module/nf_conntrack/parameters/hashsize

#Раскидываем прерывания по потокам сететвых карт
/etc/rc.d/irq-smp-balance.sh

# netconsole для логирования сообщений ядра на удаленный хост
, это если будет необходимость разбора траблшутинга
#6666@10.200.200.200/eth0 - порт, адрес, интерфейс NAT-сервера
#514@10.200.200.222/00:1B:21:40:EB:68 - порт, адрес MAC-адрес карты, куда шлются с сервера dmesg

#/sbin/modprobe netconsole netconsole="6666@10.200.200.200/eth0,514@10.200.200.222/00:1B:21:40:EB:68"

touch /var/lock/subsys/local

 Тюнинг ядра высоконагруженного NAT-сервера:

cat /etc/sysctl.conf
# Kernel sysctl configuration file for Red Hat Linux
#
# For binary values, 0 is disabled, 1 is enabled.  See sysctl(8) and
# sysctl.conf(5) for more details.

# Controls IP packet forwarding
net.ipv4.ip_forward = 1

# Controls source route verification
net.ipv4.conf.default.rp_filter = 1

# Do not accept source routing
net.ipv4.conf.default.accept_source_route = 0

# Controls the System Request debugging functionality of the kernel
kernel.sysrq = 0

# Controls whether core dumps will append the PID to the core filename
# Useful for debugging multi-threaded applications
kernel.core_uses_pid = 1

# Controls the use of TCP syncookies
net.ipv4.tcp_syncookies = 1

# Controls the maximum size of a message, in bytes
kernel.msgmnb = 65536

# Controls the default maxmimum size of a mesage queue
kernel.msgmax = 65536

# Controls the maximum shared segment size, in bytes
kernel.shmmax = 68719476736

# Controls the maximum number of shared memory segments, in pages
kernel.shmall = 4294967296

##############
# nat tuning #
##############

# Увеличиваем количество conntrack соединений, необходимо менять значение
# по умолчанию только на высоконагруженных серверах.
# ядро 2.6 лучше воспринимают размеры таблиц равные степени 2, так что можно установить
# CONNTRACK_MAX и HASHSIZE равные 1048576 (2^20) etc...
# net.ipv4.netfilter.ip_conntrack_max = 4194304
# net.nf_conntrack_max = 4194304
net.ipv4.netfilter.ip_conntrack_max = 9437184
net.nf_conntrack_max = 9437184


# increase TCP max buffer size setable using setsockopt()
# изменение размеров буферов для приема и отправки данных через сокеты, tcp-memory
net.core.rmem_default = 16777216
net.core.rmem_max = 16777216
net.core.wmem_default = 16777216
net.core.wmem_max = 16777216
# increase Linux autotuning TCP buffer limits
# min, default, and max number of bytes to use
# set max to at least 4MB, or higher if you use very high BDP paths
# net.ipv4.tcp_rmem = 4096 87380 16777216
# net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_rmem = 4096 16777216 16777216
net.ipv4.tcp_wmem = 4096 16777216 16777216

# Максимальное число сокетов в состоянии TIME-WAIT одновременно. При превышении этого порога лишний сокет разрушается 
# и пишется сообщение в системный журнал. Цель этой переменной – предотвращение простейших разновидностей DoS-атак
# Значение по-умолчанию –     180000
net.ipv4.tcp_max_tw_buckets = 1800000

# Переменная задает максимальное число осиротевших (не связанных ни с
# одним процессом) сокетов. Если это число будет превышено, то такие
# соединения разрываются, а в системный журнал пишется предупреждение. Это
# ограничение существует исключительно ради предотвращения простейших
# разновидностей DoS-атак. 
net.ipv4.tcp_max_orphans = 262144
# net.ipv4.tcp_max_orphans = 65536

# net.ipv4.tcp_max_syn_backlog = 262144

# When in a non-Napi (or Interrupt) mode, this counter indicates that the stack is dropping packets.
# net.core.netdev_max_backlog = 10000
net.core.netdev_max_backlog = 30000

# net.core.somaxconn = 262144

# These ensure that TIME_WAIT ports either get reused or closed fast.
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_tw_recycle = 1

# защита от syn-флуда
net.ipv4.tcp_syncookies=1

# запрет приёма ICMP-редиректов
# net.ipv4.conf.all.accept_redirects = 0
# net.ipv4.conf.default.accept_redirects = 0

# игнорируем широковещательные ICMP-запросы
net.ipv4.icmp_echo_ignore_broadcasts=1

# игнорируем пакеты, в которых указан путь до источника
net.ipv4.conf.all.accept_source_route=0

# Укажем диапазон портов которые разрешено использовать в качестве
# локальных. По умолчанию этот диапазон достаточно мал, и при высокой
# нагрузке вам их может просто не хватить
# net.ipv4.ip_local_port_range = 16384 61000
net.ipv4.ip_local_port_range = 1024 65535

# Уменьшим время которое используется для сообщений
# о поддержке keep alive соединений
net.ipv4.tcp_keepalive_time = 7200

# Уменьшим время до закрытия TCP соединения, данный параметр стоит менять
# только на высоко нагруженных серверах.
net.ipv4.netfilter.ip_conntrack_tcp_timeout_established = 7200

# Другие таймауты:
net.ipv4.netfilter.ip_conntrack_udp_timeout_stream = 60
net.ipv4.netfilter.ip_conntrack_udp_timeout = 60
net.ipv4.netfilter.ip_conntrack_generic_timeout = 3600

# В случае kernel panic reboot через 10 секунд (panic может возникнуть при высокой нагрузке и irqbalance, например)
kernel.panic = 10

# чтобы не переполнялась арп-таблица (пишет в логах kernel: ipv4: Neighbour table overflow)
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh3 = 4096

А вот, собственно, правила NAT в iptables (vlan888 - выходной интерфейс, который смотрит в интернет). Подсети приватных адресов разделяются между белыми ip-адресами пула.

cat /etc/sysconfig/iptables
# Firewall configuration written by system-config-securitylevel
# Manual customization of this file is not recommended.
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
##Разрешаем VPN с esp и ah
-A INPUT -p esp -j ACCEPT
-A INPUT -p ah -j ACCEPT
-A OUTPUT -p esp -j ACCEPT
-A OUTPUT -p ah -j ACCEPT
-A FORWARD -m state --state INVALID -j DROP
COMMIT

*nat
-A POSTROUTING -o vlan888 -s 	10.10.0.0/23	 -j SNAT --to 	1.2.3.1
-A POSTROUTING -o vlan888 -s 	10.10.2.0/23	 -j SNAT --to 	1.2.3.2
-A POSTROUTING -o vlan888 -s 	10.10.4.0/23	 -j SNAT --to 	1.2.3.3
-A POSTROUTING -o vlan888 -s 	10.10.6.0/23	 -j SNAT --to 	1.2.3.4
-A POSTROUTING -o vlan888 -s 	10.10.8.0/23	 -j SNAT --to 	1.2.3.5
-A POSTROUTING -o vlan888 -s 	10.10.10.0/23	 -j SNAT --to 	1.2.3.6
-A POSTROUTING -o vlan888 -s 	10.10.12.0/23	 -j SNAT --to 	1.2.3.7
-A POSTROUTING -o vlan888 -s 	10.10.14.0/23	 -j SNAT --to 	1.2.3.8
-A POSTROUTING -o vlan888 -s 	10.10.16.0/23	 -j SNAT --to 	1.2.3.9
# И т.д.

COMMIT

Указываем некоторые важные модули в конфигурационном файле iptables iptables-config:

# cat iptables-config 
# Load additional iptables modules (nat helpers)
#   Default: -none-
# Space separated list of nat helpers (e.g. 'ip_nat_ftp ip_nat_irc'), which
# are loaded after the firewall rules are applied. Options for the helpers are
# stored in /etc/modprobe.conf.
IPTABLES_MODULES="ip_conntrack_netbios_ns"

# Unload modules on restart and stop
#   Value: yes|no,  default: yes
# This option has to be 'yes' to get to a sane state for a firewall
# restart or stop. Only set to 'no' if there are problems unloading netfilter
# modules.
# IPTABLES_MODULES_UNLOAD="yes"

# Save current firewall rules on stop.
#   Value: yes|no,  default: no
# Saves all firewall rules to /etc/sysconfig/iptables if firewall gets stopped
# (e.g. on system shutdown).
IPTABLES_SAVE_ON_STOP="no"

# Save current firewall rules on restart.
#   Value: yes|no,  default: no
# Saves all firewall rules to /etc/sysconfig/iptables if firewall gets
# restarted.
IPTABLES_SAVE_ON_RESTART="no"

# Save (and restore) rule and chain counter.
#   Value: yes|no,  default: no
# Save counters for rules and chains to /etc/sysconfig/iptables if
# 'service iptables save' is called or on stop or restart if SAVE_ON_STOP or
# SAVE_ON_RESTART is enabled.
IPTABLES_SAVE_COUNTER="no"

# Numeric status output
#   Value: yes|no,  default: yes
# Print IP addresses and port numbers in numeric format in the status output.
IPTABLES_STATUS_NUMERIC="yes"

# Verbose status output
#   Value: yes|no,  default: yes
# Print info about the number of packets and bytes plus the "input-" and
# "outputdevice" in the status output.
IPTABLES_STATUS_VERBOSE="no"

# Status output with numbered lines
#   Value: yes|no,  default: yes
# Print a counter/number for every rule in the status output.
IPTABLES_STATUS_LINENUMBERS="yes"

# Подгружаем дополнительные модули чтобы через NAT работали протоколы ftp и irc
IPTABLES_MODULES="ip_nat_ftp ip_nat_irc ip_nat_pptp"
# Не выгружать модули iptables при рестарте
IPTABLES_MODULES_UNLOAD="no"


В процессе запуска NAT-сервера у нас никак не хотели определяться 10-Гбитные SFP-модули, и мы применили небольшой "патчик" драйвера ixgbe сетевой карты.

Таким образом, если SFP-модули в сетевых 10-Гбитных картах не "родные" или не "фирменные", то можно внести изменения в интелловский драйвер
ixgbe, исключающий проверку SFP-модуля (никаких гарантий, только на ваш страх и риск!):

Для версии драйвера ixgbe-3.14.5, в распакованных исходниках есть файл:

ixgbe-3.14.5/src/ixgbe_phy.c

Вам нужно найти следующий кусок кода в этом файле:

/**
 *  ixgbe_identify_sfp_module_generic - Identifies SFP modules
 *  @hw: pointer to hardware structure
 *
 *  Searches for and identifies the SFP module and assigns appropriate PHY type.
 **/
s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
{
	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
	u32 vendor_oui = 0;
	enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
	u8 identifier = 0;
	u8 comp_codes_1g = 0;
	u8 comp_codes_10g = 0;
	u8 oui_bytes[3] = {0, 0, 0};
	u8 cable_tech = 0;
	u8 cable_spec = 0;
	u16 enforce_sfp = 0;

	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
		status = IXGBE_ERR_SFP_NOT_PRESENT;
		goto out;
	}

	status = hw->phy.ops.read_i2c_eeprom(hw,
					     IXGBE_SFF_IDENTIFIER,
					     &identifier);

	if (status != 0)
		goto err_read_i2c_eeprom;
 

и вставить перед последним условием if (status != 0) всего лишь одну команду return 0;

/**
 *  ixgbe_identify_sfp_module_generic - Identifies SFP modules
 *  @hw: pointer to hardware structure
 *
 *  Searches for and identifies the SFP module and assigns appropriate PHY type.
 **/
s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
{
	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
	u32 vendor_oui = 0;
	enum ixgbe_sfp_type stored_sfp_type = hw->phy.sfp_type;
	u8 identifier = 0;
	u8 comp_codes_1g = 0;
	u8 comp_codes_10g = 0;
	u8 oui_bytes[3] = {0, 0, 0};
	u8 cable_tech = 0;
	u8 cable_spec = 0;
	u16 enforce_sfp = 0;

	if (hw->mac.ops.get_media_type(hw) != ixgbe_media_type_fiber) {
		hw->phy.sfp_type = ixgbe_sfp_type_not_present;
		status = IXGBE_ERR_SFP_NOT_PRESENT;
		goto out;
	}

	status = hw->phy.ops.read_i2c_eeprom(hw,
					     IXGBE_SFF_IDENTIFIER,
					     &identifier);

	return 0; //маленький патч, позволяющий запускать неродные SFP-модули.


	if (status != 0)
		goto err_read_i2c_eeprom;



 Ну и также нужно не забыть настроить роутинг, соответствующий вашей инфраструктуре пулов адресов.

<< Skype в Centos yum в CentOS >>

Поделиться в соцсетях:

система комментирования CACKLE
RSS