28 июля, 2016

IBM x3850 m2, ядро 4.4 и блуждающие сетевые адаптеры

Некоторое время назад дошли наконец-руки до обновления Proxmox с 3.х до актуальной сейчас версии 4.2. Прошло не без проблем, но особых трудностей они тоже не создали. За исключением одного сервера. Есть у меня среди прочих некогда очень крутой IBM x3850 m2, в который в свое время затолкали 4 6-ядерных Xeon X7460 и 112 гигов фуллбуфферед-памяти. При всей суровости комплектации, обогнать современные серверы он может разве что по энергопотреблению, но на кучку всяких не очень требовательных к производительности виртуалок его все еще хватает.

Еще попутно с обновлением проксмокса в серверы были установлены 10GBe-адаптеры Intel X540, впрочем, не буду забегать вперед.

После обновления ядра до 4.4, тот x3850 m2 напрочь отказался загружаться, впадая в кернел паник при инициализации встроенного RAID-контроллера ServeRAID-MR10k (он же LSI 1078). Беглый гуглеж показал, что не один я столкнулся с этой проблемой, в качестве решения предлагалось добавить к параметрам ядра iommu=soft. Попробовал - помогло. Сервер загрузился. Настроил 10-гигабитную сетку, все проверил, работает, но так продолжалось до следующего ребута, после которого из системы напрочь пропала 10-гигабитная карточка. lspci молчит, но сервер, однако, при начальной загрузке карточку явно распознает, да и Intel Boot Agent мелькает при этом. Но в системе карточку не видно.

Было решено копать в сторону RAID-контроллера, т.к. в сторону Intel'a ничего путного накопать не удалось. На паре форумов встретил упоминание, что от iommu=soft в параметрах загрузки некоторых избавило обновление прошивки контроллера. Самой свежей прошивкой на сайте IBM была 11.0.1-0042, у меня же была установлена 11.0.1-0024. Значит, стоит попробовать обновиться.

К слову, если вы, в попытках повторить мой опыт, испортите что-нибудь в своем сервере, то виноваты в этом будете исключительно вы сами.

Скачиваем бинарник с обновлением с сайта IBM, пытаемся запустить, и тут же получаем "No such file or directory". Это ему нужно 32битную libstdc++. Ок.

apt-get install lib32stdc++6

Снова пробуем запустить. Уже лучше, для обновления оно предлагает запускать себя с аргументом -s
Пробуем, и снова облом: Unsupported Linux Distribution. Ну конечно, ведь у нас Debian Jessie, а эта гадина хочет RHEL4/5 или SLES9/10/11.

Натравливаем strace и видим, что проверить дистрибутив оно пытается путем чтения содержимого файла /etc/redhat-release. Создадим такой файл и впишем туда содержимое для RHEL5:

Red Hat Enterprise Linux Server release 5 (Tikanga)

Пробуем еще раз, на дистриубтив уже не жалуется, но какие-то проблемы с запуском ./MegaCLI и нехваткой библиотек.
К черту всё, пойдем напролом.

Распаковываем потрошка обновления:

unzip ibm_fw_sraidmr_10k-11.0.1-0042_linux_32-64.bin
cd image
chmod +x install.sh lsiMRupdate

а вот MegaCLI заменим симлинком на уже установленный из репозитория hwraid:

rm MegaCLI
ln -s /usr/sbin/megacli ./MegaCLI

Еще одна попытка обновиться:

./install.sh

*************************************************
 LSI MR Update Utility for use with IBM hardware 
       Version 1.35 - Release Date 1/21/11       
*************************************************

This update is for the ServeRAID MR10k Controller

Found 1 ServeRAID MR or MegaRAID Controller(s)

Getting configuration for Controller 0.  Please wait....

Controller 0 is a ServeRAID MR10k Controller

Attempting to flash controller 0!

Updating Controller 0.  Please wait....

./MegaCLI -AdpFwFlash -f mr10kfw.rom -a0 > result.out

Update of controller 0 completed successfully.

Successfully flashed controller 0!

You must reboot your system to complete the firmware update process.
You do not need to reboot your system immediately.

Ну наконец-то!

Пробуем перезагрузиться без iommu=soft, но увы, ядро снова впадает в панику. Возвращаем эту опцию, загружаемся, смотрим вывод lspci:

18:00.0 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)
18:00.1 Ethernet controller: Intel Corporation Ethernet Controller 10-Gigabit X540-AT2 (rev 01)

Оп-па! Наконец-то 10-гигабитные адаптеры снова вернулись. И даже работают.

P.S. не факт, что они снова после какой-нибудь перезагрузки куда-нибудь не исчезнут, это мне еще предстоит проверить. Если кто-нибудь из читателей может внести ясность на тему того, что это вообще такое было и как с этим жить дальше, был бы очень признателен.


29 апреля, 2016

Ещё немного про SteelSeries engine в OS X

Проблемой, описанной в прошлом посте, дело не кончилось. После очередного обновления engine client опять отказался стартовать, показывая вечный Loading. На этот раз инсталлятор почему-то решил, что права на запись в ~/Library/Application Support/steelseries-engine-3-client/ мне не очень-то и нужны. Лечится, соответственно, рекурсивным добавлением соответствующих прав :)

25 февраля, 2016

Ломающий Steelseries Engine Client 3.6.6 в MacOS X

Не было печали - апдейтов накачали. В смысле, обновил SteelSeries Engine 3 для макоси до последней версии 3.6.6 и что-то пошло не так: сначала он начал утверждать, что мол де его неправильно запускают. Потом просто после запуска ничего не показывал, бесконечно изображая видимость бурной деятельности путем мигания точками около слова «LOADING» на всё своё окно.

Выйти-зайти, перезагрузиться и прочие стандартные шаманства не возымели эффекта, равно как и переустановка злополучной софтины с предварительным выпиливанием родным uninstaller'ом.

Как оказалось, uninstaller халтурит, и удаляет далеко не все продукты жизнедеятельности сносимого приложения.

В общем, исправить проблему можно так: даёте uninstaller'у сделать своё дело, затем переходите в ~/Library/Application Support и удаляете папку SteelSeries Engine 3 Client, затем заново устанавливаете SteelSeries Engine.

После этого всё начинает работать, а новую папку для себя оно вовсе с другим именем создает - steelseries-engine-3-client

30 сентября, 2015

Mikrotik WAN Failover и «повисающий» SIP

Не так давно довелось столкнуться с довольно тривиальной ситуацией, решений для которой в рунете сходу найти, к моему удивлению, не удалось. Ситуация: есть офис, раздачей интернетов в котором занимается роутер под управлением RouterOS. В офисе есть некоторое количество SIP-телефонов, а также резервный канал доступа в интернет на случай проблем с основным.

И вроде ничего не предвещало, как говорится, но вылез один очень неприятный момент: при переключении на резервный канал те самые SIP-телефоны напрочь отказывались заново устанавливать соединение с PBX (находящейся за пределами офиса), что заставляло обитателей того офиса вручную перезагружать каждый телефон, да еще и стараться побыстрее заметить, что телефоны отвалились, чтоб не пропустить какой-нибудь важный звонок.

В чем же дело? Всё довольно просто: переключение на резервный канал было реализовано с помощью двух маршрутов с destination 0.0.0.0/0 и разным значением distance в зависимости от приоритета, а также с настроенными соответствующим образом опциями check-gateway. Но переключение переключением, а вот таблицу NAT роутер при этом не очищал, т.к. его об этом никто и не просил, что приводило к «повисанию» UDP-соединений на том дефолте, который по несчастью отвалился.

Избежать подобной ситуации можно несколькими способами (мне попадались даже разного рода скриптовые ады, отключающие-включающие connection tracking, и прочие душераздирающие зрелища), но лично я решил сделать решение без ненужного скриптинга, максимально простое и лаконичное.

Итак, из руководства к RouterOS нам известно, что check-gateway проверяет доступность шлюза каждые 10 секунд, и если ответа на проверочный запрос не поступило в течение 10 секунд, то проверка считается неудачной. А после двух таких таймаутов подряд шлюз помечается как недоступный, тут-то и происходит переключение на резерв.

Для простоты будем считать, что период переключения каналов у нас равен 30 секундам. Тогда создадим netwatch, который будет пингать нашу телефонную станцию с интервалом в 15 секунд (половина от тех 30, чтоб наверняка). И да, разумеется наша телефонная станция должна в нормальной ситуации отвечать на пинг:

/tool netwatch add host=адрес_нашей_PBX interval=15s timeout=1s up-script="/ip firewall connection remove [find where dst-address~\"5060\"]" down-script="/ip firewall connection remove [find where dst-address~\"5060\"]"

Теперь, если вдруг у нас пропадет пинг до IP-АТС, из таблицы соединений будет вычищено всё, что шло на порт 5060. Но вообще я бы рекомендовал написать в up/down скрипт что-нибудь такое:

/ip firewall connection remove [find where src-address~"192.168.88."]

Под 192.168.88 подразумевается диапазон локальных офисных ip-адресов. Это сбросит все клиентские соединения (при этом не затронув те, что инициировал сам роутер, например L2TP-туннель до провайдера или еще что-нибудь), что в свою очередь сделает процесс переключения на резервный канал и обратно более «бесшовным» для пользователей, т.к. коннекты будут оборваны и пакеты точно не будут пытаться идти по умершему маршруту.

Не стоит беспокоиться насчет того, что такое решение может рвать соединения излишне часто: netwatch-скрипты выполняются по одному разу (единожды, когда пингуемый хост стал виден, и точно так же единожды, когда из виду пропал), а не циклично.
Данное решение было всячески оттестировано с пристрастием (и без), и никаких проблем выявлено не было.

14 июня, 2015

Еще одна возможная причина возникновения ошибок «Uncorrectable parity/CRC error» и борьба с ней

В интернете распространено мнение о том, что если у вас внезапно в /var/log/messages обнаружилась огромная куча ошибок вида
(ada2:ahcich2:0:0:0): WRITE_FPDMA_QUEUED. ACB: 61 00 f0 2f 9b 40 38 00 00 01 00 00
(ada2:ahcich2:0:0:0): CAM status: Uncorrectable parity/CRC error
(ada2:ahcich2:0:0:0): Retrying command
то это у вас либо диск умирает, либо питальник, либо шлейф от контроллера к диску сделан из дешевой китайской лапши. Однако, довелось столкнуться с ситуацией, когда на одном из двух абсолютно новых WD Purple у меня сразу полезло это безобразие, хотя диски явно были в порядке, шлейфы – тоже, а значения выходного напряжения у блока питания гуляли в пределах 0.03В, т.е. всё было вроде бы идеально, но ошибки продолжали сыпаться.

После долгих поисков виновника всё-таки удалось отыскать. Им оказался spread spectrum, включенный в настройках биоса материнской платы. Стоило отключить эту опцию, и ошибки исчезли, а волосы мои стали мягкими и шелковистыми.

20 мая, 2015

«Два конца»

Интересная и не совсем тривиальная задача подвернулась. Ситуация: в некоторой организации локальная сеть имеет адрес, скажем, 192.168.0.0/24, и нужно пробросить некоторый порт (пусть будет tcp/8080) для кофеварки, адрес которой 192.168.0.50.

Казалось бы, что в этом такого? Так уж сложилось, что у провайдера, через которого мы получаем доступ в интернет по L2TP, адрес VPN-сервера тоже 192.168.0.50. Соответственно, сделать так, чтобы роутер подключался к VPN через сеть провайдера, у нас есть маршрут для 192.168.0.50/32, но если попытаться пробросить порт на этот адрес, пакеты закономерно пойдут на VPN-сервер провайдера, а не на нашу кофеварку, что нам совсем не нужно.

Что же делать?

Сначала создадим маршрут:

/ip route add dst-address=192.168.0.50/32 gateway=bridge-local routing_mark=coffee_mark

Обратите внимание на routing_mark.
Теперь создадим правило в mangle:
/ip firewall mangle add chain=prerouting in-interface=WAN protocol=tcp dst-port=8080 \
action=mark-routing new-routing-mark=coffee_mark

Ну и dst-nat правило, с ним ничего необычного:
/ip firewall nat add chain=dstnat in-interface=WAN protocol=tcp dst-port=8080 action=dst-nat to-addresses=192.168.0.50

Вот и все. Теперь соединениям, идущим на нашу кофеварку по указанному порту, будет присваиваться routing_mark, с помощью которого наш роутер поймет, где искать ту кофеварку.

07 апреля, 2015

Организация a/b тестирования веб-проектов средставами nginx

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

Определимся с условиями нашей задачи:
  1.  На новую версию сервиса мы должны направить ≈20% всех пользователей
  2.  Есть ip-адреса клиентов, которые должны всенепременно попадать на старую версию
  3.  То же самое, но – всенепременно на новую.
Далее я приведу конфигурационный файл целиком, а после опишу принцип его действия.

geo $mytest_participant {
  default              1;
  10.1.1.1             0;
  192.168.45.2         2;
}

map $mytest_participant $resulting_upstream_name {
  0     "old_version_upstream";
  1     "distributed_upstream";
  2     "new_version_upstream";
}

upstream distributed_upstream {
  ip_hash;
  server 1.1.1.1 weight=8; # Old version server, 80% of clients
  server 2.2.2.2; # New version server
}

upstream old_version_upstream {
  server 1.1.1.1;
}

upstream new_version_upstream {
  server 2.2.2.2;
}

server {
  listen 80;

  server_name example.com;

  location / {
    proxy_pass http://$resulting_upstream_name;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For  $proxy_add_x_forwarded_for;
  }

}

Итак, первый блок (geo) описывает как раз распределение пользователей по апстримам.
ip-адреса (можно использовать CIDR-нотацию, разумеется), для которых выставлено значение 0, будут направляться на старую версию принудительно, 1 - распределяться по вышеуказанному алгоритму (80% – на старую, 20% – на новую версию), ну и 2 - принудительно на новую.

Именно в зависимости от этого значения и присваивается имя апстрима в следующем блоке (map).

Далее все просто: описываются апстримы для старой и новых версий, а также наш распределенный апстрим. Для последнего используется алгоритм балансировки ip_hash, благодаря которому одни и те же ip-адреса будут попадать строго на тот апстрим, на который попали впервые. Если нам нужно изменить процентное соотношение распределения по старой и новым версиям, то правим соответствующим образом параметр weight для старого апстрима.

Вот, собственно, и всё.

Нужно, однако, помнить, что ip_hash использует только первые три октета ip-адреса клиента, т.е. на ту или иную версию попадет сразу весь /24 сегмент. Однако обычно это не является чем-то критичным, тем более, что в блоке geo можно подкорректировать ситуацию для отдельных ip-адресов, при наличии необходимости.