Linux アプリケーションを Amazon クラウドにマイグレーションする: 第 1 回 初期マイグレーション

アプリケーションをクラウドにマイグレーションする方法

クラウド・コンピューティングと IaaS (Infrastructure as a Service) については、十分なドキュメントがありますが、稼働中のアプリケーションをクラウド環境に移す方法について説明したドキュメントはほとんどありません。この連載で、アプリケーションをクラウドに移す方法、そしてクラウドが提供する機能を利用する方法を学んでください。第 1 回では、物理サーバーからクラウド・サーバーに直接マイグレーションする方法を説明します。

Sean A. Walberg, Senior Network Engineer

Author photoSean Walberg は 1994年以来、学界、企業、およびインターネット・サービス・プロバイダー環境で Linux および UNIX システムに取り組んできました。この数年の間は、システム管理に関する広範な著作活動を行っています。



2010年 7月 13日

この連載について

この連載では、単一の物理サーバー上で実行されている Web アプリケーションを Amazon EC2 (Amazon Elastic Compute Cloud) にマイグレーションする手順を追います。その過程で、アプリケーションをクラウド環境に適応させる方法、クラウドが提供する機能を利用する方法を説明します。

IaaS (Infrastructure as a Service) とは、コンピューティング・リソースを使用して使用料を支払い、さらに多くのコンピューティング能力が必要になったら、追加で料金を支払って必要を満たすという素晴らしい概念です。その一方でこのモデルの欠点として、決して目にすることがなく、またあまり詳しく知ることもないコンピューターを操作しなければならないという点があります。この点を克服すれば、IaaS を使用することによってさまざまなメリットがもたらされます。

IaaS モデルは、従来のサーバー購入モデルとは大幅に異なるため、仮想コンピューターを管理する方法は同じではありません。また、アプリケーションをクラウドで実行する方法も変わってきます。したがって、サーバー間にごくわずかな遅延があるなどといった今までの常識は通用しなくなります。

Amazon EC2 の操作

Amazon EC2 では、クレジット・カード払いによって、誰でもアプリケーション・プログラミング・インターフェース (API) を使って時間単位でサーバーのオン、オフを切り替えることができます。サーバーは、メモリー、ディスク、または CPU 能力など、何を第一に優先するかによって、さまざまなタイプから選択することができます。料金は、使用したものに対してだけ支払います。

Amazon EC2 オファリングの他に、支払処理、データベース、メッセージ・キューイングなどのサービスも提供されています。この連載ではそのうちの Amazon S3 (Amazon Simple Storage Service) を使用します。このサービスでは、ディスク・スペースを使用することができ、その使用量に応じた料金を支払うようになっています。


サンプル・アプリケーション

この連載で使用するサンプル Web アプリケーションは、Ruby on Rails フレームワークと PostgreSQL バックエンドで作成された SmallPayroll.ca という名前の給与計算アプリケーションです。このサンプル・アプリケーションは多くの Web アプリケーションの典型として、データベース層、アプリケーション層、そして CSS (Cascading Style Sheet) と JavaScript ファイルなどの静的ファイルからなります。ユーザーは各種のフォームをナビゲートしてデータを入力、操作し、レポートを生成します。

サンプル・アプリケーションでは、以下の各種コンポーネントを使用しています。

  • nginx: 静的ファイルのフロントエンド Web サーバー兼、中間層に対するバランサー
  • Mongrel: アプリケーション・サーバー自体
  • Ruby: アプリケーションの作成に使用する言語
  • gem: データベースの暗号化からアプリケーション・レベルのモニタリングまでに対応するサード・パーティー製プラグインおよびライブラリー
  • PostgreSQL: SQL データベース・エンジン

このサイトの使用量は、現在サイトを収容している単一のサーバーの容量では対応しきれないほどになりました。そのため新しい環境へのマイグレーションが必要となっています。これは、クラウドに移行する絶好のチャンスです。

望まれる改善

しかし、1 つのサーバーを少数のクラウド・ベースのサーバーに移すだけでは、クラウドでの可能性を生かすことにもならなければ、面白い記事にもなりません。そこで、移行する過程でいくつかの改善を加えることにします。そのうち、以下の改善はクラウド環境でしか実現できないものです。

  • 信頼性の向上。クラウドで実行するサーバーのサイズは選択可能なので、より小さな規模のサーバーを複数実行して冗長性をもたらすことができます。
  • スケールアップおよびスケールダウンの両方に対応する容量。サービスが拡大するにつれ、サーバーは徐々にプールに追加されていきますが、サーバーの数を増やしてトラフィックの短期的急増に対応することも、トラフィックが一時的に小康状態になっている間、サーバーの数を減らすこともできます。
  • クラウド・ストレージ。アプリケーション・データを Amazon S3 にバックアップして、テープ・ストレージの必要をなくします。
  • 自動化。Amazon 環境では、サーバーからストレージ、そしてロード・バランサーに至るまでのすべてを自動化することができます。アプリケーションの管理に費やす時間が減るということは、より生産的な他の作業にその分の時間を費やせるということです。

この連載を通して、以上の改善を順次に行っていきます。


テストおよびマイグレーションのストラテジー

アプリケーションを初めてデプロイするときには通常、本番環境でのトラフィックの負荷がない状態で、アプリケーションをテストして調整するという贅沢が許されます。それとは対照的に、アプリケーションをマイグレーションするとなると、ユーザーが現在そのサイトを使用していることが問題となります。新しい環境が本番環境のトラフィックを引き継ぐと同時に、ユーザーはすべてが正常に機能することを期待しているからです。

マイグレーションとは、必ずしもダウンタイムがゼロであることを意味するわけではありません。サービスを一定の時間オフラインにできるとしたら、そのほうが遥かに容易な作業となります。このサービスが停止している時間枠を使って、最終的なデータ同期を行い、ネットワークの変更を安定化させることができるからです。この時間枠は、新しい環境への初期デプロイメントを行うために使用することはできません。つまり、初期デプロイメントの場合は、アプリケーションのマイグレーションが開始する前に、新しい環境が運用状態でなければならないということです。この点を考えると、環境間でのデータ同期と、ネットワークの変更が重要なポイントとなります。

マイグレーション・ストラテジーを計画する際には、現行の環境をウォークスルーすることから始めると、計画に役立ちます。そこで、以下の質問に答えてください。

  • アプリケーションを実行するためにサーバー上で使用しているソフトウェアは何でしょうか?
  • アプリケーションとサーバー・リソースを管理および監視するためにサーバー上で使用しているソフトウェアは何でしょうか?
  • ユーザー・データのすべてはデータベースに保持されているのでしょうか、それともファイルに保持されているのでしょうか?
  • 画像、CSS、および JavaScript ファイルなどの静的アセットはどこか別の場所に保管されているのでしょうか?
  • アプリケーションに必要な他のシステムへのタッチポイントは何でしょうか?
  • 最近すべてのものをバックアップしたでしょうか?

ユーザーへの通知

一般に、ダウンタイムの発生が予想されない場合でも、ユーザーにマイグレーションに関する通知をしておくのが得策です。SmallPayroll.ca アプリケーションの場合、ユーザーは 2 週間ごとの給与日に応じて、一定の間隔でサイトを使用する傾向があります。したがって、この場合には 2 週間前に通知するのが妥当です。Google 広告プラットフォームの管理インターフェースとなる Google AdWords のようなサイトでは、約 1 週間前に通知しています。また、Web サイトが 1 時間停止したとしてもユーザーが混乱に陥らないようなニュース・サイトであれば、サイト停止の当日に通知を行うのでも構いません。

通知の形式も、サイトの特質や、ユーザーと通信するために現在使っている手段によって異なります。SmallPayroll.ca の場合には、ユーザーがログインしたときにすぐに目につくメッセージを表示するだけで十分でしょう。例えば、「システムは 2010年 6月 24日の午前 12時 1分から午前 1時 (東部標準時) までの間、ご利用になれません。この期間の前に入力されたデータはすべて保存されます。詳細については、こちらをクリックしてください。」といったメッセージを表示します。このメッセージは、ユーザーに必要な以下の 3 つの重要な情報を提供しています。

  • 停止が予定されている期間 (タイムゾーンを含む)
  • データが安全であることの再確認
  • 詳細情報へのポインター

可能であれば、真夜中という言葉を含めるようにし、午前 12時や午後 12時という表現を使用するのは避けてください。このような表現は混乱を招きがちです。例えば 6月 17日の真夜中が早朝 (12時 1分) を意味するのか、あるいは深夜 (11時 59分) を意味するのかがわからない人々は少なくありません。同じように、正午という表現についても、それが午前 12時なのか、午後 12時なのか確信の持てない人々は大勢います。分を追加して時刻を明確にしたほうが、遥かにわかりやすくなります。

特に停止時間中に一部の機能が使用可能であることが予想される場合など、メッセージの詳細は異なります。けれども停止期間中にだけ通知を表示することにした場合 (ニュース・サイトの場合など) でも、上記と同じような情報が役立ちます。私のお気に入りのサイトが停止していたときの画面には、「このサイトはメンテナンスのため現在停止中です。午後 3時 (東部標準時) 頃に再びご利用可能になります。その間は、この Asteroids ゲームをお楽しみください!」という一節が表示されていました。

内部ユーザーについても、おろそかにしないでください。お客様担当者がいる場合には、お客様から質問された場合に備えて、彼らに通知しておく必要があります。

DNS に関する考慮事項

DNS (Domain Name System) は、例えば www.example.com という名前を 192.0.32.10 という IP アドレスに変換します。コンピューターは IP アドレスを基に接続するため、この変換は重要です。ある環境から別の環境にマイグレーションする場合、必ずと言っていいほど、前とは異なる IP アドレスを使うことになります (マイグレーションの前後で、ホスト・コンピューターのある建物が変わらない場合などは例外です)。

コンピューターは全体的な応答時間を短縮するために、TTL (Time To Live) と呼ばれる一定の期間、名前と IP とのマッピングをキャッシュしておきます。ある環境から別の環境に切り替えたときに (したがって、IP アドレスは変わります)、ユーザーのコンピューターで DNS エントリーがキャッシュに入れられていると、そのユーザーは前の環境を使用し続けようとすることになります。そのため、アプリケーションの DNS エントリーおよびそれに関連付けられた TTL は、慎重に管理しなければなりません。

一般に TTL は、1 時間から 1 日までの長さですが、マイグレーションを準備する際には、TTL をそれよりも短くしなければなりません (例えば 5 分など)。この変更は、アドレスを変更するタイミングの少なくとも 1 TTL 期間前には行わなければなりません。なぜなら、コンピューターは名前と IP のマッピングと併せて TTL を取得するためです。例えば、www.example.com の TTL が 86,400 秒 (1 日) に設定されているとしたら、マイグレーションの 1 日前までに、TTL を 5 分に設定し直さなければなりません。

以前の環境と新しい環境との分離

マイグレーションを行う前に不可欠な作業は、新しい環境のテストを十分に行うことです。テストはすべて、本番環境とは別の環境で行わなければなりません。その際、望ましいのは本番データのスナップショットを使用することで、それによって新しい環境により適したテストをすることができます。

本番データのスナップショットを使用してすべてのテストを行うことには、2 つの目的があります。1 つは、開発中に使用されるテスト・データと違って、実際に使用されるデータを予測するのは困難なため、実際のデータを使用することで、エラーを見つけやすくすることです。実際のデータを使用すると、コピーし忘れたファイルや、ウォークスルーの間に忘れられていた特定の構成を必要とするファイルに気付く場合もあります。

本番データを使用するもう 1 つの理由は、データをロードすると同時にマイグレーションの実地練習もできるためです。これにより、実際の環境の切り替えは別として、マイグレーション計画のほとんどの側面を証明することができます。

本番環境であるかの如く新しい環境を作成するとしても、アプリケーションのホスト名と関連付けられるのは、1 つの環境に限られます。この制約を回避する最も簡単な方法は、hosts ファイル内で DNS を変更することです。このファイルが置かれているのは、UNIX® では /etc/hosts、Windows® では C:\windows\system32\drivers\etc\hosts です。既存の行のフォーマットに従ってエントリーを追加し、そのエントリーでアプリケーションのホスト名を将来の IP アドレスに対応させればよいのです。この追加作業は、イメージ・サーバーや移行する予定のすべてのサーバーに対して忘れずに行ってください。ブラウザーを再起動しなければならないことになると思いますが、再起動後は、本番 URL を入力すると新しい環境にアクセスできるようになります。


Amazon EC2 入門

Amazon EC2 サービスでは、時間単位の料金で仮想マシン (VM) を使用することができます。Amazon で用意しているさまざまなタイプのマシンは、CPU、メモリー、そしてディスク・プロファイルによって分類されています。Amazon ではメモリーおよびディスクについてはギガバイト単位で測定し、CPU については Amazon ECU (EC2 Compute Units) 単位を使用します。ECU は 1.0 から 1.2 GHz の AMD Opteron または Intel® Xeon® プロセッサー (2007年当時) に相当します。例えば、標準的な small インスタンスでは、メモリーは 1.7GB、ディスク・スペースは 160GB、CPU は 1 ECU となります。この記事を執筆している時点で最大のマシンは、68.4GB のメモリー、1.7TB のディスク・スペース、そして 8 つの仮想コアで分割された 26 の ECU を備えた High-memory Quadruple Extra Large です。時間単価は、最低で 8.5 セント (US)、最大で 2.40 ドル (US) となっています。

Amazon EC2 インスタンスでは、最初に AMI (Amazon Machine Image) を選択します。AMI は、任意の数の VM を作成するために使用するテンプレートです。Amazon で公開している AMI とは別に、独自の AMI を作成して他のユーザーと共有することもできます。ユーザーが作成した AMI には、無料で使用できるものも、Amazon の時間単価に時間あたりの別料金がかかるものもあります。例えば IBM で公開している有料の AMI では、時間単位でライセンス使用料を支払えるようになっています。

VM をブートするときには、マシン・タイプと AMI を選択します。インスタンスを起動すると AMI が Amazon S3 に保管され、VM のルート・パーティションにコピーされます。ルート・パーティションは常に 10GB です。マシン・タイプに関連付けられたストレージ・スペースは、インスタンス・ストレージ (instance storage)、または一時ストレージ (ephemeral storage) と呼ばれ、個々のドライブとして VM に提示されます。このストレージが一時ストレージと呼ばれる理由は、インスタンスをシャットダウンすると、情報は永久に消えてしまうためです。データを損失しないための対策として、データを定期的にバックアップするように求められます。また、インスタンスを実行している物理ホストがクラッシュした場合には、インスタンスがシャットダウンして、一時ディスクが失われることにもなります。

AMI (Amazon Machine Image)

すべての AMI には、Amazon によって ID (ami-0bbd5462 のような ID) が割り当てられます。Amazon で提供しているパブリック AMI の他、ユーザーが独自に作成して公開している AMI もあります。このように、パブリック AMI をベースに独自の変更を加えることも、一から AMI を作成することもできます。AMI のルート・ファイルシステムに変更を加える場合には、それを新しい AMI として保存することができます。この作業は、再バンドルと呼ばれます。

この連載で最初に着手するのは、公開されている CentOS イメージですが、これとは別のイメージを選択しても構いません。いずれのイメージを使用するにしても、そのイメージをよく調べ、追加料金が発生しないこと、そしてパッケージが更新されていることを確かめるのが賢明です。また、独自の AMI を一から作成することもできますが、それについてはこの記事では説明しません。

Amazon API

Amazon EC2 クラウドを開始、停止、そして利用するために必要な機能はすべて、Web サービスを介して使用するようになっています。Amazon ではこれらの Web サービスの仕様を公開しているだけでなく、一連のコマンド・ライン・ツールも提供しています。これらのツールをダウンロードしてから (「参考文献」を参照)、記事の続きを読んでください。また、クイック・スタート・ガイド (「参考文献」を参照) を参考に環境をセットアップしておくことをお勧めします。セットアップを済ませておけば、この後の入力の手間がかなり省かれることになります。

API への認証には、セキュリティー・クレデンシャルを使用します。クレデンシャルは、AWS (Amazon Web Services) 管理コンソール (「参考文献」を参照) の Account リンクから確認することができます。必要となるのは、X.509 証明書ファイルとアクセス・キーです。この 2 つは安全に保管してください。他のユーザーがあなたになり済まして AWS リソースを使用し、料金が発生する恐れがあるためです。

最初のインスタンスを起動する前に

最初のインスタンスを起動する前に、新しいインスタンスへの認証に使用する SSH (Secure Shell) 鍵を生成して、インスタンスを保護するための仮想ファイアウォールをセットアップする必要があります。リスト 1 に、ec2-add-keypair コマンドを使用して SSH 鍵ペアを生成する方法を示します。

リスト 1. SSH 鍵ペアの生成
[sean@sergeant:~]$ ec2-add-keypair main
KEYPAIR main    40:88:59:b1:c5:bc:05:a1:5e:7c:61:23:5f:bc:dd:fe:75:f0:48:01
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAu8cTsq84bHLVhDG3n/fe9FGz0fs0j/FwZiDDovwfpxA/lijaedg6lA7KBzvn
...
-----END RSA PRIVATE KEY-----
[sean@sergeant:~]$ ec2-describe-keypairs
KEYPAIR main    40:88:59:b1:c5:bc:05:a1:5e:7c:61:23:5f:bc:dd:fe:75:f0:48:01

最初のコマンドで Amazon に対し、main という名前で鍵ペアを生成するように指示しています。出力の最初の行に示されているのは鍵のハッシュで、残りは暗号化されていない PEM 秘密鍵です。この鍵は、例えば ~/.ssh/main.pem などの場所に保管してください。鍵のペアのうち、公開鍵のほうは Amazon によって保持され、ユーザーが起動する VM で使用されます。

2 番目のコマンド、ec2-describe-keypairs では、Amazon に現行の鍵ペアのリストを要求しています。このコマンドにより、鍵ペアの名前、続いてハッシュが出力されます。

各インスタンスを保護する仮想ファイアウォールには、初期段階ではトラフィックを許可する対象が何も設定されていません。Amazon EC2 は仮想ファイアウォールによって保護されたインスタンスをセキュリティー・グループと呼び、API 呼び出しとコマンドを使ってセキュリティー・グループを操作します。セキュリティー・グループの操作については、説明が必要になった時点で詳しく説明するので、とりあえずはリスト 2 に現行のセキュリティー・グループを表示する方法を記載します。

リスト 2. 現行のセキュリティー・グループの表示
[sean@sergeant:~]$ ec2-describe-group
GROUP   223110335193    default default group

リスト 2 には、説明として「default group」と記された「default」という名前のグループが示されています。このグループに関連付けられたユーザー ID は「22311033519」です。このグループに設定されている規則はありませんが、規則が設定されているとしたら、グループの下の左側の列に PERMISSION という語が表示され、そこで規則が説明されることになります。


クラウド環境の準備

クラウド環境を準備する際の最初のステップは、アプリケーションをテストすることです。新しい環境は現行の本番環境を模倣することになります。

まず始めに、ami-10b55379 という ID が割り当てられた AMI を起動します。リスト 3 に、AMI の起動とそのステータス・チェックが行われている様子を示します。

リスト 3. CentOS AMI の起動
[sean@sergeant:~]$ ec2-run-instances ami-10b55379 -k main
RESERVATION  r-750fff1e  223110335193  default
INSTANCE  i-75aaf41e  ami-10b55379  pending  main  0  m1.small
2010-05-15T02:02:57+0000 us-east-1a  aki-3038da59  ari-3238da5b  monitoring-disabled
instance-store  
[sean@sergeant:~]$ ec2-describe-instances i-75aaf41e
RESERVATION  r-750fff1e  223110335193  default
i-75aaf41e  ami-10b55379  pending  main  0  E3D48CEE  m1.small
2010-05-15T02:02:57+0000 us-east-1a  aki-3038da59  ari-3238da5b  monitoring-disabled
instance-store  
[sean@sergeant:~]$ ec2-describe-instances i-75aaf41e
RESERVATION  r-750fff1e  223110335193  default
INSTANCE  i-75aaf41e  ami-10b55379  ec2-184-73-43-141.compute-1.amazonaws.com
domU-12-31-39-00-64-71.compute-1.internal  running  main  0  E3D48CEE  m1.small
2010-05-15T02:02:57+0000  us-east-1a  aki-3038da59  ari-3238da5b  monitoring-disabled
184.73.43.141  10.254.107.127  instance-store

最初のコマンドは ami-10b55379 AMI を使用してインスタンスを起動し、リスト 1 で生成された鍵ペアをマシンへの認証に使用すると指定しています。コマンドが返す情報の中で最も重要なのは、インスタンス ID (i-750fff1e) です。これは、Amazon EC2 クラウドでのマシンの ID です。2 番目のコマンドは、ec2-describe-instances コマンドを使用しています。このコマンドは実行中のインスタンスをすべて一覧表示しますが、リスト 3 ではインスタンス ID をコマンド・ラインに渡したため、そのインスタンスに関する情報だけが表示されています。インスタンスの状態は pending と表示されています。これは、インスタンスが起動中であることを意味します。IBM AMI はサイズが大きいため、通常は起動するだけでも 5 分から 10 分はかかります。しばらく経ってから同じコマンドを実行すると、状態は running となり、外部 IP アドレスとして 184.73.43.141 が付与されたことがわかります。10 で始まる内部 IP アドレスは Amazon EC2 クラウドと対話するのに役立ちますが、今のところはまだ使用しません。

これで SSH を使用して、前に生成した鍵を使ってサーバーに接続できる状態になりました。しかしその前に、SSH (22/TCP) を許可する必要があります。接続を許可して新しいサーバーにログインする方法は、リスト 4 に示されています。

SSH 鍵について

SSH 鍵についてよく知らない場合は、SSH ではパスワードではなく、鍵を使ってユーザーを認証できることを知っておくと役立ちます。生成する鍵のペアは、公開鍵と秘密鍵からなります。秘密鍵は人に知られないように維持し、公開鍵は authorized_keys というファイルにアップロードします。このファイルは、$HOME/.ssh ディレクトリー内にあります。SSH でサーバーに接続すると、クライアントが鍵を使って認証を試行することができます。認証に成功すれば、ログインされた状態になります。

鍵ペアが持つ 1 つの特性は、一方の鍵によって暗号化されたメッセージは、もう一方の鍵を使わなければ復号できないことです。ユーザーがサーバーに接続すると、サーバーは authorized_keys ファイルに保管された公開鍵を使ってメッセージを暗号化することができます。ユーザーが公開鍵を使ってメッセージを復号できれば、サーバーは、そのユーザーはパスワードなしでログインが許可されていることを把握します。

そこで疑問となるのは当然、「Amazon で保管される authorized_keys ファイルには、どのように公開鍵が入力されるか」という点です。それぞれの Amazon EC2 インスタンスは http://169.254.169.254 に位置する Amazon EC2 クラウドにアクセスし、クラウド内のサーバーとやりとりしてインスタンスに関するメタデータを取得することができます。URL のうち、http://169.254.169.254/latest/meta-data/public-keys/0/openssh-key という URL が、イメージに関連付けられた公開鍵を返します。

AMI は起動時に公開鍵を取得し、それを authorized_keys に保管します。サンプル AMI では、この動作は /etc/init.d/getssh で行われますが、rc.local で行うとしても簡単です。

インスタンス・メタデータの別の使い道は、情報をイメージに渡すことです。Web サーバーとしても、バックグラウンド・ジョブ・サーバーとしても使える 1 つの汎用 AMI を使用し、そのインスタンスに、イメージの起動時に渡すパラメーターを基にどのサービスを起動するかを決定させることができます。

リスト 4. インスタンスへの接続
[sean@sergeant:~]$ ec2-authorize default -p 22 -s $MYIP/32
...
[sean@sergeant:~]$ ssh -i ~/.ssh/main.pem root@184.73.43.141
The authenticity of host '184.73.43.141 (184.73.43.141)' can't be established.
RSA key fingerprint is af:c2:1e:93:3c:16:76:6b:c1:be:47:d5:81:82:89:80.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '184.73.43.141' (RSA) to the list of known hosts.
...

上記では、最初のコマンドで IP アドレスのソースからポート 22 (TCP はデフォルト・オプションです) を許可します。/32 は、ネットワーク全体ではなく、ホストだけを許可することを意味します。そして ssh コマンドで、秘密鍵を使ってサーバーに接続します。

Ruby のインストール

CentOS に付属している Ruby は古いバージョンなので、これから REE (Ruby Enterprise Edition) をインストールします。REE はハイパフォーマンス Ruby インタープリターで、現行の Ruby 1.8.7 との互換性があります。高価そうな響きの名前ですが、このソフトウェアはオープンソースです。リスト 5 に、REE のインストール方法を示します。

リスト 5. REE のインストール
# rpm -e ruby ruby-libs
# yum -y install gcc-c++ zlib-devel openssl-devel readline-devel
...
Complete!
# wget http://rubyforge.org/frs/download.php/71096/ruby-enterprise-1.8.7-2010.02.tar.gz
...
# tar -xzf ruby-enterprise-1.8.7-2010.02.tar.gz
# ruby-enterprise-1.8.7-2010.02/installer -a /opt/ree

リスト 5 の最初の 2 つのコマンドで、デフォルトの Ruby インストールを削除し、C コンパイラーといくつか必要な開発パッケージをインストールします。次に wget で現行の REE の tarball をダウンロードした後、これを tar によって解凍します。最後のコマンドでは、すべてのデフォルトを受け入れて結果を /opt/ree に配置するように指定するオプションを追加して、インストーラーを実行します。インストーラーは、欠落しているパッケージがある場合に実行する必要のあるコマンドを通知するだけの賢さを持ち合わせているため、インストールが上手く行かない場合には出力をよく調べてください。

Ruby のインストールが完了したら、export PATH="/opt/ree/bin:$PATH" を実行して bin ディレクトリーをパスに追加します。bin ディレクトリーは、システム全体の /etc/bashrc、またはホーム・ディレクトリー内の.bashrc ディレクトリーに配置することができます。

PostgreSQL のインストール

PostgreSQL サーバーは CentOS ディストリビューションに含まれているため、後は yum ユーティリティーを使ってこのサーバーをインストールするだけです。リスト 6 に、PostgreSQL をインストールし、ブート時に起動することを確認する方法を示します。

リスト 6. PostgreSQL のインストール
# yum -y install postgresql-server postgresql-devel
...
Installed: postgresql-devel.i386 0:8.1.21-1.el5_5.1 
   postgresql-server.i386 0:8.1.21-1.el5_5.1
Dependency Installed: postgresql.i386 0:8.1.21-1.el5_5.1 
   postgresql-libs.i386 0:8.1.21-1.el5_5.1
Complete!
# chkconfig postgresql on

yum コマンドはリポジトリーからパッケージをインストールします。リスト 7 では、PostgreSQL サーバー・コンポーネントと開発ライブラリーをインストールしています。こうすることによって、コアとなるデータベース・ユーティリティーと、必要なその他すべてのパッケージが自動的に取り込まれます。開発パッケージが必要になるのはまだ先の話ですが、Rails と PostgreSQL を統合する段階になったら、postgresql-devel に含まれるライブラリーが必要になります。

デフォルトでは、データベースはそのファイルを /var/lib/pgsql/data に保管します。これは、ルート・ファイルシステムの一部となっているディレクトリーです。このディレクトリーを、/mnt にあるインスタンス・ストレージに移動してください (リスト 7 を参照)。

リスト 7. PostgreSQL データ・ストアの /mnt への移動
# mv /var/lib/pgsql/data /mnt
# ln -s /mnt/data /var/lib/pgsql/data
# service postgresql start

リスト 7 のコマンドを入力した後は、PostgreSQL が /mnt から実行されます。

次に必要な作業は、payroll_prod データベース (次のステップで作成します) に対するパスワード・ログインを有効にすることです。デフォルトでは、PostgreSQL はパスワードを使用しません。使用するのは、内部識別システムです。パスワード・ログインを有効にするには、以下の行を追加します。

host    "payroll_prod" all  127.0.0.1/32   md5

上記の行を /var/lib/pgsql/data/pg_hba.conf の先頭に追加したら、以下のコマンドを実行します。

su - postgres -c 'pg_ctl reload'

これで、変更が適用されます。この構成では、PostgreSQL への通常のログインにはパスワードが不要ですが (これが、reload コマンドにパスワードが必要でなかった理由です)、給与データベースにアクセスする場合には常にパスワードが必要になります。

最後のステップでは、コマンド・ラインから Rails データベースをセットアップします。su - postgres -c psqlを実行した後、リスト 8 のコードに従ってください。

リスト 8. ユーザーおよびデータベースの作成
postgres=# create user payroll with password 'secret';
CREATE ROLE
postgres=# create database payroll_prod;
CREATE DATABASE
postgres=# grant all privileges on database payroll_prod to payroll;
GRANT

これで、データベースは作成できました。

データのマイグレーション

テストに使えるように、ある特定の時点で、本番環境のデータベース・ダンプを取得してください。SmallPayroll アプリケーションは、データをデータベースとファイルシステムの両方に保管します。データベースをダンプするには、PostgreSQL に付属の pg_dump コマンドを使用します。一方、ファイルシステム・データでは rsync を使用します。データベース・ダンプの特性から、データベースについては内容を消去してマイグレーション用に再転送しなければなりませんが、ファイルシステム・データについては、新しいファイルと変更後のファイルを転送するだけで済みます。これは、rsync では、ファイルが変更されている場合にはそれを検出できるからです。したがって、計画のテスト部分でデータの大部分がすでに用意されることになるため、マイグレーションにかかる時間が短縮されます。

データベースを最も短時間でコピーするには、以下のコマンドを実行します。

pg_dump payroll_prod | gzip -c > /tmp/dbbackup.gz

上記のコマンドを本番マシンで実行し、dbbackup.gz をクラウド・サーバーにコピーした後、以下のコマンドを実行します。

zcat dbbackup.gz | psql payroll_prod

このコマンドは、一方のサーバーでデータベースの圧縮ダンプを作成した後、もう一方のサーバーですべてのトランザクションを再現します。

rsync も同じく単純です。本番サーバーから以下のコマンドを実行してください。

rsync -avz -e "ssh -i .ssh/main.pem" /var/uploads/ root@174.129.138.83:/var/uploads/

このコマンドは、/var/uploads の内容をすべて、現行の本番サーバーから新しいサーバーにコピーします。コマンドを再度実行すると、変更されたファイルだけがコピーされるので、後で同期を行うときの時間を節約することができます。

データベースをコピーしていることから、あらかじめ Rails マイグレーションを適用する必要はありません。schema_migrations テーブルがすでにコピーされているため、Rails はデータベースが最新の状態であると認識します。

Rails アプリケーションのデプロイメント

この時点で、基本サーバーのセットアップは完了していますが、アプリケーションはまだセットアップできていません。アプリケーションを実行する前に、基本の gem と併せ、アプリケーションに必要な gem をインストールする必要があります。リスト 9 に、gem を更新するためのコマンドを記載します。注意する点として、以下のコードは Rails アプリケーションのルートから実行しなければならないので、最初にコードをサーバーにコピーしてから実行してください。

リスト 9 RubyGems の更新および必要な gem のインストール
# gem update --system
Updating RubyGems
Nothing to update
# gem install rails mongrel mongrel-cluster postgres
Successfully installed rails-2.3.8
Building native extensions.  This could take a while...
Successfully installed gem_plugin-0.2.3
Successfully installed daemons-1.1.0
Successfully installed cgi_multipart_eof_fix-2.5.0
Successfully installed mongrel-1.1.5
Successfully installed mongrel_cluster-1.0.5
Building native extensions.  This could take a while...
Successfully installed postgres-0.7.9.2008.01.28
7 gems installed
...
# rake gems:install
(in /home/payroll)
gem install haml
Successfully installed haml-3.0.12
1 gem installed
Installing ri documentation for haml-3.0.12...
Installing RDoc documentation for haml-3.0.12...
gem install money
...

上記では、最初のコマンドで RubyGems 自体が最新の状態であることを確認し、2 番目のコマンドで以下の有用な gem をインストールしています。

  • rails: Ruby on Rails フレームワーク
  • postgres: PostgreSQL を ActiveRecord と一緒に使用できるようにするデータベース・ドライバー
  • mongrel: Rails アプリケーションをホストするために使用するアプリケーション・サーバー
  • mongrel_cluster: mongrel のグループを同時に起動、停止するために使用できるユーティリティー

最後のコマンドは Rails タスクを実行し、アプリケーションに必要なその他すべての gem をインストールします。config/environment.rb ファイルで config.gem ディレクティブを使用していなかったとしたら、gem install gemname コマンドを使用して、追加の gem を手動でインストールしなければならないことも考えられます。

RAILS_ENV=production script/console コマンドを実行してアプリケーションを起動してみてください。このコマンドが成功したら、アプリケーションを停止して、以下のコマンドで一連の mongrel を起動します。

mongrel_rails cluster::start -C /home/payroll/current/config/mongrel_cluster.yml

最初のコマンドが成功しないと、大量のエラー・メッセージを受け取ることになります。これらのエラー・メッセージは、問題 (通常は gem やファイルの欠落) を突き止めるのに役立ちます。今後 gem を忘れないように、この機会を利用して欠落している config.gem ディレクティブを入力しておいてください。

フロントエンド Web サーバーのインストール

nginx は、多くの仮想環境で選ばれている Web サーバーです。nginx のオーバーヘッドは少なく、mongrel のようなバックエンド・サービスへの接続を代行するにはうってつけです。リスト 10 に、nginx のインストール方法を示します。

リスト 10. nginx のインストール
# rpm -Uvh http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-3.noarch.rpm
...
# yum install nginx
...
Running Transaction
Installing     : nginx                                             [1/1]
Installed: nginx.i386 0:0.6.39-4.el5
Complete!
# chkconfig nginx on

リスト 10 では EPEL (Extra Packages for Enterprise Linux®) リポジトリーをインストールした後、nginx をインストールし、起動時にこれが立ち上がることを確認しています。

リスト 11. Rails アプリケーション用の nginx の構成
# Two mongrels, balanced based on least connections
upstream mongrel-payroll {
	fair;
	server 127.0.0.1:8100;
	server 127.0.0.1:8101;
}

server {
	listen 80;
	server_name  app.smallpayroll.ca;

	root   /home/payroll/current/public;
	gzip_static on;

	access_log  /var/log/nginx/app.smallpayroll.ca_log  main;
	error_page  404       /404.html;

	location / {
		# Because we're proxying, set some environment variables indicating this
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header Host $http_host;
		proxy_redirect false;
		proxy_max_temp_file_size 0;


		# Serve static files out of Root (eg public)
		if (-f $request_filename) {
			break;
		}

		# Handle page cached actions by looking for the appropriately named file
		if (-f $request_filename.html) {
			rewrite (.*) $1.html;
			break;
		}

		# Send all other requests to mongrel
		if (!-f $request_filename) {
			proxy_pass http://mongrel-payroll;
			break;
		}
	}
	error_page   500 502 503 504  /500.html;
	location = /500.html {
		root   /home/payroll/current/public;
	}
}

リスト 11 に記載した nginx の構成は極めて典型的なもので、Rails ページのキャッシングを処理し、動的リクエストをアップストリームの mongrel に送信するための要素が組み込まれています。ここでは必要に応じて、他の URL をファイル名にマッピングすることもできます。

構成は用意できました。これで、service nginx start と実行すると Web サーバーが起動します。

テスト

テストの際には、本番サイトではなく、確実にテスト・サイトを使用するようにしなければなりません。そのため、アプリケーションの通常のドメイン名を使ってクラウド・インスタンスを参照できるとしたら助けになります。通常のドメイン名を使用できるようにするには、ローカル DNS を変更します。Windows では C:\windows\system32\drivers\etc\hosts を、UNIX では /etc/hostsを編集して、以下のような行を追加します。

x.x.x.x  app.smallpayroll.ca

ここで、x.x.x.x は使用するクラウド・サーバーの IP アドレス、app.smallpayroll.ca はアプリケーションの名前です。ブラウザーを再起動して、Web サイトを参照してください。現在使用しているのは、クラウド版のアプリケーションです (本番サイトに戻る場合は、上記で追加した行を忘れずにコメント・アウトしてください)。

この時点で、クラウド版のアプリケーションが本番サイトのアプリケーションとまったく同じく動作をするかどうかをテストして、見つかった問題を修正することができます。気付いたことがあったら、何でもメモしておいてください。2 番目のサーバーを立ち上げるとしたら、メモの内容をスクリプトにする必要があるからです。使用しているアプリケーションはクラウド版なので、データベースを削除してリストアしても、ユーザーが文句を言うことはありません。

新しい AMI のバンドル

最後に行う作業は、AMI の再バンドルです。新しいインスタンスを起動すると常に、/mnt の内容がすべてクリアされ、ルート・パーティションが AMI での設定にリセットされます。/mnt の問題についてはまだ何の対処もできませんが、再バンドルによって、確実に AMI が終了時の状態を維持できるようにします。

最初に取り掛かった AMI に AMI ツールがない場合には、以下のコマンドによって AMI ツールをインストールすることができます。

rpm -i --nodeps http://s3.amazonaws.com/ec2-downloads/ec2-ami-tools.noarch.rpm

AMI をバンドルするプロセスには、以下の 3 つのステップがあります。

  1. インスタンス自体でイメージを作成します。
  2. 作成したイメージを Amazon S3 にアップロードします。
  3. AMI を登録します。

作業に進む前に、mongrel および PostgreSQL インスタンスをシャットダウンしてください。これは単に、開いたファイルがすべて適切に処理されるようにするためです。また、X.509 鍵 (Amazon コンソールを調べるとわかります) をサーバー上の /mnt にコピーすることも必要です。リスト 12 に、バンドルの最初の 2 つのステップを記載します。これらのステップは、VM 自体で行います。

リスト 12. AMI のバンドル
# ec2-bundle-vol -d /mnt -e /mnt --privatekey /mnt/pk-mykey.pem  \
--cert /mnt/cert-mycert.pem --user 223110335193 -p centos-ertw
Please specify a value for arch [i386]:
Copying / into the image file /mnt/centos-ertw...
...
Generating digests for each part...
Digests generated.
Creating bundle manifest...
ec2-bundle-vol complete.
# ec2-upload-bundle -b ertw.com -m /mnt/centos-ertw.manifest.xml \
--secret-key MYSECRETKEY --access-key MYACCESSKEY
Creating bucket...
Uploading bundled image parts to the S3 bucket ertw.com ...
...
Uploaded centos-ertw.part.37
Uploading manifest ...
Uploaded manifest.
Bundle upload completed.

最初のコマンドでは、/mnt を無視すること、そしてバンドルを /mnt に配置することを指定して (それぞれ -e オプション、-d オプションで指定)、バンドルを生成します。-k--cert、および --user オプションが指すのは、セキュリティー・クレデンシャルおよび AWS ユーザー ID です (いずれも、AWS 管理コンソールのアカウント設定を見るとわかります)。最後の -p オプションでは、この AMI に名前を付けることで他の AMI と区別することができます。

ルート・パーティションの占有状況によっては、最初のコマンドが完了するまでに約 10 分ほどかかる場合があります。2 番目のコマンドは、バンドルを Amazon S3 にアップロードします。-b オプションが指定するのはバケット名です。指定された名前のバケットがまだ存在していない場合には、その名前のバケットが作成されます。-m オプションは、最初のステップで作成されるマニフェスト・ファイルを指します。最後の 2 つのオプションは、Amazon S3 クレデンシャルです (AWS 管理コンソールの X.509 クレデンシャルのすぐ隣にあります)。Amazon EC2 の操作では X.509 クレデンシャルが使用される一方、Amazon S3 ではテキスト・キーを使用するとだけ、覚えておいてください。

最後に、以下のコマンドを実行します。

ec2-register ertw.com/centos-ertw.manifest.xml

このコマンドによって AMI が登録されると、今後使用することになる AMI ID が表示されます。ec2-register コマンドは AMI と一緒には配布されないため、元の AMI を起動したサーバーから実行するのが最も簡単な方法です。また、Amazon EC2 インスタンスに Amazon EC2 ツールをインストールすることもできます。


マイグレーションの実行

クラウド環境を実行中の状態にまですることができれば、マイグレーション自体の作業は比較的簡単です。すべてが上手くいっていることは確認できているので、後はデータを再同期させて、決められた方法でカットオーバーするだけです。

マイグレーション前のタスク

マイグレーションに先立って、必ずドメイン名レコードの TTL を 5 分に設定してください。また、すべてを移動するために行うステップ、すべてが機能することを検証するために実行するテスト、そして必要な場合に変更をバックアウトするための手順をすべて網羅したチェックリストを作成します。

ユーザーには必ず、マイグレーションについて通知してください!

マイグレーションの直前に、クラウド環境をもう一度調べ、同期を行って本番トラフィックを受け入れる準備ができていることを確認します。

アプリケーションのマイグレーション

以下の手順に従って、アプリケーションをマイグレーションします。

  1. サイトの性質に応じて、現行の本番サイトを使用不可にするか、または読み取り専用モードにします。

    SmallPayroll のリクエストのほとんどは、データベースやファイルシステムへの書き込みが関わってくるため、サイトは使用不可にされます。Capistrano デプロイメント gem に組み込まれている cap deploy:web:disable というタスクは、ユーザーにサイトがメンテナンスのために停止していることを通知するメンテナンス・ページをサイトに配置します。

  2. mongrel プロセスをキルすることによってクラウド環境でのアプリケーション・サービスを停止し、データ・マイグレーションに備えます。
  3. テストの際と同じようにデータベースをコピーします。
  4. 必要に応じて rsync を再実行します。
  5. 以下のコマンドを実行して、アプリケーション・サーバーを再起動します。
    mongrel_rails cluster::start -C /home/payroll/current/config/mongrel_cluster.yml
  6. hosts ファイルがクラウド環境を指していることを確認した後、スモーク・テストを行います。ユーザーがサイトにログインし、サイトをブラウズできることを確認します。

DNS の更新

スモーク・テストに合格したら、クラウド環境を指すように DNS レコードを変更します。このとき、Web サーバーのログ・ファイルで tail -f を実行中の状態にして、サイトを訪れる人々を監視すると役に立つと思います。

ローカル DNS サーバーに古い情報が残っていて、その情報が次の 5 分間キャッシュに入れられる可能性があるので、これを確認するために dig コマンドを使用します (リスト 13 を参照)。

リスト 13. DNS サーバーがクエリーをキャッシュに入れているかどうかの確認
# dig  app.smallpayroll.ca @172.16.0.23

; <> DiG 9.3.4 <> app.smallpayroll.ca @172.16.0.23
; (1 server found)
;; global options:  printcmd
;; Got answer:
;; ->HEADER<- opcode: QUERY, status: NOERROR, id: 38838
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 13, ADDITIONAL: 0

;; QUESTION SECTION:
;app.smallpayroll.ca.           IN      A

;; ANSWER SECTION:
app.smallpayroll.ca.    251     IN      A       69.164.205.185
...

ANSWER セクションを見ると、251 秒後にエントリーの有効期限が切れることがわかります。hosts ファイルは当分の間 DNS を無効にするため、dighost、または nslookup のようなツールを使って DNS を確認することが重要です。ping を使用すると、hosts ファイル内のあらゆるものが使用されることになります。

DNS が伝播するまで待っている間、最終的な受け入れテストを行ってください。


まとめ

これまでの手順で、アプリケーションは正常にクラウドにマイグレーションされました。基本的な手順は以下のとおりです。

  1. 新しい環境をセットアップします。
  2. 本番データのコピーを使ってテストします。
  3. 古い環境を無効にします。
  4. 本番データを新しい環境にコピーします。
  5. 新しい環境を指すように DNS を変更します。

今や「クラウドの中」にあるとは言え、アプリケーションの状態は以前よりも悪くなっているはずなので、以下の点について考慮する必要があります。

  • アプリケーションは今でも 1 つのサーバー上で実行されていること
  • サーバーがクラッシュした場合、すべてのデータが失われること
  • 物理サーバーでのようには強力にパフォーマンスを制御できないこと
  • マシンとアプリケーションがロックダウンされていないこと

次回の記事では、以上の問題を解決する方法を説明し、アプリケーションのための、より堅牢な環境を作成する作業に取り掛かります。

参考文献

学ぶために

製品や技術を入手するために

  • Ruby Enterprise Edition は、ハイパフォーマンスの Ruby 実装で、単独で使用することも、Phusion Passenger と併用して Apache または nginx と統合することもできます。いずれの方法で使用するにしても、迅速にメモリー管理が行えるようになり、ガーベッジ・コレクションが改善されます。
  • IBM Industry Application Platform AMI for Development Use にサインアップして、クラウド内の各種 IBM 製品を使い始めてください。チェックアウト・プロセスを完了する必要がありますが、実際に使用するまでは料金は発生しません。また、ami-90ed0ff9 も使用することができます。
  • Amazon API と通信してインスタンスの起動、終了、そして新規インスタンスの再バンドルを行うには、Amazon EC2 API ツールを使用します。これらのツールは、Amazon EC2 での新しい機能の導入に従って定期的に更新されるので、製品発表の後に、このページが更新されているかどうかをチェックする価値はあります。少なくとも 2009-05-15 時点での更新が必要です。この更新に、連載で今後使用する負荷分散機能が含まれています。
  • ご自分に最適な方法で IBM 製品を評価してください。評価の方法としては、製品の試用版をダウンロードすることも、オンラインで製品を試してみることも、クラウド環境で製品を使用することもできます。また、SOA Sandbox では、数時間でサービス指向アーキテクチャーの実装方法を効率的に学ぶことができます。

議論するために

  • My developerWorks コミュニティーに加わってください。ここでは他の developerWorks ユーザーとのつながりを持てる他、開発者が主導するブログ、フォーラム、グループ、ウィキを調べることができます。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Linux, Cloud computing, Open source
ArticleID=506704
ArticleTitle=Linux アプリケーションを Amazon クラウドにマイグレーションする: 第 1 回 初期マイグレーション
publish-date=07132010