令和になったけど、UnionFSとNFSでテスト環境用ストレージを構築する
こんにちは。インフラ担当のいせです。
みなさんはテストに使用するデータをどのように用意していますか?
ラクーンが運営するSUPER DELIVERYはECサイトなので商品の画像がたくさん並んでいます。
リリース前のテストでは、それらの画像を当てはめて確認したくなるときがあります。
本番環境では商品の画像はストレージサーバに保存されており、NFSで各アプリケーションサーバにマウントされています。
しかし、テスト中に画像の追加や削除が行われる可能性があるため、本番環境のストレージをそのままテストサーバにマウントさせるわけにはいきません。
かといってテスト用のストレージサーバを作るとなると、テスト環境の数だけサーバを用意する必要がでてきます。また、本番環境のストレージサーバから定期的に画像を転送するという手間も発生してしまいます。
今回はこのような課題をUnionFSを使用して解決したいと思います。
UnionFSとは
UnionFSはコンテナ型仮想化のDockerの文脈で聞いたことがある方も多いかと思います。
一言で言えば、UnionFSは複数のディレクトリを統合して一つのパスにマウントさせるためのツールです。
例えば、以下のような2つのディレクトリがあるとします。
- /data/readonly
- /data/writable
UnionFSを使い、/data/readonly
は読み取り専用として、/data/writable
と統合させて以下のディレクトリにマウントします。
- /data/merge
すると、/data/readonly
配下のファイルは、統合先の/data/merge
配下のファイルであるかのようにアクセスできます。
また、/data/merge
配下のファイルを編集すると、その変更は/data/writable
の方へ書き込まれます。
その後は/data/merge
を通してこのファイルにアクセスすると、更新日がより新しい/data/writable
のファイルが読みだされます。
以上のように、UnionFSを使用するとあるディレクトリは読み取り専用にして、その読み取り専用のファイルに追加・変更・削除があった場合は、その差分だけを書き込み可能な別のディレクトリに保存することができます。
今回は/data/readonly
に本番環境で使用しているストレージサーバをNFSでマウントし、テスト中に書き込みがあった場合はその差分が/data/writable
に書き込まれるようにしました。
UnionFSのインストール手順
UnionFSはkernelのパッチとして提供されているので、使用するためにはkernelを自前でビルドする必要があります。
今回は以下の環境で実施しました。
- CentOS 6.10
- UnionFS 2.5.9
- kernel(作業開始時) 2.6.32-754.10.1.el6
- kernel(ビルド対象) 2.6.33.7
kernelコンパイル時の設定にmake oldconfig
を使用したかったので、ビルドするkernelのバージョンは元のバージョンより少し高いものを選定しました。
1.ソースを準備する
UnionFSのパッチとkernlのソースをダウンロードします。
$ wget http://download.filesystems.org/unionfs/unionfs-2.x/unionfs-2.5.9_for_2.6.33.7.diff.gz
$ wget https://mirrors.edge.kernel.org/pub/linux/kernel/v2.6/linux-2.6.33.7.tar.gz
ダウンロードしたソースはそれぞれ解凍します。
$ gzip -d unionfs-2.5.9_for_2.6.33.7.diff.gz
$ tar zxf linux-2.6.33.7.tar.gz
2.kernelにパッチを適用する
patch
コマンドを使用して、UnionFSのパッチをkernelのソースに適用します。
$ cd linux-2.6.33.7
$ patch -p1 -u < ../unionfs-2.5.9_for_2.6.33.7.diff
3.kenelの設定を編集する
今回はパッケージから導入したCentOS標準のkernelコンフィグをもとに.config
を設定します。
現在インストールされているkernelの.config
は/boot
配下にあるので、それを上書きコピーします。
$ cp /boot/config-2.6.32-754.10.1.el6.x86_64 .config
以下のコマンドでkernelバージョン間で差異のある項目を設定します。
設定値を対話的に聞かれますが、何も入力せずエンターを押下するとデフォルトの値が設定されます。
今回はすべてデフォルトのままの設定としました。
$ make oldconfig
このままだとUnionFSが設定上は有効化されないので、.config
をvi
などで開き、以下の内容を追記します。
CONFIG_UNION_FS=m
CONFIG_UNION_FS_XATTR=y
CONFIG_UNION_FS_DEBUG=y
4.コンパイルおよびインストールを実行する
コンパイルとインストールを行います。最後まで無事に完了するよう祈りましょう。
$ make
$ make modules_install
$ make install
5.ブートローダーの設定を変更する
kernelをインストールすると自動で/etc/grub.conf
に設定が追記されますが、起動時の優先順位が最低になっており再起動しても新しいkernelで起動してきませんでした。今回ビルドしたkernelで起動してくるように優先順位を変更します。
優先順位は/etc/grub.conf
の以下のパラメータで設定されているので、vi
などを使用して変更します。
default=0
6.再起動・動作確認を行う
ここまでくればOSを再起動します。
$ reboot
起動後は以下のコマンドでUnionFSが追加されていることを確認します。
$ cat /proc/filesystems |grep union
nodev unionfs
UnionFSでマウントする
では、UnionFSを使用してディレクトリをマウントしてみます。
$ mount -t unionfs none /data/merge -o dirs=/data/writable=rw:/data/readonly=ro
dirオプションが少々わかりにくいですが、:
区切りでパス=属性
の形で指定します。
属性は、読み書き可能であればrw
、読み取り専用であればro
と記述します。
マウントすると、/data/merge
から/data/readonly
と/data/writable
の両方のファイルを参照できることがわかります。
$ ls -l /data/readonly/
total 0
-rw-r--r-- 1 root root 0 Mar 29 15:24 A.txt
$ ls -l /data/writable/
total 0
-rw-r--r-- 1 root root 0 Mar 29 15:24 B.txt
$ ls -l /data/merge/
total 0
-rw-r--r-- 1 root root 0 Mar 29 15:24 A.txt
-rw-r--r-- 1 root root 0 Mar 29 15:24 B.txt
/data/merge/A.txt
を編集することはできますが、
$ cat /data/merge/A.txt
raccoon
$ echo superdelivery >> /data/merge/A.txt
$ cat /data/merge/A.txt
raccoon
superdelivery
その変更内容は、/data/readonly
配下のA.txt
には書き込まれません。
$ cat /data/readonly/A.txt
raccoon
代わりに、/data/writable
配下にA.txt
が作成され、そちらが更新されました。
$ cat /data/writable/A.txt
raccoon
superdelivery
ファイルの編集だけでなく、ファイルやディレクトリの追加・削除についても同じように/data/readonly
配下のデータが書き換わることはありません。
ファイルを削除したときは、削除されたことを表す隠しファイルが/data/writable
に作成されます。
$ rm /data/merge/A.txt
$ ls -l /data/merge/
total 0
-rw-r--r-- 1 root root 0 Mar 29 15:24 B.txt
$ ls -l /data/readonly/
total 4
-rw-r--r-- 1 root root 8 Mar 29 15:30 A.txt
$ ls -la /data/writable/
total 8
drwxr-xr-x 2 root root 4096 Mar 29 15:43 .
drwxr-xr-x 5 root root 4096 Mar 29 15:19 ..
---------- 1 root root 0 Mar 29 15:43 .wh.A.txt ← 削除されたことを表す隠しファイル
-rw-r--r-- 1 root root 0 Mar 29 15:24 B.txt