VirtualBoxの仮想マシンをAWS EC2へ移行する手順(VM Import)

VirtualBox上の仮想マシンを、AWS EC2へ移行する機会があったので、手順を残します。

概要

手順は大きく3つになる。

  1. Amazon EC2 API Tools をダウンロード
  2. VirtualBoxのディスクイメージの変換
  3. ディスクイメージをEC2へインポート

前提

手順

手順は、こちらのサイトを参考にしました。 https://www.totalsolution.biz/virutalbox_vmimport_ec2_instance/

1. Amazon EC2 API Tools をダウンロード

まずは「Amazon EC2 API Tools」をダウンロードします。 このツールの動作には JRE or JDK が必要なので、なければインストールしておきます。

Amazon EC2 API Tools」をダウンロードすると、ZIPになっているので、お好きな場所へ展開します。

2. VirtualBoxの仮想ディスクイメージの変換

Amazon EC2 API Tools」で対応している仮想ディスクイメージの形式は、以下のとおりです。 - VMDK - RAW - VHD

このため、VDI形式から対応している形式へ変換する必要があります。 (VMwareなら、そのままインポートできるようですね。)

仮想ディスクイメージの形式を変換するには、VBoxManageコマンドを使用します。 VBoxManageコマンドへのパスが通っていない場合は、 通常はC:\Program Files\Oracle\VirtualBoxにあるので、 こちらへパスを通すかカレントディレクトリを変更します。

コマンドプロンプトで、以下のコマンドを実行すると、VDI形式からRAW形式へ変換できます。

VBoxManage internalcommands converttoraw <VDI形式ファイルパス.vdi> <RAW形式ファイルパス.img>

3. ディスクイメージをEC2へインポート

ディスクイメージをEC2へインポートするには、「Amazon EC2 API Tools」のec2-import-instanceコマンドを使用します。

実行前に、環境変数の設定を行います。

※環境依存の値は、適宜置換してください。

  • アクセスキーID、シークレットアクセスキー
set AWS_ACCESS_KEY=<アクセスキーID>
set AWS_SECRET_KEY=<シークレットアクセスキー>
  • JAVA_HOMEを設定
set JAVA_HOME=C:\Program Files\Java\jdk1.8.0_102
  • その他必要な環境変数
    以下の例では、リージョンを「東京」にしています。
set EC2_HOME=<Amazon EC2 API Tools を配置したパス>
set EC2_URL=https://ec2.ap-northeast-1.amazonaws.com
set EC2_REGION=ap-northeast-1
  • プロキシの設定が必要な場合には、EC2_JVM_ARGS変数に設定します。
set EC2_JVM_ARGS=-DproxySet=true -Dhttp.proxyHost=<address> -Dhttp.proxyPort=<port> -Dhttps.proxySet=true -Dhttps.proxyHost=<address> -Dhttps.proxyPort=<port>
  • パスを通しておきます。
set PATH=%PATH%;%EC2_HOME%

ec2-import-instanceコマンドを実行します。

以下のコマンドを実行すると、RAW形式のディスクイメージがS3にアップロードされ、 その後EC2インスタンスが作成されます。

ec2-import-instance ^
  "<変換したRAW形式ファイルパス>" ^
  -t t2.micro ^
  -f RAW ^
  -a x86_64 ^
  -p Linux ^
  --region ap-northeast-1 ^
  --bucket <S3バケット名> ^
  -o %AWS_ACCESS_KEY% ^
  -w %AWS_SECRET_KEY%

私の環境の場合、アップロード中は、以下のようなエラーが出力され自動で再開されの繰り返しだった。 でも進捗は進んでいるので放置しました。

[Fatal Error] :2:18: Open quote is expected for attribute "http-equiv" associated with an  element type  "META".

しかし進捗が99%のまま全然進まなかったので、一度コマンドを途中でキャンセル(Ctrl+C)してしまいました。 この場合、もう一度アップロードするには時間がかかりますが、レジューム用のコマンドが用意されているので、助かった。

レジュームするには、まずタスクIDを知る必要があるが、以下のコマンドで確認することができる。

ec2-describe-conversion-tasks

レジュームしたいタスクIDが分かったら、以下のコマンドを実行すると、レジュームできる。

ec2-resume-import ^
  "<変換したRAW形式ファイルパス>" ^
  -t <タスクID> ^
  -o %AWS_ACCESS_KEY% ^
  -w %AWS_SECRET_KEY%

キャンセルとレジュームを繰り返していたら、いつの間にかタスクが完了したためレジュームができなくなって、EC2インスタンスが作成されていた。

とりあえず起動できたので、よしとする。

SSL上のCakePHP2でロードバランサやWAFを導入する際の注意点

最近、CakePHPで作られたSSL前提のサイトでWAFを導入することになったのですが、気になったことがあったので調べて見ました。

SSLで暗号化するサイトで、ロードバランサやWAFを導入する場合、 Webサーバーではフロント側(ロードバランサやWAF)で復号化されたリクエストを受け付ける構成が多いかと思います。

この構成の場合、WebサーバーではもちろんHTTPSではなくHTTPで通信しているものと解釈されます。

ここでCakePHPで2つ問題点が出てきます。(まだあるかも)

  1. Cookieにsecure属性がつかない
  2. リダイレクト時のURLが異なる

対応方法

1. Cookieにsecure属性がつかない

CakePHPではHTTPかHTTPSかで、セッションIDを保存するCookieのsecure属性を切り替えているようです。 セッション — CakePHP Cookbook 2.x ドキュメント

このため、あまりよろしくない状態になります。

対応方法としては、公式ドキュメントを参考に、phpの設定「session.cookie_secure」を有効にすればよいです。

<? php
Configure::write('Session', array(
    'defaults' => 'php',
    'ini' => array(
        'session.cookie_secure' => true
    )
));

SSL通信だけのWebサーバーなら、php.iniで有効にしてもいいですね。

session.cookie_secure = 1
2. リダイレクト時のURLが異なる

ログインなどでリダイレクトが使われているのですが、このリダイレクト先のURLがHTTPとなるので、接続できなくなる可能性があります。 というか、HTTPSしか許可していないなら接続できないですね。

この対応は、CakePHPで用意されているRouter::fullBaseUrlメソッドで、ベースとなるサイトのURLを設定すればよいみたいです。URLの最後にスラッシュはいらないようです。 Routing — CakePHP Cookbook 2.x documentation

<? php
Router::fullbaseUrl( 'https://example.jp/hogehoge' );

こちらのサイトにある、ロードバランサ等からの情報で切り替えるようにするのも有効かもしれない。 CakePHPでロードバランサ配下のサーバでHTTPSのリクエストが正常に判断されない問題 - 【鋭利団体】PK-Brothers

<? php
if ( isset($_SERVER['HTTP_X_FORWARDED_PORT']) && 443 == $_SERVER['HTTP_X_FORWARDED_PORT'] ) {
    Router::fullbaseUrl( 'https://'.$_SERVER['HTTP_HOST'] );
}