Ceph を使ってみる

作成日:2011.09.08
更新日:2012.03.07

このページでは ceph のインストール方法と基本的な使い方を解説する。

以下は関連ページ。


更新履歴
(2011.12.26) Linux の configuration の変更方法を追加。
(2012.02.10) レプリケーション数の変更を追加。
(2012.03.07) 「モニタサーバとメタデータサーバの名前」と「OSD サーバを内部ネットワークにと外部ネットワークに別々につなげる」を追加。


目次


1. Ceph とは

Ceph は Linux 上で動作する分散ファイルシステム(Distributed File System; DFS)の一つ。 UCSC の Sage Weil の博士論文が元となり、ペタバイト級の高性能な DFS を実現することを目標としている。 オープンソースとして開発されており、ceph の一部機能は Linux カーネル 2.6.34 から取り込まれている。

詳細は以下のページを見て欲しい。

適当に解説すると、以下のような特徴を持っている。

ただし開発中のファイルシステムなので恐ろしくバギー。

2. インストール

Ceph をインストールするために必要な Linux 側の手順と ceph のビルド手順を述べる。 この処理は ceph クラスタに含めるすべてのノードで実行すること。

2.1 OS のインストール

現在の ceph は分散ファイルシステムを管理する本体と、それをファイルシステムとしてマウントするために必要なカーネルモジュール(ceph.ko)があり、前者は http://ceph.newdream.net/ で開発が進んでいるが、後者は Linux カーネルのメインストリームに取り込まれた。 ceph のバージョンアップに合わせてカーネルモジュール側にも変更が及んでおり、最新の ceph を使うには Linux カーネルのバージョンアップが必要となる。

ceph のバージョンと Linux カーネルのバージョンは適合条件があり、古すぎても新しすぎても動作しない。 ceph の関連文書にも記述がないので比較的新しい組み合わせを試したほうがよい。

今回は Fedora 15 をインストール後に、Linux カーネルだけ最新のもの(この文書を書いている時は linux-3.0.4)に入れ替える。

以下は Linux カーネルのインストールの簡単なメモ。

$ bzcat linux-3.0.4.tar.bz2 | tar xvf -
$ cd linux-3.0.4
$ export LANG=C
$ make menuconfig

ここで ceph 関係のオプションを有効にする。 メニューの中でCeph distributed file system (EXPERIMENTAL)Rados block device (RBD)を有効にしてから終了する。

.config ファイルの中に以下の行が含まれているのを確認。

CONFIG_CEPH_FS=m
CONFIG_BLK_DEV_RBD=m

Linux カーネルをビルドする。

$ make -j4 all

インストール

# make modules_install
# make install

インストール後に GRUB を編集して linux-3.0.4 が立ち上がるように切り替える。

# vi /boot/grub/grub.conf

2.2 OS インストール後の設定

OS の一般的な設定の後に ceph のビルド & 実行のために以下のような設定を行った方がよい。

ファイヤーフォールの停止

ceph 用にファイヤーウォールの適切なポートを通過させる必要があるが、面倒なので全体を停止する。

# chkconfig iptables off

SELinux の停止

本来であれば SELinux は有効な状態で使いたいが、SELinux が有効なままでは cephfs (ceph.ko) でのマウントが失敗する。 FUSE だけを使うのであれば SELinux は有効なままでもよい。

ceph-0.32 では SELinux を停止させないと動作しなかったが、ceph-0.34 では問題なく動作する。駄目だやっぱり動かない。

root 用の ssh-keygen

Ceph のスクリプトの一部は、ssh 経由で他のクラスタノードにアクセスする。 root 用の ssh-keygen を作成し、クラスタ間ではパスワードなしでログインできるようにするか、ssh-agent で自動的にパスワード入力が可能なようにした方がよい。

サーバー間の時刻同期

ceph はサーバ間の時刻が大きくずれていると誤動作する。 例えば ceph-mon デーモンの CPU 使用率が 100% に近いところに貼りついて落ちなくなる。 NTP などを用いて時刻を一致させること。

2.3 ceph のインストール

yum のアップデート

まず全体をアップデートする。これは時間がかかる。

#  yum update

次に http://ceph.newdream.net/wiki/Installing_on_RedHat_or_CentOS で要求されているパッケージを追加でインストールする。

# yum install gcc gcc-c++ automake libtool expat expat-devel boost-devel nss-devel cryptopp cryptopp-devel libatomic_ops-devel fuse-devel

以下のパッケージも必要となる。 入っていなければインストールする。

# yum install google-perftools-devel libedit-devel btrfs-progs libuuid-devel libaio-devel

ceph のビルド

インストールする ceph は、このサイト からダウンロードできる。 ここでは最新の ceph-0.37.tar.gz をダウンロードし、コンパイルする。

$ tar xzvf ceph-0.37.tar.gz
$ cd ceph-0.37
$ ./autogen.sh
$ CXXFLAGS="-g -O2" ./configure --prefix=/usr --sbindir=/sbin --localstatedir=/var --sysconfdir=/etc
$ make -j 8

もし CentOS 6.0 を用いていて google-perftools-devel パッケージが不足している場合には、--without-tcmalloc も追加する。

$ CXXFLAGS="-g -O2" ./configure --prefix=/usr --sbindir=/sbin --localstatedir=/var --sysconfdir=/etc --without-tcmalloc

さらに root 権限でインストールを行う。

# make install

起動スクリプトのコピーも行う。

# cp ceph-0.37/src/init-ceph /etc/rc.d/init.d/ceph
# chmod a+x /etc/rc.d/init.d/ceph

3. ファイルシステムの作成とマウント

3.1 構成の設計とファイルシステムの作成

Ceph を利用するためには、ceph にクラスタとして参加するノード(サーバ)とディスクを決める必要がある。 これを ceph.conf という形で記述し、mkcephfs で構成する。

今回は host0(10.0.0.1)、host1(10.0.0.2)、host2(10.0.0.3) の3台ノードで ceph クラスタを組むものとする。 3台のホスト名は /etc/hosts か DNS に登録しておくこと。 また host0、host1、host2 はおのおの /dev/sdb1 に空きディスクを持っており、これを OSD として利用するものとする。

OSD 構成方法の選択肢

OSD の領域は、専用のブロックデバイスを btrfs 形式でフォーマットして割り当てるか、ディレクトリツリーの指定ディレクトリ以下のいずれかを使用する。 専用ブロックデバイスを使うには [osd.x]btrfs devs を記述する。 記述がない場合には [osd]osd data 指定したディレクトリ以下が割り当てられる。

OSD はまた、OSD データを置く場所とジャーナルの 2 種類のデータがある。 OSD への書き込みはまずジャーナルへ行われ、ジャーナルに書き込まれたデータが OSD へ転送される。 これは ext3 のデータジャーナルdata=journal に相当する機能だが、ceph の OSD はこれをユーザランドのデータ構造で実現している。 ジャーナルは OSD データと分離が可能で、むしろジャーナルは SSD のような高速デバイス側に移すことが推奨されている。

専用ブロックデバイスを使用し、ジャーナル用の専用デバイスを設けない場合の設定

host0、host1、host2 にある /dev/sdb1 を専用の OSD データ領域として使う設定例を示す。 クラスタ間の役割分担は、以下のように行う。

[global]
	pid file = /var/run/ceph/$name.pid
	debug ms = 0
	auth supported = cephx
	keyring = /etc/ceph/keyring.bin

[mon]
	mon data = /data/mon$id

[mon.0]
	host = host0
	mon addr = 10.0.0.1:6789

[mds]
	keyring = /etc/ceph/keyring.$name

[mds.0]
	host = host0

[mds.1]
	host = host1

[mds.2]
	host = host2

[osd]
	osd data = /data/osd$id
	osd journal = /data/osd$id/journal
	osd journal size = 512
	keyring = /etc/ceph/keyring.$name

[osd.0]
	host = host0
	btrfs devs = /dev/sdb1

[osd.1]
	host = host1
	btrfs devs = /dev/sdb1

[osd.2]
	host = host2
	btrfs devs = /dev/sdb1

モニタサーバとメタデータサーバの名前

モニタサーバとメタデータサーバは [mon.0][mds.0] のような数字ではなく、[mon.alpha][mds.alpha] のようなアルファベットを付けても構わない。

ただし OSD サーバだけは数字で指定する必要がある。

ディレクトリツリーの指定ディレクトリ以下を使用する場合

OSD を特別なデバイスを使わずに通常のファイルツリーのディレクトリを指定することもできる。 この時は btrfs devs を指定しない。

空きディスク(/dev/sdb)を自前でフォーマットして、[osd]osd data 指定したディレクトリ以下にマウントすれば、OSD ディスクを任意のファイルシステムとして利用することが可能となる。

[osd.0]
	host = host0
#	btrfs devs = /dev/sdb1

ジャーナルを分離する

OSD のジャーナルを分離するには [osd]osd journal にパスかデバイスを指定する。 ジャーナルは OSD データよりも高速なデバイス上に載せることが推奨されているが、OSD データと同じ種類の HDD でも分離する方が高速である。

osd journal size はジャーナルのサイズを MB で指定しているが、デバイスを指定した場合には osd journal size の指定は不要となる。

[osd]
	osd journal = /dev/sdc

OSD の通常の動作は、ジャーナルにデータが書き込んだ後に、ジャーナルのデータを OSD データに写し、ジャーナルを消去する。 ただし OSD のジャーナルを btrfs 形式にした場合には、ジャーナルと OSD データに並行に書き込む(parallel mode)。

[osd]
	filestore journal parallel = true

OSD サーバを内部ネットワークにと外部ネットワークに別々につなげる

分散ファイルシステムでは、クラスタシステムの内部のネットワークとクライアントが繋がっている外部のネットワークを切り分けたいものである。

Ceph は OSD サーバだけ特別扱いがあり、OSD サーバが他の OSD サーバと行う通信と、それ以外のコンポーネントと行う通信を分離できる。 Replication の説明 で説明したように、ceph は OSD 間の通信を結構大量に行う。

通常の設定で host で指定する部分を、public addrcluster addr に置き換える。 ここに IP アドレスではなくホスト名を書いた時の動作は未検証。

[osd.0]
	host = 10.0.0.1
                  ↓
	public addr = 10.0.0.1
	cluster addr = 10.1.0.1

public addrcluster addr に同一サブネット内の別の IP アドレスを割り振る場合、同一サブネットに2枚以上の NIC が刺さっている場合の動作 を参考に追加設定を行う必要がある。 もししないと先に反応した NIC に両方の IP アドレスが割り振られてしまう。

3.2 ファイルシステムの作成

ファイルシステムを作成する前に ceph.conf を参加するすべてのノードに配布する。 ceph クラスタを構成するサーバの ceph.conf が喰い違っているといろいろトラブルになるので注意。

# scp ceph.conf host0:/etc/ceph/ceph.conf
# scp ceph.conf host1:/etc/ceph/ceph.conf
# scp ceph.conf host2:/etc/ceph/ceph.conf

クラスタを代表するノード上で mkcephfs を実行すると、ceph.conf に従ってファイルシステムの構成が行われる。 OSD のために提供したデバイス(btrfs devs)はこのスクリプトの中で mkfs.btrfs が掛かって初期化されるので注意。

# mkcephfs -c /etc/ceph/ceph.conf --allhosts --mkbtrfs

OSD デバイスとして btrfs 形式を使わない場合には --mkbtrfs は指定しない。 ただし ceph.conf の [osd] セクションの osd data の項で指定されるディレクトリをあらかじめ作成してが必要がある。

# ssh host0 mkdir -p /data/osd0
# ssh host1 mkdir -p /data/osd1
# ssh host2 mkdir -p /data/osd2
# mkcephfs -c /etc/ceph/ceph.conf --allhosts

途中 root のパスワードを何回も聞かれるが、その度に入力するか、ssh-keygen などを使ってパスワードを不問にするようにしておくこと。

3.3 起動

各ノードで /etc/rc.d/init.d/ceph を起動する。

# ssh host0 /etc/rc.d/init.d/ceph start
# ssh host1 /etc/rc.d/init.d/ceph start
# ssh host2 /etc/rc.d/init.d/ceph start

あるいは -a オプションを指定することで、ceph.conf で関係するホストをいっぺんに起動することができる。

/etc/rc.d/init.d/ceph -a start

3.4 マウント

ceph のファイルシステムは、カーネルモジュール(ceph.ko)を使った cephfs ファイルシステムとして、FUSE を使ったマウント方法の二種類がある。 cephfs を使った方が高速である。

以降は host0 の /mnt/ceph にマウントする場合を説明する。

cephfs でのマウント

cephfs を使うには admin のセキュリティキーを事前に調べておく必要がある。 これには ceph-authtool を実行した場合に青字の部分がキーとなる。 ただし ceph の 0.35 以前のバージョンは ceph-authtool は cauthtool というコマンド名だった。

# ceph-authtool -l /etc/ceph/keyring.bin 
[client.admin]
         key = AQA6Qm5OOCPSJxAAz2ENDf8F0suN5BMrezXRaQ==
         auid = 18446744073709551615

mount コマンドにファイルシステムとして ceph を指定し、オプションにセキュリティキーを入力する。 secret には ceph-authtool の結果を渡す。

# mount -t ceph host0:/ /mnt/ceph/ -vv -o name=admin,secret=AQA6Qm5OOCPSJxAAz2ENDf8F0suN5BMrezXRaQ==

mount 実行中に mount.ceph が mount: error writing /etc/mtab: Invalid argument というエラーメッセージが出すが、これは無視してもよい。

FUSE を使ったマウント

FUSE を使ったマウントは以下のようになる。 モニタが動作しているホストの IP アドレスを指定する。 IP アドレスの後にはモニタの動作するポート番号(デフォルトだと 6789)を指定する。 セキュリティーキーの指定は不要である。 ただし ceph の 0.35 以前のバージョンは ceph-fuse は cfuse というコマンド名だった。

# ceph-fuse -m 10.0.0.1:6789 /mnt/ceph

IP アドレスの代わりにホスト名で指定したいところだが、unable to parse addrs in 'host0:6789' というエラーが出る。 なぜだろう?

4. スケールアウト

ceph は運用中にシステムを停止せずに新しい OSD を追加してファイルシステムを拡張することができる。この手順を紹介する。

これまでに構成した host0 〜 host2 の 3 台構成の ceph クラスタに、新しく host3 とその配下の /dev/sdb1 のディスクを追加して 4 台構成にしてみる。

新しく追加する host3 は、事前に 2. の作業を済ませて OS と ceph のインストールを完了したものとする。

下記の内容は http://ceph.newdream.net/wiki/OSD_cluster_expansion/contraction を参考にした。

以降の手順の説明は、新規の追加ノード(host3)で行うものと既存のノードで行うものがある。 既存のノードは host0 で行うように解説しているが、おそらく host1 や host2 で行っても大丈夫のはず。

STEP1: ceph.conf の修正と再配布

新しい OSD を追加した形に ceph.conf を修正したものを ceph.conf.2 とする。 これは ceph.conf に以下を加えたものとなる。

[osd.3]
	host = host3
	btrfs devs = /dev/sdb1

これをすべてのノードに配る。

# scp ceph.conf.2 host0:/etc/ceph/ceph.conf
# scp ceph.conf.2 host1:/etc/ceph/ceph.conf
# scp ceph.conf.2 host2:/etc/ceph/ceph.conf
# scp ceph.conf.2 host3:/etc/ceph/ceph.conf

STEP2: 追加する OSD を mkfs.btrfs & マウント (host3 での作業)

まず host3 にログインし、OSD 用のデバイスを mkfs.btrfs で初期化する。

# mkfs.btrfs /dev/sdb1

次にこれを ceph.conf の osd data で指定した位置(/data/osd3)にマウントする。 /data/osd3/ がない場合には事前に mkdir すること。

# mount -t btrfs /dev/sdb1 /data/osd3/

STEP3: monmap を作成 (host0 での作業)

monmap を作成する。

# ceph mon getmap -o /tmp/monmap

monmap ファイルができたら、これを host3 に転送する。

# scp /tmp/monmap host3:/tmp/monmap

STEP4: OSD を作成 (host3 での作業)

host3 で以下のコマンドを打ち込む。 赤字の番号は追加したい OSD の番号となる。

# cosd -c /etc/ceph/ceph.conf -i 3 --mkfs --monmap /tmp/monmap --mkkey

OSD のキーが host3 の /etc/ceph/keyring.osd.3 にできているはずなので、これを ceph ファイルシステムに追加するために host0 に転送する。

# scp /etc/ceph/keyring.osd.3 host0:/tmp/keyring.osd.3

v0.36 から cosd は ceph-osd に名前が変わっている。

STEP5: OSD の追加 (host0 での作業)

ファイルシステムに新しい OSD を追加する。

# ceph auth add osd.3 osd 'allow *' mon 'allow rwx' -i /tmp/keyring.osd.3

成功すれば added key for osd.3 と表示される。

次に現在の OSD 数を確認し、それを +1 する。

# ceph osd dump -o - | grep max 
max_osd 3

現在は 3 台なので +1 して 4 台になる。

# ceph osd setmaxosd 4

成功すれば set new max_osd = 4 と表示される。

STEP6: host3 で ceph 起動 (host3 での作業)

host3 にログインし、/etc/rc.d/init.d/ceph を起動する。

# /etc/rc.d/init.d/ceph start

STEP7: CRUSH マップを確保

host0 での作業。 このあたりでいい加減面倒になる。

# ceph osd getcrushmap -o /tmp/crush

/tmp/crush はバイナリファイルなので、これを編集可能なテキストに変換する。

crushtool -d /tmp/crush -o /tmp/crush.txt

/tmp/crush.txt を手作業で編集し、赤字の部分を追加する。 device の番号は、OSD の番号と同じとする。

CRUSH マップの書き方の詳細は「Ceph の CRUSH マップの書き方」を参考のこと。

# begin crush map

# devices
device 0 device0
device 1 device1
device 2 device2
device 3 device3

# types
type 0 osd
type 1 domain
type 2 pool

# buckets
domain root {
         id -1           # do not change unnecessarily
         # weight 2.000
         alg straw
         hash 0  # rjenkins1
         item device0 weight 1.000
         item device1 weight 1.000
         item device2 weight 1.000
         item device3 weight 1.000
}

編集が終わった後は、バイナリ形式の CRUSH マップに戻す。

# crushtool -c /tmp/crush.txt -o /tmp/crush.new

これを登録する。

# ceph osd setcrushmap -i /tmp/crush.new

STEP8: Reweight の実行 (host0 での作業)

最後の最後に、既存の OSD と追加した OSD の間でデータの再配置を行う。 これを ceph では reweight と呼んでいる。 DFS によっては rebalance と呼んだりもする。

以下のコマンドを打つと reweight がはじまる。 進捗状態に応じてパーセンテージに示される進捗が 0% になれば終了となる。 「完了」というメッセージはでないので、自分で判断して Control+C で止める。

# ceph -w

これで OSD の追加は完了。

5. レプリケーション数を変更する

Ceph のレプリケーション数は実行時に変更することができる。

Ceph はディレクトリやファイルの属性を管理するメタデータとファイルの実体に別々のレプリケーションを設定できる。 デフォルトはそれぞれ 2 になっている。 これを変更するには以下のように打つ。

# ceph osd pool set metadata size 2
# ceph osd pool set data size 2

設定変更を適用するには以下のように reweight が必要になる。 これを実行すると、レプリケーション数が増えた場合には OSD 間でオブジェクトのコピーが、減らした場合にはオブジェクトの削除が発生する。

# ceph -w

現在の設定の確認は以下のように行う。 赤字が現在のレプリケーション数となる。

# ceph osd dump -o - | grep pg_size
pool 0 'data' rep size 2 crush_ruleset 0 object_hash rjenkins pg_num 768 pgp_num 768 lpg_num 2 lpgp_num 2 last_change 1 owner 0 crash_replay_interval 45
pool 1 'metadata' rep size 2 crush_ruleset 1 object_hash rjenkins pg_num 768 pgp_num 768 lpg_num 2 lpgp_num 2 last_change 1 owner 0
pool 2 'rbd' rep size 2 crush_ruleset 2 object_hash rjenkins pg_num 768 pgp_num 768 lpg_num 2 lpgp_num 2 last_change 1 owner 0

6. スナップショット

ceph ファイルシステムは、read only のスナップショットを作成できる。

例えば ceph ファイルシステムを /mnt/ceph/ にマウントした場合、現在の状況を snapshot1 という名前でスナップショットを採るには、マウント直下にある隠しディレクトリ /.snap/ の下に /.snap/snapshot1 というディレクトリを作成する。

# mkdir /mnt/ceph/.snap/snapshot1

/mnt/ceph/.snap/snapshot1/ 以下のファイルは、上記の mkdir をした瞬間のファイルシステムイメージが保存されている。

特定のディレクトリ以下のスナップショットを作ることも可能である。 ceph ファイルシステム上に /mnt/ceph/vm-image-001/ というディレクトリがあった場合に、snapshot2 という名前で スナップショットを採るには以下のように mkdir を実行する。

# mkdir /mnt/ceph/vm-image-001/.snap/snapshot2

同一 ceph ファイルシステムの中でスナップショット名が被ってはいけないようだ。

スナップショットを削除するには rmdir でスナップショットディレクトリを削除すればよいようだ。 ただし高確率でエラーになるんですけど。

問題点

ceph は完成度が低く、結構な頻度でクラッシュする。 それ以外にも色々問題がある。

OSD の容量不足で ENOSPC エラー

Ceph で使用している OSD は CRUSH アルゴリズムによって、割り当てられているが各 OSD の残容量を見て分散方法を変えてくれない。 また 特定の OSD が完全に枯渇した場合、その OSD をよけてオブジェクトを割り付けるということもしてくれない。

容量的に不均等な OSD を使った場合、容量の少ない OSD がディスクを消費したところで ceph ファイルシステムとして ENOSPC エラー(No Space)が出るようになる。

ディレクトリサイズの問題

コメント

コメントを書き込む

TOP    掲示板    戻る
Written by NAKAMURA Minoru, Email: nminoru atmark nminoru dot jp, Twitter:@nminoru_jp