Использование Linux В Сети San. Маленькая Хитрость

Добрый день всем.

Не думаю, что описанная мной ситуация типична для большинства, но тем не менее думаю, что будет полезно знать.

Моя история о методе надежной защиты на случай, если у вас есть САН сети имеется несколько СХД (систем хранения данных), не поддерживающих технологию ограничения доступа к определенным LUN (номеру логического устройства) и серверам на базе Linux (в нашем случае все действия будут осуществляться с использованием ОС SLES 10SP1) .



Фон

В 2008 году мне пришлось сдавать в эксплуатацию вычислительную инфраструктуру одного заказчика.

Была построена небольшая сеть SAN с определенным количеством запоминающих устройств (около 10 единиц разных классов).

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

Но проблема в том, что для некоторых подсистем инфраструктуры было выделено хранилище, которое не умеет ограничивать доступ к определённым LUN-ам с определённых хостов (у каждого производителя это называется по-разному Port Masking, LUN MAPPING и т.п.

), а точнее может сделать это, но вам нужно приобрести доп.

лицензию, но этого сделано не было.

И тут возникла проблема — все сервера, подключающиеся к данному хранилищу, видят все его разделы.

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

данные каждой подсистемы очень важны.

Итого имеем:

  • Система хранения данных БИС (точнее один из его партнёров)
  • Серверы на базе SLES10 SP1 с двухголовым адаптером FC
  • Огромное желание застраховать себя и заказчика от ошибок.



Шаг первый, вводный

Сразу оговорюсь для тех, кто не обладает глубокими знаниями темы: Каждое устройство в сети SAN имеет уникальный адрес WWN (World Wide Name), это своего рода аналог MAC-адреса сетевого адаптера, но, как и в случае с Ethernet, свитч не знает, что находится внутри пакет приходит на свитч, поэтому сделать ограничение на свитче (зонирование) невозможно, можно только ограничить область видимости СХД для определенных узлов, что и было сделано.

Поиск решения ограничился следующими вариантами:

  1. Наличие в драйвере возможности использовать только определенные LUN
  2. Используйте инструменты ОС для блокировки ненужных LUN


Первый вариант
Он исчез после того, как мы посмотрели информацию по этому модулю.

Он содержит только возможность сканирования устройства и определяет максимальное количество LUN. Так что этот вариант исключен

Второй вариант
Эта опция сразу направляет нас на «проведение земляных работ» в сторону подсистемы udev. Именно она отвечает в Linux за инициализацию устройств, присвоение им специализированных имен и другие действия.

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

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

устройства (например, /dev/sdb, /dev/sdc и т. д.), но физически хост будет видеть все доступные ему LUN.

Шаг второй, исследование

Перейдем к детальному изучению темы.

После беглого изучения документации, а также правил, существующих в системе, мы можем выделить следующие интересующие нас блоки:

  1. Блок «SUBSYSTEM», определяющий подсистему.

    Существует три типа подсистем: «block» (блочные устройства), «char» (символьные устройства) и «pipe» (устройства FIFO).



    man mknod

    Нас интересует «блочная» подсистема, поскольку диски относятся именно к этому классу.

  2. udev может просматривать атрибуты устройства.

    Обычно они хранят различные данные, такие как:

    • тип производителя,
    • название модели,
    • различные аппаратные данные.

    Чтобы узнать нужные нам параметры, нам понадобится: Утилита lssci отображает все устройства SCSI, доступные в системе, а также имя специального устройства.

    устройство, назначенное этому устройству SCSI Утилита udevinfo — показывает все необходимые данные о запрашиваемом устройстве.

    Давайте начнем: Во-первых, нам нужно отобразить список всех устройств, доступных на этом сервере:

    # lssci SCSI ID TYPE VENDOR MODEL REV. device [5:0:0:10] disk XXX YYYYY 0619 /dev/sdr [5:0:0:20] disk XXX YYYYY 0619 /dev/sds [5:0:0:21] disk XXX YYYYY 0619 /dev/sdu .

    [5:0:1:10] disk XXX YYYYY 0619 /dev/sdan [5:0:1:20] disk XXX YYYYY 0619 /dev/sdao [5:0:1:21] disk XXX YYYYY 0619 /dev/sdar

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

    Итак, теперь мы знаем: SCSI ID — идентификатор в формате H:B:T:L (Host:Bus:Target:Lun).

    Host — серийный номер адаптера, который отвечает за это устройство.

    Bus(Channel) — номер канала SCSI. на адаптере Target — номер FC-порта на хранилище, LUN — идентификатор раздела, выделенного на хранилище.

    VENDOR - название производителя хранилища МОДЕЛЬ - название модели РЕД.

    — Версия прошивки на памяти устройство - специальное устройство, доступное пользователю В этой операции нас интересовали поля «устройство» и «SCSI ID».

    Остальные поля игнорируем.

  3. Следующим шагом будет получение списка атрибутов хранилища, которые нам нужны:
    • имя водителя
    • название производителя
    • название модели
    Для этого нам понадобится утилита udevinfo, а также файловая система sysfs (для версий ядра 2.6), т.к.

    именно там хранится вся необходимая нам информация.



    # udevinfo -a -p /sys/block/sds looking at device '/block/sds': KERNEL=="sds" SUBSYSTEM=="block" SYSFS{stat}==" 151707 2355 3422965 430068 436954 12273 18585533 1098588 0 651944 1528756" SYSFS{size}=="2129838080" SYSFS{removable}=="0" SYSFS{range}=="16" SYSFS{dev}=="65:32" looking at device '/devices/pci0000:00/0000:00:04.0/0000:08:00.0/host5/rport-5:0-0/target5:0:0/5:0:0:20': ID=="5:0:0:20" BUS=="scsi" DRIVER=="sd" SYSFS{ioerr_cnt}=="0x7" SYSFS{iodone_cnt}=="0xec62d" SYSFS{iorequest_cnt}=="0xec62d" SYSFS{iocounterbits}=="32" SYSFS{retries}=="5" SYSFS{timeout}=="60" SYSFS{state}=="running" SYSFS{rev}=="0619" SYSFS{model}=="YYYYY " SYSFS{vendor}=="XXX " SYSFS{scsi_level}=="6" SYSFS{type}=="0" SYSFS{queue_type}=="simple" SYSFS{queue_depth}=="64" SYSFS{device_blocked}=="0" .

    looking at device '/devices/pci0000:00/0000:00:04.0/0000:08:00.0': ID=="0000:08:00.0" BUS=="pci" DRIVER=="mptfc" SYSFS{modalias}=="pci:v00001000d00000646sv00001000sd00001020bc0Csc04i00" SYSFS{local_cpus}=="00000000,00000000,00000000,0000000f" SYSFS{irq}=="169" SYSFS{class}=="0x0c0400" SYSFS{subsystem_device}=="0x1020" SYSFS{subsystem_vendor}=="0x1000" SYSFS{device}=="0x0646" SYSFS{vendor}=="0x1000"

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

    Вывод «lsscsi» содержит повторяющиеся записи.

    Это пути к определенному LUN через разные устройства (например, 1 FC порт на хосте и 3 Port на хранилище), а так как это одно и то же хранилище, то и требуемые нами параметры будут одинаковыми для всех.

Краткое содержание:
  1. DRIVER==“sd” — это имя драйвера, который идентифицирует это устройство.

    Почему «sd», а не драйвер FC «mptfc» — потому что именно драйвер «sd» отвечает за идентификацию дискового устройства, полученного от адаптеров SCSI/FC.

  2. SYSFS{vendor}==“XXX” — производитель хранилища.

    Если вы обратите внимание, его имя — это не просто «ХХХ», но и ряд пробелов.

    Именно по этой причине вывод lsscsi не столь информативен и если используется только «XXX», то правило просто не будет работать.

  3. SYSFS{model}==“YYYYY” — название модели.

    Причина та же, что и в пункте выше.

  4. ID==“5:0:0:20” — идентификатор в формате H:B:T:L. Его тоже нужно запомнить, потому что… Он нам понадобится позже.

  5. BUS==“scsi” — тип шины.

    Нам нужно будет более точно идентифицировать устройство

Итак, теперь у нас есть вся необходимая информация для написания правила.



Шаг третий, пишет контора!

Теперь перейдем к написанию правил.

Нам понадобится документация udev. Вот окончательное правило и описание опций:

# If not a block device (ex. tape) ignore this rule SUBSYSTEM!="block", GOTO="go_ignore_end" # Phisical device section BUS=="scsi", DRIVER=="sd", SYSFS{vendor}=="XXX ", SYSFS{model}=="YYYYY ", ID=="*:*:*:20", GOTO="go_ignore_end" BUS=="scsi", DRIVER=="sd", SYSFS{vendor}=="XXX ", SYSFS{model}=="YYYYY ", ID=="*:*:*:21", GOTO="go_ignore_end" BUS=="scsi", DRIVER=="sd", SYSFS{vendor}=="XXX ", SYSFS{model}=="YYYYY ", OPTIONS+="ignore_device,last_rule" LABEL="go_ignore_end"

А теперь объяснение что к чему:

SUBSYSTEM!="block", GOTO="go_ignore_end"

Эта опция сообщает udev, что если подсистема работает с каким-либо неблоковым устройством, то данное правило применять не следует.

BUS=="scsi", DRIVER=="sd", SYSFS{vendor}=="XXX ", SYSFS{model}=="YYYYY ", ID=="*:*:*:20", GOTO="go_ignore_end" BUS=="scsi", DRIVER=="sd", SYSFS{vendor}=="XXX ", SYSFS{model}=="YYYYY ", ID=="*:*:*:21", GOTO="go_ignore_end"

Это самая важная часть, собственно ради этой части и была написана данная статья.

Правило определяет поведение: если устройство проходит через шину BUS==“scsi” и использует драйвер DRIVER==“sd”, у нас также есть производитель SYSFS{vendor}==“XXX” и название модели SYSFS. {model}==“YYYYY” и LUN этого устройства соответствует ID=="*:*:*:20", то это устройство должно следовать всем остальным правилам и создать специальное устройство в каталоге /dev. Запись ID=="*:*:*:20" — это запись в формате H:B:T:L, которая описывает только идентификатор LUN; остальные поля могут быть любыми.

Это позволяет нам пропускать из хранилища все устройства, имеющие данный LUN. Если нам нужно расширить список LUN, то мы просто добавляем записи и в последнее поле пишем нужный нам идентификатор.

Главное, чтобы они располагались перед следующим правилом.



BUS=="scsi", DRIVER=="sd", SYSFS{vendor}=="XXX ", SYSFS{model}=="YYYYY ", OPTIONS+="ignore_device,last_rule"

Это правило применяет те же условия, что и предыдущее, только OPTIONS+="ignore_device,last_rule" сообщает udev игнорировать все дальнейшие действия с этим устройством.

Те.

все устройства, кроме указанных, будут игнорироваться.



LABEL="go_ignore_end"

Это правило представляет собой простую метку конца файла.

Оно должно быть последним в списке.



Шаг четвертый, финальная битва

Теперь все, что нам нужно сделать, это сохранить это правило и использовать его.

Сохраняем это правило в папке /etc/udev/rules.d в правильном формате.

Я использовал имя «52-ignore-unused-devices.rules».

После этого нужно сделать еще одну вещь.

Если драйвер адаптера находится на рамдиске, то его необходимо удалить оттуда и загружать только после запуска подсистемы udev, иначе это правило не сработает, поскольку устройства будут созданы до запуска udev. Для этого вам необходимо внести изменения в файл /etc/sysconfig/kernel:

  1. Удалите драйвер устройства FC из переменной INITRD_MODULES=".

    "

  2. Добавьте его в переменную MODULES_LOADED_ON_BOOT=".

    "

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

Остальные хоть и видны в системе, но не указаны.

файлы, и поэтому пользователь не сможет ничего с ними сделать.

Это будет выглядеть так:

# lssci SCSI ID TYPE VENDOR MODEL REV. device [5:0:0:10] disk XXX YYYYY 0619 - [5:0:0:20] disk XXX YYYYY 0619 /dev/sds [5:0:0:21] disk XXX YYYYY 0619 /dev/sdu .

[5:0:1:10] disk XXX YYYYY 0619 - [5:0:1:20] disk XXX YYYYY 0619 /dev/sdao [5:0:1:21] disk XXX YYYYY 0619 /dev/sdar

В результате наша задача была решена элегантно и красиво.

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

Материалы, которые очень помогли

Теги: #linux #SAN #suse #udev #SLES #Chulan
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.