Компания
85,67
рейтинг
25 октября 2013 в 14:34

Разное → «Идеальный» www кластер. Часть 1. Frontend: NGINX + Keepalived (vrrp) на CentOS



Этом цикле статей «Идеальный www кластер», я хочу передать базовые основы построения высокодоступного и высокопроизводительного www решения для нагруженных web проектов для неподготовленного администратора.
Статья будет содержать пошаговую инструкцию и подойдет любому человеку кто освоил силу copy-paste
Ошибки найденые вами, помогут в работе и мне и тем кто будет читать эту статью позже! Так что любые улучшение и правки приветствуются!

Хочу отметить, что эта инструкция родилась в процессе миграции web-систем компании Acronis в высокодоступный кластер. Надеюсь мои заметки будут полезны и для Вас!.

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

На frontend мы будем использоваться связку из двух службы:



keepalived — реализации протокола VRRP (Virtual Router Redundancy Protocol) для Linux. Демон keepalived следит за работоспособностью машин и в случае обнаружения сбоя — исключает сбойный сервер из списка активных серверов, делегируя его адреса другому серверу.

Другими словами, у нас 2 сервера на которых прописано по одному публичному адресу. Если любой из этих серверов падает, то адрес упавшего подхватывается вторым.
Демоны keepalived общаются по протоколу VRRP, посылая друг другу сообщения на адрес 224.0.0.18.
Если сосед не прислал свое сообщение, то по истечению периода он считается умершим и оба адреса обслуживает оставшаяся нода. Как только упавший сервер начинает слать свои сообщения в сеть, все возвращается на свои места


nginx [engine x] — это HTTP-сервер и обратный прокси-сервер, а также почтовый прокси-сервер, написанный Игорем Сысоевым. Уже длительное время он обслуживает серверы многих высоконагруженных российских сайтов, таких как Яндекс, Mail.Ru, ВКонтакте и Рамблер. Согласно статистике Netcraft nginx обслуживал или проксировал 15.08% самых нагруженных сайтов в октябре 2013 года.

Основная функциональность HTTP-сервера

  • Обслуживание статических запросов, индексных файлов, автоматическое создание списка файлов, кэш дескрипторов открытых файлов;
  • Акселерированное обратное проксирование с кэшированием, простое распределение нагрузки и отказоустойчивость;
  • Акселерированная поддержка FastCGI, uwsgi, SCGI и memcached серверов с кэшированием, простое распределение нагрузки и отказоустойчивость;
  • Модульность, фильтры, в том числе сжатие (gzip), byte-ranges (докачка), chunked ответы, XSLT-фильтр, SSI-фильтр, преобразование изображений; несколько подзапросов на одной странице, обрабатываемые в SSI-фильтре через прокси или FastCGI, выполняются параллельно;
  • Поддержка SSL и расширения TLS SNI.


Другие возможности HTTP-сервера

  • Виртуальные серверы, определяемые по IP-адресу и имени;
  • Поддержка keep-alive и pipelined соединений;
  • Гибкость конфигурации;
  • Изменение настроек и обновление исполняемого файла без перерыва в обслуживании клиентов;
  • Настройка форматов логов, буферизованная запись в лог, быстрая ротация логов;
  • Специальные страницы для ошибок 3xx-5xx;
  • rewrite-модуль: изменение URI с помощью регулярных выражений;
  • Выполнение разных функций в зависимости от адреса клиента;
  • Ограничение доступа в зависимости от адреса клиента, по паролю (HTTP Basic аутентификация) и по результату подзапроса;
  • Проверка HTTP referer;
  • Методы PUT, DELETE, MKCOL, COPY и MOVE;
  • FLV и MP4 стриминг;
  • Ограничение скорости отдачи ответов;
  • Ограничение числа одновременных соединений и запросов с одного адреса;
  • Встроенный Perl.






Важно! Для приведенного ниже решения, у нас должно быть 2 сетевых интерфейса на каждой из нод keepalived
мы должны точно указать нашу маску и понимать где в нашей сети находится broadcast, если этого не сделать, то будем очень долго пытаться понять почему у нас все работает не так как мы хотим!

# Моя приватная сеть
[root@nginx-frontend-01 ~]#


nano /etc/sysconfig/network-scripts/ifcfg-eth2


DEVICE=eth2
BOOTPROTO=static
ONBOOT=yes
IPADDR=10.100.100.56
NETWORK=10.100.100.0
NETMASK=255.255.255.0
BROADCAST=10.100.100.255


# Публичная сеть
[root@nginx-frontend-01 ~]#


 nano /etc/sysconfig/network-scripts/ifcfg-eth3 


DEVICE=eth3
BOOTPROTO=static
ONBOOT=yes
IPADDR=72.x.x.1
NETMASK=255.255.255.248
BROADCAST=72.x.x.55
GATEWAY=72.x.x.49


То есть в моей публичной сети, маска /29 и значит мой broadcast x.x.x.55, если бы была сеть /24, то можно было бы указать x.x.x.255
Если это перепутать, то вы отгребете кучу проблем


# Устанавливаем keepalived
yum install keepalived -y 


# Это очень плохо, этого делать не нужно! только в тестовых целях и на свой страх и риск, я предупредил. Выключаем selinux
sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux 


# Настраиваем keepalived на первой ноде nginx-frontend-01, очень важно, знак коментария "!" а не "#"

mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.old && nano /etc/keepalived/keepalived.conf 


[root@nginx-frontend-01 ~]#

 nano /etc/keepalived/keepalived.conf 


! Configuration File for keepalived

global_defs {
        notification_email {
                root@localhost
        }
        notification_email_from root@localhost
        smtp_server                     localhost
        smtp_connect_timeout            30
! Именное обозначение этого сервера
        router_id                       nginx-frontend-01
}

vrrp_instance nginx2 {
! Состояние в котором стартует нода, в этом случае она резерв
        state                   BACKUP

! Наш публичиный интерфейс
        interface               eth3

! Индификатор, в разных vrrp_instance он должен быть разным 
        virtual_router_id       102

! Это приоритет этой ноды перед другими, у BACKUP он всегда должен быть ниже чем у MASTER
        priority                100

        advert_int              1
        dont_track_primary

! Тут можно на всякий случай указать наш broadcast
        mcast_src_ip x.x.x.55

! Пароль можно указать любой, но одинаковый для серверов
        authentication {
                auth_type PASS
                auth_pass b65495f9
        }
! Этот адрес возмет себе сервер, если MASTER в сети упадет
        virtual_ipaddress {
                x.x.x.2/29 dev eth3
        }

        }
vrrp_instance nginx1 {
! Эта нода - мастер, она использует адрес из этой секции и ее заменит другая, если эта упадет
        state                   MASTER

! Наш публичиный интерфейс
        interface               eth3

! Индификатор, в разных vrrp_instance он должен быть разным 
        virtual_router_id       101

! Для мастера это значение обязательно выше чем для backup
        priority                200

        advert_int              1
        dont_track_primary

! Тут можно на всякий случай указать наш broadcast
        mcast_src_ip x.x.x.55

! Пароль можно указать любой, но одинаковый для серверов
        authentication {
                auth_type PASS
                auth_pass b65495f8
        }
        virtual_ipaddress {
! Нода стартует с этим адресом, если эта нода упадет, этот адрес подхватит другая
                x.x.x.1/29 dev eth3
                        }
! Для мастера нужно прописать gateway
        virtual_routes {
                default via x.x.x.49 dev eth3 metric 2
        }
}


# Настраиваем keepalived на второй ноде nginx-frontend-02 очень важно, знак коментария "!" а не "#"

mv /etc/keepalived/keepalived.conf /etc/keepalived/keepalived.conf.old && nano /etc/keepalived/keepalived.conf 


[root@nginx-frontend-02 ~]#

nano /etc/keepalived/keepalived.conf 


! Configuration File for keepalived

global_defs {
        notification_email {
                root@localhost
        }
        notification_email_from root@localhost
        smtp_server                     localhost
        smtp_connect_timeout            30
! Именное обозначение этого сервера
        router_id                       nginx-frontend-02
}

vrrp_instance nginx1 {
! Состояние в котором стартует нода, в этом случае она резерв
        state                   BACKUP

! Наш публичиный интерфейс
        interface               eth3

! Индификатор, в разных vrrp_instance он должен быть разным 
        virtual_router_id       101

! Это приоритет этой ноды перед другими, у BACKUP он всегда должен быть ниже чем у MASTER
        priority                100

        advert_int              1
        dont_track_primary

! Тут можно на всякий случай указать наш broadcast
        mcast_src_ip x.x.x.55

! Пароль можно указать любой, но одинаковый для серверов
        authentication {
                auth_type PASS
                auth_pass b65495f9
        }
! Этот адрес возмет себе сервер, если MASTER в сети упадет
        virtual_ipaddress {
                x.x.x.1/29 dev eth3
}

        }
vrrp_instance nginx2 {
! Эта нода - мастер, она использует адрес из этой секции и ее заменит другая, если эта упадет
        state                   MASTER

! Наш публичиный интерфейс
        interface               eth3

! Индификатор, в разных vrrp_instance он должен быть разным 
        virtual_router_id       102

! Для мастера это значение обязательно выше чем для backup
        priority                200

        advert_int              1
        dont_track_primary

! Тут можно на всякий случай указать наш broadcast
        mcast_src_ip x.x.x.55

! Пароль можно указать любой, но одинаковый для серверов
        authentication {
                auth_type PASS
                auth_pass b65495f9
        }
! Нода стартует с этим адресом, если эта нода упадет, этот адрес подхватит другая
        virtual_ipaddress {
                x.x.x.2/29 dev eth3
                        }
        virtual_routes {
! Для мастера нужно прописать gateway
                default via x.x.x.49 dev eth3 metric 2
        }
}


# Добавляем в автозагрузку и запускаем

 chkconfig keepalived on && service keepalived restart 


# Добавляем разрешения фаервола, больше половины проблем, из за того что мы забываем про фаервол!

iptables -A INPUT -i eth3 -p vrrp -j ACCEPT
iptables -A OUTPUT -o eth3 -p vrrp -j ACCEPT
iptables -A INPUT -d 224.0.0.0/8 -i eth3 -j ACCEPT
iptables-save > /etc/sysconfig/iptables


# Это очень важный шаг
Установка этой переменной позволяет отдельным локальным процессам выступать от имени внешнего (чужого) IP адреса


echo "net.ipv4.ip_nonlocal_bind=1" >> /etc/sysctl.conf && sysctl -p 


# Проверяем

/etc/init.d/keepalived restart && tail -f -n 100 /var/log/messages


# Проверяем как между собой общаются наши ноды keepalived
 tcpdump -vvv -n -i eth3 host 224.0.0.18 


# Мы должны увидеть это

x.x.x.55 > 224.0.0.18: VRRPv2, Advertisement, vrid 102, prio 200, authtype simple, intvl 1s, length 20, addrs: x.x.x.2 auth "b65495f9"
07:50:50.019548 IP (tos 0xc0, ttl 255, id 5069, offset 0, flags [none], proto VRRP (112), length 40)
x.x.x.55 > 224.0.0.18: VRRPv2, Advertisement, vrid 101, prio 200, authtype simple, intvl 1s, length 20, addrs: x.x.x.1 auth "b65495f9"


Теперь можно попеременно выключать сервера, опускать интерфейсы, дергать провода итд
У нас в сети всегда будут присутствовать оба этих адреса и на них будет отвечать наш nginx




# Подключаем официальный репозиторий nginx для CentOS 6
rpm -Uhv http://nginx.org/packages/rhel/6/noarch/RPMS/nginx-release-rhel-6-0.el6.ngx.noarch.rpm


# Обновляем систему и устанавливаем nginx

yum update -y
yum install nginx 


# Удаляем хосты поумолчанию, по умолчанию там стандартное приветствие nginx

rm -f /etc/nginx/conf.d/default.conf
rm -f /etc/nginx/conf.d/virtual.conf
rm -f /etc/nginx/conf.d/ssl.conf


# Приводим главный конфиг к подобному виду

 mv  /etc/nginx/nginx.conf /etc/nginx/nginx.conf.old 
nano /etc/nginx/nginx.conf 


user  nginx;

# Количество процессов ожидаюищих соединения
worker_processes 10;

pid /var/run/nginx.pid;

events {
# Максимальное количество обслуживаемых клиентов онлайн
	worker_connections 1024;

# epoll — эффективный метод, используемый в Linux 2.6+ http://nginx.org/ru/docs/events.html
        use epoll;

# Рабочий процесс за один раз будет принимать сразу все новые соединения
multi_accept on;

}
error_log  /var/log/nginx/error.log warn;

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

        connection_pool_size            256;
        client_header_buffer_size       4k;
	client_max_body_size 100m;
        large_client_header_buffers     8 8k;
        request_pool_size               4k;
 	output_buffers  1 32k;
        postpone_output 1460;

# Все страницы будут ужиматься gzip
gzip  on;
gzip_min_length 1024;
gzip_proxied     any;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/xml application/xml application/x-javascript text/javascript text/css text/json;
    gzip_comp_level  5;
    gzip_disable "MSIE [1-6]\.(?!.*SV1)";

        sendfile        on;
        tcp_nopush      on;
        tcp_nodelay     on;

        keepalive_timeout       75 20;

	server_names_hash_max_size 8192;
        ignore_invalid_headers  on;
        server_name_in_redirect off;

        proxy_buffer_size       8k;
        proxy_buffers           8 64k;
        proxy_connect_timeout   1000;
        proxy_read_timeout      12000;
        proxy_send_timeout      12000;

# Мы рассказываем где будет храниться кеш, но по умолчанию я его не использую
	proxy_cache_path /var/cache/nginx levels=2 keys_zone=pagecache:5m inactive=10m max_size=50m;

# Передаем backend реальный адрес клиента для mod_rpaf
        real_ip_header          X-Real-IP;
        proxy_set_header        Host            $host;
        proxy_set_header        X-Real-IP       $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;

        allow all;

    include /etc/nginx/conf.d/*.conf;
}


# Теперь приведем в порядок наш универсальный vhost

nano /etc/nginx/conf.d/all.conf


upstream web {
# Перечисляем все backend между которыми nginx будет балансировать клиентов, говорим количество fail для баны backend ноды и таймаут
	# back01
	server		10.211.77.131 weight=10 max_fails=60 fail_timeout=2s;
	# back02
	server         10.211.77.136 weight=10 max_fails=60 fail_timeout=2s;

}
server  {
   listen   80;
	location / {
		proxy_pass	http://web;
proxy_set_header   Host   $host;
proxy_set_header   X-Real-IP  $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
}
}



# И наш конфиг для работы сайта по SSL, для кажого сайта должен быть свой конфиг со своим сертификатом

 nano /etc/nginx/conf.d/ssl.conf 


upstream ssl {
        # back01
        # server                10.211.77.131 weight=10 max_fails=60 fail_timeout=2s;
        # back02
        server 10.100.100.63 weight=10 max_fails=60 fail_timeout=2s;

}
server  {
   listen   443;

ssl on;
ssl_certificate         /etc/nginx/ssl/GeoTrustCA.crt;
ssl_certificate_key     /etc/nginx/ssl/GeoTrustCA.key;

# Увеличиваем безопасность нашего SSL соединения 
ssl_ciphers      RC4:HIGH:!aNULL:!MD5:!kEDH;
ssl_session_cache shared:SSL:10m;
ssl_prefer_server_ciphers on;
ssl_protocols           SSLv3 TLSv1;

        location / {
                proxy_pass      http://ssl;
proxy_set_header   Host   $host;
proxy_set_header   X-Real-IP  $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
}
}


# Запускаем nginx и добавляем его в автозагрузку!

 /etc/init.d/nginx start && chkconfig nginx on 


Продолжение следует, спасибо за внимание!

Автор: @SyCraft
Acronis
рейтинг 85,67

Комментарии (77)

  • +1
    # Увеличиваем безопасность нашего SSL соединения

    В каком месте? То-есть TLSv1.2 и TLSv1.1 не нужны? А еще SSLv3 рекомендуется не использовать. TLSv1.0 все современные браузеры поддерживают. Да и RC4 слабоват будет, лучше исключить его. А Forward Secrecy? А Strict Transport Security?
    • +1
      Руководствовался этой статьей habrahabr.ru/post/173125/ и результатами www.ssllabs.com
      • –1
        Ну, скажем так: эта статья далека от идела. nginx 1.4.x, openssl 1.0.1c
        server {
            listen	443 ssl;
            server_name	metalabs.io;
        
            ssl				on;
            ssl_protocols		TLSv1.2 TLSv1.1 TLSv1;
            ssl_certificate		/var/certs/metalabs.io.crt;
            ssl_certificate_key		/var/certs/metalabs.io.key;
            ssl_prefer_server_ciphers	on;
            ssl_session_cache		shared:SSL:10m;
            ssl_session_timeout		10m;
            ssl_ciphers "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+aRSA+RC4 EECDH EDH+aRSA RC4 !aNULL !eNULL !LOW !3DES !MD5 !EXP !PSK !SRP !DSS !RC4";
        
        • +5
          Вы считаете что от идеала ее отделяет ваше замечаение по SSL?
          • 0
            Так в ней всего то и говорится о том, как правильно настроить SSL. И то не правильно.

            P.S.: Я имел ввиду не эта статья. Ну эта… под которой мы комментарии оставляем. А та. Про SSL и PCI-Compliance
  • +1
    В данной конфигурации у нас один сервер активен и обрабатывает весть трафик, а второй все ждет когда первый упадет? Не рассматривали варианты с обоими активными серверами?

    Например 2 разных keepalived, которые перекидывают внешние адреса между машинами, а в DNS добавить 2 А записи?
    • 0
      С DNS сложно: он сильно кэшируется, keepalive в этом смысле намного лучше
    • +1
      В данной конфигурации оба сервера активны и если один из них падает то его адрес принимает второй
      • 0
        Да, с DNS все понятно, что записи могут кэшироваться, но речь про то, чтобы иметь 2 внешних IP, по одному на каждый сервер и в случае падения одного из серверов, второй назначает себе оба внешних адреса.
        • +1
          Именно так все и происходит в этом примере
          • 0
            Вчитался в конфиг, понятно, спасибо
  • 0
    Хорошее how-to, с достаточно хорошо прокоментированными конфигами. Но имхо, недостаточно объяснений, например:
    1) Почему используется именно такая конфигурации keepalived? Она избыточна и это неспроста, а вот почему не рассказано.
    2) Почему удаляете хосты по умолчанию и приводите их к совершенно другому виду.
    3) Это очень важный шаг: net.ipv4.ip_nonlocal_bind=1 — Почему?
    • 0
      1 Это сама базовая конфигурация с двумя одновременными мастерами и бекапами
      2 По умолчанию там стандартное приветствие nginx
      3 Установка этой переменной позволяет отдельным локальным процессам выступать от имени внешнего (чужого) IP адреса
    • 0
      Добавил правки в текст, теперь это будет понятно из текста
  • 0
    Спорный момент про fail_timeout=2s — фронтенд не всегда будет отвечать меньше 2с
    • 0
      fail_timeout=2s Это время через которое nginx попробует снова тыкнуть в fail сервер и так пока не будет достигнуто максимально значение max_fails
      • 0
        Не уверен, что это правда
        wiki.nginx.org/HttpUpstreamModule
        max_fails = NUMBER — number of unsuccessful attempts at communicating with the server within the time period (assigned by parameter fail_timeout) after which it is considered inoperative. If not set, the number of attempts is one. A value of 0 turns off this check. What is considered a failure is defined by proxy_next_upstream or fastcgi_next_upstream (except http_404 errors which do not count towards max_fails).
        fail_timeout = TIME — the time during which must occur *max_fails* number of unsuccessful attempts at communication with the server that would cause the server to be considered inoperative, and also the time for which the server will be considered inoperative (before another attempt is made).
        • 0
          fail_timeout = TIME — время, в течение которого должно произойти * max_fails * Количество неудачных попыток связи с сервером, что бы заставить сервер рассматриваться в нерабочем состоянии, а также время, в течение которого сервер будет считается неработоспособным (до другой попытки ).
          • 0
            Определение max_fails (как и наш опыт реализации этих директив) указывает на первую версию fail_timeout — «number of unsuccessful attempts at communicating with the server within the time period (assigned by parameter fail_timeout) after which it is considered inoperative»
            • 0
              max_fails=число
              задаёт число неудачных попыток работы с сервером, которые должны произойти в промежуток времени, заданный параметром fail_timeout, чтобы сервер считался неработающим на период времени, также заданный параметром fail_timeout. По умолчанию число попыток устанавливается равным 1. Нулевое значение отключает учёт попыток. Что считается неудачной попыткой, определяется директивами proxy_next_upstream, fastcgi_next_upstream и memcached_next_upstream.

              fail_timeout=время задаёт время, в течение которого должно произойти заданное число неудачных попыток работы с сервером для того, чтобы сервер считался неработающим;
              и время, в течение которого сервер будет считаться неработающим.
              По умолчанию параметр равен 10 секундам.

              nginx.org/ru/docs/http/ngx_http_upstream_module.html
            • 0
              А то что вы имеете ввиду задается параметрами

              proxy_connect_timeout 1000;
              proxy_read_timeout 12000;
              proxy_send_timeout 12000;
  • 0
    Тема хорошая, спасибо. Но статья выглядит неполно. Хотелось бы общее описание решения. О том, что у Вас 2 внешних IP адреса, о том, что они балансируются как-то (кстати как?). И нарисовать хотябы минимальную схему. Потому что первый рисунок не соотвествует статье и немного сбивает с толку.

    Акцент, мне кажется, нужно делать именно на суть решения. Вы долго описываете что такое nginx, а про протокол vrrp особо не рассказали.
    Также у вас нет приоритезации трафика для vrrp. Если будет ddos, то вы получите ситуацию split-brain.

    • 0
      Рисунок вполне про статью
      Добавил описание в текст:

      Другими словами, у нас 2 сервера на которых прописано по одному публичному адресу. Если любой из этих серверов падает, то адрес упавшего подхватывается вторым.
      Демоны keepalived общаются по протоколу VRRP, посылая друг другу сообщения на адрес 224.0.0.18.
      Если сосед не прислал свое сообщение, то по истечению периода он считается умершим и оба адреса обслуживает оставшаяся нода. Как только упавший сервер начинает слать свои сообщения в сеть, все возвращается на свои места
      • 0
        >Рисунок вполне про статью
        различаются ip-адреса на рисунке и в статье. Мелочь, конечно, но меня напрягло.
        • 0
          справедливо
    • 0
      > Если будет ddos, то вы получите ситуацию split-brain.
      Что? Каким образом?
      • 0
        Потеряются multicast пакеты vrrp, ноды не увидят друг друга и одновременно станут мастерами.
        • 0
          Если сетевая не в состоянии увидеть multicast то для второй это правильный повод назначить себя мастером, потому что потерявшаяся нода очевидно не обслуживает запросы клиентов
          я правильно понял вопрос?
          • 0
            т.к. при ddos нет гарантии прохождения именно vrrp пакетов, то они могут пропасть. backup-нода увидевшая пропажу нужного vrrp станет мастером. Она пошлет gratuitous arp, которые тоже могут пропасть частично. А т.к. первая нода считает себя мастером, то ip адрес на ней висит и на arp она отвечает. Часть клиентов будут обращаться к одной ноде, а часть к другой.

            Если на переезд master-backup навешено выполнение каких-то скриптов (добавление/удаление маршрутов, например), то ситуация еще более усугубляется.

            В некоторых статьях по lvs я видел рекомендации вообще использовать отдельный serial-кабель для heartbeat'а. Но тут, правда, всплывает масса других проблем.
            • 0
              Вы коммутатор вообще исключаете из всего процесса?
              • 0
                коммутатор не исключаю, не совсем понял о чем Вы.
                • 0
                  кто хранит arp сети? кому адресован запрос gratuitous arp
                  • 0
                    gratuitous arp адресован всем в сети. А коммутатор обновляет свою таблицу соответствия macaddress-порт.
                    так что делать, если garp будут теряться?
                    • 0
                      В рамках протокола ARP возможны самообращенные запросы (gratuitous ARP). При таком запросе инициатор формирует пакет, где в качестве IP используется его собственный адрес. Это бывает нужно, когда осуществляется стартовая конфигурация сетевого интерфейса. В таком запросе IP-адреса отправителя и получателя совпадают.
                      Самообращенный запрос позволяет ЭВМ решить две проблемы. Во-первых, определить, нет ли в сети объекта, имеющего тот же IР-адрес. Если на такой запрос придет отклик, то ЭВМ выдаст на консоль сообщение Dublicate IP address sent from Ethernet address <...>.
                      • 0
                        спасибо за описание, но мне кажется, мы понимаем что такое garp и зачем он нужен. или Вас что-то смутило в моих словах…
                        Я все пытаюсь сказать, что при ddos может быть ситуация, когда на двух нодах будет висеть один и тот же ip-адрес. А garp будут то приходить, то нет (ddos же!). И когда arp-записи на машинах или коммутаторах будут expired, а нового garp не поступит, то будет сделан arp-запрос, на который может ответить ненужная нода.

                        • 0
                          если будет ddos и на обоих серверах будет висеть один и тот же адрес, работать при этом будет один
                          как только второй прийдет в себя, он пошлет garp запрос и получит ответ о том что этот адрес уже занят. Тогда он будет слать сообщение о том что он уже доступен и хочет принять мастера.
                          Как только это сообщение получит бекап сервер, то он опустит у себя бекапный адрес и его этот адрес возмет мастер
                          и столько раз сколько это будет нужно или в тот период который мы укажем в конфиге
                          я так понимаю, вы говорите о ситуации когда оба сервера отвечают что они владельцы этого адреса, но при этом не в состоянии обмениваться сообщениями по multicast
                          Коммутатор не должен позволить возникнуть такой ситуации
                    • 0
                      Во-вторых, в случае смены сетевой карты производится корректировка записи в АRP-таблицах ЭВМ, которые содержали старый МАС-адрес инициатора. Машина, получающая ARP-запрос c адресом, который содержится в ее таблице, должна обновить эту запись.
                    • 0
                      Вторая особенность такого запроса позволяет резервному файловому серверу заменить основной, послав самообращенный запрос со своим МАС-адресом, но с IP вышедшего из строя сервера. Этот запрос вызовет перенаправление кадров, адресованных основному серверу, на резервный. Клиенты сервера при этом могут и не знать о выходе основного сервера из строя. При этом возможны и неудачи, если программные реализации в ЭВМ не в полной мере следуют регламентациям протокола ARP.
  • 0
    По поводу сонфига nginx, не рекомендуется ставить уровень сжатия больше 5.
    Не совсем понял сути keepalived, по идее у нас есть основной сервер, на котором стоит балансировщик, но nginx сам — прокси, поэтому
    upstream web { server 10.211.77.131 weight=10 max_fails=60 fail_timeout=2s; server 10.211.77.136 weight=10 max_fails=60 fail_timeout=2s; }
    выступает в качестве раздатки, и он сам видит живой ли хост, если нет передает дальше по приоритету. Ну а если он упадет, главный который, то смысла то и нет во всём остальном.
    • 0
      Почему не рекомендуется?
      а если упадет сервер где стоит nginx?
      • +2
        1) Если уровень компрессии преодолевает порог в 5-ку, дальнейшее сжатие неоправданно. Дело в том, что нагрузка на процессор увеличивается, а КПД уровня сжатия стремится к нулю.
        Пример сжатия text/html в вариациях уровней:
        0    55.38 KiB (100.00% of original size)
        1    11.22 KiB ( 20.26% of original size)
        2    10.89 KiB ( 19.66% of original size)
        3    10.60 KiB ( 19.14% of original size)
        4    10.17 KiB ( 18.36% of original size)
        5     9.79 KiB ( 17.68% of original size)
        6     9.62 KiB ( 17.37% of original size)
        7     9.50 KiB ( 17.15% of original size)
        8     9.45 KiB ( 17.06% of original size)
        9     9.44 KiB ( 17.05% of original size)
        

        Пример сжатия application/x-javascript в вариациях уровней:
        0    261.46 KiB (100.00% of original size)
        1     95.01 KiB ( 36.34% of original size)
        2     90.60 KiB ( 34.65% of original size)
        3     87.16 KiB ( 33.36% of original size)
        4     81.89 KiB ( 31.32% of original size)
        5     79.33 KiB ( 30.34% of original size)
        6     78.04 KiB ( 29.85% of original size)
        7     77.85 KiB ( 29.78% of original size)
        8     77.74 KiB ( 29.73% of original size)
        9     77.75 KiB ( 29.74% of original size)
        

        Взято отсюда: serverfault.com/questions/253074/what-is-the-best-nginx-compression-gzip-level

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

        • 0
          1. Спасибо, это очень полезная информация, внес изменения текст
          2. Если у вас плановый майнтенанс, падение сервера и прочее
          от воды в коммутаторе это не спасет)
          • 0
            Пятница, может завтра осознаю то, что сегодня не понял. Спасибо за статью.
            • –1
              Спасибо за ценное дополнение
        • 0
          уровень компрессии это одно, а вот если бы посмотреть относительно компрессии к времени сжатия, было бы намного интереснее, что опттимальнее
          • 0
            Процитирую-ка сам себя:
            Когда-то давным давно делал небольшой gzip бенчмарк. Есть огрехи в методологии: например, нет сравнения с чистым копированием файла — но общее представление даёт. Обратите внимание на листы с графиками (внизу), особенно отрезвляет Relative compress ratio, т.е. прирост степени сжатия по сравнению с предыдущим уровнем.
      • 0
        На хабре проводили опыты в рамках топика "Исследование степени gzip-сжатия и загрузки процессора".
  • 0
    Спасибо, интересно.
    Есть несколько способов построения HA — почему именно Keepalived?
    • 0
      Это вы про ucarp?
      на самом деле только keepalived получилось настроить в режиме мастер бекап, мастер бекап
      ucarp перемещает между друг другом некий адрес алиас, но это не подходит для горизонтального масштабирования
      • +2
        Нет, я имею в виду Pacemaker ( раз и два) или LVS
        • 0
          Пока что не готов ответить, нужно попробовать в деле
          • 0
            Тогда вот еще пара вопросов по статье :)
            1) Что дает включение «net.ipv4.ip_nonlocal_bind=1»? Т.е. без этой опции схема не работает?
            2) Тоже самое про SELinux — что дам дает его отключение? И как написано в статье — это очень плохо… Тогда решение в статье не пригодно для боевого использования?..
            3) Ноды общаются по броадкасту? Если у нас два сервера — их можно соеденить напрямую через вторые сетевые ( хотя в этом случае аппаратный сбой сетевой карты приведет к эффекту, когда они друг друга не видят и каждый гордо поднимает флаг последнего из магикан :) ) А если три? 4?.. Подозреваю, что тут поможет bond… Просто интересно :)
            • 0
              1. Нет
              2. Это ирония на тему хейтеров этого решения. Мы выключаем это потому что далеко не весь софт работает с selinux  нормально и требует дополнительной настройки правил.
              3. На случай сбоя сетевой карты это решение и нужно, очевидно что в таком случае сервер не сможет принимать запросы к nginx
              • 0
                Не, у нас же вводная следующая:
                Есть 2 сервера с nginx и двумя интерфейсами на каждом + там же крутится некое приложение (не будем делать фронтенд-бэкэнд, все в одном для удобства)
                На сервере А внешний интерфейс 172.10.10.10 и внутренний скажем 192.168.10.10
                На сервере В внешний интерфейс 172.10.10.11 и внутренний скажем 192.168.10.11
                Keepalived в случае недоступности одной из нод вешает адрес второй на живую ноду. Если на картинке в самом верху поста выходит из строя красная линия (соединяющая две сетевые карты для общения нод), то ноды сами по себе живые, друг друга не видят и считаю напарницу трупиком — гордо поднимают на себе по два адреса.
                Извините, если я вам надоел такими вопросами — мне самому очень хочется разобраться с HA решениями и спать чуточку спокойнее :)
                • 0
                  Они опрашивают друг друга по внешнему же интерфейсу, если нарушается соединение одной то она теряет доступ в публичную суть, второй то и она тоже
                  • 0
                    Тогда я вообще запутался :)
                    Публичная сеть — мы считаем это Интернетом? А зачем тогда второй интерфес? Если вас не затруднит — нарисуйте пожалуйста картинку с интерфейсами, адресами и как траффик ходит в сети…
                    • 0
                      Второй интерфейс для связи с backend
                      Первый интерфейс для получения запросов от пользователей, по нему же происходит опрос соседней ноды
                      • 0
                        Ок, спасибо) Пошел осознавать
                        • 0
                          Рад помочь
  • 0
    LVS (ipvs) решает все проблемы напрочь, плюс там в обвязках (pyball, например) много интересного функционала. Keepalived выглядит каким-то прошлым веком.
    • 0
      keepalived как раз надстройка над ipvs
  • 0
    А почему на схеме один свич? Должно быть два, если мы говорим о высокой доступности. И тогда всё несколько усложняется.
    • 0
      Их может быть и 10, главное что бы между ними был возможен broadcast и multicast
      • 0
        Дело не только в этом. Наличие двух коммутаторов подразумевает, что каждая нода кластера должна иметь два сетевых интерфейса, каждый из которых подключается к каждому отдельному свичу. А это усложняет решение, т.к. нужно задействовать механизм автоматического переключения сетевого интерфейса. Или ещё лучше — настроить Nic Teaming на нодах, на свичах — etherchanel, если они в одном стеке, тогда ещё можно получить и балансировку нагрузки.
        • 0
          Возможно и так, но проще поставить несколько серверов esxi
          так сделано и у нас
          • 0
            а ESXi у Вас без резервирования коммутаторов и сетевых плат? Там это кстати очень легко настраивается.
            • 0
              Это все конечно есть, но виртуалке про это не нужно ничего знать. В этом суть
  • 0
    а что если так. сервер падает (топор в него воткнули). ip переключается на другую машину. GW узнает о смене мака привязанного к ip только, когда протухнет его arp таблица. т.е пока arp на шлюзе старый — пакеты будут лететь в лежащую машину. ARP может и 30 секунд протухать. 30 секунд даунтайма?
    • 0
      keepalived посылает gratuitous arp
  • 0
    всегда использовал хитрую ДНС балансировку, когда каждый ДНС отдает только сам себя и ТТЛ 60. есть нюансы, но они для нас приемлиы, а тут как-то геморно… уж простите. я считаю, чем проще — тем лучше.

    не увидел ничего про тюнинг TCP стека, а хотелось бы…

    п.с. сейчас используется 4 фронта для балансировки ~4000 rps в пиках и ~ 30-40 лимонов запросов в стуки. при отключении ноды (выключения bind), через 2-3 минуты остается траффик с 3-5 хостов. остальные аккууратно перетекают на другие ноды. проверяли и на тестах и на боевых под нагрузкой.

    п.п.с пробовали писмайкер и НА. не срослось.
    • 0
      если нода упадет то 25 процентов запросов фейлятся целую минуту?
  • 0
    да. на 1 минуту текущие клиенты получат отлуп. новые уйдут на работающие сервера. такое поведение автоматического режима файловера для нас приемлимо. 24/7 не обеспечит никто, а 1 минута не высокая цена для наших проектов.

    да, наверное на торгах или биржах это крах, но там совсем другое оборудование и технологии, но мы же говорим о практически стандартных решениях? если сайт будет недоступен 1 минуту для 25% клиентов, думаю это очень не плохой файловер.

    представьте, что у вас сервер в далеком ДЦ. падает канал. техподдержка молчит из-за перегрузки, сервер недоступен. вы не в курсе воообще что происходит. начальник нервно бегает с пистолетом и приставляет его к вашей голове.

    а в это время я спокойно сплю и знаю, что утром приду. посмотрю логи. спокойно проанализирую ситуацию и разберусь.

    нервы они, знаете ли, мне очень дороги, а уж нервы начальника вообще для меня святыня.
    • 0
      решение в этой статье помогает избежать подобного простоя, да возможно оно сложно в реализации. я постарался сделать пошаговую инструкцию с которой не должно возникнуть затруднений
  • 0
    подскажите, пожалуйста, — возможно ли использовать данную конфигурацию за кластером из 2-х CISCO ASA (active/standby) ?!
    у меня на виртуалках, которые master и slave есть 2 интерфейса, (management и DMZ). keepalived для взаимодействия использует интерфейс DMZ(IP адреса соотв. на master 10.1.2.35 на slave 10.1.2.36) VRRP IP 10.1.2.135 который я опубликовал на ASA и который работает до выключения master — потом ASA его теряет, хоть он и поднимается на slave!
    что делать?
    на ASA проскакивает такое сообщение (это после моего эксперимента — выключить обе ноды, затем включить первой slave и только потом master)
    4 Apr 23 2015 20:16:36 Received ARP request collision from 10.1.2.135/0021.f6xx.42a8 on interface DMZ with existing ARP entry 10.1.2.135/0021.f6yy.c241

    4 Apr 23 2015 20:18:36 Received ARP request collision from 10.1.2.135/0021.f6yy.c241 on interface DMZ with existing ARP entry 10.1.2.135/0021.f6xx.42a8


  • 0
    подскажите, для чего использовалась именно такая конфигурация keepalived — два vrrp_instance?
    Нельзя обойтись просто:
    [root@nginx-frontend-01 ~]#
    nano /etc/keepalived/keepalived.conf

    vrrp_instance nginx1 {
            state MASTER
            interface eth3
            virtual_router_id 51
            priority 101
            mcast_src_ip x.x.x.55
            authentication {
                    auth_type PASS
                    auth_pass b65495f9
            }
            virtual_ipaddress {
                    x.x.x.2/29
            }
    }

    [root@nginx-frontend-02 ~]#
    nano /etc/keepalived/keepalived.conf

    vrrp_instance nginx1 {
            state MASTER
            interface eth3
            virtual_router_id 51
            priority 100
            mcast_src_ip x.x.x.55
            authentication {
                    auth_type PASS
                    auth_pass b65495f9
            }
            virtual_ipaddress {
                    x.x.x.2/29
            }
    }
    • 0
      что бы оба сервера и адреса были активный, одновременно
  • 0
    sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/sysconfig/selinux
    Без --follow-symlink рискуете остаться с неотключенным selinux, т. к. на centos6/rhel6 с некоторого момента оно выглядело так:
    # ls -l /etc/selinux/config /etc/sysconfig/selinux 
    -rw-r--r--. 1 root root 457 Mar  2 21:56 /etc/selinux/config
    lrwxrwxrwx. 1 root root  17 Apr  9  2014 /etc/sysconfig/selinux -> ../selinux/config

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.

Самое читаемое Разное