2012年3月23日金曜日

AWS 上の Rails 環境

「クラウド上に Rails 環境を作るのであれば Heroku じゃないの?」という疑問が聞こえてきそうですが、欲しかった環境が ruby 1.8.x + Rails 2.3.5 (かつ Bundler の恩恵を受けていないアプリケーション?)だったので、heroku で動かすには苦労しそうだとプロの意見もいただいたので、AWS に白羽の矢を立てた次第です。

んで、以下は AWS の Linux AMI に rails 環境を作った記録です:

…と思ったんですが、結局、昔書いた Openskip の環境構築の手順のほとんどそのままで動かせました。違いは
  • 今回は rvm 環境を先に用意した
  • Amazon Linux AMI がデフォルトで用意しているパッケージが少ないのでいろいろ yum install した
    • patch, make, gcc,...
    • git
    • mailx (/bin/mail コマンド)
    • mysql-server
    • *-devel (ここは CentOS でも一緒か…)
  • インストールした gem は同じだけれどバージョンがちょっと違う
くらいです。
当たり前と言えば当たり前ですね、Amazon Linux AMI が CentOS 類似OSなので。

Amazon EC2 を使ってみる

手元で改修したプログラムの動作を見てもらおうと思ったときに、これまでは手元でしか動かせなかったので直接会った時にしかどんな感じで動くのか見てもらえませんでした。
これだと会えないと開発の機会がなくなります。困ります。

ということで、
「インターネット上にテスト環境が欲しい!」
と思い、Amazon EC2 の無料使用範囲を利用してテスト環境(ステージング環境?)を作ってみることにしました。

初めの一歩

多分このドキュメントなんだと思います:
Get Started with EC2 with a Linux/UNIX Instance

手順として
  1. サインアップ
  2. インスタンス(仮想マシン)の作成と起動
  3. インスタンスへのアクセス
  4. インスタンスの terminate 
となっています。

サインアップ

サインアップは普通にweb上のサービスを利用する感じで進みます。途中、ケータイへ Amazon さんから自動着信&webページに表示された4桁の番号入力を求められるのが普通でない感じ。
サインアップが終わると、AWS Management Console というWebサイトが使えるようになると思います。このWebサイトでインスタンスの管理(作成、起動、一時停止、停止などなど)を行えます。

あ。ssh の鍵生成はこのタイミングでやっておくとよいと思います。

インスタンスの作成と起動

インスタンスの作成のプロセスも、Web上のクリックぽちぽちで進められます。
今回は Quick Launch Start のウィザードを使って、AMI Linux 2011.9 x86_64 を立ち上げてみました。
Amazon Linux AMI についてのドキュメント を読んでみると、
Amazon Linux AMI is similar to CentOS in file system layout and package management. Applications built for CentOS should run without recompilation on the Amazon Linux AMI.
と書いてあって、「CentOS と同様のファイル構造とパッケージ管理」というところを重視して思わず選びました。手元の環境(CentOS 6 on VMware & Thinkpad)に近い方が楽だと思ったので…。
Quick だとほとんど選ぶことは無いのですが、インスタンスのタイプが micro (= 無料使用範囲で使えるインスタンス)であることだけはしっかりと確認しました。

インスタンスの起動はAWS management console から行います。これも「クリックぽち」です。

インスタンスへのアクセス…の前に

インスタンスが持っているFQDNの確認と、セキュリティグループの概念の理解が(多分)必要です。

インスタンスのFQDNを確認するには、AWS management conslole から確認します。これがないとsshできませんし…。

セキュリティグループは、「ネットワークの口に存在するファイアウォール(のルールセット)」に相当するものだと思っています。
定義するものはファイアウォールルールそのもので、そのルールをセキュリティグループとしてまとめ、各インスタンスにどのセキュリティグループに属させるかを設定します。
複数の同様のサーバを運用する場合にセキュリティグループが威力を発揮しそうです。今は一台なので、OS上でiptables を走らせても(セキュリティレベルと言う意味では)あまり変わりないかもしれません。

インスタンスへのアクセス 

SSH の鍵があって、FQDN が分かっていれば、後は ssh コマンドを走らせるだけです。
…が、一度引っかかりました。AWS management console で生成した ssh の秘密鍵をダウンロードするんですが、そのパーミッションを 6xx から 400 にしないといけません。秘密鍵ですもんね。
普段 ssh-keygen で作ると自動的に 400 だと思いますが、ダウンロードファイルだから普通のパーミッションになってました。

インスタンスのterminate

「停止」と言う言葉を使わずに terminate と書いたのは、ちょっと悲しい体験をきちんと伝えたかったからです…。

停止っていうと、僕の中では再開できるものだったんです。が、ご存知の通り、インスタンスを terminate するとそのインスタンス上のデータは破棄され、再利用することはできません。
"Get started" を読むと Note として、
You cannot restart a terminated instance. However, you can launch additional instances of the same AMI.
と書いてあるのでちゃんと読めという話なんですが、ドキュメントの手順どおり terminate してパニックになりました。

「このインスタンスをしばらく使わないから課金されない状態にしたいわー」と言うときはインスタンスに対する操作として stop というのがあるので、そちらを使うと start ←→ stop を行き来できます。


こんな感じで Amazon EC2 に Linux サーバを立てて、その上で rails の環境を動かしています。
立ち上がった Linux サーバはいろいろひどい状況なので、もう少しマトモな環境にしていかねば…。

2012年3月8日木曜日

vmware tools の仕業?

昨日せっかくどうでもいいことでハマッタので、ブログに書いておこうと思います。

3/4 に CentOS の yum upgrade (多分このとき 6.0 → 6.2になる)を行い、3/6 に VMware Player の 4.0.2 へのアップグレードと VMware tools の再インストールをしたのですが、3/7 に
「VMware ゲストOSの画面を全画面表示したときに、ウィンドウ領域全体で描画されない(800x600になる)」
という事態になりました。

開発なんてやってられない狭さなので時間をかけてでも解決させたわけですが、結論から言うと
  • インストールされているはずの /usr/lib/xorg/modules/drivers/vmwlegacy_drv.so (from xorg-x11-drv-vmware パッケージ)が無かった
  • /etc/X11/xorg.conf の設定で、device identifier "Videocard0" に対する driver が "vesa" になっていた
というところが原因らしく、それぞれ
  • xorg-x11-drv-vmware の再インストール( yum reinstall )
  • driver を "vmware" に変更
    • man vmware すると VMware SVGA video driver についてのマニュアルが立ち上がるのは知らなかった…
ということをやって元通りの環境を奪回しました。

/etc/X11/xorg.conf 辺りが関わっているので、ゲストOS上の操作が何か関わっているはずで、vmware-tools-config.pl あたりが怪しそうな予感だけはあります。追跡しないけれど。

…あ。VMware player の再インストール(4.0.0 へのダウングレード)しちゃったけど、次のアップグレードが怖いなっと。

2012年2月9日木曜日

小さな commit ベースで仕事すること

一応、rails プロジェクトを作るときに一番最初に git init && git . && git commit して、rails プロジェクト全体を git でコントロールできるようにしてはいました。

が。

実際のところ、commit したことはこれまでありません。「ある程度の状態にしてから…」とかダメな事を考えています。

で、今どうなっているかというと、
  • 今まで何したか良く覚えていない
  • 次に何をすればいいのか良く覚えていない
という状態です。まさに、昨日の自分は他人。

コードレビューをしてもらえる機会ができそうなんですが、その時に「何を思って問題にどう対処したのか」を説明できない悪寒がひしひしと忍び寄っています。
こういう時に変な完璧主義が出てきて、一から作り直したい症候群になるんですよね。まぁ、今作っているのは習作なので何度でも一からやり直せばいいと思うんですけど…。

…みたいなことを、たまたま本を読んでいたタイミングで思うのです。


2012年1月6日金曜日

devise でメールアドレス以外を認証に使う

先ほどメールアドレスで認証するサンプルが作れたのですが、今、考えている状況に
  • メールアドレスが確定しない状況(変更可能な状況)
  • そもそも持っていない可能性もある状況
  • 将来的に外部認証と組み合わせる時にメールアドレスを強制できない状況
が含まれるので、メールアドレス以外をユーザIDとして使う方法が必要になりました。

今の時代は恵まれているので、しっかり誰かが道を作ってくれています。
http://ja.asciicasts.com/episodes/210-customizing-devise
http://d.hatena.ne.jp/kaorumori/20110824/1314168534

config/initializers/devise.rb にて
config.authentication_keys = [ :username ]
元々の設定値は :email になっています。

さらに、app/views/devise/session/new.html.erb および app/views/devise/registrations/new.html.erb にて、:username 用の text_field を追加します。

この辺り(テキストフィールド欄の追加)は見よう見まねで何とかなったのですが…。
上記の2つの記事では「既に存在しているユーザのフィールド(username)の値を認証に使う」というものでしたが、username の値を登録したいと思って regisrations/new.html.erb に単純にテキストフィールドを追加したらハマりました。

コンソールログをきちんと読め、という話なのですが、
WARNING: Can't mass-assign protected attributes: username
というログが出てきます。
app/models/user.rb で、attr_accessible に :username を追加してあげる必要があったようです。
こんな記事を見つけました。
http://trwtnb.blogspot.com/2009/11/rubyrails-warning-cant-mass-assign.html

おまけ

email フィールドに unique 制約があるので(適当なメールアドレスをでっち上げればいいだけなんですが…)、user テーブルを何度も作り直しました。
ってことで、 rake db:migrate:reset をおぼえた!