ストレージ関連

LVM

10.04 は 2.02.54 だったのが、12.04 では 2.02.66 になっている。
更新内容はソースをチェック。

lvconvert に snapshot のマージ機能が付いた。
これを使うと、万が一アップデートに失敗して切り戻すときに、アップデート前にとっておいたスナップショットの内容に巻き戻しができる。

10.04 の LVM は --enable-udev_sync がついていなかったが、12.04 ではつくようになった。

iSCSI target

Linux 3.1 で SCST から LIO に実装が変わった
Ubuntu は 12.04 から LIO がデフォルトになったとあるが、入れるパッケージが iscsitarget から targetcli に変わっている。

Backstore

詳細はこちらにある通り。
PSCSI は pass through SCSI の意味で、SCSI デバイスに直接 SCSI コマンドを流す。
IBLOCK はブロックデバイス上で SCSI コマンドをエミュレーションする。

LVM ロジカルボリュームはもちろん論理ブロックデバイスなので IBLOCK となる。

targetcli

セットアップ:

$ sudo apt-get install --no-install-recommends targetcli python-urwid
$ sudo reboot

targetcli のドキュメントはコマンド内ヘルプしかない
使い方:

$ sudo targetcli
/> help
(snip)
AVAILABLE COMMANDS
  The following commands are available in the current path:

    - bookmarks action [bookmark]
    - cd [path]
    - exit
    - get [group] [parameter...]
    - help [topic]
    - ls [path] [depth]
    - pwd
    - refresh
    - saveconfig
    - set [group] [parameter=value...]
    - status
    - version

/> cd backstores/pscsi
/backstores/pscsi> help
(snip)
AVAILABLE COMMANDS
(snip)
    - create name dev
    - delete name

> help create
SYNTAX
  create name dev

DESCRIPTION
  Creates a PSCSI storage object, with supplied name and SCSI device. The SCSI
  device dev can either be a path name to the device, in which case it is
  recommended to use the /dev/disk/by-id hierarchy to have consistent naming
  should your physical SCSI system be modified, or an SCSI device ID in the
  H:C:T:L format, which is not recommended as SCSI IDs may vary in time.

python-rtslib

targetcli は Python で作られたクライアントツールだが、Python ライブラリとして python-rtslib パッケージがある。
API ドキュメントは /usr/share/doc/python-rtslib/doc/html に存在する。Web 経由でアクセスするなら以下でポート 8000 番にブラウザでつなげば読める。

$ cd /usr/share/doc/python-rtslib/doc/html
$ python -m SimpleHTTPServer

rtslib にひとつバグがある。set_parameter メソッドで値の末尾に空白をつけているため、
例えばターゲットポータルグループの InitialR2T を設定するのに失敗する。パッチは以下。

set_parameter patch
--- /usr/lib/python2.7/dist-packages/rtslib/node.py     2012-06-06 17:59:41.515308657 +0000
+++ node.py     2012-06-06 17:59:50.185146504 +0000
@@ -189,7 +189,7 @@
                               % str(parameter))
         else:
             try:
-                fwrite(path, "%s \n" % str(value))
+                fwrite(path, "%s\n" % str(value))
             except IOError, msg:
                 msg = msg[1]
                 raise RTSLibError("Cannot set parameter %s: %s"
initialization
from rtslib.target import *

fabric = FabricModule('iscsi')
if not fabric.exists:
    for mod in fabric.load(): pass
if not fabric.exists:
    error('failed to load iSCSI fabric modules')
create storage object
from rtslib.tcm import *

bs = IBlockBackstore(0)
storage = None
for s in bs.storage_objects:
    if s.name == 'NAME':
        storage = s
        break
if storage is None:
    storage = bs.storage_object('NAME', '/dev/ubuntu/VOLUME')
make a target
from rtslib.target import *

target = Target(fabric, 'iqn.2012-03.com.cybozu:HOST:NAME')
tpg = TPG(target, 1)
if len(tpg.luns) == 0:
    tpg.lun(0, storage, 'NAME at HOST')
tpg.network_portal('IP', 3260)
tpg.set_attribute('authentication', '0')
tpg.set_attribute('generate_node_acls', '1')
tpg.set_attribute('demo_mode_write_protect', '0')
tpg.set_parameter('InitialR2T', 'No')

tpg.enable = True

LUNのリサイズ

iET では LUN のリサイズには一度ターゲットを消して作り直す必要があったが、LIO では lvresize で済む。
ただし、イニシエーター側ではセッションのリスキャンが必要。

initiator$ sudo blockdev --getsize64 /dev/sdb
1073741824

target$ sudo lvresize -L 2g /dev/ubuntu/i_test

initiator$ sudo iscsiadm -m session -R
Rescanning session [sid: 10, target: iqn.2012-03.com.cybozu:ymmt2:test, portal: 10.1.5.213,3260]

initiator$ sudo blockdev  --getsize64 /dev/sdb
2147483648

接続数制限

iSCSI のセッションには MaxConnections というパラメーターがあるが、これはセッション中にマルチパスの目的で複数の TCP コネクションを持てるようにするためのもの。我々に必要なのはイニシエーター VM のスプリットブレインへの対処だが、これに対応できるものではない。iSCSI セッションはセッション ID で識別されるのだが、これが一致するかどうかは実行環境次第だから。

LIO はカーネルドライバーで iSCSI ターゲットを実装しているので、これを制御するにはカーネルに手を入れる必要がある。
https://gist.github.com/4528252

このパッチは TPG につき一つのコネクションしか許さないようにしたもの。

検証した項目

  • targetcli
    sudo で起動したら後はマニュアル通り。
  • ネットワークポータルの共有
    同一の IP / ポートで複数のターゲットにネットワークポータルを設定可能。
  • rtslib のキャッシュ動作
    内部でキャッシュはしていないので、システムの変更は特別な操作なく検出できる。
    素直な configfs のラッパー。
  • 接続数制限
    kernel にパッチをあてて、TPG への同時接続が1本に制限されるのを確認。
  • LUN の拡張
    lvresize とセッションのリスキャンで可能なことを確認。
  • アクティブセッションの確認方法
    demo mode だと存在しない。。upstream は /proc でとれるようにしたけど、mainline で reject されている。
    https://groups.google.com/forum/?fromgroups#!topic/linux-iscsi-target-dev/xlGJPVfpT7I

iSCSI initiator

open-iscsi なのはそのまま。

$ sudo apt-get install open-iscsi

I/O 高負荷時に CRC32C エラーを誤計算する不具合がある。LIO側でも CRC32C を有効にしていると
エラーリカバリーとなるが、open-iscsi はエラーリカバリレベル 0 しかサポートしていないので再接続
となり、I/O 性能が極端に低下してしまう。

mdadm

man mdadm(8) の差分を見ても大した変更点はないように見えるが、実際には 10.04 から 12.04 の間に mdadm はメジャーバージョンがあがっており、デバイスファイルまわりの扱いの変更が特に大きい。

ドキュメント

man にも /usr/share/doc/mdadm にも情報はない。ソースをもってきて、中の ANNOUNCE ファイルを確認すること。

デバイスファイル

Quote from ANNOUNCE-3.0:

Also the approach to device names has changed significantly.

If udev is installed on the system, mdadm will not create any devices
in /dev. Rather it allows udev to manage those devices. For this to work
as expected, the included udev rules file should be installed.

If udev is not installed, mdadm will still create devices and symlinks
as required, and will also remove them when the array is stopped.

mdadm now requires all devices which do not have a standard name (mdX
or md_dX) to live in the directory /dev/md/. Names in this directory
will always be created as symlinks back to the standard name in /dev.

The man pages contain some information about the new externally managed
metadata. However see below for a more condensed overview.

この変更およびこれに伴う以下の不具合あり。
https://gist.github.com/3300419

オンラインリサイズ

10.04 の MD は以下の手順を全ディスクで繰り返す必要があった。

  1. 一台 fail させる
  2. remove する。
  3. remove 後、MD のスーパーブロック内のサイズを "-A --update=devicesize" で書き換える

12.04 では以下の手順でいけて楽になった。

$ sudo mdadm -G DEVICE --bitmap=none
$ sudo mdadm -G DEVICE --size=max
$ sudo mdadm --wait DEVICE
$ sudo mdadm -G DEVICE --bitmap=internal

時々 MD の初期化に失敗する

バグらしい。こちらを参照。

bitmap 関係の sysfs

/sys/block/md*/md 以下に追加されている。

+  bitmap/location
+     This indicates where the write-intent bitmap for the array is
+     stored.
+     It can be one of "none", "file" or "[+-]N".
+     "file" may later be extended to "file:/file/name"
+     "[+-]N" means that many sectors from the start of the metadata.
+       This is replicated on all devices.  For arrays with externally
+       managed metadata, the offset is from the beginning of the
+       device.
+  bitmap/chunksize
+     The size, in bytes, of the chunk which will be represented by a
+     single bit.  For RAID456, it is a portion of an individual
+     device. For RAID10, it is a portion of the array.  For RAID1, it
+     is both (they come to the same thing).
+  bitmap/time_base
+     The time, in seconds, between looking for bits in the bitmap to
+     be cleared. In the current implementation, a bit will be cleared
+     between 2 and 3 times "time_base" after all the covered blocks
+     are known to be in-sync.
+  bitmap/backlog
+     When write-mostly devices are active in a RAID1, write requests
+     to those devices proceed in the background - the filesystem (or
+     other user of the device) does not have to wait for them.
+     'backlog' sets a limit on the number of concurrent background
+     writes.  If there are more than this, new writes will by
+     synchronous.
+  bitmap/metadata
+     This can be either 'internal' or 'external'.
+     'internal' is the default and means the metadata for the bitmap
+     is stored in the first 256 bytes of the allocated space and is
+     managed by the md module.
+     'external' means that bitmap metadata is managed externally to
+     the kernel (i.e. by some userspace program)
+  bitmap/can_clear
+     This is either 'true' or 'false'.  If 'true', then bits in the
+     bitmap will be cleared when the corresponding blocks are thought
+     to be in-sync.  If 'false', bits will never be cleared.
+     This is automatically set to 'false' if a write happens on a
+     degraded array, or if the array becomes degraded during a write.
+     When metadata is managed externally, it should be set to true
+     once the array becomes non-degraded, and this fact has been
+     recorded in the metadata.

メタデータ

デフォルトが 0.9 から 1.2 になった。