2014年2月27日木曜日

/proc/diskstats のメモ

こんな簡単なメモでも誰かの役に立つかもしれない
RHEL 6 kernel-2.6.32-431.5.1.el6.src.rpm から。
Field No.変数簡単な説明タイプ単位関数
1MAJOR(part_devt(hd))メジャー番号
2MINOR(part_devt(hd)マイナー番号
3disk_name(gp, hd->partno, buf)ディスク名
4ios[0]完了済み読み込みIO数カウンターblk_account_io_done
5merges[0]マージ済み読み込みIO数カウンターdrive_stat_acct
6sectors[0]完了済み読み込みセクター数カウンターblk_account_io_completion
7ticks[0]読み込みで使用された秒数カウンターミリ秒blk_account_io_done
8ios[1]完了済み書き込みIO数カウンターblk_account_io_done
9merges[1]マージ済み書き込みIO数カウンターdrive_stat_acct
10sectors[1]完了済み書き込みセクター数カウンターblk_account_io_completion
11ticks[1])書き込みで使用された秒数カウンターミリ秒blk_account_io_done
12part_in_flight(hd)実行中のIO数ゲージdrive_stat_acct,blk_account_io_done
13io_ticksIOにかかった時間カウンターミリ秒drive_stat_acct
14time_in_queueキューにIOがあった合計時間 (in_flight x io_ticks の合計)カウンターミリ秒drive_stat_acct
blk_finish_request
->blk_account_io_done
─────────────────────
2003  unsigned long duration = jiffies - req->start_time;
2011  part_stat_inc(cpu, part, ios[rw]);
2012  part_stat_add(cpu, part, ticks[rw], duration);
2013  part_round_stats(cpu, part);
2014  part_dec_in_flight(part, rw);
2015
─────────────────────

blk_update_request
->blk_account_io_completion
──────────────────────────
1981static void blk_account_io_completion(struct request *req, unsigned int bytes)
1982{
1983 if (blk_do_io_stat(req)) {
1984  const int rw = rq_data_dir(req);
1985  struct hd_struct *part;
1986  int cpu;
1987
1988  cpu = part_stat_lock();
1989  part = disk_map_sector_rcu(req->rq_disk, blk_rq_pos(req));
1990  part_stat_add(cpu, part, sectors[rw], bytes >> 9);
1991  part_stat_unlock();
1992 }
1993}
──────────────────────────

blk_insert_request
blk_queue_bio
blk_insert_cloned_request
->drive_stat_acct
──────────────────────────
1199static void part_round_stats_single(int cpu, struct hd_struct *part,
1200        unsigned long now)
1201{
1202 if (now == part->stamp)
1203  return;
1204
1205 if (part_in_flight(part)) {
1206  __part_stat_add(cpu, part, time_in_queue,
1207    part_in_flight(part) * (now - part->stamp));
1208  __part_stat_add(cpu, part, io_ticks, (now - part->stamp));
1209 }
1210 part->stamp = now;
1211}
──────────────────────────

2014年2月12日水曜日

ZFS on AWS LINUX (2) ファイルシステムの作成

前回でモジュールの導入が完了したので、今回はファイルシステムを作成します。 今回のエントリの作成に当たっては以下の文書を参考にしています。 https://pthree.org/2012/12/05/zfs-administration-part-ii-raidz/
マネージメントコンソールとコンソールを行ったり来たりするのは面倒なので、 可能な限りコンソールコマンドだけで処理しようと思います。
今回せっかくなので RAID z3 ボリュームを作成してみようと思います。 RAID z3 はトリプルパリティーを持つ非常に頑丈なファイルシステムで、 最低5台の HDD を必要とします。

事前準備

マネジメントコンソールにてIAMユーザーを作成ます。
作成時に出力されるアクセスキーとシークレットキーを取得して、 aws cli に登録します。
自分で .aws/config ファイルを編集してもいいですが、 "aws configure" コマンドが便利です。
[ec2-user@ip-10-160-162-8 ~]$ aws configure
AWS Access Key ID [None]: AKIxxxxxxxxxxxxxxxxx
AWS Secret Access Key [None]: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Default region name [None]: ap-northeast-1
Default output format [None]:
※ IAM ロールを指定してもいいですが、つけ忘れたのでwww

EBSボリュームの作成

"aws ec2 create-volume" コマンドで、EBSボリュームを作成します。 今回は、RAID Z3 ボリュームを作成するので、5つの EBS ボリュームを確保する必要があります。 同じ要領でコマンドを5回繰替えしてください。
コマンド実行時に出力される項目のうち "VolumeId" は控えておいてください。
以下の出力例では、"vol-5b4bb851" となります。
今回指定した "aws ec2 create-volume" コマンドのオプションの意味は以下の通りです。
  • "--availability-zone"
    アタッチするインスタンスと同じ、AZを指定してください。
  • "--size"
    GB 単位で必要なサイズを指定してください。
[ec2-user@ip-10-160-162-8 ~]$ aws ec2 create-volume --availability-zone ap-northeast-1a --size 10
{
"AvailabilityZone": "ap-northeast-1a",
"Attachments": [],
"Tags": [],
"VolumeType": "standard",
"VolumeId": "vol-5b4bb851",
"State": "creating",
"SnapshotId": null,
"CreateTime": "2014-02-06T07:21:27.214Z",
"Size": 10
}
続いて、"aws ec2 describe-volumes" で作成したボリュームのステータスが "available" になっていることを確認してください。
[ec2-user@ip-10-160-162-8 ~]$ aws ec2 describe-volumes
{
"Volumes": [
...............(snip)...............
{
"AvailabilityZone": "ap-northeast-1a",
"Attachments": [],
"VolumeType": "standard",
"VolumeId": "vol-5b4bb851",
"State": "available",★ここ
"SnapshotId": null,
"CreateTime": "2014-02-06T07:21:27.214Z",
"Size": 10
}
...............(snip)...............
]
}

EBSボリュームのアタッチ

インスタンスにアタッチする際にインスタンスid が必要となりますが、 不明な場合(控え忘れたともいう)はインスタンスメタデータを参照することで確認できます。
コマンドラインは以下の通りです。
[ec2-user@ip-10-160-162-8 ~]$ GET http://169.254.169.254/latest/meta-data/instance-id
i-27cc6720 ★
"aws ec2 attach-volume" コマンドを利用して EBS ボリュームをインスタンスにアタッチします。
作成した5つのEBSボリュームに対して実行してください。
今回使用した "aws ec2 attach-volume" コマンドのオプションは以下の通りです。
  • "--instance-id"
    EBSボリュームが アタッチされるインスタンスのIDです。先ほど取得した値を指定してください。
  • "--volume-id"
    アタッチするボリュームのIDです。ボリューム作成時に控えた値を指定してください。
  • "--device"
    アタッチするデバイス名です。AWS EC2 上のEBSでは、sdfからsdpを指定することが推奨されています。
    今回はsdf,sdg,sdh,sdi,sdj の5つのデバイスとして接続しました。
[ec2-user@ip-10-160-162-8 ~]$ aws ec2 attach-volume --instance-id i-27cc6720 --volume-id vol-5b4bb851 --device sdf { "AttachTime": "2014-02-06T07:31:01.035Z", "InstanceId": "i-27cc6720", "VolumeId": "vol-5b4bb851", "State": "attaching", "Device": "sdf" }
EBSボリュームのアタッチに成功すると、以下のようなログがシスログ(/var/log/messages)に出力されます。
Feb 6 07:31:04 ip-10-160-162-8 kernel: [ 1570.630510] blkfront: xvdf: barrier or flush: disabled; persistent grants: disabled; indirect descriptors: disabled;
Feb 6 07:31:04 ip-10-160-162-8 kernel: [ 1570.653521] xvdf: unknown partition table
※デバイス名がxvdf に変わってしまうことに注意してください。

ZFSボリュームの作成

ここまで、EBS作成とアタッチの手順だけですねwww。本命のzfs ボリュームの作成です。
zpool コマンドを利用して、ボリューム(正確にはストレージプール)を作成します。
以下の例では、"zpool create" コマンドで "tank" という名前のストレージプールを raidz3 で作成し、ディスク xvdf,xvdg,xvdh,xvdi,xvdj(sdf,sdg,sdh,sdi,sdj) を登録しています。
[ec2-user@ip-10-160-162-8 ~]$ sudo zpool create tank raidz3 xvd{f..j}
確認は、"zpool status" コマンド実施します。
[ec2-user@ip-10-160-162-8 ~]$ sudo zpool status tank
pool: tank
state: ONLINE
scan: none requested
config:
NAME STATE READ WRITE CKSUM
tank ONLINE 0 0 0
raidz3-0 ONLINE 0 0 0
xvdf ONLINE 0 0 0
xvdg ONLINE 0 0 0
xvdh ONLINE 0 0 0
xvdi ONLINE 0 0 0
xvdj ONLINE 0 0 0

errors: No known data errors
この状態で、"/tank" に zfs ボリュームがマウントされています。 このほかのzfsの便利機能は、また改めて。

補足

以下のようなエラーがでてコマンドが失敗する場合があります。
[ec2-user@ip-10-160-162-8 ~]$ sudo zpool create tank raidze xvd{f..j}
Failed to load ZFS module stack.
Load the module manually by running 'insmod /zfs.ko' as root.
Failed to load ZFS module stack.
上記のエラーが出力された場合 dkms によるモジュール作成が失敗している場合があります。
モジュール作成が失敗する原因としては、"kernel-devel" および "kernel-headers" パッケージと "kernel" パッケージとの間でバージョンが一致していないことが考えられます。
バージョン不一致の原因は、yum で導入した場合に、"kernel-devel" および "kernel-headers"の 最新版が導入され、"kernel" パッケージがアップデートされていないことに起因します。
確認方法は "rpm" コマンドを例えば以下のように実行して、"kernel-devel" および "kernel-headers"と "kernel" パッケージのバージョンを確認してください。
[ec2-user@ip-10-160-162-8 ~]$ rpm -qa | grep kernel kernel-devel-3.4.76-65.111.amzn1.x86_64 kernel-headers-3.4.76-65.111.amzn1.x86_64 kernel-3.4.73-64.112.amzn1.x86_64
上記実行例では、"kernel" パッケージのバージョン は "3.4.73-64.112"で、"kernel-devel" および "kernel-headers" のパッケージバージョンは "3.4.76-65.111" なので、dkms によるパッケージ作成が失敗します。。 素直に"yum update" して、再起動で対処できます。
なお、dkms を利用している場合は、kernel アップデート後最初の一回目の再起動で、モジュールの再コンパイルが必要となるため起動に通常時よりも多くの時間がかかります。