VM Importでイメージインポートしてみた

2016.09.23

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちわ。A.T.フィールドよりIフィールド派な市田です。
今回は、みんな大好きVM Importについてのエントリになりますが、今回は「イメージによるインポート」についてご紹介したいと思います。

イメージのインポートとインスタンスのインポートの違い

VMインポートでよく混同されるのが、「イメージのインポート」と「インスタンスのインポート」です。それぞれインポートするものが異なり、利用するツールも異なります。
実際、ec2-api-toolsのことを公式ドキュメントでは「Amazon EC2 CLI」という表現になっており、「AWS CLI」と混同される要因の一つになっているのかもしれません。

いずれもコマンドラインから操作するので、よく混同される傾向があるようですが下記のような違いがあります。

特徴 イメージのインポート インスタンスのインポート
CLIサポート AWS CLI Amazon EC2 CLI (ec2-api-tools)
インポートでサポートされる形式 OVA、VHD、VMDK、raw VHD、VMDK、raw
複数ディスクのサポート 不可
Windows BYOLサポート 不可
作成されるもの AMI
(インスタンスは作成されない)
EC2インスタンス
(AMIは作成されない)

参考: VM Import/Export の仕組み

今回の対象はイメージインポート

今回ご紹介するのは、イメージのインポートの方法についてです。
「インスタンスのインポート」については、下記のエントリで紹介させていただいています。

VM ImportでVMwareからAWS EC2へマイグレーションしてみた | Developers.IO

どちらがいいか

VMware環境からの単なる移行なら「インスタンスのインポート」が手っ取り早いと思いますが、ec2-api-toolsを使うための環境構築が少々手間になります。

イメージインポートの場合、AMIが作られる形になるため、AMIからインスタンスを作成する際に、セキュリティグループや、EBSサイズの指定などができます。
またAWS CLIは、MacやWindows、Linuxなどに比較的簡単にインストールできるので、個人的にはイメージインポートがお薦めかなと思います。

注意点

インポート可能なOSに制限などがあるので、事前に確認しておくようにしましょう。

VM Import/Export 前提条件

手順の概要

  • IAMユーザの作成と必要権限の付与
  • インポートするVMの準備
  • VMwareの環境からファイルエクスポート
  • S3バケットの作成
  • VM Import サービスロールの作成
  • エクスポートしたファイルをS3へアップロード
  • インポート

それでは、手順を見ていきたいと思います。
ちなみに、今回はCentOS6.8をインポートしてみます。

IAMユーザーに必要なアクセス許可の設定

専用のIAMユーザ(vmimportuser)を作成します。
ポリシーは下記の通りです。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:ListAllMyBuckets"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:CreateBucket",
        "s3:DeleteBucket",
        "s3:DeleteObject",
        "s3:GetBucketLocation",
        "s3:GetObject",
        "s3:ListBucket",
        "s3:PutObject"
      ],
      "Resource": ["arn:aws:s3:::mys3bucket","arn:aws:s3:::mys3bucket/*"]
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CancelConversionTask",
        "ec2:CancelExportTask",
        "ec2:CreateImage",
        "ec2:CreateInstanceExportTask",
        "ec2:CreateTags",
        "ec2:DeleteTags",
        "ec2:DescribeConversionTasks",
        "ec2:DescribeExportTasks",
        "ec2:DescribeInstanceAttribute",
        "ec2:DescribeInstanceStatus",
        "ec2:DescribeInstances",
        "ec2:DescribeTags",
        "ec2:ImportInstance",
        "ec2:ImportVolume",
        "ec2:StartInstances",
        "ec2:StopInstances",
        "ec2:TerminateInstances",
        "ec2:ImportImage",
        "ec2:ImportSnapshot",
        "ec2:DescribeImportImageTasks",
        "ec2:DescribeImportSnapshotTasks",
        "ec2:CancelImportTask"
      ],
      "Resource": "*"
    }
  ]
}

作成したら、AWS CLIにこのユーザ情報を記載しておきます。 (私の場合、複数のIAMユーザがあるので、--profileオプションで切り替える為です。)
具体的な手順は下記をご確認ください。

AWS CLIへの設定方法

すでに複数のIAMユーザを使っている場合は、下記のようにユーザ毎の設定を追加します。
(想定している環境はMacです。)

$ aws configure --profile vmimportuser

AWS Access Key ID [********************]:
AWS Secret Access Key [********************]:
Default region name [ap-northeast-1]:
Default output format [None]:json

ステップ 1: インポートするVMの準備

AWSにイメージインポートするVMware仮想マシンに対して、事前に下記の作業を行っておきます。

  • 仮想マシンにAWS CLIのインストール
  • VMのウイルス対策ソフトウェアまたは侵入検出ソフトウェアを無効にする
  • VMware VMからVMware Toolsをアンインストール
  • あらゆる(仮想または物理)CD-ROMドライブを切断
  • ネットワーク設定を、静的IPアドレスではなくDHCPに設定
  • エクスポートする前にVMをシャットダウン

CentOS6の場合は、/etc/sysconfig/network-scripts/ifcfg-ethXのファイルのBOOTPROTOの設定をDHCPに変更します。

# 下記を変更
BOOTPROTO=dhcp

今回はCentOS6.8をインポートしますので、追加で以下の対応を行います。

  • リモートアクセスの Secure Shell(SSH)を有効
  • ホストのファイアウォール(Linux iptables など)でSSHへのアクセスが許可されていることを確認
  • インポート後に、非ルートユーザーはパブリックキーベースのSSHを使用してインスタンスにアクセスするように設定されていることを確認
  • Linux VM でブートローダーとして GRUB(GRUB レガシー)またはGRUB2が使用されていることを確認
  • Linux VM で EXT2、EXT3、EXT4、Btrfs、JFS、XFS のいずれかのルートファイルシステムが使用されていることを確認
    • CentOS6なので、EXT4になります。

参考:
ステップ 1: VM を準備する

ステップ 2: VMをその仮想化環境からエクスポート

VMwareからのエクスポートについてはご利用の環境に合わせて行ってください。 私の場合は、Macのローカル上にあるVMware Fusionの仮想マシンをエクスポートしました。

Macは標準ではVMマシンをエクスポートできないので、専用のツールである「VMware OVF Tool for Mac OSX」を別途インストールします。
下記ページからダウンロードしてインストールします。

OVF Tool Documentation

インストールできたら早速ovftoolを使ってエクスポートを行います。今回はovf形式にしました。

$ /Applications/VMware\ OVF\ Tool/ovftool ¥
--acceptAllEulas /users/**********/Documents/Virtual\ ¥
Machines.localized/MYCentOS6.vmwarevm/MYCentOS6.vmx ~/mycentos68.ovf

Opening VMX source: /users/**********/Documents/Virtual Machines.localized/MYCentOS6.vmwarevm/MYCentOS6.vmx
Opening OVF target: /Users/**********/mycentos68.ovf
Writing OVF package: /Users/**********/mycentos68.ovf
Transfer Completed
Completed successfully

完了すると「mycentos68.mf」「mycentos68.ovf」「mycentos68-disk1.vmdk」という3つのファイルが作成されています。

参考:
ステップ 2: VM をその仮想化環境からエクスポートする

ステップ 3: イメージとして VM をインポート

いよいよインポート作業に入ります。

作成したVMDKファイルを保存するS3バケットを作成

任意のS3バケットを作成します。既存のバケットでも構いません。

VM Import サービスロールの作成

公式ドキュメントにあるように、サービスロールの作成を行います。

VM Import では、Amazon S3 バケットからのディスクイメージのダウンロードなど、特定の操作の実行にロールが必要です。

以下のポリシーを定義したtrust-policy.jsonという名前のファイルを作成します。

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Principal": { "Service": "vmie.amazonaws.com" },
         "Action": "sts:AssumeRole",
         "Condition": {
            "StringEquals":{
               "sts:ExternalId": "vmimport"
            }
         }
      }
   ]
}

create-roleコマンドを使用して、vmimportという名前のロールを作成し、そのロールに VM Import/Export のアクセス権限を付与します。 今回は、vmimportuserという名前のIAMユーザを利用しているので、--profileでそのユーザ(vmimportuser)を指定しています。

aws iam --profile vmimportuser create-role --role-name vmimport --assume-role-policy-document file://trust-policy.json

次に下記のポリシーを定義したrole-policy.jsonという名前のファイルを作成します。 disk-image-file-bucketの箇所は、ステップ3で作成したバケット名を指定してください。

{
   "Version": "2012-10-17",
   "Statement": [
      {
         "Effect": "Allow",
         "Action": [
            "s3:ListBucket",
            "s3:GetBucketLocation"
         ],
         "Resource": [
            "arn:aws:s3:::disk-image-file-bucket"
         ]
      },
      {
         "Effect": "Allow",
         "Action": [
            "s3:GetObject"
         ],
         "Resource": [
            "arn:aws:s3:::disk-image-file-bucket/*"
         ]
      },
      {
         "Effect": "Allow",
         "Action":[
            "ec2:ModifySnapshotAttribute",
            "ec2:CopySnapshot",
            "ec2:RegisterImage",
            "ec2:Describe*"
         ],
         "Resource": "*"
      }
   ]
}

次にput-role-policyコマンドを使用して、このポリシーを上記で作成したロールにアタッチします。

aws iam --profle vmimport put-role-policy --role-name vmimport --policy-name vmimport --policy-document file://role-policy.json

これらは、マネジメントコンソールから行っても構いません。

VMインポート

vmdkファイルのアップロード

作成したS3バケットに、エクスポートしたvmdkファイルをアップロードします。方法はなんでも構いません。今回は、AWS CLIでアップロード(コピー)しました。
(disk-image-file-bucketの箇所は作成したバケット名を指定してください。)

$ aws s3 cp --profile vmimportuser mycentos68-disk1.vmdk s3://disk-image-file-bucket/

VMのインポート

次に、インポートする各種パラメータを定義したcontainers.jsonというファイルを作成します。 (disk-image-file-bucketの箇所は作成したバケット名を指定してください。)

単一ディスクの場合

[
  {
    "Description": "My Original CentOS 6.8",
    "Format": "vmdk",
    "UserBucket": {
        "S3Bucket": "disk-image-file-bucket",
        "S3Key": "mycentos68-disk1.vmdk"
    }
  }
]

複数ディスクの場合

[
  {
    "Description": "First disk",
    "Format": "vmdk",
    "UserBucket": {
        "S3Bucket": "my-import-bucket",
        "S3Key": "mycentos68-disk1.vmdk"
    }
  },          
  {
    "Description": "Second disk",
    "Format": "vmdk",
    "UserBucket": {
        "S3Bucket": "my-import-bucket",
        "S3Key": "mycentos68-disk1.vmdk"
    }
  }
]

import-imageコマンドを使用して、イメージインポートタスクを作成します。

$ aws ec2 import-image --profile vmimportuser --description "My CentOS6.8 VMDK" --disk-containers file://containers.json

実行すると下記のような表示が返ってきます。

{
    "Status": "active",
    "Description": "My CentOS6.8 VMDK",
    "Progress": "2",
    "SnapshotDetails": [
        {
            "UserBucket": {
                "S3Bucket": "mytest2016",
                "S3Key": "mycentos68-disk1.vmdk"
            },
            "DiskImageSize": 0.0,
            "Format": "VMDK"
        }
    ],
    "StatusMessage": "pending",
    "ImportTaskId": "import-ami-fgzp52v0"
}

このProgressが100になれば完了です。
途中の進捗状況を確認する場合は、describe-import-image-tasksコマンドで確認できます。このとき上記のImportTaskIdを指定します。

aws ec2 describe-import-image-tasks --import-task-ids import-ami-fgzp52v0

キャンセルする場合

aws ec2 cancel-import-task --import-task-id import-ami-fg4z7c9h

下記のように、Statuscompletedになれば完了です。 この状態で、AMIが使えるようになっています。

{
    "ImportImageTasks": [
        {
            "Status": "completed",
            "LicenseType": "BYOL",
            "Description": "My CentOS6.8 VMDK",
            "ImageId": "ami-********",
            "Platform": "Linux",
            "Architecture": "x86_64",
            "SnapshotDetails": [
                {
                    "DeviceName": "/dev/sda1",
                    "Description": "My Original CentOS 6.8",
                    "Format": "VMDK",
                    "DiskImageSize": 1396196352.0,
                    "SnapshotId": "snap-********",
                    "UserBucket": {
                        "S3Bucket": "mytest2016",
                        "S3Key": "mycentos68-disk1.vmdk"
                    }
                }
            ],
            "ImportTaskId": "import-ami-fgzp52v0"
        }
    ]
}

後は、EC2インスタンスを作成したり、AMIを別のリージョンにコピーして利用したりと、普通に使えます。

参考:
ステップ 3: イメージとして VM をインポートする

最後に

AWS CLIだけで利用できるのでインスタンスのインポートに比べて、随分と楽にVM Importできました。 利用可能なOSの制限などがありますが、手軽にインポートできるのは魅力的だと思います。

以上になります。