LXCでAUFSを使うので、AUFSを使えるようにKernelをビルドした話。
使ったOSはCentOS 6.2(x86_64)。6.4で試せばよかった。
ソースコードを取得。
aufsのプロジェクトからgit cloneする。
aufsのプロジェクトにKernelのソースコードもある。
gitはyum install gitしておきましょう。
cd /usr/local/src yum install -y git git clone git://git.code.sf.net/p/aufs/aufs3-linux aufs-aufs3-linux cd aufs-aufs3-linux/ git checkout refs/tags/v3.13 # 必要なさそうだけど必要だった cd /usr/local/src/aufs-aufs3-linux git clone git://git.code.sf.net/p/aufs/aufs3-standalone cd aufs3-standalone git checkout origin/aufs3.13 # util cd /usr/local/src/aufs-aufs3-linux git clone git://git.code.sf.net/p/aufs/aufs-util cd aufs-util git checkout origin/aufs3.9 # aufs3.9を使うのは、aufs3.13のものが無かったので。多分大丈夫だと思う。
パッチ当て
本家Kernelを使っているときに必要な作業かもしれないので、本家からforkしたaufs-aufs3-linuxを使うなら要らないかもしれない。
cd /usr/local/src/aufs-aufs3-linux patch -N -p1 < ./aufs3-standalone/aufs3-kbuild.patch patch -N -p1 < ./aufs3-standalone/aufs3-base.patch patch -N -p1 < ./aufs3-standalone/aufs3-mmap.patch patch -N -p1 < ./aufs3-standalone/aufs3-standalone.patch
standaloneからいくつかファイルをコピーする。
# \マークは含めておかないとforceオプションが効かない。yes | cp -r でもいいけど。 \cp -rf ./aufs3-standalone/{Documentation,fs,include/uapi/linux/aufs_type.h} ./ \ cp ./aufs3-standalone/include/uapi/linux/aufs_type.h ./include/uapi/linux/aufs_type.h
旧kernelのconfig複製
現在のKernelのconfigファイルをコピー。
なくても、yumでkernel-develを入れれば入るはず。
cd /usr/local/src/aufs-aufs3-linux mv .config .config.org cp /boot/config-`uname -r` ./.config
AUFS向け設定
AUFSのために以下のあたりを有効にする
cat << __EOF__ >> .config CONFIG_AUFS_FS=m CONFIG_AUFS_BRANCH_MAX_127=y CONFIG_AUFS_SBILIST=y CONFIG_AUFS_EXPORT=y CONFIG_AUFS_INO_T_64=y CONFIG_AUFS_BR_RAMFS=y CONFIG_AUFS_BR_FUSE=y CONFIG_AUFS_POLL=y CONFIG_AUFS_BDEV_LOOP=y __EOF__
上の設定はmenuconfigで以下の設定をしたのと同じ。(数が一致しないけど、依存関係で有効になったりするものもあるからそういうもの。)
File systems ---> -*- Miscellaneous filesystems ---> <M> Aufs (Advanced multi layered unification filesystem) support (NEW) [*] NFS-exportable aufs [*] Ramfs (initramfs/rootfs) as an aufs branch [*] Fuse fs as an aufs branch
LXC向け設定
LXCを使うつもりなので、以下のページを参考にして設定をしておく。
http://lxc.teegra.net
cat << __EOF__ >> .config CONFIG_GROUP_SCHED=y CONFIG_FAIR_GROUP_SCHED=y CONFIG_RT_GROUP_SCHED=y CONFIG_CGROUP_SCHED=y CONFIG_CGROUPS=y CONFIG_CGROUP_FREEZER=y CONFIG_CGROUP_DEVICE=y CONFIG_CPUSETS=y CONFIG_PROC_PID_CPUSET=y CONFIG_CGROUP_CPUACCT=y CONFIG_RESOURCE_COUNTERS=y CONFIG_MEMCG=y CONFIG_MEMCG_SWAP=y CONFIG_MEMCG_SWAP_ENABLED=y CONFIG_MEMCG_KMEM=y CONFIG_MM_OWNER=y CONFIG_NAMESPACES=y CONFIG_UTS_NS=y CONFIG_IPC_NS=y CONFIG_USER_NS=y CONFIG_PID_NS=y CONFIG_NET_NS=y CONFIG_NET_CLS_CGROUP=y CONFIG_SECURITY_FILE_CAPABILITIES=y CONFIG_DEVPTS_MULTIPLE_INSTANCES=y __EOF__
ただ、いくつか名前が変わってた。2009年の記事だし仕方ない。
- CONFIG_CGROUP_MEM_RES_CTLR
- CONFIG_MEMCGの事
- CONFIG_CGROUP_MEM_RES_CTLR_SWAP
- CONFIG_MEMCG_SWAPの事
- CONFIG_CGROUP_NS
- ない
- CONFIG_SECURITY_FILE_CAPABILITIES
- ない。調べたら削除するパッチが2009年ぐらいに出てて、マージされたんだと思う。
この辺りで調べました。http://cateee.net/lkddb/web-lkddb
どのバージョンのkernelに存在したかわかるので、そこから変更したんかなーとか推測できる。
そんなこんなで、2.6系のkernelと3.x系のkernelは大分差分があり、いくつか設定がなかったりしたので調整する。
(特にNetwork周りの設定の定義名がIPV4,IPV6で分けて書かれており、デフォルト無効になっているなど。)
古いconfigファイルから今風のconfigファイルに作り替える。
# 古いconfigファイルを新しいconfigファイルに作り直す # 設定値は対話で入力すると日が暮れるので、デフォルト値を使うようにする。(そのためのolddefconfig) make olddefconfig # 少しグラフィカルな設定変更を行う yum install ncurses-devel -y # 必要なモジュール make menuconfig
以下は元のconfigとのdiff取ったりして、なるべく元のKernelの設定になるようにしてみたつもり。
相変わらず設定の意味はよくわかってない。なので自分専用って事で。
cat << __EOF__ >> .config # ネットワーク周りだけならここらへん CONFIG_NET_IPGRE_DEMUX=m CONFIG_NF_NAT=m CONFIG_NF_NAT_NEEDED=y CONFIG_NF_NAT_PROTO_DCCP=m CONFIG_NF_NAT_PROTO_UDPLITE=m CONFIG_NF_NAT_PROTO_SCTP=m CONFIG_NF_NAT_AMANDA=m CONFIG_NF_NAT_FTP=m CONFIG_NF_NAT_IRC=m CONFIG_NF_NAT_SIP=m CONFIG_NF_NAT_TFTP=m CONFIG_NF_TABLES=m CONFIG_NFT_EXTHDR=m CONFIG_NFT_META=m CONFIG_NFT_CT=m CONFIG_NFT_RBTREE=m CONFIG_NFT_HASH=m CONFIG_NFT_COUNTER=m CONFIG_NFT_LOG=m CONFIG_NFT_LIMIT=m CONFIG_NFT_NAT=m CONFIG_NFT_COMPAT=m CONFIG_NETFILTER_XT_TARGET_LOG=m CONFIG_NETFILTER_XT_TARGET_NETMAP=m CONFIG_NETFILTER_XT_TARGET_REDIRECT=m CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=m CONFIG_NF_TABLES_IPV4=m CONFIG_NFT_REJECT_IPV4=m CONFIG_NFT_CHAIN_ROUTE_IPV4=m CONFIG_NFT_CHAIN_NAT_IPV4=m CONFIG_NF_TABLES_ARP=m CONFIG_NF_NAT_IPV4=m CONFIG_IP_NF_TARGET_MASQUERADE=m CONFIG_IP_NF_TARGET_NETMAP=m CONFIG_IP_NF_TARGET_REDIRECT=m CONFIG_NF_NAT_SNMP_BASIC=m CONFIG_NF_NAT_PROTO_GRE=m CONFIG_NF_NAT_PPTP=m CONFIG_NF_NAT_H323=m CONFIG_NF_TABLES_IPV6=m CONFIG_NFT_CHAIN_ROUTE_IPV6=m CONFIG_NFT_CHAIN_NAT_IPV6=m CONFIG_NF_NAT_IPV6=m CONFIG_IP6_NF_TARGET_MASQUERADE=m CONFIG_IP6_NF_TARGET_NPT=m CONFIG_NF_TABLES_BRIDGE=m # その他よくわからんちん CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_EXPERT=y CONFIG_UNINLINE_SPIN_UNLOCK=y CONFIG_HYPERVISOR_GUEST=y CONFIG_PARAVIRT=y CONFIG_PARAVIRT_SPINLOCKS=y CONFIG_XEN=y CONFIG_XEN_DOM0=y CONFIG_XEN_PRIVILEGED_GUEST=y CONFIG_XEN_PVHVM=y CONFIG_XEN_MAX_DOMAIN_MEMORY=500 CONFIG_XEN_SAVE_RESTORE=y CONFIG_KVM_GUEST=y CONFIG_PARAVIRT_CLOCK=y CONFIG_PCI_XEN=y CONFIG_XEN_PCIDEV_FRONTEND=y CONFIG_OPENVSWITCH_GRE=y CONFIG_SYS_HYPERVISOR=y CONFIG_XEN_BLKDEV_FRONTEND=y CONFIG_HYPERV_STORAGE=m CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_INPUT_XEN_KBDDEV_FRONTEND=y CONFIG_HYPERV_KEYBOARD=m CONFIG_HVC_IRQ=y CONFIG_HVC_XEN=y CONFIG_HVC_XEN_FRONTEND=y CONFIG_FB_SYS_FILLRECT=y CONFIG_FB_SYS_COPYAREA=y CONFIG_FB_SYS_IMAGEBLIT=y CONFIG_FB_SYS_FOPS=y CONFIG_FB_DEFERRED_IO=y CONFIG_HYPERV=m CONFIG_HYPERV_UTILS=m CONFIG_HYPERV_BALLOON=m CONFIG_XEN_FBDEV_FRONTEND=y CONFIG_XEN_BALLOON=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_DEV_EVTCHN=y CONFIG_XEN_BACKEND=y CONFIG_XENFS=y CONFIG_XEN_COMPAT_XENFS=y CONFIG_XEN_SYS_HYPERVISOR=y CONFIG_XEN_XENBUS_FRONTEND=y CONFIG_XEN_GNTDEV=m CONFIG_XEN_GRANT_DEV_ALLOC=m CONFIG_SWIOTLB_XEN=y CONFIG_XEN_PCIDEV_BACKEND=m CONFIG_XEN_PRIVCMD=y CONFIG_XEN_ACPI_PROCESSOR=m CONFIG_XEN_HAVE_PVMMU=y CONFIG_NFS_FS=y CONFIG_NFS_V2=y CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_NFS_V4_2=y CONFIG_PNFS_FILE_LAYOUT=y CONFIG_NFS_V4_SECURITY_LABEL=y CONFIG_LOCKD=y CONFIG_NFS_ACL_SUPPORT=y CONFIG_SUNRPC=y CONFIG_SUNRPC_GSS=y __EOF__
一応これでlxc-checkconfigが全部緑になったので良いはず。
Kernelのビルドとインストール
# 必要なライブラリ yum install bc # ビルド make clean make -j5 bzImage && make -j5 modules # -jの値は並列数になる。CPUの数+1ぐらいにしている。 # インストール make modules_install && make install # boot時に新しく作ったkernelを読ませるようにする(installすると0番目に入るので、0にする。) sed -i.bak 's/default=1/default=0/' /boot/grub/grub.conf # Reboooooooooooooooooot reboot
AUFS-utilのビルドとインストール
# ヘッダを/usr/include/linuxへコピー(READMEには書いてあったけど読み間違いしてる気がするので、多分要らない) # cd /usr/local/src/aufs-aufs3-linux # cp -p ./aufs_type.h /usr/include/linux/ cd /usr/local/src/aufs-aufs3-linux/aufs-util yum install glibc-static make CPPFLAGS="-I /usr/local/src/aufs-aufs3-linux/usr/include -I /usr/local/src/aufs-aufs3-linux/aufs3-standalone/include" make install
AUFSを使う
まず作業ディレクトリを用意する。普通のファイルシステムであればどこでも。
mkdir /tmp/aufs-example
ブランチ用のディレクトリを用意する
read-only はaufsから見て読み取り専用ディレクトリ。ベースになる部分となる。
work はaufsから見て作業用ディレクトリ。aufsによって編集されたファイルがここに置かれたり削除されたりする。
work はあくまでaufsの作業用ディレクトリで、ユーザがここを操作するといったことは無い。
cd /tmp/aufs-example mkdir read-only work
read-onlyにファイルをいくつか作る
cd /tmp/aufs-example/read-only echo "read-only-1" > ./file1.txt echo "read-only-2" > ./file2.txt ls -l
実際にAUFSでマウントする
マウント先となるrootfsを作る。
cd /tmp/aufs-example mkdir rootfs
マウントする。brオプションで用意したディレクトリを並べる。左にあるものが一番上にくるイメージ。
# SELinuxの都合上、contextオプションも指定する。 # 何も指定しないとtypeがunlabeled_tになってしまう。(これだと書き込めない) # ただ設定しているtmp_tはたぶん適切ではない。が、まずは書き込みたいのでとりあえず適当に設定。 mount -t aufs -o context=unconfined_u:object_r:tmp_t:s0 -o br=/tmp/aufs-example/branched:/tmp/aufs-example/read-only=ro aufs /tmp/aufs-example/rootfs
手動でマウントするのではなく、勝手にマウントさせたいときは/etc/fstabに書いてmount -a。
echo 'aufs /tmp/aufs-example/rootfs aufs br=/tmp/aufs-example/work:/tmp/aufs-example/read-only=ro,context=unconfined_u:object_r:tmp_t:s0 0 0' >> /etc/fstab mount -a
マウントした内容をみる。
workには何もしていないので、read-onlyと同じ内容が見える。
cd /tmp/aufs-example/rootfs ls -l
マウント先にファイルを新規追加してみたり、file2.txtを削除してみる
cd /tmp/aufs-example/rootfs echo "rootfs-3" > file3.txt rm -f file2.txt
確認。
file3.txtが追加され、file2.txtが削除されている。ふつーにファイル操作できている。
ls -l
read-onlyの中身を確認してみる。
read-onlyは何も変わっていないで、file1.txtとfile2.txtが残ったまま。
cd /tmp/aufs-example/read-only ls -l
続いてworkの中身も確認。
こちらにはほぼrootfsにある同じ情報であるが、隠しファイルが存在する。
削除を判定するために".wh."プレフィクスをつけて管理している模様?
file3.txtは追加した内容そのものだった。
cd /tmp/aufs-example/work ls -al
いたずらしてみる。削除情報らしきファイルを削除する
cd /tmp/aufs-example/work rm -f .wh.file2.txt ls -al
確認。file2.txtが出てくる。やっぱりな!
cd /tmp/aufs-example/rootfs ls -l
ところで、rootfsにfile2.txtと.wh.file2.txtを作ったらどうなるんだろうなー、file2.txtが削除されたことになるんじゃないかなーと思いやってみようとしたら
cd /tmp/aufs-example/rootfs echo "hogehoge" > .wh.file2.txt # -bash: .wh.file2.txt: 許可されていない操作です
ダメでした。
乾燥
AUFS自体は簡単に扱えて良い。
これだけだとあんまりありがたみが実感ないけど、LXCで組み合わせて使うことを考えると、複数のファイルの複製が不要になるので、コンテナを作る時間も減るし、ファイルサイズも比較的小さく済むのが良い。
現状はlxc-createすると、400MB近いコピーが走るので、作って壊す・・・というにはちょっと重い。(十分早いけど)
あとSELinux辛い。
マウントしたらunlabeled_tになってファイル作れないってなんだよ!ほかの人はなんで同じ問題にひっかからないんだよ!!
SELinuxを無効にするのが当たり前なのか、本当は問題もないけど自分が間抜けな設定をして起きてるのか、よくわからん。
これを切り分けるにはどうアプローチしていけばいいんだろうなー。
動くからそれでいいやっていう考え方はしたくないし。・・・上の手順では結構やっちゃってるけど。
勉強しないとだめすなぁ。