Как стать автором
Обновить

Комментарии 79

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

В каком месте? То-есть TLSv1.2 и TLSv1.1 не нужны? А еще SSLv3 рекомендуется не использовать. TLSv1.0 все современные браузеры поддерживают. Да и RC4 слабоват будет, лучше исключить его. А Forward Secrecy? А Strict Transport Security?
Ну, скажем так: эта статья далека от идела. 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";
Вы считаете что от идеала ее отделяет ваше замечаение по SSL?
Так в ней всего то и говорится о том, как правильно настроить SSL. И то не правильно.

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

Например 2 разных keepalived, которые перекидывают внешние адреса между машинами, а в DNS добавить 2 А записи?
С DNS сложно: он сильно кэшируется, keepalive в этом смысле намного лучше
В данной конфигурации оба сервера активны и если один из них падает то его адрес принимает второй
Да, с DNS все понятно, что записи могут кэшироваться, но речь про то, чтобы иметь 2 внешних IP, по одному на каждый сервер и в случае падения одного из серверов, второй назначает себе оба внешних адреса.
Именно так все и происходит в этом примере
Вчитался в конфиг, понятно, спасибо
Хорошее how-to, с достаточно хорошо прокоментированными конфигами. Но имхо, недостаточно объяснений, например:
1) Почему используется именно такая конфигурации keepalived? Она избыточна и это неспроста, а вот почему не рассказано.
2) Почему удаляете хосты по умолчанию и приводите их к совершенно другому виду.
3) Это очень важный шаг: net.ipv4.ip_nonlocal_bind=1 — Почему?
1 Это сама базовая конфигурация с двумя одновременными мастерами и бекапами
2 По умолчанию там стандартное приветствие nginx
3 Установка этой переменной позволяет отдельным локальным процессам выступать от имени внешнего (чужого) IP адреса
Добавил правки в текст, теперь это будет понятно из текста
Спорный момент про fail_timeout=2s — фронтенд не всегда будет отвечать меньше 2с
fail_timeout=2s Это время через которое nginx попробует снова тыкнуть в fail сервер и так пока не будет достигнуто максимально значение max_fails
Не уверен, что это правда
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).
fail_timeout = TIME — время, в течение которого должно произойти * max_fails * Количество неудачных попыток связи с сервером, что бы заставить сервер рассматриваться в нерабочем состоянии, а также время, в течение которого сервер будет считается неработоспособным (до другой попытки ).
Определение 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»
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
А то что вы имеете ввиду задается параметрами

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

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

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

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


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

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

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

если будет ddos и на обоих серверах будет висеть один и тот же адрес, работать при этом будет один
как только второй прийдет в себя, он пошлет garp запрос и получит ответ о том что этот адрес уже занят. Тогда он будет слать сообщение о том что он уже доступен и хочет принять мастера.
Как только это сообщение получит бекап сервер, то он опустит у себя бекапный адрес и его этот адрес возмет мастер
и столько раз сколько это будет нужно или в тот период который мы укажем в конфиге
я так понимаю, вы говорите о ситуации когда оба сервера отвечают что они владельцы этого адреса, но при этом не в состоянии обмениваться сообщениями по multicast
Коммутатор не должен позволить возникнуть такой ситуации
Во-вторых, в случае смены сетевой карты производится корректировка записи в АRP-таблицах ЭВМ, которые содержали старый МАС-адрес инициатора. Машина, получающая ARP-запрос c адресом, который содержится в ее таблице, должна обновить эту запись.
Вторая особенность такого запроса позволяет резервному файловому серверу заменить основной, послав самообращенный запрос со своим МАС-адресом, но с IP вышедшего из строя сервера. Этот запрос вызовет перенаправление кадров, адресованных основному серверу, на резервный. Клиенты сервера при этом могут и не знать о выходе основного сервера из строя. При этом возможны и неудачи, если программные реализации в ЭВМ не в полной мере следуют регламентациям протокола ARP.
По поводу сонфига 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; }
выступает в качестве раздатки, и он сам видит живой ли хост, если нет передает дальше по приоритету. Ну а если он упадет, главный который, то смысла то и нет во всём остальном.
Почему не рекомендуется?
а если упадет сервер где стоит nginx?
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

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

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

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

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

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

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

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

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

нервы они, знаете ли, мне очень дороги, а уж нервы начальника вообще для меня святыня.
решение в этой статье помогает избежать подобного простоя, да возможно оно сложно в реализации. я постарался сделать пошаговую инструкцию с которой не должно возникнуть затруднений
подскажите, пожалуйста, — возможно ли использовать данную конфигурацию за кластером из 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


подскажите, для чего использовалась именно такая конфигурация 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
        }
}
что бы оба сервера и адреса были активный, одновременно
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
IPADDR=72.x.x.1
NETMASK=255.255.255.248
BROADCAST=72.x.x.55
То есть в моей публичной сети, маска /29 и значит мой broadcast x.x.x.55

Нет. Маска Префикс /29 говорит о том, что четвертый октет разбит на группы по 2^(32-29) адресов в группе, что равняется 8 адресам, но никак не 56.
Если у вас работала эта конфигурация, а в статье несколько раз упомянуто о проблемах при неправильном указании широковещательного адреса, то я удивлен.
С маской 255.255.255.248 (префиксом /29) для широковещательного адреса х.х.х.55 адрес сети будет х.х.х.48
Возможно, вы ошиблись с указанием первого используемого адреса 72.x.x.1

SyCraft Если возможно, свяжитесь с модераторами для внесения правок.
Зарегистрируйтесь на Хабре, чтобы оставить комментарий