[Linux][Cloud][Storage] オブジェクトストレージをファイルシステムのごとく扱う

やった事

現在、HQから災対サイトに対してデータのバックアップを取得しています。これはCIFSもNFSも同様に行っていることなんですが、NFSに関しては毎日5:00-6:00にバックアップを行っています。コレに加え、さらに二次バックアップである災対サーバ側のデータをAWS S3へバックアップすることを考え、それを行いました。ざっくりした概要は以下のとおりです。

今回、災対サーバ(CentOS7)側で、AWS S3に作成したバケットをファイルシステムとして見せることを考えました。こういうことが出来るツールは結構OSSとして出回っているようですが、今回それにS3QLを選定しました。そのTipsを書いてみました。

S3QLとは

S3QLとは、オブジェクトストレージへの接続を前提とした仮想ファイルシステムの一種と見られます。仮想デバイスを提供するFUSE(Filesystem in Userspace)を介して接続されるようです。開発言語にはPythonが使用されています。

S3QLには必要なコマンド(mkfs/mount/umount等)毎に専用コマンドが整備されており、コレを使用することでオブジェクトストレージへのファイルシステム作成・マウント・アンマウントを行います。オブジェクトストレージとのデータのやり取りは非同期で行われるため、ローカルディスクにキャッシュを設け、それで整合性を担保するという構成になっています。

また、S3にはS3QLからのみ読み取れるチャンクデータとして配置されます。よって、S3から直接データを読み取られることはありません。さらに、S3QLにはデータ暗号化機能があり、特定のパスワードをseedとして暗号化状態でのデータ転送が行えるようです。ほかにもこんな機能が。

  • ダイナミックサイズ:データを追加すれば増え、削除すれば減る、つまりは実際の使用量だけしかS3のバケットを消費しない
  • 圧縮:GZIP形式での圧縮を透過的に行います。
  • 重複排除:内容が一致するファイルはポインタだけをコピーし、二重コピーはしない。S3QLのサイトを見る限り、ブロック一致型の重複排除機能みたいです。
  • WORM的な使用が可能っぽい:一度きりのWriteのみ許可し、その後Read Onlyにすることが出来るようです。S3QLのサイトではImmutable Treesと呼ばれてるようです。
  • Copy on Writeベースのスナップショット:スナップショット取得が可能っぽいです。
  • ネットワーク遅延影響を受けない:Read/Writeキャッシュを備えており、一旦はキャッシュでやり取りするため、ネットワーク遅延影響を受けにくい構造になっている。同様の理由により、狭帯域ネットワークに対してその影響が出にくい構造になっている。

凄い。もの凄い。こんなん本当に使っていいの?って思っちゃったぐらい。

今回試した経緯

コレを試した理由としては、昨今のオブジェクトストレージの使い方の一つとして、

  • FUSEと言う手法があることを知った
  • それを応用したクラウドとの連携を試してみたかった

事が挙げられます。

というのも、実は休職前にオブジェクトストレージと連携したストレージヘッドが提案の選択肢として浮上したことがあるんです。

実際にどういう風にデータが解釈され、そして配置されるのか、暗号化に伴うオーバーヘッドや差分はどう扱われるのか?と言うところが当時は気になったものの、評価とかをする暇もなく、当時はお蔵入り案として選択肢から消したのですが、実際どういう代物なんだろう?と近似した仕組みでもいいから試したかったというのが一番の理由です。

課金がちょいと怖いんですが、容量やファイル数から月額を試算した所、どうやらなんとか$10以内に収まりそうに見えたため、勇気を振り絞って踏み込んでみたのでした。

大前提:S3へのバケット新規作成

ここは大まかにしか説明しません。

  • AWSコンソールへログインし、S3バケットを新規作成します。
  • 本記事ではバケット直下にs3qlデータを配置するようにしていますが、実際には1階層ディレクトリを作っておいたほうが良いです。理由としては以下の点です。
    • 同一バケット内にデータが保存され、統一ポリシーのもとでデータ運用ができる
    • ディレクトリに対して可用性レベルの設定が行える
      • バケット直下だと、全部Standard扱いになり、例えば今回のような可用性をそこまで求めない場合だとRRS(低可用性ストレージ)の選択が困難になります。(実質不可能?)
  • バケット作ったら、I AMコンソールを開き、グループとユーザを作成します。グループポリシーには、AWSS3FullAccess権限を付与すると良いようです。
  • ユーザのAccess KeyとSecret Keyを控えておきます。これは後の作業で必要になります。

前提パッケージの導入(yum)

# yum --enablerepo=epel install python34-devel \
> python34-setuptools \
> python34-crypto \
> python34-apsw \
> systemd-devel \
> libattr-devel \
> sqlite-devel \
> fuse-devel \
> psmisc

前提パッケージの導入(pip)

# easy_install-3.4 pip

前提パッケージの導入(pipを使用)

# pip3 install \
> defusedxml \
> requests \
> dugong \
> llfuse \
> pytest \
> pytest-catchlog \
> git+https://github.com/systemd/python-systemd.git#egg=systemd

s3qlのインストール

# cd /usr/local/src
# curl -L -O https://bitbucket.org/nikratio/s3ql/downloads/s3ql-2.21.tar.bz2

# tar jxf s3ql-2.21.tar.bz2
# python3 setup.py build_ext --inplace
# python3 setup.py install

# which mkfs.s3ql
/usr/bin/mkfs.s3ql

ファイルシステムの作成

# mkfs.s3ql s3://bluecore-test
Enter backend login: ←I AMアカウントのAccess Key
Enter backend passphrase: ←I AMアカウントのSecret Key
Before using S3QL, make sure to read the user's guide, especially
the 'Important Rules to Avoid Loosing Data' section.
Enter encryption password: ←任意のパスワードを入力します。
Confirm encryption password: ←Enter encryption passwordで入力したものをもう一度入力します。
Generating random encryption key...
Creating metadata tables...
Dumping metadata...
Dumping metadata...
..objects..
..blocks..
..inodes..
..inode_blocks..
..symlink_targets..
..names..
..contents..
..ext_attributes..
Compressing and uploading metadata...
Wrote 149 bytes of compressed metadata.
Cycling metadata backups...
Backing up old metadata...
Please store the following master key in a safe location. It allows
decryption of the S3QL file system in case the storage objects holding
this information get corrupted:
---BEGIN MASTER KEY---
**** **** **** **** **** **** **** **** **** **** ****
---END MASTER KEY---

ファイルシステム認証情報ファイルの作成

# touch ~/.s3ql/authinfo2
# chmod 600 ~/.s3ql/authinfo2
# vi ~/.s3ql/authinfo2

以下の通り編集します。

[s3]
storage-url: s3://bluecore-test
backend-login: **************** ←I AMアカウントのAccess Key
backend-password: *****************************←I AMアカウントのSecret Key
fs-passphrase: ******* ←ファイルシステムに適用したパスワードを入力します。

マウントディレクトリの準備

# mkdir /s3_storage

サービス起動停止スクリプトの作成

# vi /etc/init.d/s3ql

以下の通り編集します。

#!/bin/bash
#
# chkconfig: 35 60 40
# description: S3QL Backup File System
#
# Source function library.
. /etc/init.d/functions
#
AUTHFILE="/root/.s3ql/authinfo2"
BUCKET="s3://bluecore-test"
MOUNTPOINT="/s3_storage"
OPTIONS="--allow-other"
start() {
 echo -n $"Mounting S3QL: "
 mount | grep $MOUNTPOINT > /dev/null
 if [ $? -eq 0 ];then
 echo $"Cannot mount $MOUNTPOINT. Already mounted !!"
 echo
 exit 1
 fi
 echo
 fsck.s3ql --batch $BUCKET
 mount.s3ql $OPTIONS $BUCKET $MOUNTPOINT
 RETVAL=$?
 [ $RETVAL -eq 0 ] && success || failure
 echo
}
stop() {
 echo -n $"Unmounting S3QL: "
 mount | grep $MOUNTPOINT > /dev/null
 if [ $? -ne 0 ];then
 echo $"Already unmounted !!"
 echo
 exit 1
 fi
 umount.s3ql $MOUNTPOINT && success || failure
 echo
}
case "$1" in
 start)
 start
 ;;
 stop)
 stop
 ;;
 *)
 echo "Usage: `basename $0` {start|stop}"
 exit 1
 ;;
esac

保存後、以下の通りコマンド実行し、実行属性を付与します。その後、サービスとして登録します。

# chmod +x /etc/init.d/s3ql
# chkconfig --add s3ql

サービス起動&マウント状態確認

# service s3ql start
Starting s3ql (via systemctl): [ OK ]

マウント状態を確認する。
# df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/mapper/centos-root 54G 4.9G 49G 9% /
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 25M 3.8G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/sda1 497M 223M 275M 45% /boot
192.168.239.245:/data/NFS-DS 5.5T 3.4T 2.1T 62% /nfs
192.168.239.245:/data/MailArchives/store 5.5T 3.4T 2.1T 62% /var/store
192.168.239.245:/data/MailArchives/index 5.5T 3.4T 2.1T 62% /var/index
tmpfs 783M 0 783M 0% /run/user/0
s3://bluecore-test/ 1.0T 0 1.0T 0% /s3_storage

一番下の行にS3のバケットがマウントされていることがわかると思います。容量について、初期値としては1.0TiBと言う扱いになるのですね。実際のバケット内にはチャンクされたデータファイルが入ってました。

サービス停止&アンマウント状態確認

# service s3ql stop
Stopping s3ql (via systemctl): [ OK ]

マウント状態を確認する。
# df -h
ファイルシス サイズ 使用 残り 使用% マウント位置
/dev/mapper/centos-root 54G 4.9G 49G 9% /
devtmpfs 3.9G 0 3.9G 0% /dev
tmpfs 3.9G 0 3.9G 0% /dev/shm
tmpfs 3.9G 25M 3.8G 1% /run
tmpfs 3.9G 0 3.9G 0% /sys/fs/cgroup
/dev/sda1 497M 223M 275M 45% /boot
192.168.239.245:/data/NFS-DS 5.5T 3.4T 2.1T 62% /nfs
192.168.239.245:/data/MailArchives/store 5.5T 3.4T 2.1T 62% /var/store
192.168.239.245:/data/MailArchives/index 5.5T 3.4T 2.1T 62% /var/index
tmpfs 783M 0 783M 0% /run/user/0

S3バケットのマウントが解除されていることがわかると思います。

サービス自動起動有効化

# chkconfig s3ql on

あとはサービス起動しとく。
#service s3ql start
Starting s3ql (via systemctl): [ OK ]

これで、/s3_storage と言うディレクトリに対してS3上のバケットと接続が行われ、ファイルシステムとしてアクセスができるようになります。

S3上のバケットはどうなっているか?

S3上のバケットでは、データは全てチャンク化されており、どれがどのデータかわからないようになっています。更に暗号化も加えられているため、ファイルを拾われてもまともに開けません。たぶん。

試しにrsyncしてみた

試しに、rsyncスクリプトを作成してちゃちゃっと実行してみていますが、さすがサーバ側で暗号化処理が走ってる分、CPU使用率が中々に高く、Load Averageもそれなりに高いです。

現状、15:00頃から処理を開始して、16:45の時点で18GB程度のデータ転送が完了しています(総量は80GB弱ぐらい)。ということで、およそ780MB/min(13MB/sec)ぐらいのスループットでデータコピーしているようです。そう考えると、かなりイッパイイッパイ帯域使ってデータコピーをしているように見えます。(実家のバックボーンは100Mbpsだから)

その後、かな~りの時間をデータコピーに要しましたが、2:04に処理がやっとこさ完了しました。結果は以下のような感じ。

sent 48035301625 bytes received 11925525 bytes 1218714.94 bytes/sec
total size is 75012350628 speedup is 1.56

コピー終了までどえらく待たされた感じになりましたが、要所要所で見る限り、以下の傾向が見られました。率直に思ったのは「結構実用に耐えられる感じでいいなぁ」です。

  • 圧縮・重複排除効果がそれなりにあるようです。78GBの領域をバックアップしましたが、およそ58GBぐらいになってました。効果としては16%の容量削減ができてるようです。
  • 重複排除が聞いている場合の処理はかなり高速でした。恐らくポインタ付処理のみで済んでしまうため、その間のIO処理能力が上がったんだと思われます。
  • キャッシュ領域の使用量はピークで10GB程度、時々眺めましたが、それ以上の容量は使ってなさそうでした。root-vgは40GBで構成しているんですが、別領域を構成する必要は今のところなさそうです。(詳しくは「キャッシュディレクトリの状況」で述べますね)
    • この領域、実家サーバのローカルデータストア(SAS300GB x2(RAID1))を使ってるんですが、これがSSDとかだともっと高速化するんですかねー・・・・
  • 重複排除処理が動いてるとたいていメモリを結構食うはずなんですが、ピークでも10%前後で済んでました。
    • 処理実行したサーバはメモリ8GB搭載しているんで、およそ1GB弱程度がピークなんじゃないかなと思われます。
    • 重複排除の単位がブロックではなく、ファイル単位なんじゃないかな?とコピー処理の動きを見てると感じました。・・・と思ったら、どうやらブロック単位の重複排除みたいです。(s3qlの説明についてこちらが参考になるかと。17.3章を参照のこと。)

キャッシュディレクトリの状況

デフォルト設定だと、キャッシュはローカルディスクになります。具体的なパスとして/root/.s3ql ディレクトリ配下にキャッシュディレクトリが作られ、そこに格納されます。初期状態はこうだったのですが、

# du
16992 ./s3:=2F=2Fbluecore-test=2F-cache
25208 .

rsync処理が進んでいくとこうなりました。

# du
9046208 ./s3:=2F=2Fbluecore-test=2F-cache
9067224 .

あらまぁ、立派に成長しちゃって・・・9GB近くキャッシュ領域を使用している状況を確認しました。が、どうやらコピー終了まで見続けた結果、これがピーク値だったようです。

ジョブの仕込み

コピーも無事終わったということで、これを定期実行ジョブにしました。hinemosのコマンドジョブにバックアップ処理を追加しています。

隔地保管ジョブである「NFSBACKUP_CMD」が正常終了したら「S3BACKUP_CMD」を実行するようにしています。NFS領域が損傷した場合は、/s3_storage 領域からコピーバックする感じになります。

Mastodonインスタンスのスタートは別にこのS3バックアップ処理を待つ必要はないため、開始条件は変更していません。初期同期は11時間ぐらいかかりましたが、差分同期はどのぐらいかかるかな?ある意味見ものです。

終わりに

最近こうしたオブジェクトストレージと連携したストレージ製品が増えてきています。というのも、最近のユーザの傾向として「資産を持ちたくない」と言うものが挙げられます。

できるだけクラウドへシフトしたい、だけど、クラウドに接続する際の回線コストが・・・・あるいは拠点間のデータ整合性が・・・・と悩んだ際に、こうしたオブジェクトストレージは安価なので、だいぶ使い勝手が良いようです。

そのことを狙い、各拠点にはストレージヘッドとして、いくぶんかのキャッシュ容量をSSDなどで積んでおき、使われないデータはオブジェクトストレージから取り出す、そんな製品がちらほら出てきました。

こういう製品を使うことで、

  • 表向きのデータ転送速度は向上させる事が可能(オンプレ並みのパフォーマンスに近似できる)
  • 大容量のデータ保管をオブジェクトストレージ設備の可用性に頼る
  • 確かに外部にデータは書き出してしまうが、オブジェクトストレージから直接データを取り出してもアプライアンスがないと読み出しできないことでセキュリティレベルも担保できる

こうしたところなんかが、「資産を最低限にしたい」と言うニーズにマッチしているようです。

実際には、「オブジェクトストレージの設備が倒れたらどーすんの?」と言うのがあったりします。そこを思考停止して、クラウドバンザイと言うのは少々違和感はあるのですが、データの多重化を考えたときの一つの方策として、その一つにこうした製品やサービスを連携させるのはありなのかもしれません。

それにしても、クラウドとの連携の仕方の一つとして、これはかなり勉強になりました。久々のストレージネタになりましたね(笑)

外にどんなものがあるのか

こんなスライドを見つけたのでリンク張っておきます。

  • バケットをそのままファイルシステムとしてみせるソフトウェア
    • バケット上には、そのままファイルが置かれる。つまりS3コンソールからファイルが普通に見れる。
    • 基本的にオワコンもしくは不具合があるらしい・・
    • s3fs, riofs, goofys
  • ファイルシステムのデータをバケット上に保存するソフトウェア
    • バケット上には、ファイルシステムを構成するためのチャンクデータが置かれる。S3コンソールからは構成ファイルとしてしか見えない。
    • s3ql(ファイルを複数のチャンクに分割し、オブジェクトとして配置する), s3backer(ブロックをオブジェクトとして配置する)