[Amazon EC2] AMI をゼロから作る CentOS 6.2 / S3-Backed 版 このエントリをはてなブックマークに登録

2012年01月24日

もりもりもりもり / , , , ,

まえがき

もりやまです。
今回は、一昨年の 7 月に弊社サイトをリニューアルして、サイトのアクセス数が大分増えるよりも前に書いた EC2 の AMI を作る記事を、CentOS 6.2 ベースでやってみようと思います。
少し長いですが、お付き合いください。

はじめに

公式の手順は「From a Loopback – Amazon Elastic Compute Cloud」にあります。
基本はこの通りなのですが、如何せん Fedora Core 4 を使った例なので、最新の OS で作るにはそのままでは使えませんのでご注意ください。

CentOS 6.2 のベースである RHEL6 は、rpm パッケージのペイロードが xz 形式で圧縮されるようになったため、RHEL5 以前の rpm では展開することができません
そのため AMI のビルド環境は、xz 形式のペイロードを展開できるバージョンの rpm が使われている OS を使う必要があります。
今回はビルド用の環境に、Momonga Linux (64bit) の trunk 環境を使用しましたが、作成する AMI と同じ OS・アーキテクチャで揃えておくのが安心です。
それでは実際に作っていきたいと思います。

0. 準備

AMI の作成には、EC2 AMI Tools というパッケージを使うので、インストールしておいてください。
ruby で書かれているので、ruby も入っている必要があります。

1. loopback イメージを作成

dd if=/dev/zero of=CentOS-6.2-1.kray-i386.img bs=1G count=8

このイメージがそのままインスタンスのルートデバイスになります。今回は 8GB で作成します。
AMI にする際にイメージの空き領域はほとんど圧縮されてしまうので、必要な領域がそれほど多くなくても大きめに作っておいて問題ありません。
ただし、S3-Backed なインスタンスで使えるルートデバイスの最大サイズは 10GB です。

2. loopback イメージにファイルシステムを作成してマウント

mkfs.ext4 -F -L _/ CentOS-6.2-1.kray-i386.img
mkdir ami-root
mount -o loop CentOS-6.2-1.kray-i386.img ami-root
cd ami-root

今回はルートデバイスを ext4 でフォーマットします。ルートデバイスで使えるファイルシステムは「Enabling Your Own Linux Kernels – Amazon Elastic Compute Cloud」に記載されています。
以前は AWS 側で用意されている kernel しか使えなかったのですが、2010 年 7 月に、PV-GRUB を使ってインスタンスにインストールされている kernel を起動できるようになりました。
今回はそれを使う AMI を作るので、PV-GRUB が認識できるファイルシステムを使う必要があります。

3. インストールに必要なファイルを作成

mkdir etc proc dev

cat > etc/fstab <<EOS
LABEL=_/   /         ext4    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

こちらはほぼ公式のドキュメントの通りで、特筆すべきところはありません。

4. インストール用の yum.conf を作成

wget -O ../RPM-GPG-KEY-CentOS-6 http://ftp.riken.jp/Linux/centos/RPM-GPG-KEY-CentOS-6
cat > ../repos.conf <<EOS
[ami-base]
name=CentOS-6 - Base
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=i386&repo=os
gpgcheck=1
gpgkey=file://${PWD}/../RPM-GPG-KEY-CentOS-6

#released updates
[ami-updates]
name=CentOS-6 - Updates
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=i386&repo=updates
gpgcheck=1
gpgkey=file://${PWD}/../RPM-GPG-KEY-CentOS-6
EOS

こちらもほぼ公式のドキュメント通りですが、ビルドに使用するホストが Momonga Linux で CentOS の GPG 公開鍵を持っていないため、事前にダウンロードしています。

5. 最小限の構成をインストール

setarch i386 yum -y -c ../repos.conf --installroot=$PWD --disablerepo=* --enablerepo=ami-base,ami-updates groupinstall Core

公式のドキュメントでは「Base」グループでインストールしていますが、ここではさらに少ない「Core」グループでインストールします。
「setarch i386」は、ビルドに使用するホストが 64bit 環境のため指定しています。
-disablerepo=* -enablerepo=ami-base,ami-updates」は、ビルドに使用するホストに設定してあるリポジトリまでロードされてしまうため、このように指定しています。
以降 yum を実行する際は、すべてこれらを指定します。

6. 不要なパッケージを削除

rpm -e --root $PWD selinux-policy-targeted selinux-policy policycoreutils libselinux-utils libsemanage checkpolicy iptables-ipv6
setarch i386 yum -y --installroot=$PWD remove "*-firmware"

SELinux や IPv6 は使わないので、関連するパッケージを削除します。
さらに、EC2 で動かすには必要ないファームウェアも削除してしまいます。

7. kernel をインストール

setarch i386 yum -y -c ../repos.conf --installroot=$PWD --disablerepo=* --enablerepo=ami-base,ami-updates install kernel

PV-GRUB で User Provided Kernel による起動をするので、kernel をインストールします。
ディストリビューションによっては Xen 用の kernel が別にあるものもありますが、CentOS6 では kernel パッケージで問題ないようです。

8. ec2-ami-tools と ec2-metadata をインストール

setarch i386 yum -y -c ../repos.conf --installroot=$PWD --disablerepo=* --enablerepo=ami-base,ami-updates install ruby rsync
rpm -Uvh --root=$PWD http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm
wget -O usr/bin/ec2-metadata http://s3.amazonaws.com/ec2metadata/ec2-metadata
chmod +x usr/bin/ec2-metadata

ここは必須ではありませんが、あると便利なので入れておきます。

9. fstab に /mnt と swap パーティションの設定を追加

cat >> etc/fstab << EOS
/dev/xvde2 /mnt      ext4    defaults        1 0
/dev/xvde3 swap      swap    defaults        0 0
EOS

instance storage をマウントする設定を追加します。デバイス名が xvde2, xvde3 と決め打ちですが、これは t1.micro を除く 32bit のインスタンスで設定されます。
64bit 環境ではまた変わってくるので、詳しくは「Amazon EC2 Instance Storage – Amazon Elastic Compute Cloud」を参照してください。

ちなみに、Amazon Linux AMI を起動すると xvda になるのですが、今回の方法で作った AMI では xvde になってしまいました。
AWS 公式の RHEL6 の AMI でも xvde になるので、Amazon Linux AMI が特別なのでしょうか。

10. ネットワークの設定

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

こちらはほぼ公式のドキュメントの通りです。

11. rc.local に ssh 公開鍵を取得する設定を追加

cat > etc/rc.local << EOS
# Update the Amazon EC2 AMI creation tools
rpm -Uvh http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm
 
# Update ec2-metadata
wget -O /usr/bin/ec2-metadata http://s3.amazonaws.com/ec2metadata/ec2-metadata
chmod 755 /usr/bin/ec2-metadata

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 0700 /root/.ssh
fi

ATTEMPTS=5
FAILED=0
# Fetch public key using HTTP
while [ ! -f /root/.ssh/authorized_keys ]; do
  curl -f http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /tmp/aws-key 2>/dev/null
  if [ $? -eq 0 ]; then
    cat /tmp/aws-key >> /root/.ssh/authorized_keys
    chmod 0600 /root/.ssh/authorized_keys
    rm -f /tmp/aws-key
    echo "Successfully retrieved AWS public key from instance metadata"
  else
    FAILED=$(($FAILED + 1))
    if [ $FAILED -ge $ATTEMPTS ]; then
      echo "Failed to retrieve AWS public key after $FAILED attempts, quitting"
      break
    fi
    echo "Could not retrieve AWS public key (attempt #$FAILED/$ATTEMPTS), retrying in 5 seconds..."
    sleep 5
  fi
done
EOS

基本は「Sharing AMIs Safely – Amazon Elastic Compute Cloud」に記載されている通りです。
合わせて ec2-ami-tools と ec2-metadata のアップデートをするようにしています。

12. 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 を無効にしています。

13. grub の設定を追加

cat > boot/grub/menu.lst <<EOS
default=0
timeout=0
hiddenmenu
title CentOS6.2
        root (hd0)
        kernel /boot/vmlinuz-$(rpm --root=$PWD -q --queryformat "%{version}-%{release}.%{arch}\n" kernel) ro root=LABEL=_/
        initrd /boot/initramfs-$(rpm --root=$PWD -q --queryformat "%{version}-%{release}.%{arch}\n" kernel).img
EOS

PV-GRUB 用の設定です。通常の GRUB の設定と同じですね。

14. 「4gb seg fixup」対策

echo "hwcap 1 nosegneg" > etc/ld.so.conf.d/libc6-xen.conf
chroot . ldconfig

EC2 に限らず、Xen 環境で発生する問題のようですが、「4gb seg fixup …」というようなメッセージが延々と /var/log/messages に出力されてしまうことがあります。
上記はそれを防ぐための設定です。

15. 不要なファイルを削除してイメージをアンマウント

setarch ${ARCH} yum -y -c ../repos.conf --installroot=$PWD --disablerepo=* --enablerepo=ami-base,ami-updates clean all
cd ..
umount ami-root/proc
umount -d ami-root

AMI を作成する前に、yum のキャッシュ等を削除します。
スクラッチから作る場合には問題ないと思いますが、既存のインスタンスを AMI 化する際には、ssh の公開鍵や sshd のホストキー、.bash_history やログ等、削除すべきファイルが多々あるので注意しましょう。

16. loopback イメージをバンドル

mkdir ami-bundle
ec2-bundle-image -i CentOS-6.2-1.kray-i386.img -k ${EC2_PRIVATE_KEY} -c ${EC2_CERT} -u ${AWS_ACCOUNT_NUMBER} -d ./ami-bundle -r i386 --kernel aki-ec5df7ed

インストールが済んだ loopback イメージを AMI としてバンドルします。
ここで PV-GRUB の AKI を指定するのですが、同じ AKI でもリージョンごとに ID が違います。今回は東京リージョン(ap-northeast-1)のものを指定します。
PV-GRUB 用の最新の AKI は、User Provided Kernel のドキュメントに載っています。
ファイル名の pv-grub- の後が、hd0 のものが S3-Backed 用、hd00 のものが EBS-Backed 用のようです。
今回は「東京リージョン」「S3-Backed」「32bit」なので、「aki-ec5df7ed ec2-public-images-ap-northeast-1/pv-grub-hd0_1.02-i386.gz.manifest.xml」を指定します。

17. バンドルした AMI を S3 にアップロード

ec2-upload-bundle -b ${S3_BUCKET} -a ${AWS_ACCESS_KEY} -s ${AWS_SECRET_ACCESS_KEY} -m ./ami-bundle/CentOS-6.2-1.kray-i386.img.manifest.xml --retry --location ap-northeast-1

東京リージョンのバケットにアップロードするので、「-location ap-northeast-1」を指定しています。
この際、アップロード先のバケット名にドットが含まれていると、証明書の検証に失敗してアップロードに失敗します。
ec2-upload-bundle を使わずに別の方法でアップロードするか、ec2-upload-bundle が内部で curl を使うので、~/.curlrc に「insecure」と書いておくことで回避できます。
後者が簡単ですが、アップロードが完了したら「insecure」を削除することをお忘れなく。

18. AMI を登録

さて、いよいよアップロードした AMI を登録するのですが、実は登録用のコマンドは EC2 AMI Tools には含まれていません。
登録用のコマンドは EC2 API Tools というパッケージに含まれているのですが、今回はそれを使わずに AWS Management Console から登録してみます。

  1. EC2 のタブを開く
  2. Navigation の Region を「Asia Pacific(Tokyo)」に変更
  3. Navigation から「AMI」を選択

  1. Amazon Machine Images の「Register New AMI」を選択
  2. AMI Manifest Path に、アップロードした AMI の URL を入力して「Register

  1. 登録完了!

まとめ

あとは起動して動作確認して、問題なければ完成です。
今回の手順をシェルスクリプトにして、コマンド一発で S3 へのアップロードまで済むようにしたものを Gist に上げたので、参考にしてみてください。

今回 S3-Backed の AMI を作ったので、次回はそれを EBS-Backed の AMI にする方法を紹介したいと思います。

クレイについてもっと知りたい方は…

  1. クレイの3つの強みを見てみる。
  2. WEBシステムのことなら何でもご相談ください。

「いいね!」で応援よろしくお願いします!

このエントリーに対するコメント

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)


トラックバック
  1. EC2でCentOS6のEBS-Backed AMIをゼロから作る | シーズブログ2012/11/18, 7:41 PM

    […] [Amazon EC2] AMI をゼロから作る CentOS 6.2 / S3-Backed 版 SUZ-LAB謹製 CentOS AMI 6.0.0″の作り方 Amazon EBS-Backed AMI の作成 (公式) Amazon loopback S3-Backed の作成 (公式) Sharing AMIs Safely […]

we use!!Ruby on RailsAmazon Web Services

このページの先頭へ