Игорь Олемской — практические заметки по системному администрированию Linux CentOS

Архив тега ‘storage’

ATA Over Ethernet (перепечатка)

Комментариев нет

ATA Over Ethernet (ATAoE,AoE,aoe) — протокол доступа к блочным SATA/SAS устройствам напрямую через транспорт Ethernet. Предназначен для организации бюджетного Storage Area Network (SAN) в пределах одного Ethernet сегмента.

Разработкой и поддержкой протокола занимается компания Coraid
Структурно состоит из «сервера» (Taget’а) и «клиента» (Initiator’а).

Почему ATAoE?

Мой выбор пал на ATAoE прежде всего из-за топорной своей простоты и элегантности, сочетающейся с производительностью и стабильностью. Как известно, чем проще протокол, тем меньше в нем потенциальных глюков.

На протоколе ATAoE можно очень быстро поднять сторедж или его клиент под любым линуксом.

ATAoE работает на уровне Ethernet и не использует TCP стек и его накладные расходы вообще. Что касается авторизации, присутствует фильтр по MAC адресам.

Конечно, у iSCSI больше свистелок и перделок чем в ATAoE. Но они в моих задачах не нашли применения. Авторизация в пределах одного Ethernet сегмента не нужна, ибо я в силах обозвать свой сегмент безопасным. Протокол TCP ни к чему, ибо я еще не дошел до маразма гонять ATA команды через глобальные сети.

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

ATAoE Target

Серверная часть AoE, представляет из себя драйвер, который экспортирует заданное блочное устройство в сегмент Ethernet.

При настройках экспорта указываются номера «Shelf» и «Slot». Shelf — порядковый номер компьютера или стораджа, на котором находится блочное устройство, Slot — порядковый номер блочного устройства. Например, номер ATAoE устройства 1.2 говорит о том, что блочное устройство располагается на сервере (shelf) с порядковым номером 1 под порядковым номером (Slot) 2.

В ОС GNU/Linux представляет из себя user-space GPL-демона vblade из пакета aoetoolsvblade может экспортировать любое блочное устройство, как то диск, партицию, устройство md или LVM logical volume. Так же vlbade может экспортировать файл заданного размера на файловой системе как блочное устройство.

Так же, Coraid поставляет готовые к использованию хардварные стораджи, выступающие в качестве AoE Target в сегменте Ethenet. Они работают под управлением OS Plan9, для доступа к ним по Ethernet необходима GPL утилита «Coraid Ethernet Console» или «cec» из пакета aoetools.

ATAoE Initiator

Клиентская часть AoE, представляет из себя драйвер, позволяющий импортировать расшаренные в Ethernet сегменете диски (AoE targets).

В ОС GNU/Linux представляет из себя модуль ядра aoe, входящий в ванильное ядро Linux. Однако для корректной работы модуля и использования последних нововведений рекомендуется обновлять драйвер aoe из пакета aoetools до последней версии (при каждом обновлении версии ядра).

Импортированные диски видны в системе в директории /dev/etherd/ с именами «eN.M», например /dev/etherd/e1.0. Где N — номерShelf, M — номер Slot.

При этом, если устройство eN.M имеет главную таблицу разделов, то соответствующие партиции будут видны как/dev/etherd/eN.Mp1/dev/etherd/eN.Mp2 и т.д.

Установка AoE Initiator под OS GNU/Linux

Программные требования:

  • OS CentOS >=5 (можно и любой другой Linux, но описанный способ использует CentOS)
  • Ядро из стандартной ветки
  • RPM: kernel-headers, kernel-devel, make, gcc

Требования по железу:

  • 1Gbps Ethernet
  • Желательно, выделенный Ethernet-сегмент для коммуникаций с AoE Targets
  • Желательно, сетевая карта с поддержкой Jumbo Frames на Initiator’е и Target’ах, свитч с поддержкой Jumbo frames, Ethernet кабель категории 6

Качаем aoeX-YY.tar.gz, распаковываем.

Делаем make install.

Для корректной загрузки драйвера при старте, имеется RC-скрипт. Он загружает модуль, конфигурирует MTU и txqueuelength на сетевом интерфейсе, и делает поиск сетевых дисков:

#!/bin/bash
#
# aoe          Start/Stop the aoe.
#
# chkconfig: 3 15 30
# description: Starts/Stops AOE Initiator for GPFS
# processname: aoe                                        
 
# Source function library.
. /etc/init.d/functions
 
prog="aoe"
t=/usr/bin/test
 
if [ -f /etc/sysconfig/$prog ]; then
    . /etc/sysconfig/$prog
fi
 
start() {
        echo $"Starting $prog."
        echo -n $"Checking aoe not loaded"
        s=`/sbin/lsmod | /bin/grep aoe | /bin/grep -v grep`
        if $t -n "$s" ; then
            failure
            echo
            return 1
        fi
        passed
        echo
 
        echo -n $"Configuring $AOE_IF"
 
        /sbin/ifconfig $AOE_IF txqueuelen $AOE_IF_TXQ mtu $AOE_IF_MTU up
        RETVAL=$?
        if [ $RETVAL -ne 0 ]; then
            failure
            echo
            return 1
        fi
 
        passed
        echo
 
        echo -n $"Loading aoe module...."
        /sbin/modprobe aoe aoe_deadsecs=$AOE_TIMEOUT aoe_maxsectors=$AOE_MAXSECTORS aoe_iflist=$AOE_IF aoe_maxout=$AOE_MAXOUT
        RETVAL=$?
        if [ $RETVAL -ne 0 ]; then
            failure
            echo
            return 1
        fi
 
        passed
        echo
 
        # Give some time to identiy devices
 
        echo -n $"Prepare for discover...."
 
        num1=0
        while [ ! -c /dev/etherd/discover ]; do
            sleep 1
            num1=$(($num+1))
            if [ $num1 -gt 60 ]; then
                echo -n $"timeout $num1"
                failure
                echo
                return 1
            fi
        done
 
        passed
        echo
 
        echo -n $"Waiting for devices...."
 
        /usr/sbin/aoe-discover
        num=0
# Здесь необходимо дождаться появления определенного блочного устройства - изменить на свой вкус
#        until [ -b /dev/etherd/e1.0 ]; do
        until [ -d /dev/etherd ]; do
            sleep 1
            num=$(($num+1))
            if [ $num -gt 60 ]; then
                echo -n $"timeout $num"
                failure
                echo
                return 1
            fi
            /usr/sbin/aoe-discover
        done
 
        passed
        echo
 
        touch "/var/lock/subsys/$prog";
        echo -n $"AOE driver initialization complete"
        success
        echo
        return 0
 
}
 
stop() {
        echo -n $"Stopping $prog: not supported"
        success
        echo
        return 0
}
 
rhstatus() {
        status $prog
}
 
restart() {
        stop
        start
}
 
case "$1" in
  start)
        start
        ;;
  stop)
        stop
        ;;
  restart)
        restart
        ;;
  status)
        rhstatus
        ;;
  condrestart)
        [ -f "/var/lock/subsys/$prog" ] && restart || :
        ;;
  *)
        echo $"Usage: $0 {start|stop|status|restart|condrestart}"
        exit 1
esac

Скрипт автозагрузки требует конфигурационный файл /etc/sysconfig/aoe:

# IO Timeout
AOE_TIMEOUT=180
# Max Sectors Per single IO
AOE_MAXSECTORS=4096
# AOE Interface
AOE_IF=eth2
# Interface txqueuelen
AOE_IF_TXQ=5000
# Interface MTU
AOE_IF_MTU=4200
# AOE Sleep settle
AOE_SLEEP=4
AOE_MAXOUT=100

Где

  • AOE_TIMEOUT — таймаут в секундах ожидания ответа от Target, после которого выдается ошибка IO.
  • AOE_IF — интерфейс, который смотрит в сегмент Ethernet с AoE Targets.
  • AOE_IF_TXQ — txqueuelength для AOE_IF
  • AOE_IF_MTU — MTU для AOE_IF
  • AOE_SLEEP,AOE_MAXOUT,AOE_MAXSECTORS — недокументированные параметры, подсказанные мне поддержкой Coraid, для моего случая.

После чего, включаем aoe в автозагрузку:

chkconfig --add aoe

И пробуем:

/etc/init.d/aoe start

Jumbo frames

Для продуктивной работы ATAoE требуется установить MTU на транспортном сетевом интерфейсе в 4200, а txqueuelength (OS GNU/Linux) в 5000.

Установка MTU в значение >1500 называется «поддержкой Jumbo frames»

Далеко не все сетевые карты поддерживают jumbo frames, по этому перед установкой необходимо убедиться в том, что карта поддерживает эту возможность. Сделать это можно командой:

ifconfig eth2 mtu 4200

Если команда выполнена без ошибок, то все в порядке.

Jumbo frames должен поддерживать как Initiator так и Target. Кроме того, jumbo frames должен поддерживать еще и свитч. Т.е. jumbo frames должны поддерживаться на всем пути от Initiator до Target, иначе они не имеют смысла.

Dual-primary DRBD with OCFS2 (перепечатка)

Один комментарий

As promised in one of my previous posts about dual-primary DRBD and OCFS2, I've compiled a step-by-step guide for Fedora. These instructions should be somewhat close to what you would use on CentOS or Red Hat Enterprise Linux. However, CentOS and Red Hat don't provide some of the packages needed, so you will need to use other software repositories like RPMFusion or EPEL.

In this guide, I'll be using two Fedora 14 instances in the Rackspace Cloud with separate public and private networks. The instances are called server1 and server2 to make things easier to follow.

NOTE: All of the instructions below should be done on both servers unless otherwise specified.


First, we need to set up DRBD with two primary nodes. I'll be using loop files for this setup since I don't have access to raw partitions.

yum -y install drbd-utils
dd if=/dev/zero of=/drbd-loop.img bs=1M count=1000

Put this loop file initialization init script in /etc/init.d/loop-for-drbd and finish setting it up:

chmod a+x /etc/init.d/loop-for-drbd
chkconfig loop-for-drbd on
/etc/init.d/loop-for-drbd start

Place this DRBD resource file in /etc/drbd.d/r0.res. Be sure to adjust the server names and IP addresses for your servers.

resource r0 {
	meta-disk internal;
	device /dev/drbd0;
	disk /dev/loop7;
 
	syncer { rate 1000M; }
        net {
                allow-two-primaries;
                after-sb-0pri discard-zero-changes;
                after-sb-1pri discard-secondary;
                after-sb-2pri disconnect;
        }
	startup { become-primary-on both; }
 
	on server1 { address 10.181.76.0:7789; }
	on server2 { address 10.181.76.1:7789; }
}

The net section is telling DRBD to do the following:

  • allow-two-primaries — Generally, DRBD has a primary and a secondary node. In this case, we will allow both nodes to have the filesystem mounted at the same time. Do this only with a clustered filesystem. If you do this with a non-clustered filesystem like ext2/ext3/ext4 or reiserfs, you will have data corruption. Seriously!
  • after-sb-0pri discard-zero-changes — DRBD detected a split-brain scenario, but none of the nodes think they're a primary. DRBD will take the newest modifications and apply them to the node that didn't have any changes.
  • after-sb-1pri discard-secondary — DRBD detected a split-brain scenario, but one node is the primary and the other is the secondary. In this case, DRBD will decide that the secondary node is the victim and it will sync data from the primary to the secondary automatically.
  • after-sb-2pri disconnect — DRBD detected a split-brain scenario, but it can't figure out which node has the right data. It tries to protect the consistency of both nodes by disconnecting the DRBD volume entirely. You'll have to tell DRBD which node has the valid data in order to reconnect the volume. Use extreme caution if you find yourself in this scenario.

If you'd like to read about DRBD split-brain behavior in more detail, review the documentation.

I generally turn off the usage reporting functionality in DRBD within /etc/drbd.d/global_common.conf:

global {
	usage-count no;
}

Now we can create the volume and start DRBD:

drbdadm create-md r0
/etc/init.d/drbd start && chkconfig drbd on

You may see some errors thrown about having two primaries but neither are up to date. That can be fixed by running the following command on the primary node only:

drbdsetup /dev/drbd0 primary -o

If you run cat /proc/drbd on the secondary node, you should see the DRBD sync running:

version: 8.3.8 (api:88/proto:86-94)
srcversion: 299AFE04D7AFD98B3CA0AF9
 0: cs:SyncTarget ro:Secondary/Primary ds:Inconsistent/UpToDate C r----
    ns:0 nr:210272 dw:210272 dr:0 al:0 bm:12 lo:1 pe:2682 ua:0 ap:0 ep:1 wo:b oos:813660
        [===>................] sync'ed: 20.8% (813660/1023932)K queue_delay: 0.0 ms
        finish: 0:01:30 speed: 8,976 (6,368) want: 1024,000 K/sec

Before you go any further, wait for the DRBD sync to fully finish. When it completes, it should look like this:

version: 8.3.8 (api:88/proto:86-94)
srcversion: 299AFE04D7AFD98B3CA0AF9
 0: cs:Connected ro:Secondary/Primary ds:UpToDate/UpToDate C r----
    ns:0 nr:1023932 dw:1023932 dr:0 al:0 bm:63 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0

Now, on the secondary node only make it a primary node as well:

drbdadm primary r0

You should see this on the secondary node if you've done everything properly:

version: 8.3.8 (api:88/proto:86-94)
srcversion: 299AFE04D7AFD98B3CA0AF9
 0: cs:Connected ro:Primary/Primary ds:UpToDate/UpToDate C r----
    ns:1122 nr:1119 dw:2241 dr:4550 al:2 bm:1 lo:0 pe:0 ua:0 ap:0 ep:1 wo:b oos:0

We're now ready to move on to configuring OCFS2. Only one package is needed:

yum -y install ocfs2-tools

Ensure that you have your servers and their private IP addresses in /etc/hosts before proceeding. Create the /etc/ocfs2 directory and place the following configuration in /etc/ocfs2/cluster.conf (adjust the server names and IP addresses):

cluster:
	node_count = 2
	name = web
 
node:
	ip_port = 7777
	ip_address = 10.181.76.0
	number = 1
	name = server1
	cluster = web
 
node:
	ip_port = 7777
	ip_address = 10.181.76.1
	number = 2
	name = server2
	cluster = web

Now it's time to configure OCFS2. Run service ocfs2 configure and follow the prompts. Use the defaults for all of the responses except for two questions:

  • Answer «y» to «Load O2CB driver on boot»
  • Answer «web» to «Cluster to start on boot»

Start OCFS2 and enable it at boot up:

chkconfig o2cb on && chkconfig ocfs2 on
/etc/init.d/o2cb start && /etc/init.d/ocfs2 start

Create an OCFS2 partition on the primary node only:

mkfs.ocfs2 -L "web" /dev/drbd0

Mount the volumes and configure them to automatically mount at boot time. You might be wondering why I do the mounting within /etc/rc.local. I chose to go that route since mounting via fstab was often unreliable for me due to the incorrect ordering of events at boot time. Using rc.local allows the mounts to work properly upon every reboot.

mkdir /mnt/storage
echo "/dev/drbd0  /mnt/storage  ocfs2  noauto,noatime  0 0" >> /etc/fstab
mount /dev/drbd0
echo "mount /dev/drbd0" >> /etc/rc.local

At this point, you should be all done. If you want to test OCFS2, copy a file into your /mnt/storage mount on one node and check that it appears on the other node. If you remove it, it should be gone instantly on both nodes. This is a great opportunity to test reboots of both machines to ensure that everything comes up properly at boot time.

Dual-primary DRBD with OCFS2 is a post from: Major Hayden's Racker Hacker blog.

Thanks for following the blog via the RSS feed. Please don't copy my posts or quote portions of them without attribution.

GlusterFS on the cheap with Rackspace's Cloud Servers or Slicehost (перепечатка)

Комментариев нет

High availability is certainly not a new concept, but if there's one thing that frustrates me with high availability VM setups, it's storage. If you don't mind going active-passive, you can set up DRBD, toss your favorite filesystem on it, and you're all set.

If you want to go active-active, or if you want multiple nodes active at the same time, you need to use a clustered filesystem like GFS2, OCFS2 or Lustre. These are certainly good options to consider but they're not trivial to implement. They usually rely on additional systems and scripts to provide reliable fencing and STONITH capabilities.

What about the rest of us who want multiple active VM's with simple replicated storage that doesn't require any additional elaborate systems? This is where GlusterFS really shines. GlusterFS can ride on top of whichever filesystem you prefer, and that's a huge win for those who want a simple solution. However, that means that it has to use fuse, and that will limit your performance.

Let's get this thing started!

Consider a situation where you want to run a WordPress blog on two VM's with load balancers out front. You'll probably want to use GlusterFS's replicated volume mode (RAID 1-ish) so that the same files are on both nodes all of the time. To get started, build two small Slicehost slices or Rackspace Cloud Servers. I'll be using Fedora 13 in this example, but the instructions for other distributions should be very similar.

First things first — be sure to set a new root password and update all of the packages on the system. This should go without saying, but it's important to remember. We can clear out the default iptables ruleset since we will make a customized set later:

# iptables -F
# /etc/init.d/iptables save
iptables: Saving firewall rules to /etc/sysconfig/iptables:        [  OK  ]

GlusterFS communicates over the network, so we will want to ensure that traffic only moves over the private network between the instances. We will need to add the private IP's and a special hostname for each instance to /etc/hosts on both instances. I'll call mine gluster1 and gluster2:

10.xx.xx.xx gluster1
10.xx.xx.xx gluster2

You're now ready to install the required packages on both instances:

yum install glusterfs-client glusterfs-server glusterfs-common glusterfs-devel

Make the directories for the GlusterFS volumes on each instance:

mkdir -p /export/store1

We're ready to make the configuration files for our storage volumes. Since we want the same files on each instance, we will use the --raid 1 option. This only needs to be run on the first node:

# glusterfs-volgen --name store1 --raid 1 gluster1:/export/store1 gluster2:/export/store1
Generating server volfiles.. for server 'gluster2'
Generating server volfiles.. for server 'gluster1'
Generating client volfiles.. for transport 'tcp'

Once that's done, you'll have four new files:

  • booster.fstab — you won't need this file
  • gluster1-store1-export.vol — server-side configuration file for the first instance
  • gluster2-store1-export.vol — server-side configuration file for the second instance
  • store1-tcp.vol — client side configuration file for GlusterFS clients

Copy the gluster1-store1-export.vol file to /etc/glusterfs/glusterfsd.vol on your first instance. Then, copy gluster2-store1-export.vol to /etc/glusterfs/glusterfsd.vol on your second instance. The store1-tcp.vol should be copied to /etc/glusterfs/glusterfs.vol on both instances.

At this point, you're ready to start the GlusterFS servers on each instance:

/etc/init.d/glusterfsd start

You can now mount the GlusterFS volume on both instances:

mkdir -p /mnt/glusterfs
glusterfs /mnt/glusterfs/

You should now be able to see the new GlusterFS volume in both instances:

# df -h /mnt/glusterfs
Filesystem            Size  Used Avail Use% Mounted on
/etc/glusterfs/glusterfs.vol
                      9.4G  831M  8.1G  10% /mnt/glusterfs

As a test, you can create a file on your first instance and verify that your second instance can read the data:

[root@gluster1 ~]# echo "We're testing GlusterFS" > /mnt/glusterfs/test.txt
.....
[root@gluster2 ~]# cat /mnt/glusterfs/test.txt
We're testing GlusterFS

If you remove that file on your second instance, it should disappear from your first instance as well.

Obviously, this is a very simple and basic implementation of GlusterFS. You can increase performance by making dedicated VM's just for serving data and you can adjust the default performance options when you mount a GlusterFS volume. Limiting access to the GlusterFS servers is also a good idea.

If you want to read more, I'd recommend reading the GlusterFS Technical FAQ and the GlusterFS User Guide.


Thank you for your e-mails! I'll be expanding on this post later with some sample benchmarks and additional tips/tricks, so please stay tuned.

GlusterFS on the cheap with Rackspace's Cloud Servers or Slicehost is a post from: Major Hayden's Racker Hacker blog.

c0b6ad7e-f251-11df-b20b-4040336e00ef