Posted on Fri Mar 09 20:01:27 +0900 2012 by nabeken
皆さんAMIの拾い食いはしていませんか?野良AMIにはさまざまなリスクがあります。信頼できる人/組織が作成したAMI以外は基本的に自作したほうがよいと思います。今回はAmazon Linux 2011.09上でCentOS 5.6のリリース版AMIを作成する手順を記します。
Amazon Linux はEC2用AMIとしてAmazonがメンテナンスしているディストリビューションです。 最新版はRHEL6互換 + ec2系のツール、cloud-initがセットアップ済みです。
どうしてもCentOSでなければならない理由がなければ、そのままAmazon Linuxを使うのが楽だと思います。 今回はどの環境でも動くことが要件なので、CentOSをベースにする必要がありました。
そんなわけで、Amazon Linux上でCentOS 5、今回は事情により特にCentOS 5.6 (x86_64)のリリース版最小構成でAMIを作成します。 このAMIは今後のカスタマイズの基本AMIとするため、swap領域、cloud-init的なものは一切セットアップしません。 root deviceはinstance store-backedで、ephemeral領域とsshの公開鍵のセットアップのみを施します。
使用するAmazon Linuxは Basic 64-bit Amazon Linux AMI 2011.09 (AMI Id: ami-0a44f00b) です。
節約のため、作業用インスタンスはスポットインスタンスで起動させます。 また、AMI用のディスクイメージ作成作業用の領域としてEBSはコストがかかるため、ephemeral領域(instance store)にディスクイメージを展開して作業します。
スポットインスタンスにephemeral領域を付けて起動する場合、Management Consoleからはできないため、コマンドから入札します。 コマンドの詳細はヘルプを見てもらうとして、ここで大事なのは -b /dev/sdb=ephemeral0 の部分だけです。
$ ec2-request-spot-instances ami-0a44f00b -b /dev/sdb=ephemeral0 --region ap-northeast-1 \ -t m1.large -k your-keypair --price your-price --instance-count 1
入札が成功するとインスタンスが起動するはずです。 起動したインスタンスにec2-userでログインします。
ephemeral領域にディスクイメージを作成し、loopbackマウントします。 マウント後、いくつか下ごしらえをします。
$ cd /media/ephemeral0 $ sudo mkdir ami-{bundle,root} $ sudo dd if=/dev/zero of=CentOS-5.6-x86_64.img bs=1M count=8000 $ sudo /sbin/mkfs.ext4 -F CentOS-5.6-x86_64.img $ sudo mount -o loop CentOS-5.6-x86_64.img /media/ephemeral0/ami-root $ sudo mkdir /media/ephemeral0/ami-root/{etc,proc,dev} $ sudo mount -t proc none /media/ephemeral0/ami-root/proc $ for i in console null zero; do sudo /sbin/MAKEDEV -d /media/ephemeral0/ami-root/dev -x $i; done
AMI用のfstabは /etc/fstab をコピーし、一部修正します。
$ sudo cp /etc/fstab ami-root/etc/ $ sudo vi ami-root/etc/fstab ephemeral0の部分は必要ないので削除します。
ディスクイメージの下ごしらえは完了です。
今回は基本AMIとして作るため、CentOS 5.6 (x86_64)のリリース版でyumを実行します。作成時点ではアップデートは一切適用しません。 DVDのISOイメージをすでに持っている場合はその中身をどこか適当なWebサーバへ展開します。
持っていない場合はvault.centos.org (アーカイブ)から調達する必要があります。 今回の作成にあたり、私が5.6のi386, x86_64をrsyncしたものを以下で公開しています。 このリポジトリは予告なく公開を終了する場合があります。 (ちなみに、isosをexcludeしても26GBほどあります。updatesとi386もexcludeすればDVD1枚分になりそう…)
リポジトリの準備ができたら、次は yum.conf を用意します。updates-releasedリポジトリは無効化しています。 baseurlの部分は適宜読み替えてください。
$ cat /media/ephemeral0/yum.conf [main] cachedir=/var/cache/yum debuglevel=2 logfile=/var/log/yum.log exclude=*-debuginfo gpgcheck=0 obsoletes=1 reposdir=/dev/null [base] name=CentOS 5.6 - Base baseurl=https://projects.tsuntsun.net/~nabeken/CentOS/5.6/os/$basearch/ enabled=1 [updates-released] name=CentOS 5.6 - Released Updates baseurl=https://projects.tsuntsun.net/~nabeken/CentOS/5.6/updates/$basearch/ enabled=0
groupinstallしたくなりますが、まずは yum コマンドだけ先にインストールします。
実はAmazon Linuxの yum およびrpm実行環境はCentOS 5系からみるとrpmデータベースで使っているデータベース(Berkeley DB)の形式が新しいため、 このままでは作成したAMIで起動しても自分自身の yum コマンド(rpmコマンド)が使えなくなります。そこで、
の手順を踏みます。
$ sudo yum -c /media/ephemeral0/yum.conf --installroot=/media/ephemeral0/ami-root install -y yum
chrootした後に必要となるファイルを予めコピーしておきます。
$ sudo cp /etc/resolv.conf /media/ephemeral0/ami-root/etc $ sudo cp /media/ephemeral0/yum.conf /media/ephemeral0/ami-root/ (このファイルは最後に削除します)
chrootします。
$ sudo chroot /media/ephemeral0/ami-root /bin/bash # source /etc/profile # yum (ここでyumがデータベースのバージョンが新しすぎると文句をいう) Loaded plugins: fastestmirror rpmdb: /var/lib/rpm/Packages: unsupported hash version: 9 error: cannot open Packages index using db3 - Invalid argument (22) error: cannot open Packages database in /var/lib/rpm Traceback (most recent call last): File "/usr/bin/yum", line 29, in ? yummain.user_main(sys.argv[1:], exit_code=True) File "/usr/share/yum-cli/yummain.py", line 309, in user_main errcode = main(args) File "/usr/share/yum-cli/yummain.py", line 157, in main base.getOptionsConfig(args) File "/usr/share/yum-cli/cli.py", line 187, in getOptionsConfig self.conf File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 665, in <lambda> conf = property(fget=lambda self: self._getConfig(), File "/usr/lib/python2.4/site-packages/yum/__init__.py", line 240, in _getConfig self._conf = config.readMainConfig(startupconf) File "/usr/lib/python2.4/site-packages/yum/config.py", line 804, in readMainConfig yumvars['releasever'] = _getsysver(startupconf.installroot, startupconf.distroverpkg) File "/usr/lib/python2.4/site-packages/yum/config.py", line 877, in _getsysver idx = ts.dbMatch('provides', distroverpkg) TypeError: rpmdb open failed # rm -f /var/lib/rpm/* # yum -c /yum.conf install -y yum (もう1度すべてインストールしなおすことでrpmデータベースも再作成) # ls -l /var/lib/rpm # yum -c /yum.conf groupinstall -y Core Base
CentOS 5.6リリース版環境の構築が完了しました。
本来インストーラーで行なわれる処理をchroot内で手動にて行ないます。
ネットワーク設定
# cat /etc/sysconfig/network-scripts/ifcfg-eth0 DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes TYPE=Ethernet USERCTL=yes PEERDNS=yes IPV6INIT=no # cat /etc/sysconfig/network NETWORKING=yes # echo '127.0.0.1 localhost.localdomain localhost' > /etc/hosts
sshdの設定
パスワード認証を無効化し、公開鍵認証のみにします。
# vi /etc/ssh/sshd_config PasswordAuthentication no PermitRootLogin without-password UsePAM no
/etc/shadowの生成
/etc/shadowが存在していない場合、 passwd コマンドが使用できません。手動で pwconv コマンド を実行し、生成します。
# pwconv
selinuxの無効化
disabledにします。
# vi /etc/sysconfig/selinux SELINUX=disabled
起動サービスの設定
必要のないサービスを落とします。
# chkconfig --list | grep -E '[2345]:on' # for i in bluetooth firstboot gpm hidd ip6tables iscsi iscsid \ kudzu nfslock pcscd portmap rpcgssd rpcidmapd smartd yum-updatesd; do \ chkconfig --level 2345 $i off; \ done
root用のssh公開鍵の取得処理
インスタンスの初回起動時にmetadataからkeypairを取得し、rootのssh公開鍵として設定する必要があります。 RHEL6系であれば、Amazon Linuxのcloud-initパッケージを流用できそうですが、今回は [Amazon EC2] AMI をゼロから作る CentOS 6.2 / S3-Backed 版 を参考に /etc/rc.local へ取得処理を追加します。
Xen domU用カーネルのインストール
CentOS 5系では標準カーネルのままだとXenのdomUとしては起動しないため、別途カーネルをインストールします。
# yum install -y kernel-xen
Xen domU用にinitrdを再生成
domU用に必要なモジュールを組み込んで再生成します。
# ls -l /boot (el5xenなカーネルを探します。) # mkinitrd --with xenblk --with xennet /boot/initrd-2.6.18-274.18.1.el5xen_ec2.img 2.6.18-274.18.1.el5xen # ls -l /boot/initrd-2.6.18-274.18.1.el5xen_ec2.img (できあがっているのを確認する)
grubの設定
後述しますが、このAMIはpvgrub経由で起動させるため、grubの設定を用意します。 今回はinstance store-backedなのでkernelに渡すrootは sda1 を指定します。
# cat /boot/grub/menu.lst default=0 timeout=0 hiddenmenu title CentOS 5.6 (x86_64) root (hd0) kernel /boot/vmlinuz-2.6.18-274.18.1.el5xen root=/dev/sda1 initrd /boot/initrd-2.6.18-274.18.1.el5xen_ec2.img
一時ファイルの削除
最後にセットアップに使ったファイルを削除します。chrootから抜けて作業します。
# exit (chrootから抜ける) $ sudo rm /media/ephemeral0/ami-root/{yum.conf,root/.bash_history}
また、 yum コマンドを再インストールした際のrpmnewファイルを削除します。 (パッケージを入れ直した時、既存ファイルを上書きせずに新しいファイルをファイル名.rpmnewとして保存する仕組みがあります。 今回は初期状態のため、rpmnewファイルは削除しても問題ありません。)
$ sudo find /media/ephemeral0/ami-root -type f -name *\.rpmnew (対象ファイルが問題なさそうなことを確認) $ sudo find /media/ephemeral0/ami-root -type f -name *\.rpmnew | sudo xargs rm
作成したディスクイメージをS3へアップロードする下準備をします。まずはイメージをunmountします。
$ cd /media/ephemeral0 $ sudo umount /media/ephemeral0/ami-root/proc $ sudo umount /media/ephemeral0/ami-root $ sudo chown ec2-user:ec2-user -R . (ec2-*コマンドをec2-userで使いため)
ec2コマンドを作業用インスタンスで行なうための下準備は済んでいるものとします。 (環境変数の設定、証明書のコピーなど。リージョンは環境変数で指定していると仮定。)
下準備ができたら ec2-bundle-image コマンドを実行します。
$ ec2-bundle-image --cert ${EC2_CERT} --privatekey ${EC2_PRIVATE_KEY} --user 1111-2222-3333 \ -i CentOS-5.6-x86_64.img -r x86_64 -d /media/ephemeral0/ami-bundle/ (--userの引数に与えるIDはアカウントアクティビティから確認可能)
内部ではディスクイメージをtarしてgzipしてAESで暗号化しているようです。
bundleイメージ保存用のS3のバケットはすでに作成済みとします。ここでは nabeken-amis とします。
$ ec2-upload-bundle --access-key ${EC2_ACCESS_KEY} --secret-key ${EC2_SECRET_KEY} \ --bucket nabeken-amis/CentOS/5.6/ -m ./ami-bundle/CentOS-5.6-x86_64.img.manifest.xml (外部からS3へアップロードするよりも、EC2、S3間は非常に早い)
今回作成するAMIはinstance store-backedなAMIです。
instance store-backed (S3-backed)
インスタンスストレージ(ephemeral領域と同じ種別)上にディスクイメージを展開したものをroot deviceにする。 root deviceになる場合、domUからはsdaとしては見えず、パーティション1(sda 1)として見える。
EBS-backed
EBSは通常のディスク(sdaなど)として見せることも可能。実際には、各インスタンス種別 (m1.{small,large}, t1.microなど)にかかわらず使えるようにする場合は instance store-backedと合せて sda1 を / と構成することをオススメします。
ただし、LVMルートやRAIDXルートをする場合は /boot を分ける必要があるため、 パーティションを切る必要があるでしょう。
pvgrubを使う場合、この違いが重要になります。
Enabling Your Own Linux Kernels
Several PV-GRUB AKIs are available depending on the type and location of your instance. There are AKIs for 32-bit and 64-bit architecture types, with each having one AKI for partitioned images and another AKI for partitionless images. You must choose an AKI with "hd0" in the name if you want a raw or unpartitioned disk image (most images). Choose an AKI with "hd00" in the name if you want an image that has a partition table.
インスタンスのロケーション、種類に応じて数種類の PV-GRUB AKI (Amazon Kernel Image)が利用可能です。 32bit, 64bitにそれぞれパーティションテーブルのあるディスクイメージとパーティションテーブルのないディスクイメージに対して1つのAKIがあります。 rawパーティションあるいはパーティションテーブルのないディスクイメージで使いたい場合は "hd0" のAKIを選ばなければなりません。 パーティションテーブルのあるディスクイメージで使いたい場合は "hd00" のAKIを選択してください。
今回は東京リージョン(northeast-1)でinstance store-backedなx86_64のAMIを作るので、 aki-ee5df7ef ec2-public-images-ap-northeast-1/pv-grub-hd0_1.02-x86_64.gz.manifest.xml を選択します。
$ ec2-register --cert ${EC2_CERT} --private-key ${EC2_PRIVATE_KEY} nabeken-amis/CentOS/5.6/CentOS-5.6-x86_64.img.manifest.xml \ -a x86_64 -n 'CentOS 5.6 (x86_64) instance store/ephemeral0-3' -d 'CentOS 5.6 (x86_64) instance store w/ephemeral[0-3]' \ -b '/dev/sdc=ephemeral0' -b '/dev/sdd=ephemeral1' -b '/dev/sde=ephemeral2' -b '/dev/sdf=ephemeral3' \ --kernel aki-ee5df7ef --root-device-name /dev/sda1 IMAGE ami-XXXXXXXX
スポットインスタンスで起動してみます。今回はManagement Consoleから作成したAMIで起動します。 起動したら root でログインできるはずです。
$ ssh -l root ec2-XXX-XXX-XXX-XXX.ap-northeast-1.compute.amazonaws.com # uname -a Linux ip-XXX-XXX-XXX-XXX 2.6.18-274.18.1.el5xen #1 SMP Thu Feb 9 13:27:02 EST 2012 x86_64 x86_64 x86_64 GNU/Linux # cat /etc/redhat-release CentOS release 5.6 (Final)
ec2-get-console-output でコンソールのログを確認できます。 このログはリアルタイムではなく、2分程度のバッチ更新になっているようです。
$ ec2-get-console-output i-XXXXXXX
今後はこのAMIをベースに作り込みを行い、EBS-backedなAMIにしていきます。