среда, 31 января 2018 г.

Ошибки при удалении multipath диска


В продолжение предыдущей статьи. Что происходит, когда произошла авария (или просто накосячили) и все пути для multipath устройства находятся в состоянии failed? Пример ниже:

# multipath -ll
mpathb (360a98000646e6c512f4a6f714f46324f) dm-6 NETAPP ,LUN
size=110G features='4 queue_if_no_path pg_init_retries 50 retain_attached_hw_handle' hwhandler='1 alua' wp=rw
|-+- policy='service-time 0' prio=0 status=enabled
| |- 0:0:0:42 sdc 8:32 failed faulty running
| `- 1:0:2:42 sdad 65:208 failed faulty running
`-+- policy='service-time 0' prio=0 status=enabled
|- 0:0:2:42 sdl 8:176 failed faulty running
`- 1:0:1:42 sdw 65:96 failed faulty running

Удаление multipath устройства может закончиться ошибкой:

# multipath -f mpathb
Jan 29 13:42:58 | mpathb: map in use
Jan 29 13:42:58 | failed to remove multipath map mpathb

При этом утилиты просмотра дисков, такие как pvs, начинают зависать, в системе начинают появляться неубиваемые процессы в состоянии D - uninterruptible sleep. Все это, конечно же, очень печалит и ставит в тупик. Но, как говорится, даже если вас съели — то у вас все равно есть два пути. Этой беде тоже можно помочь.
Обратите внимание на опцию в конфигурации multipath диска - "queue_if_no_path" — дословно держать очередь, если нет активных путей. Опцию нужно убрать из конфигурации и затем нужно перечитать конфигурационный файл. После чего уйдут процессы в состоянии uninterruptible sleep, которые держат диск. 
Эта опция может отсутствовать в явном виде в конфигурационном файле, она часто встречается в дефолтной настройке даемона multipathd для различных схд. Убрать опцию queue_if_no_path на multipath диске можно следующим образом:

# dmsetup message mpathb 0 fail_if_no_path

После чего диск можно удалить:

# multipath -f mpathb

вторник, 30 января 2018 г.

Как правильно удалить multipath диск из ОС


Друзья, коллеги, просто читатели, ОС - это конечно же linux. Еще точнее это rhel 6 или rhel 7. Порядок добавления дисков multipath ни у кого, как правило, не вызывает особых проблем. Тем не менее, если есть желание почитать как — напишите в комментариях. Но при удалении диска/дисков можно допустить досадные промахи. Таким образом порядок следующий:

Посмотрите, какие диски составляют multipath диск:

# multipath -ll
mpathb (360060e802214ab00504114ab00000116) dm-5 HITACHI ,OPEN-V
size=1.0T features='0' hwhandler='0' wp=rw
`-+- policy='service-time 0' prio=1 status=active
|- 0:0:1:1 sdi 8:128 active ready running
|- 0:0:3:1 sdr 65:16 active ready running
|- 1:0:0:1 sdt 65:48 active ready running
`- 1:0:3:1 sdaj 66:48 active ready running

Отмонтируем раздел:

# umount /mount_point

Теперь необходимо зачистить lvm. В случае удаления одного диска из lvm группы необходимо освободить экстенты:

# pvmove /dev/mapper/mpathb

и далее удалить его из группы:

# vgreduce volume_group /dev/mapper/mpathb

В случае вывода из эксплуатации всех дисков составляющих группу нужно деактивировать volume group:

# vgchange -a -n volume_group

далее, удалить volume group:

# vgremove volume_group

не обязательно, но можно удалить метаданные физического (в терминологии lvm) тома:

# pvremove /dev/mapper/mpathb

И вот теперь можно удалить multipath устройство:

# multipath -f mpathb

Но пока это не все - очистим буфера scsi дисков(sdi, sdr, sdt и т.д.):

# blockdev --flushbufs /dev/sdi

Финальный этап: удаляем все диски, которые составляли multipath устройство, пример:

# echo 1 > /sys/block/sdi/device/delete

воскресенье, 10 декабря 2017 г.

Как "привязать" исходящий трафик некоторого приложения к определенному source IP

Часто сказки народов севера начинаются со слова "как". Название статьи тоже начинается со слова "как" - сейчас поясню, что это название под собой подразумевает.
Краткое описание задачи - есть прокси сервер (haproxy), на котором работают несколько публикаций, каждая на своем IP адресе. Необходимо проверить работоспособность TLS бэкенда одной из публикации. Казалось бы все просто:

$ openssl s_client -connect backend_ip:port -showcerts

ОС попытается открыть соединение с основного IP сервера, но в нашем случае нужно соединение открыть с IP публикации. Для telnet есть возможность указать адрес, с которого нужно установить соединение:

$ telnet -b server_ip backend_ip port

А для openssl - нет. Можно выкрутиться с помощью iptables - сделать банальный source NAT. Чтобы ненароком не затронуть остальные коннекты и, как следствие, не усложнять правило условиями - добавим ограничение по UID пользователя:

# iptables -t nat -A POSTROUTING -m owner --uid-owner user_id -j SNAT --to-source server_ip


Как видите, можно легко привязать к определенному IP bash скрипт или сделать обертку для запуска ПО, которое лишено возможности выбора source IP.

суббота, 21 октября 2017 г.

Медленная синхронизация времени.

Ситуация была следующая: старый сервер на Suse 11, время ушло на несколько минут вперед. Поправить время скачком совсем не вариант, т.к. на нем финансовое приложение, и что может получиться - одному богу известно. Быстрое гугление не дало результатов, пришлось читать маны. Засим выкладываю свой рецепт.

Ntpd нужно потушить и запустить руками:

ntpd -g -x -d

 Где:
-g - стандартно ntpd не будет синхронизировать время, если есть большая разница времени между сервером и клиентом, по умолчанию это разница установлена в 1000с. Данная опция убирает это ограничение.
-x - ntpd подгоняет плавно время, если смещение меньше порогового значения (по умолчанию 128мс), если больше - выставляет скачком. Данная опция заставляет ntpd подгонять плавно время во всех случаях.
-d - режим отладки, просто больше выводится информации в консоль.

Время синхронизации зависит от значений minpoll\maxpoll - интервал опроса. При стандартном minpoll 6 (секунды, количество составляет степень 2, т.е. 64с) подстройка времени занимает 2000 секунд на каждую секунду смещения.

понедельник, 25 апреля 2016 г.

Как осуществить балансировку исходящей почты.

Балансировка исходящей почты может пригодиться, когда в качестве следующего получателя (next-hop) письма есть несколько серверов. Для одного домена можно указать несколько MX записей и/или несколько IP адресов (Round robin DNS). Этот вариант широко распространен для публичного интернета. Однако, этот вариант не подходит, если вы не имеете возможность менять DNS зону. Или к примеру, для почтового сервера используемого внутри LAN: пересылка всех писем может осуществляется на next-hop, который указан в (или для определенных случаев в таблице transport). Уточню, в postfix в директиве relayhost нельзя указать перечень серверов. Усложним задачу: необходимо определять доступность next-hop серверов. Сделать требуемое позволит haproxy. Его можно развернуть на этом же почтовом сервере. Haproxy будет слушать на loopback'е, перенаправляя входящий трафик на сервера next-hop. Помимо пересылки трафика он так же будет мониторить доступность серверов. Пример конфигурации haproxy:

# cat /etc/haproxy/haproxy.cfg
global
log 127.0.0.1 local2
chroot /var/lib/haproxy
pidfile /var/run/haproxy.pid
maxconn 4000
user haproxy
group haproxy
daemon

# turn on stats unix socket
stats socket /var/lib/haproxy/stats

defaults
log global
option tcplog
option log-health-checks
option dontlognull
option redispatch
retries 3
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout check 10s
maxconn 3000

listen stats gwip:5111
mode http
stats enable
stats hide-version
stats auth admin:password
stats uri /admin?stats
stats show-desc server.domain.com

listen base_relay 127.0.0.1:5222
mode tcp
balance roundrobin
option smtpchk HELO server.domain.com
server nexthop1 ip1:25 check inter 5000 fall 3 rise 3
server nexthop2 ip2:25 check inter 5000 fall 3 rise 3
server nexthop3 ip3:25 check inter 5000 fall 3 rise 3
server nexthop4 ip4:25 check inter 5000 fall 3 rise 3

Кратко по листингу:
  • listen stats gwip:5111 — блок описания графического интерфейса статистики и управления haproxy, gwip должен быть ip сервера. Не забудьте поменять пароль!
  • listen base_relay 127.0.0.1:5222 — блок описания балансировки исходящей почты.
    • balance roundrobin — политика балансировки соединений, название говорит само за себя.
    • option smtpchk HELO server.domain.com — проверка доступности серверов next-hop на седьмом уровне модели OSI, укажите свое имя сервера.
    • server nexthop1 ip1:25 check inter 5000 fall 3 rise 3 — информация по next-hop серверу, его имя — nexthop1, ip — ip1, и параметры проверки:
      • inter - временной интервал проверки, 5000 мс.
      • fall - количество неудачных попыток подряд, после чего сервер исключается из списка балансировки соединений.
      • rise - количество удачных попыток подряд, после чего сервер возвращается в список.

Теперь осталось только поменять в конфигурации postfix адрес в директиве relayhost на 127.0.0.1:5222. Данная статья хорошо сочетается с этой публикацией. Могу добавить, что в моем случае количество проходящих писем составляет более миллиона в сутки.

воскресенье, 22 ноября 2015 г.

Имя сетевого устройства

Старое название интерфейсов, такое как к примеру eth0, кануло в лету (ну почти, иногда старые имена можно встретить). В RHEL7 используются следующие варианты схем наименования сетевого интерфейса, в порядке применения:
  1. Имя, предоставляемое аппаратным обеспечением (Firmware или BIOS), включающее порядковый номер, для устройств, расположенных на материнской плате, к примеру eno1. Если выбор имени не произведен, используется схема 2.
  2. Имя, предоставляемое аппаратным обеспечением (Firmware или BIOS), включающее порядковый номер слота PCI Express, к примеру ens1. Если выбор не произведен, используется схема 3.
  3. Имя формируется из физического положения точки подключения устройства, к примеру enp2s0. Иначе используется схема 5.
  4. Имя включает MAC устройства, к примеру enx94de80a44f0c. Эта схема по умолчанию не используется.
  5. Старая схема, где имя присваивается ядром в порядке обнаружения интерфейса, к примеру eth0 и т.д.
Это поведение по умолчанию.

Новые имена сами по себе содержат полезную информацию. Принятое соглашение о наименовании следующее: первые два символа отражают тип интерфейса:
  1. en — Ethernet.
  2. wl — беспроводная локальная сеть, WLAN.
  3. ww — беспроводная глобальная сеть, WWAN.
Далее следует тип, отражающий схему наименования, описанную выше:
  1. o<index> индекс для устройств расположенных на материнской плате.
  2. s<slot>[f<function>][d<dev_id>] сначала идет номер PCI Express слота, далее f<function> - номер функции у многофункционального PCI устройства (я не встречал таких плат) и последним идет идентификатор устройства.
  3. p<bus>s<slot>[f<function>][d<dev_id>] расположение устройства на PCI шине. Домен PCI (p<bus>) указывается только если он отличен от нулевого (это можно увидеть в больших системах). Номер функции и номер устройства аналогично предыдущему примеру.
  4. p<bus>s<slot>[f<function>][u<port>][..][c<config>][i<interface>] расположение устройства на USB шине, причем учитывается вся цепочка портов.
  5. x<MAC> MAC адрес.
Нужно отметить, что имя не может быть более 15 символов, это ограничение ядра.

В случае использования VLAN добавляется следующее соглашение о имени интерфейса:
  1. vlan<vlanid> — имя с полным номером vlanid, к примеру vlan0012 или имя с сокращенным vlanid — vlan12
  2. device_name.<vlanid> - имя интерфейса и VLAN ID в полном или сокращенном виде, к примеру ens3.0012 или ens3.12
Как бы глупо это не звучало, но помимо описанных соглашений о наименовании, есть еще одно, используемое при помощи утилиты udev — biosdevname (насколько я понял, возникло это соглашение по инициативе DELL и используется на их серверах). Оно имеет силу только при наличии установленного пакета biosdevname и при указании biosdevname=1 при загрузке системы. Переименования будут производится только для встроенных интерфейсов. При этом:
  1. Встроенные интерфейсы будут иметь имя типа em[123...]
  2. Интерфейсы, подключенные по шине PCI — p<slot>p<ethernet port>, к примеру p3p4
Чтобы окончательно не запутаться в теоретической части, рассмотрим более глубоко процесс присваивания имени интерфейсу по шагам. Ниже пример того что происходит, когда в системе появляется новый интерфейс:

# udevadm monitor
...
KERNEL[27783.869667] add /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/eth0 (net)
...
KERNEL[27783.879674] move /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/enp0s20u7u4 (net)
UDEV [27783.892038] add /devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/enp0s20u7u4 (net)
...

Т.е. сначала интерфейс появился со старым, знакомым именем eth0, а далее стал enp0s20u7u4. Нетрудно заметить, что новое имя сразу отображает что это адаптер Ethernet (en), подключенный к USB шине через usb хаб (в имени два usb порта u7u4). Достаточно удобно.

Посмотрим, что выполняет udev над интерфейсом:

  • Шаг первый:
# udevadm test /sys/devices/pci0000:00/0000:00:14.0/usb1/1-7/1-7.4/1-7.4:1.0/net/enp0s20u7u4
...
PROGRAM '/lib/udev/rename_device' /usr/lib/udev/rules.d/60-net.rules:1
starting '/lib/udev/rename_device'

Что происходит: правило udev /usr/lib/udev/rules.d/60-net.rules при помощи /lib/udev/rename_device, просматривает конфигурационные файлы сетевых интерфейсов - /etc/sysconfig/network-scripts/ifcfg-*, и если есть соответствие MAC адреса добавляемого интерфейса и адреса в директиве HWADDR, то имя интерфейса устанавливается в соответствии с директивой DEVICE.
Сейчас воспользуемся небольшой хитростью, чтобы процесс применения правил udev был более наглядным. Создадим конфигурационный файл ifcfg-tstif0 с именем tstif0 для нашего адаптера и вставим адаптер. Интерфейс в системе станет tstif0. Теперь удалим конфигурационный файл, и посмотрим на обработку правил еще раз, но уже для интерфейса tstif0, в конечном итоге мы должны будем получить имя enp0s20u7u4.
Запустим еще раз, первое правило не отработает, т.к. конфигурационный файл мы удалили:

PROGRAM '/lib/udev/rename_device' /usr/lib/udev/rules.d/60-net.rules:1
starting '/lib/udev/rename_device'
'/lib/udev/rename_device' [5023] exit with return code 0

  • Шаг второй, смотрим дальше:
PROGRAM '/sbin/biosdevname --policy physical -i tstif0' /usr/lib/udev/rules.d/71-biosdevname.rules:22
starting '/sbin/biosdevname --policy physical -i tstif0'
'/sbin/biosdevname --policy physical -i tstif0' [5024] exit with return code 2

Правило /usr/lib/udev/rules.d/71-biosdevname.rules реализует выше рассмотренное соглашение о именах при использовании biosdevname. Уточнение, это правило работает, если в системе установлен biosdevname, при загрузке не был использован параметр biosdevname=0, и если имя не было назначено на предыдущем шаге.

  • Шаг третий:
IMPORT builtin 'net_id' /usr/lib/udev/rules.d/75-net-description.rules:6
IMPORT builtin skip 'usb_id' /usr/lib/udev/rules.d/75-net-description.rules:8
IMPORT builtin 'hwdb' /usr/lib/udev/rules.d/75-net-description.rules:8

На этом этапе правилом /usr/lib/udev/rules.d/75-net-description.rules, заполняются следующие директивы описания устройства: ID_NET_NAME_ONBOARD, ID_NET_NAME_SLOT, ID_NET_NAME_PATH и ID_NET_NAME_MAC. Не все директивы могут быть заполнены, поскольку не все устройства могут иметь требуемую информацию.

  • Шаг четвертый:
IMPORT builtin 'path_id' /usr/lib/udev/rules.d/80-net-setup-link.rules:5
IMPORT builtin 'net_setup_link' /usr/lib/udev/rules.d/80-net-setup-link.rules:9
Config file /usr/lib/systemd/network/99-default.link applies to device tstif0
NAME 'enp0s20u7u4' /usr/lib/udev/rules.d/80-net-setup-link.rules:11

Вот оно правило, которое устанавливает имя для интерфейса в данном случае - /usr/lib/udev/rules.d/80-net-setup-link.rules. Что по этому правило происходит: если интерфейс не был переименован на предыдущих шагах, и если не задан параметр ядра net.ifnames=0, то имя интерфейса устанавливается в соответствии с порядком по приоритету из полученных ранее директив: ID_NET_NAME_ONBOARD, ID_NET_NAME_SLOT, ID_NET_NAME_PATH. Если ни одна из директив не определена, то интерфейс остается не переименованным, т.е. старый вариант именования — eth0.
Для понимания, посмотреть возможные имена можно так:

# udevadm info /sys/class/net/tstif0 | grep ID_NET_NAME
E: ID_NET_NAME=enp0s20u7u4
E: ID_NET_NAME_MAC=enx00101402bca7
E: ID_NET_NAME_PATH=enp0s20u7u4

Можно заметить, что почти все пункты (за исключением 5 — старого именования) из стандартного соглашения о наименовании реализуются в правилах udev: 75-net-description.rules и 80-net-setup-link.rules. Можно возразить, а где наименование по MAC адресам? Включение его можно произвести правкой правила 80-net-setup-link.rules. Скопируйте его:

# cp /usr/lib/udev/rules.d/80-net-name-slot.rules /etc/udev/rules.d

И добавьте строку выделенную курсивом на листинге:

# grep -v "^#\|^$" /etc/udev/rules.d/80-net-name-slot.rules
ACTION!="add", GOTO="net_name_slot_end"
SUBSYSTEM!="net", GOTO="net_name_slot_end"
NAME!="", GOTO="net_name_slot_end"
IMPORT{cmdline}="net.ifnames"
ENV{net.ifnames}=="0", GOTO="net_name_slot_end"
NAME=="", ENV{ID_NET_NAME_MAC}!="", NAME="$env{ID_NET_NAME_MAC}"
NAME=="", ENV{ID_NET_NAME_ONBOARD}!="", NAME="$env{ID_NET_NAME_ONBOARD}"
NAME=="", ENV{ID_NET_NAME_SLOT}!="", NAME="$env{ID_NET_NAME_SLOT}"
NAME=="", ENV{ID_NET_NAME_PATH}!="", NAME="$env{ID_NET_NAME_PATH}"
LABEL="net_name_slot_end"

Не уверен, что данный вариант именования удобен.

Итак, мы обсудили несколько соглашений о наименовании сетевых интерфейсов, рассмотрели по шагам, как происходит выбор имени, попутно узнали, что net.ifnames=0 отключает новую схему наименования, и последнее замечание: не используйте имена из пространства ядра - ethX в схеме с присвоением имен через файлы ifcfg-*.