wiki:linux/cheap-nas

хранилище iscsi zfs для нищебродов

синопсис

по результатам посещения магазинов имеется четыре жёстких диска, одна нормальная ssd, две ssd ниочень, сервер с резервным блоком питания, батарейкой для контроллера и корзинами для дисков. к великому сожалению, устанавливать на сервер FreeBSD лишено смысла, т.к. под неё нет софта для управления контроллером. в случае выхода из строя жёсткого диска для его замены весь nas придётся перегружать, чтобы добавить новый диск.

кроме того, после нескольких попыток установить FreeBSD выяснилось, что грузится она с этого контроллера только с zfs зеркала. если делать raidz2 или stripe из mirror, то zfsloader по какой-то причине не видит дисков.

поскольку из всех линуксов наибольший опыт работы у меня с CentOS, то я решил остановиться на нём, а именно на версии 6.6, как последней версии без systemd, который ещё предстоит изучать.

установка

перед установкой необходимо дать возможность операционной системе получить доступ до дисков. hp smartarray p410 не умеет jbod, а в рамках использования zfs возможности контроллера по работе с дисковыми массивами мне неинтересны. придётся обойтись костылём: сделать из каждого диска отдельный массив raid0.

внятного описания как грузить линукс с zfs мне найти не удалось, поэтому грузиться я буду с ext4. первые два диска я подготовил вот так:



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


если выбрать что-то другое, то ничего не загрузится: после инициализации рейда будет просто чёрный экран с одним мигающим курсором. хотя на виртуальной машине с обычными sas дисками работает, даже если загрузчик записать на md10. видимо, особенность контроллера hp smartarray p410 - не такой он уж и smart.

конфигурирование

система

после установки сразу стоит сделать yum update -y, поскольку пакет zfs on linux предназначен для последней версии ядра и на старьё не установится.

zfs занимает весь объём оперативной памяти для кэша (arc) и в некоторых случаях может не успеть освободить часть памяти, необходимую для работы софта. в этом случае ядро начнёт геноцид приложений и служб, а чтобы этого не произошло в систему нужно добавить swap.

помимо этого на оставшиеся два диска я добавлю ещё зеркала для раздела /boot, кашу маслом не испортишь:

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:

LABEL=swap swap swap defaults 1 3

и выполню swapon -a, чтобы swap подцепился.

во время установки grub был записан в загрузчик только первого диска. мы все умираем и этот диск когда-то тоже умрёт, поэтому grub нужно записать в загрузчики остальных дисков, чтобы сервер мог загрузиться с любого диска. для этого в /boot/grub/device.map я напишу:

(hd0) /dev/sda
(hd1) /dev/sdb
(hd2) /dev/sdc
(hd3) /dev/sdd

и выполню:

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 я добавил:

# 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-47139912868bcb9d754441ec
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 = 16777216 16777216 16777216
net.ipv4.tcp_wmem = 16777216 16777216 16777216
net.ipv4.tcp_mem = 16777216 16777216 16777216
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 = 16777216
vm.min_free_kbytes = 720896

zfs

самый неинтересный раздел. zfs заводится с полпинка, как описано тут:

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

for i in a b c d; do
 sgdisk \
  -n 3:46649344:5859649343 /dev/sd${i}
  -c 3:ztd${i}
done

так как я создавал разделы на дисках, которые уже подключены к mdraid, то после этих команд будет куча предупреждений типа

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. разбивал их я вот таким образом:

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

т.е. получилось вот так:

/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:

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:

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

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 добавляю:

Patch111: put_page_callback-2.6.32-504.patch
Patch112: scst_exec_req_fifo-2.6.32.patch

после ApplyOptionalPatch linux-kernel-test.patch соответственно:

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, а

#CONFIG_PREEMPT_NONE is not set
CONFIG_PREEMPT_VOLUNTARY=y

заменить на

CONFIG_PREEMPT_NONE=y
#CONFIG_PREEMPT_VOLUNTARY is not set

сервер же всё таки, незачем ему бездельничать.

после всего этого запускаю сборку rpm пакетов ядра с включенными файлами firmware, предварительно запустив rngd -r /dev/urandom, чтобы генерация ключей не страдала:

cd rpmbuild/SPECS
rpmbuild -ba \
 --without kabichk \
 --with baseonly \
 --with firmware \
 --without debuginfo \
 --target=`uname -m` kernel.spec

после завершения сборки устанавливаю новое ядро, firmware, заголовочные файлы:

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 может закружиться голова, но за меня их уже сравнили, поэтому я этого делать не буду, а поверю на слово и сразу выберу scst.

cd scst3
make scst scst_install iscsi iscsi_install scstadm scstadm_install
chkconfig scst on
service scst start

/etc/scst.conf:

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. http://habrahabr.ru/post/200466/;
  2. http://fedoraproject.org/wiki/Building_a_custom_kernel/;
  3. http://www.spiderbird.com/2013/08/20/centos-6-with-scst/;
  4. http://habrahabr.ru/post/209460/;
  5. http://habrahabr.ru/post/209666/.

обсуждение

почесать языком можно здесь.

Last modified at 2016-04-03T08:21:35Z Last modified on 2016-04-03T08:21:35Z

Attachments (2)

Download all attachments as: .zip