CentOS6.6(x86_64)HVM版のAMIを作成した手順

2015/01/27

参考にさせていただいたエントリ群

大変助かりました。ありがとうございます

構築作業用の暫定Instance

  • 基本的に同じ感じのインスタンスで構築しよう
  • CentOS6 With Update の HVM版を利用
yum install parted wget
yum update
yum upgrade #(CentOS6.5だったので/別にしなくてもいいのではないか)
chkconfig iptables off
chkconfig ip6tables off
sed -i 's@SELINUX=enforcing@SELINUX=disabled@g'   /etc/selinux/config
sed -i 's@SELINUX=permissive@SELINUX=disabled@g' /etc/selinux/config
reboot

Webコンソール 構築する前に

  • “/dev/xvda1 9.9G 1.9G 7.5G 20% /” となっている
  • “/dev/xvdf1” として作業領域EBSをアタッチする

Webコンソール EBS作成しアタッチする

  • 構築作業用の暫定Instanceと同一AZに作成する
  • 10 Gibで作成
  • Volume Typeなどはどうでもよい(たぶん)
  • アタッチする先が重要
  • /dev/sdf とした -> /dev/xvdfとして認識される
  • アタッチが成功すると fdisk -l で確認が可能
# fdisk -l

Disk /dev/xvda: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

    Device Boot      Start         End      Blocks   Id  System
/dev/xvda1   *           2        1305    10474380   83  Linux

Disk /dev/xvdf: 10.7 GB, 10737418240 bytes
255 heads, 63 sectors/track, 1305 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000
  • cat /proc/partitions でもよい
# cat /proc/partitions
major minor  #blocks  name

 202        0   10485760 xvda
 202        1   10474380 xvda1
 202       80   10485760 xvdf

/dev/xvdf が存在することが確認できる

EC2インスタンスログイン アタッチ後にパーティション切って領域を作成する

  • 作業用インスタンスのCentOS6には partedは初期インストールされていないこと に注意
parted /dev/xvdf --script 'mklabel msdos mkpart primary 1M -1s print quit'
partprobe /dev/xvdf
udevadm settle
  • ext4とする
mkfs.ext4 /dev/xvdf1
tune2fs -c 0 -i 0 /dev/xvdf1
fdisk -l # xvdf1 が確認できる

mkdir -p /mnt/ami
mount /dev/xvdf1 /mnt/ami
/sbin/MAKEDEV -d /mnt/ami/dev -x console
/sbin/MAKEDEV -d /mnt/ami/dev -x null
/sbin/MAKEDEV -d /mnt/ami/dev -x zero
/sbin/MAKEDEV -d /mnt/ami/dev -x random
/sbin/MAKEDEV -d /mnt/ami/dev -x urandom
mkdir /mnt/ami/proc
mount -t proc none /mnt/ami/proc
mkdir /mnt/ami/etc
cat > /mnt/ami/etc/fstab <<'FSTAB.EOF'
LABEL=ROOT /         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
FSTAB.EOF

LABEL=ROOT / が重要

EC2インスタンスログイン RPMパッケージ導入

cd /mnt/ami
wget -O ../RPM-GPG-KEY-CentOS-6 http://ftp.riken.jp/Linux/centos/RPM-GPG-KEY-CentOS-6
cat > ../repos.conf <<'AMI.REPOS.EOF'
[ami-base]
name=CentOS-6 - Base
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=os
gpgcheck=1
gpgkey=file:///mnt/RPM-GPG-KEY-CentOS-6
[ami-updates]
name=CentOS-6 - Updates
mirrorlist=http://mirrorlist.centos.org/?release=6&arch=x86_64&repo=updates
gpgcheck=1
gpgkey=file:///mnt/RPM-GPG-KEY-CentOS-6
AMI.REPOS.EOF


cd /mnt/ami/
setarch x86_64 yum -y -c ../repos.conf --installroot=/mnt/ami --disablerepo=* --enablerepo=ami-base,ami-updates groupinstall Core
setarch x86_64 yum -y -c ../repos.conf --installroot=/mnt/ami --disablerepo=* --enablerepo=ami-base,ami-updates install kernel
setarch x86_64 yum -y -c ../repos.conf --installroot=/mnt/ami --disablerepo=* --enablerepo=ami-base,ami-updates install wget gcc automake autoconf make patch zlib-devel openssh-clients bash
setarch x86_64 yum -y -c ../repos.conf --installroot=/mnt/ami --disablerepo=* --enablerepo=ami-base,ami-updates install ruby rsync
setarch x86_64 yum -y -c ../repos.conf --installroot=/mnt/ami --disablerepo=* --enablerepo=ami-base,ami-updates update
rpm -Uvh --root=/mnt/ami 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
  • 作業領域である(最終的にAMIそのもとのなる) /mnt/ami 以下にインストールしていく形となる

EC2インスタンスログイン カーネル設定

cp -a /dev/xvdf /dev/xvdf1 /mnt/ami/dev/
cp -a /mnt/ami/usr/*/grub/*/*stage* /mnt/ami/boot/grub/

# 要チェックや (hd0) -> (hd0,0)
cat > /mnt/ami/boot/grub/menu.lst <<MENU.LST.EOF
default=0
timeout=0
hiddenmenu
title CentOS6
        root (hd0,0)
        kernel /$(ls boot/vmlinuz-*) root=LABEL=ROOT ro consoleblank=0 console=ttyS0 xen_pv_hvm=enable xen_blkfront.sda_is_xvda=1
        initrd /$(ls boot/initramfs-*)
MENU.LST.EOF
chroot /mnt/ami
ln -s /boot/grub/menu.lst /boot/grub/grub.conf
ln -s /boot/grub/grub.conf /etc/grub.conf
exit

cat <<EOF | chroot /mnt/ami grub --batch
device (hd0) /dev/xvdf
root (hd0,0)
setup (hd0)
EOF

e2label /dev/xvdf1 ROOT
tune2fs -l /dev/xvdf1 |grep 'Filesystem volume name'

rm -f /mnt/ami/dev/xvdf /mnt/ami/dev/xvdf1
  • AMI上において /boot/grub/menu.lst 相当となるファイルだが、当初この設定を間違えていてはまった
  • 気づくのに2日かかった
  • root (hd0,0) が今設定のツボであった
  • 当初は root (hd0) としていたため起動せずGet System Logすらでない状態だった

EC2インスタンスログイン NW設定

cat > /mnt/ami/etc/sysconfig/network <<NETWORK.EOF
NETWORKING=yes
NETWORK.EOF

cat > /mnt/ami/etc/sysconfig/network-scripts/ifcfg-eth0 <<NETWORK_ETH0.EOF
DEVICE=eth0
BOOTPROTO=dhcp
ONBOOT=yes
TYPE=Ethernet
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
NETWORK_ETH0.EOF

EC2インスタンスログイン hosts ipv6無効 (『AMI作成』という点においてのみで言えば特に影響は与えない/お好み)

sed -i '2d' /mnt/ami/etc/hosts

if [ `grep disable_ipv6 /mnt/ami/etc/sysctl.conf | wc -l` -ne 2 ]; then
    cat >> /mnt/ami/etc/sysctl.conf << EOM
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
EOM
fi
# 90-nproc.conf  (CentOS/Scientific Linux 6)
if [ -f /mnt/ami/etc/security/limits.d/90-nproc.conf ] ; then
  if [ ! -f /mnt/ami/etc/security/limits.d/90-nproc.conf.orig ] ; then
    cp -a /mnt/ami/etc/security/limits.d/90-nproc.conf{,.orig}
    echo '' > /mnt/ami/etc/security/limits.d/90-nproc.conf
  fi
fi

if [ ! -f /mnt/ami/etc/security/limits.conf.orig ] ; then
  cp -a /mnt/ami/etc/security/limits.conf{,.orig}
  cat > /mnt/ami/etc/security/limits.conf <<'LIMITS.EOF'
*    -    nproc    32768
*    -    nofile   65536
*    -    stack    10240
### rc/init script や apachectl などはこの設定を読み込まない ###
LIMITS.EOF
fi

if [ ! -f /mnt/ami/etc/sysconfig/init.orig ] ; then
  cp -a /mnt/ami/etc/sysconfig/init{,.orig}
  cat >> /mnt/ami/etc/sysconfig/init <<'SYSCONFIG_INIT.EOF'

ulimit -n 65536
ulimit -u 32768
ulimit -s 10240

SYSCONFIG_INIT.EOF
fi

EC2インスタンスログイン iptables,ip6tables無効(ついでにpostfixも無効にしてある)

rm -f /mnt/ami/etc/rc{2,3,4,5}.d/S08iptables
rm -f /mnt/ami/etc/rc{2,3,4,5}.d/S08ip6tables
rm -f /mnt/ami/etc/rc{2,3,4,5}.d/S80postfix

EC2インスタンスログイン SELinux無効

sed -i 's@SELINUX=enforcing@SELINUX=disabled@g'  /mnt/ami/etc/selinux/config
sed -i 's@SELINUX=permissive@SELINUX=disabled@g' /mnt/ami/etc/selinux/config

EC2インスタンスログイン SSHConfig

接続元ホスト名名前解決(無効-接続時認証までの速度改善)

sed -i "s/^#UseDNS yes/UseDNS no/"                                   /mnt/ami/etc/ssh/sshd_config
sed -i "s/^GSSAPIAuthentication yes/#GSSAPIAuthentication yes/"      /mnt/ami/etc/ssh/sshd_config
sed -i "s/^#GSSAPIAuthentication no/GSSAPIAuthentication no/"        /mnt/ami/etc/ssh/sshd_config

rootログインは公開鍵認証必須(2行目のsedは一般ユーザにおいても鍵認証を求める設定であることに留意されたし)

sed -i "s/^#PermitRootLogin yes/PermitRootLogin without-password /"  /mnt/ami/etc/ssh/sshd_config
sed -i "/^PasswordAuthentication yes/d"                              /mnt/ami/etc/ssh/sshd_config

EC2インスタンスログイン rc.local に追記(SELinuxは無効化してあるためrestoreconは不要かもしれない)

cat >> /mnt/ami/etc/rc.local <<'RC.LOCAL.EOF'
if [ ! -d /root/.ssh ]; then
  mkdir -m 0700 -p /root/.ssh
  restorecon /root/.ssh
fi
# Get the root ssh key setup
ReTry=0
while [ ! -f /root/.ssh/authorized_keys ] && [ $ReTry -lt 5 ]; do
  sleep 2
  curl -f http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key > /root/.ssh/authorized_keys
  ReTry=$[Retry+1]
done
chmod 600 /root/.ssh/authorized_keys && restorecon /root/.ssh/authorized_keys
RC.LOCAL.EOF

EC2インスタンスログイン ローカルタイム

rm -f /mnt/ami/etc/localtime
cp -p /mnt/ami/usr/share/zoneinfo/Japan /mnt/ami/etc/localtime

EC2インスタンスログイン epel も入れよう

  • chrootをしなければ /etc/resolv.conf (/mnt/ami/etc/resolv.conf) 作成は不要とは思うのだが
chroot /mnt/ami

cat > /etc/resolv.conf <<'EOF'
nameserver 8.8.8.8
EOF

cd /root/
VERSION='6'
URL="http://dl.fedoraproject.org/pub/epel/${VERSION}/x86_64/"
epel=`wget ${URL} -O - 2> /dev/null   |
      grep epel-release               |
      perl -pe 's@^.*\"(.*)\".*$@\1@g'`
wget ${URL}/${epel}
rpm -ivh ${epel}

sed -i 's@enabled=1@enabled=0@g'  /etc/yum.repos.d/epel.repo
sed -i 's@enabled=1@enabled=0@g'  /etc/yum.repos.d/epel-testing.repo

yum list --disablerepo=\* --enablerepo=epel
yum clean all
rm -f /etc/resolv.conf
exit

EC2インスタンスログイン 不要ファイル削除

  • findとforの組み合わせ圧倒的にださい……
cd /mnt/ami
setarch x86_64 yum -y -c ../repos.conf --installroot=/mnt/ami --disablerepo=* --enablerepo=ami-base,ami-updates,epel clean all 
chroot /mnt/ami
rpm -vv --rebuilddb
exit


for logfile in $(find  /mnt/ami/var/log/ -type f)
do
  sed -i '1,$d' ${logfile}
done

EC2インスタンスログイン アンマウント

rm -f /mnt/ami/dev/xvd*
cd /mnt
umount /mnt/ami/proc
umount /mnt/ami

Webコンソール EBSデタッチからのスナップショット

  • 対象作業領域EBSデタッチする
  • スナップショットとる

Webコンソール スナップショットからAMI作成する

  • Create Image みたいなやつ
  • わかりやすい名前を付けよう
  • 処理が終わるまではAMIsには表示されない
  • そこそこ時間かかる

Webコンソール EC2を起動してみよう

  • /dev/sda1 で起動できるはず
    • 起動しない場合はAMIを削除(deregister)する(やり直すのに紛らわしいから)
    • SnapShotもDeleteする
    • 必要なのはEBSのファイルなので
    • EBSを再び作業インスタンスにアタッチして修正をかける
    • 上記で実行してきたmount系コマンドを改めて実行すればmountしての再修正が可能
    • 大概はgrubまわりと予想する(僕がそうだったので)
  • Get System Log みよう
  • なお僕の場合「失敗したけどGet System Logが表示された」ということは一度もなかった

アタッチし直しやり直すときは

mount /dev/xvdf1 /mnt/ami
mount -t proc none /mnt/ami/proc
cp -a /dev/xvdf /dev/xvdf1 /mnt/ami/dev/

enjoy :)
ご指摘ありましたら @ngsw(Twitter) などで教えていただけると助かります