= хранилище iscsi zfs для нищебродов [[PageOutline(2-3,содержание)]] == синопсис по результатам посещения магазинов имеется четыре [http://market.yandex.ru/product/10718570 жёстких диска], одна [http://market.yandex.ru/product/10949785 нормальная ssd], две ssd [http://google.com/search?q=SSD2SC120G709A104-43227894 ниочень], [http://ebay.com/itm/261448063080 сервер] с резервным [http://ebay.com/itm/110971415802 блоком питания], [http://ebay.com/itm/121137400203 батарейкой для контроллера] и [http://ebay.com/itm/351127460049 корзинами для дисков]. к великому сожалению, устанавливать на сервер FreeBSD лишено смысла, т.к. под неё нет софта для управления контроллером. в случае выхода из строя жёсткого диска для его замены весь nas придётся перегружать, чтобы добавить новый диск. кроме того, после нескольких попыток установить FreeBSD выяснилось, что грузится она с этого контроллера только с zfs зеркала. если делать raidz2 или stripe из mirror, то zfsloader по какой-то причине не видит дисков. поскольку из всех линуксов наибольший опыт работы у меня с CentOS, то я решил остановиться на нём, а именно на версии 6.6, как последней версии без systemd, который ещё предстоит изучать. == установка перед установкой необходимо дать возможность операционной системе получить доступ до дисков. hp smartarray p410 не умеет jbod, а в рамках использования zfs возможности контроллера по работа с дисковыми массивами мне неинтересны. придётся обойтись костылём: сделать из каждого диска отдельный массив raid0. внятного описания как грузить линукс с zfs мне найти не удалось, поэтому грузиться я буду с ext4. первые два диска я подготовил вот так:[[br]][[br]] [[Image(anaconda-disk-layout.png​)]] [[br]][[br]] когда спросят про то, куда писать загрузчик, то нужно выбирать вот такую схему:[[br]][[br]] [[Image(grub.png)]] [[br]] если выбрать что-то другое, то ничего не загрузится: после инициализации рейда будет просто чёрный экран с одним мигающим курсором. хотя на виртуальной машине с обычными sas дисками работает, даже если загрузчик записать на `md10`. видимо, особенность контроллера hp smartarray p410 - не такой он уж и smart. == конфигурирование === система после установки сразу стоит сделать `yum update -y`, поскольку пакет zfs on linux предназначен для последней версии ядра и на старьё не установится. zfs занимает весь объём оперативной памяти для кэша (arc) и в некоторых случаях может не успеть освободить часть памяти, необходимую для работы софта. в этом случае ядро начнёт геноцид приложений и служб, а чтобы этого не произошло в систему нужно добавить swap. помимо этого на оставшиеся два диска я добавлю ещё зеркала для раздела /boot, кашу маслом не испортишь: {{{ #!bash yum install -y gdisk for i in c d; do sgdisk -g \ -n 1:2048:1138687 /dev/sd${i} \ -t 1:fd00 /dev/sd${i} \ -c 1:boot${i} -n 2:1138688:46649343 /dev/sd${i} \ -t 2:fd00 /dev/sd${i} \ -c 2:main${i} done mdadm --grow /dev/md10 \ --raid-devices=4 \ --add /dev/sdc1 \ --add /dev/sdd1 mdadm --create /dev/md22 \ --level=1 --raid-devices=2 \ /dev/sdс2 \ /dev/sdd2 mkswap -L swap /dev/md22 }}} допишу строчку про swap в /etc/fstab: {{{ #!text LABEL=swap swap swap defaults 1 3 }}} и выполню `swapon -a`, чтобы swap подцепился. во время установки grub был записан в загрузчик только первого диска. мы все умираем и этот диск когда-то тоже умрёт, поэтому grub нужно записать в загрузчики остальных дисков, чтобы сервер мог загрузиться с любого диска. для этого в /boot/grub/device.map я напишу: {{{ #!text (hd0) /dev/sda (hd1) /dev/sdb (hd2) /dev/sdc (hd3) /dev/sdd }}} и выполню: {{{ #!bash for i in a b c d; do grub-install --root-directory=/ /dev/sd${i} grub-install --root-directory=/ /dev/sd${i}1 done }}} в /etc/sysctl.conf я добавил: {{{ #!linux-config # disable core files http://www.cyberciti.biz/faq/linux-disable-core-dumps/ fs.suid_dumpable = 0 # disable ipv6 http://wiki.centos.org/FAQ/CentOS6#head-d47139912868bcb9d754441ec b6a8a10d41781df net.ipv6.conf.all.disable_ipv6 = 1 net.ipv6.conf.default.disable_ipv6 = 1 # reboot after kernel panic kernel.panic = 10 # http://habrahabr.ru/post/200466/ # http://habrahabr.ru/post/209460/ net.ipv4.tcp_reordering = 127 net.core.rmem_max = 33554432 net.core.wmem_max = 33554432 net.core.rmem_default = 16777216 net.core.wmem_default = 16777216 net.ipv4.tcp_rmem = 1048576 1048576 1048576 net.ipv4.tcp_wmem = 1048576 1048576 1048576 net.ipv4.tcp_mem = 1048576 1048576 1048576 net.ipv4.tcp_no_metrics_save = 1 net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_timestamps = 0 net.ipv4.tcp_sack = 0 net.ipv4.tcp_dsack = 0 net.core.netdev_max_backlog = 300000 net.core.optmem_max = 524287 vm.min_free_kbytes = 720896 }}} === zfs самый неинтересный раздел. zfs заводится с полпинка, как описано [http://zfsonlinux.org/epel.html тут]: {{{ #!bash rpm -ivh http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm yum localinstall --nogpgcheck https://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm yum localinstall --nogpgcheck http://archive.zfsonlinux.org/epel/zfs-release.el6.noarch.rpm yum install kernel-devel zfs }}} основная часть места на моих четырёх 3тб винтах осталась не разбита. сделаю разделы для zfs {{{ #!bash for i in a b c d; do sgdisk \ -n 3:46649344:5859649343 /dev/sd${i} -c 3:ztd${i} done }}} так как я создавал разделы на дисках, которые уже подключены к mdraid, то после этих команд будет куча предупреждений типа {{{ #!text Warning: The kernel is still using the old partition table. The new table will be used at the next reboot. }}} поэтому это нужно делать либо до создания mdraid, либо сейчас перегружаться. после каждого раздела оставлен небольшой кусочек примерно в 400 мегабайт. это сделано с заделом на будущее. когда пройдёт много времени и диски начнут умирать, то с большой вероятностью точно такие же найти не удастся. новые могут быть не только чуть-чуть больше, но и чуть-чуть меньше. остаётся надеяться, что если новые диски будут чуть-чуть меньше, то эта разница уложится в те 400 мегабайт, что я оставил. напомню, что у меня ещё есть три штуки ssd, которые я использую для zil и l2arc. разбивал их я вот таким образом: {{{ #!bash sgdisk -g \ -n 1:2048:46139391 /dev/sde \ -c 1:zil1 -n 2:46139392:417335295 /dev/sde \ -c 2:cache1 \ -n 1:2048:46139391 /dev/sdf \ -c 1:zil2 -n 2:46139392:207620095 /dev/sdf \ -c 2:cache2 \ -n 1:2048:207620095 /dev/sdg \ -c 1:cache3 }}} т.е. получилось вот так: {{{ #!text /dev/sde: Number Start (sector) End (sector) Size Code Name 1 2048 46139391 22.0 GiB 8300 zil1 2 46139392 417335295 177.0 GiB 8300 cache1 /dev/sdf: Number Start (sector) End (sector) Size Code Name 1 2048 46139391 22.0 GiB 8300 zil2 2 46139392 207620095 77.0 GiB 8300 cache2 /dev/sdg: Number Start (sector) End (sector) Size Code Name 1 2048 207620095 99.0 GiB 8300 cache3 }}} примерно 15% от объёма каждой ssd я оставил свободным. мне не удалось найти сведений, реализована ли в zfs on linux функция trim для ssd. даже если реализована, то неизвестно дойдёт ли она через raid0 до дисков. по этим причинам лишним не будет облегчить работу сборщика мусора для ssd. иначе можно получить от них внезапные тормоза и будет неприятно. в zfs пуле каждый диск должен быть на своём месте, поэтому делать `zpool create` с использование имён `/dev/sd[abcd]` - это плохая идея. после подключения ещё одного диска буквы могут съехать и пул работать перестанет. диски для `zpool create` нужно использовать исключительно по их идентификаторам из `/dev/disk/by-id` от которых становится грустно. но для этого и придуман `/etc/zfs/vdev_id.conf`: {{{ #!aconf alias d1 wwn-0x600508b1001c3723c04acd739d1441b5 alias d2 wwn-0x600508b1001c9bb2d572318a7dfba682 alias d3 wwn-0x600508b1001c9429d1da0c1f6c95391d alias d4 wwn-0x600508b1001cb13c45efe162b8d19796 alias d5 wwn-0x600508b1001ce116ccc886cb253e8b58 alias d6 wwn-0x600508b1001ca7ee80413b03991d8abf alias d7 wwn-0x600508b1001c254f9cd481d490762791 }}} финальный аккорд для создания пула и сразу за ним блочного устройства для iscsi: {{{ #!bash zpool create \ -o ashift=12 tank raidz d1-part3 d2-part3 d3-part3 d4-part3 log mirror d5-part1 d6-part1 cache d5-part2 d6-part2 d7-part1 zfs create -V 7600g tank/bvol }}} === ядро для использования scst рекомендуется добавить патчи в ядро. это необязательно, но с ними производительность выше. {{{ #!bash kernel="2.6.32-504.12.2.el6" svn co https://svn.code.sf.net/p/scst/svn/trunk scst3 svn co https://svn.code.sf.net/p/scst/svn/branches/2.2.x scst2 wget http://ftp.redhat.com/pub/redhat/linux/enterprise/6Server/en/os/SRPMS/kernel-${kernel}.src.rpm yum install -y \ yum-utils \ rpmdevtools \ elfutils-libelf-devel \ elfutils-devel \ zlib-devel \ binutils-devel \ python-devel \ audit-libs-devel \ newt-devel \ perl-ExtUtils-Embed \ rng-tools \ bison yum-builddep -y --nogpgcheck kernel-${kernel}.src.rpm rpm -Uvh kernel-${kernel}.src.rpm cp scst2/scst/kernel/rhel/scst_exec_req_fifo-2.6.32.patch \ rpmbuild/SOURCES cp scst3/iscsi-scst/kernel/patches/rhel/put_page_callback-2.6.32-504.patch \ rpmbuild/SOURCES }}} в `rpmbuild/SPECS/kernel.spec` после `Source86: config-s390x-debug-rhel` добавляю: {{{ #!text Patch111: put_page_callback-2.6.32-504.patch Patch112: scst_exec_req_fifo-2.6.32.patch }}} после `ApplyOptionalPatch linux-kernel-test.patch` соответственно: {{{ #!text ApplyPatch put_page_callback-2.6.32-504.patch ApplyPatch scst_exec_req_fifo-2.6.32.patch }}} `#% define buildid .local` лучше поменять на `%define buildid .scst`, чтобы не запутаться в ядрах. в `rpmbuild/SOURCES/config-generic` нужно добавить строчку `CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION=y`, а {{{ #!text #CONFIG_PREEMPT_NONE is not set CONFIG_PREEMPT_VOLUNTARY=y }}} заменить на {{{ #!text CONFIG_PREEMPT_NONE=y #CONFIG_PREEMPT_VOLUNTARY is not set }}} сервер же всё таки, незачем ему бездельничать. после всего этого запускаю сборку rpm пакетов ядра с включенными файлами firmware, предварительно запустив `rngd -r /dev/urandom`, чтобы генерация ключей не страдала: {{{ #!bash cd rpmbuild/SPECS rpmbuild -ba \ --without kabichk \ --with baseonly \ --with firmware \ --without debuginfo \ --target=`uname -m` kernel.spec }}} после завершения сборки устанавливаю новое ядро, firmware, заголовочные файлы: {{{ #!bash kernel="2.6.32-504.12.2.el6.scst" rpm -ivh \ kernel-firmware-${kernel}.x86_64.rpm \ kernel-${kernel}.x86_64.rpm \ kernel-devel-${kernel}.x86_64.rpm \ kernel-headers-${kernel}.x86_64.rpm }}} и перегружаюсь. === scst от выбора iscsi target под linux может закружиться голова, но за меня их уже [#link1 сравнили], поэтому я этого делать не буду, а поверю на слово и сразу выберу scst. {{{ #!bash cd scst3 make scst scst_install iscsi iscsi_install scstadm scstadm_install chkconfig scst on service scst start }}} /etc/scst.conf: {{{ #!linux-config HANDLER vdisk_blockio { enabled 1 DEVICE bvol { filename /dev/zvol/tank/bvol nv_cache 1 } } TARGET_DRIVER iscsi { enabled 1 IncomingUser "login password" TARGET iqn.2015-04.org.tank:bvol { enabled 1 LUN 0 bvol IncomingUser "login password" } } }}} == полезные ссылки 1. [=#link1 http://habrahabr.ru/post/200466/]; 1. http://fedoraproject.org/wiki/Building_a_custom_kernel 1. http://www.spiderbird.com/2013/08/20/centos-6-with-scst/ 1. http://habrahabr.ru/post/209460/; 1. http://habrahabr.ru/post/209666/. == обсуждение почесать языком можно [blog:2015/04/17 здесь].