一ヶ月ぶりになってしまいました。もりやまです。
今回は Amazon EC2 で使う AMI の作り方です。
以前から EC2 上へのアプリのインストールや設定をしたことはあったんですが、今回始めて自分でインスタンスを作るところからやる機会ができたので、せっかくなので自分で AMI を作るところからやってみました。
基本的には公式のドキュメント通りですが、いくつかハマった点もあったので、最初から説明していきます。
インストールする OS は CentOS 5.3 ですが、yum が使えれば他のディストリビューションでも同じ手順でできると思います。
作業はすべて root で行います。
事前に ec2-ami-tools のインストールと、AMI を公開するアカウントの X.509 証明書と秘密鍵を用意しておいてください。アクセスキーとシークレットアクセスキーも使用します。
イメージ用の loopback ファイルを作成
# dd if=/dev/zero of=centos-5.3.img bs=1G count=10
このファイルがそのままインスタンスの /dev/sda1 になります。
ec2-bundle-image でアップロード用のファイルを作成する時に、イメージの空き領域はほとんど圧縮されてしまうので、必要な領域がそれほど多くなくても大きめに作っておいて問題ありません。
ただし、ami-bundle-image の最大サイズが 10GB なので、それ以上のサイズで作ってしまってもアップロードできません。
(ami-bundle-image のソースを確認したら、MAX_SIZE = 10 * 1024 * 1024 * 1024 となっている箇所があったので、そこ書き換えればもっと大きなイメージは作れそうですが、アップロードして起動できるかまではわかりません)
それと、イメージの作成をやり直す際には、この loopback ファイルの作成からやり直した方がいいようです。一度使ったファイルを mke2fs でフォーマットし直しただけだと、ami-bundle-image であまり圧縮できませんでした(最小で 330MB くらいまで圧縮できていたものが、同じ手順でインストールしているにもかかわらず 1.5GB くらいにしかならない)
loopback ファイルにファイルシステムを作成してマウント
# mke2fs -F -j centos-5.3.img # mount -o loop centos-5.3.img ami-root # cd ami-root
ここでは ext3 を使用していますが、他のファイルシステム(Reiser4 / XFS / JFS 等)で作ったものが起動できるかどうかはわかりません。EBS は ext3 以外でも使えるようなので、kernel としては他のファイルシステムもサポートしているようです。
インストールに必要なファイルを作成
# mkdir etc proc dev # MAKEDEV -d dev -x console # MAKEDEV -d dev -x null # MAKEDEV -d dev -x zero # cat > etc/fstab << EOS /dev/sda1 / ext3 defaults 1 1 none /dev/pts devpts gid=5,mode=620 0 0 none /dev/shm tmpfs defaults 0 0 none /proc proc defaults 0 0 none /sys sysfs defaults 0 0 EOS # mount -t proc none proc
OS をインストール
インストール用の yum.conf を用意します。
[main] cachedir=/var/cache/yum keepcache=0 debuglevel=2 logfile=/var/log/yum.log distroverpkg=redhat-release tolerant=1 exactarch=1 obsoletes=1 gpgcheck=0 # Note: yum-RHN-plugin doesn't honor this. metadata_expire=1h installonly_limit = 5 [base] name=CentOS-5 - Base mirrorlist=http://mirrorlist.centos.org/?release=5&arch=i386&repo=os [updates] name=CentOS-5 - Updates mirrorlist=http://mirrorlist.centos.org/?release=5&arch=i386&repo=updates
このファイルはイメージに含める必要はないので、イメージの外に yum-cenos-i386-xen.conf として置いておきます。x86_64 の場合は i386 のところを置き換えてください。
# yum -c ../yum-centos-i386-xen.conf --installroot=$PWD -y groupinstall Core # chroot . pwconv # chroot . grpconv # chroot . chkconfig --add sshd # chroot . chkconfig --level 345 sshd on # yum -c ../yum-centos-i386-xen.conf --installroot=$PWD -y install \ ruby ruby-libs ruby-irb ruby-rdoc ruby-ri ruby-devel \ curl libidn wget which rsync
最低限のファイルのみインストールするため Core グループを選択していますが、インスタンスの起動に必要なファイルが含まれていないので、ruby や curl 等を追加でインストールします。
pwconv と grpconv でシャドウパスワードを使う設定と、ssh の自動起動を設定します。
何度もやりなおしていてたまに遭遇したんですが、i386 版をインストールするときだけ、pam パッケージの postscript がエラーになる場合があって、それに気付かずにインスタンス起動してみたら ssh ログインできない、ということがありました。
作業していたホスト OS が x86_64 版だからなのかもしれませんが、インストールログをよく確認して、エラーが出ていたら手動で postscript と同じ内容を実行するようにしてみてください。
不要なパッケージの削除
# rpm -e --root $PWD \ grub redhat-logos audit-libs-python checkpolicy dhcpv6-client \ kudzu libselinux-utils libsemanage policycoreutils selinux-policy \ selinux-policy-targeted setools setserial tcl udftools
ここは必須ではないんですが、個人的には不要なパッケージは極力削りたいので、これだけのパッケージを削っています。
上記に加えて、i386 の場合は
# rpm -e --root $PWD gnu-efi nash mkinitrd
を、x86_64 の場合は
# rpm -e --root $PWD nash mkinitrd.i386 mkinitrd.x86_64
を削っています。
ネットワークの設定
# cat > etc/sysconfig/network-scripts/ifcfg-eth0 << EOS DEVICE=eth0 BOOTPROTO=dhcp ONBOOT=yes TYPE=Ethernet USERCTL=yes PEERDNS=yes IPV6INIT=no EOS # cat > etc/sysconfig/network << EOS NETWORKING=yes EOS # cat > etc/hosts << EOS 127.0.0.1 localhost.localdomain localhost EOS
公式のマニュアル通りですね。/etc/hosts だけ追加してあります。
fstab に sda1 以外のパーティションの追加
アーキテクチャによって設定が変わります。
i386 の場合は
# cat >> etc/fstab << EOS /dev/sda2 /mnt ext3 defaults 0 0 /dev/sda3 swap swap defaults 0 0 EOS
x86_64 の場合は
# cat >> etc/fstab << EOS /dev/sdb /mnt ext3 defaults 0 0 EOS
になります。x86_64 の場合はインスタンスが xlarge の場合には sdc 〜 sde も使えるようですが、ここでは最小限にしておきます。
詳細はこちらの Instance Storage の項目を参照してください。
rc.local に EC2 用のコードを追加
# cat >> etc/rc.local << EOS # Update the Amazon EC2 AMI creation tools echo " + Updating ec2-ami-tools" wget http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm && \ rpm -Uvh ec2-ami-tools.noarch.rpm && \ echo " + Updated ec2-ami-tools" rm -f ec2-ami-tools.noarch.rpm if [ -f "/root/firstrun" ] ; then dd if=/dev/urandom count=50|md5sum|passwd --stdin root rm -f /root/firstrun else echo "* Firstrun *" && touch /root/firstrun fi if [ ! -d /root/.ssh ] ; then mkdir -p /root/.ssh chmod 700 /root/.ssh fi # Fetch public key using HTTP curl http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /tmp/my-key if [ $? -eq 0 ] ; then if [ -z "$(grep "$(cat /tmp/my-key)" /root/.ssh/authorized_keys)" ]; then cat /tmp/my-key >> /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys fi rm /tmp/my-key fi EOS
基本的にはマニュアル通りですが、アップデートが済んだ ec2-ami-tools の rpm を削除するのと、ダウンロードした ssh の公開鍵がすでに /root/.ssh/authorized_keys に存在した場合にスキップする処理を追加しています。
sshd の設定変更
# perl -p -i -e 's,^#PermitRootLogin yes,PermitRootLogin without-password,' etc/ssh/sshd_config # perl -p -i -e 's,^#UseDNS yes,UseDNS no,' etc/ssh/sshd_config # perl -p -i -e 's,^PasswordAuthentication yes,PasswordAuthentication no,' etc/ssh/sshd_config # perl -p -i -e 's,^UsePAM yes,UsePAM no,' etc/ssh/sshd_config
マニュアルで推奨されている項目に加えて、パスワード認証と PAM を無効にしています。
selinux の設定変更
# perl -p -i -e 's,^SELINUX=enforcing,SELINUX=disabled,' etc/sysconfig/selinux # perl -p -i -e 's,^SELINUX=enforcing,SELINUX=disabled,' etc/selinux/config
「不要なファイルの削除」で selinux 関連を削除してしまっているので、基本的には不要ですが、残す場合は disabled にしておかないと ssh でログインできませんでした。
きちんとポリシーを設定すれば enforcing でもログインできるのかもしれませんが、バッサリ切ってしまいます。
カーネルモジュールをインストール
使用する AKI に対応したモジュールをインストールします。ここでは ec2-public-images/ec2-vmlinuz-2.6.21.7-2.fc8xen.i386.manifest.xml を使用するものとします。
上記 AKI に対応したモジュールを、http://s3.amazonaws.com/ec2-downloads/ec2-modules-2.6.21-2952.fc8xen-i686.tgz からダウンロードして、イメージの外に配置してあるものとします。
# tar xfz ../ec2-modules-2.6.21-2952.fc8xen-i686.tgz # cd lib/modules # ln -s 2.6.21-2952.fc8xen 2.6.21.7-2.fc8xen # cd ../../ # chroot . depmod -a 2.6.21.7-2.fc8xen
ldconfig を実行
# chroot . ldconfig
これをしておかないと、"4gb seg fixup ... " というメッセージが /var/log/messages に吐き出され続けてしまうようです。
不要なファイルを削除してイメージをアンマウント
# yum -c ../yum-centos-i386-xen.conf --installroot=$PWD -y clean all # cd .. # umount ami-root/proc # umount -d ami-root
yum のキャッシュを削除します。
バンドルイメージを作成して S3 にアップロード
公開用の AWS のアカウントのアクセスキー / シークレットアクセスキーと、秘密鍵 / X.509証明書が必要です。
AWS のYour Account > Access Identifiers から参照、ダウンロードしておいてください。
AWS_UID は、上記ページの右上に出ている Account Number からハイフンを抜いたものです。
# rm -f ami-bundle/* # ec2-bundle-image -i centos-5.3.img -k pk-HOGEHOGE.pem -c cert-HOGEHOGE.pem -u AWS_UID -d ./ami-bundle -r i386 --kernel aki-a71cf9ce --ramdisk ari-a51cf9cc # ec2-upload-bundle -b S3_BUCKET_NAME -m ami-bundle/centos-5.3.img.manifest.xml -a ACCESS_KEY -s SECRET_ACCESS_KEY
EC2 にイメージを登録
# ec2-register -K pk-HOGEHOGE.pem -C cert-HOGEHOGE.pem S3_BUCKET_NAME/centos-5.3.img.manifest.xml
これでインスタンスとして使用する準備ができました。
きちんと動くイメージを作るのに 1 週間近くかかってしまいました。S3 へのアップロードに時間がかかるのがネックですね。
現在はこのイメージに puppet を追加して、インスタンスを追加した際に初期設定を puppet を使ってできるように試行錯誤しています。こちらもある程度まとまったらブログに載せようと思います。
このエントリーに対するコメント
-
はじめまして。
ポストを見て本当に役に立ちました。
しかし、ひとつ質問がありますが。。10GB以上のイメージの生成はどうやってするのでしょうか。
他のインスタンスを持ち、EC2を作ると/mntのところが100GBもあったりしますが。。
Fdiskでcheckするとマウントされてますね。^^;;どうかお願いします。
2011年05月25日, 10:01 PM
-
はじめまして。コメントありがとうございます。
イメージのサイズについてですが、10GB が上限のようです。
/mnt はイメージとは別に、インスタンスタイプ毎に割り当てサイズが決まっています。こちらのドキュメントをご参照ください。よろしくお願いいたします。
2011年05月27日, 10:24 AM
- トラックバック
-
- [Amazon EC2] AMI をゼロから作る CentOS 6.2 / S3-Backed 版 | KRAY Inc2012/01/24, 1:03 PM
[…] 社サイトをリニューアルして、サイトのアクセス数が大分増えるよりも前に書いた EC2 の AMI を作る記事を、CentOS 6.2 ベースでやってみようと思います。 少し長いですが、お付き合いくだ […]
「いいね!」で応援よろしくお願いします!