AWS環境ならAmazon Linuxを利用した方が良いことづくめなのは重々承知していたのですが、監視製品のサポート外ということでCentOS6を使おうということになったところからAWS Marketplace版CentOSとの戦いが始まったのでした。
Product Codes
はじまりは現行インスタンスタイプの一部がHVMのみをサポートすることになったこと。CentOS6はPV版しか見当たらなかった(CentOS7は逆にHVMのみ)のだけど、Amazon Linuxなら検証環境のt1.micro(PV)からt2.micro(HVM)への移行作業は何度もやっていたので、少々面倒なことになったなあとは思いつつも、WEB上にも多々情報が転がっているし、大きな問題とはならないだろうと思ったのです。しかし、そろそろ構築準備をしようと念の為検証をしてみたところ、CentOS6(PV)から作成したEBSを他のワークサーバからマウントしようとしたところ、下記のエラーが。。。
A client error (UnsupportedOperation) occurred when calling the AttachVolume operation: The instance configuration for this AWS Marketplace product is not supported. Please see http://aws.amazon.com/marketplace/pp?sku=aacglxeowvn5hy8sznltowyqe for more information about supported instance types, regions, and operating systems.
よくよく探すと下記のような記事を発見。
EC2 に SSH できない時の対処法、あるいは Marketplace の AMI を気軽に選ぶべきでない理由
一応、AWSサポートに頼むとロックを解除してくれることがわかり、早速お願いしてみることにした。何度かやり取りをして、スナップショットを共有設定して解除してもらうことに成功。これだけでやり取りにも数日を要してしまった。Management ConsoleのEBS、Snapshot、AMIの詳細をよく見るとProduct Codesという記載があるのでした。
CentOS6(PV)をHVMに変換
Amazon Linux(PV)をHVMに変換するのと同じ要領で進めたけど、grubもインストールされているし、試行錯誤の結果何もしなくても良いことが判明。つまり、CentOS6(PV)から作成したスナップショットからCreate ImageしてAMI化するときに、Virtualization typeでHVMを指定して起動するだけで良かった。何だそれならロック解除してもらう必要無かったじゃねえか!と思ったら、SnapshotからAMIを作成するまでは成功するものの、下記のエラーでインスタンス起動エラー。
The instance configuration for this AWS Marketplace product is not supported. Please see http://aws.amazon.com/marketplace/pp?sku=aacglxeowvn5hy8sznltowyqe for more information about supported instance types, regions, and operating systems.
各処にもう少しこの仕様について説明があっても良さそうなものなのだが。
CenOS6(HVM)リリース
気付いたらされてました。10月末は間違いないはずだけど、正式リリース日はCentOSのMarketplaceページを見てもよくわからず。例によってどこよりも早いクラスメソッドさんのブログでその事実を認識。こういったリリース情報を一体どうやって手に入れているのだろうかと不思議に思いつつ、やっぱりロック解除要らなかったじゃねえかよ!と毒付きながらもう一度検証をし直すのでした。AWSみたいな五月雨式なリリースをするサービスの最新情報をキャッチするのに最も優れているのはTwitter。皆さんがどんどん最新のニュースを配信してくれているのです。感謝感謝です。
CentOS6でcloud-initまで
ベースとなるAMIを作ることができることはわかったけど、Amazon Linuxライクに使いたい。ということで、下記を目標にした。
- aws cliを使えるようにする
- cloud-initを使えるようにする
- Management ConsoleからSSH鍵を新規インスタンスに配置できる
ということで、少々の課題は残るものの、試行錯誤の上で作ったベースAMI構築手順をまとめてみるのです。
1. インスタンス起動
CentOS 6 (x86_64) – with Updates HVMをベースにEC2インスタンスを起動。デフォルトで接続可能なユーザはroot。CentOS 7だとcentosユーザだし、cloud-initで設定揃えるだけなんだから、この辺りもAmazonがちゃんと旗を振って接続ユーザを揃えてもらえたら混乱が少なくて済むのに。Marketplaceは管理する気ないのでしょうけど。
2. cloud-initインストール
EPELリポジトリを使ってcloud-initをインストールする。cloud-utils-growpartが必要となる理由は後述。
# yum install http://download.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm -y
# yum install cloud-init.noarch cloud-utils-growpart -y
3. aws cliインストール
cloud-initのインストールで、python-setuptoolsも入るのでpipを使えばこれは簡単。
# easy_install pip
# pip install awscli
4. SSH鍵削除
CentOS6の/etc/rc.localにはrootパスワードをリフレッシュする仕組みが入っていたので、それを利用するのと一緒に、SSH鍵は削除してしまう。当然、これ以降はこのサーバにはログインできなくなるので注意が必要。rsyslogサービスを停止して、これもやっておくべきだが今回は割愛。
# touch /root/firstrun # rm -f /root/.ssh/authorized_keys
ちなみにrootのauthorized_keysを消さないと、cloud-initから設定しようとした新しい鍵情報が改行なしで追記されていました。authorized_keysの先頭に”command=”等を書くことで、”Please login as the user 〜”のメッセージが実現されていたのか。勉強になりますね。
5. cloud.cfgを修正
Amazon Linuxだとcloud.cfg.d配下のファイルで管理されているみたいだけど、あえてそうする必要も無さそうなので、cloud.cfgを直接修正した。UserDataをただ渡すだけなのであればそのままでも動きそう。とにかくcloud-initについての情報が探しても全然無い。redhat版やらも含めてとにかく比較して動作確認をしまくって、正直自信がないところだらけだけど、こちらに最終的に落ち着いた。”repo_upgrade: none”はお好みで。
# cat /etc/cloud/cloud.cfg users: - default disable_root: 1 ssh_pwauth: 0 locale_configfile: /etc/sysconfig/i18n mount_default_fields: [~, ~, 'auto', 'defaults,nofail', '0', '2'] resize_rootfs: noblock resize_rootfs_tmp: /dev ssh_deletekeys: 0 ssh_genkeytypes: ~ syslog_fix_perms: ~ cloud_init_modules: - migrator - bootcmd - write-files - growpart - resizefs - set_hostname - update_hostname - update_etc_hosts - rsyslog - users-groups - ssh cloud_config_modules: - mounts - locale - set-passwords - yum-add-repo - package-update-upgrade-install - timezone - puppet - chef - salt-minion - mcollective - disable-ec2-metadata - runcmd cloud_final_modules: - rightscale_userdata - scripts-per-once - scripts-per-boot - scripts-per-instance - scripts-user - ssh-authkey-fingerprints - keys-to-console - phone-home - final-message system_info: default_user: name: ec2-user lock_passwd: true gecos: EC2 Default User groups: [ wheel ] sudo: [ "ALL=(ALL) NOPASSWD:ALL" ] shell: /bin/bash distro: rhel paths: cloud_dir: /var/lib/cloud templates_dir: /etc/cloud/templates ssh_svcname: sshd # vim:syntax=yaml preserve_hostname: true datasource: Ec2: timeout: 10 max_wait: 30 repo_upgrade: none repo_upgrade_exclude: - kernel - nvidia* - cudatoolkit
6. resize2fsとの戦い
とにかくここが一番苦戦した。
EC2をLaunchするときにディスクサイズを好きなものに変更したい。情報を漁ってはみたものの、これもデフォルト接続ユーザ同様、OSによって設定が整っていない模様。ESXとか普通にオンラインでディスク拡張できるのに、EC2は停止してスナップショットから作り直しが必要なのはとても面倒です。Xenの仕組みに依存しているのか知識が無いけど、cloud-initの設定もきちんと揃えてリリースすることはできないものか。パーティション分割されているだけが理由でも無い気がするのだけど、とにかく想定通りに動作しない。
cloud-utils-growpartパッケージを入れておけば、growpartは動作する(localeを日本語に変えたら動作しないとか本当に勘弁して欲しい)のだけど、何故かresize2fsが同時に実行されていない。cloud-initのバージョンが新しいことが原因なのか、ログも/var/log/boot.logと/var/log/cloud-init-output.logだとAmazon Linuxのものと比較すると出力が不十分。デバッグ指定とかできるのかもしれないけどあえなく断念。
手動でgrowpartやresize2fsを実行していると、どうやらgrowpartをした後にもう1回再起動をしないとresize2fsができない(というより正しくパーティション拡張された情報が認識されていない?)ということがわかった。
# resize2fs /dev/xvda1 resize2fs 1.41.12 (17-May-2010) The filesystem is already 2096896 blocks long. Nothing to do!
ということで、前述のcloud.cfg指定をしておけば、2回リブートをすることで、パーティション自動拡張(1回目)→ファイルシステム拡張(2回目)と動作してくれることがわかった。fdiskでパーティション作り直すよりはリブート2回の方が楽かなということで、このあたりで力尽きた。似たようなことを書いている人も発見したので、運用回避で我慢することにしようと思います。
Maybe not a big deal because we would reboot after each job.外国人の人はこういうことさらっと言うよなあ。せっかくAWSを使うのだから、OSと格闘するところにはコストをかけたくないものです。