chikoblog

やってみたことの掃溜め

aws ec2 import-imageを使ってVMwareイメージをAMIにインポートしてみた

VMwareイメージをAWS移行するって話があるかなと思い検証しました!

参考にしたドキュメント aws.amazon.com

VMwareイメージのインポートについて

AWS環境のEC2でVM を使用する際、AMIにインポートや
直接インスタンスとしてEC2 にインポートすることができます。

今回は個人的に使い勝手がいいなと思う、AMIにインポートする手順をまとめました。 AMIへのインポートの場合、AMIからインスタンスの作成時に セキュリティグループやEBSサイズの指定などができます。

また、CloudFormationでのテンプレートに組み込みが簡単なのはうれしいです!

インスタンスのインポートについては AWSの公式サイトに記載されていますので、
気になる方はご確認いただければと思います。

手順の大まかな概要

  • 作業用PCにAWS CLIのインストール
  • VM Import/Exportの事前準備
  • VMwareから必要イメージファイルをエクスポート
  • VMイメージファイル格納用のS3バケット作成・アップロード
  • VM Import/Export用のIAM ロール (vmimport) の作成
  • VMのインポート

作業用PCにAWS CLIのインストール

インポートコマンドを実行するために使用する作業用PCに AWS CLIをインストールしていない場合は、 AWS CLI のインストールを参照してインストールします。

VM Import/Exportの事前準備

※今回はCentOS 7を対象とします。

※実行前にVM Import/Export の要件を確認しておきましょう。

全般

IAM ユーザーに必要なアクセス許可
IAMユーザーとしてログインしている場合は
VM Import/Export を使用するには、IAM ポリシーに以下アクセス許可が必要です。

IAM ポリシー

{
  "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": [
        "iam:CreateRole",
        "iam:PutRolePolicy"
      ],
      "Resource": "*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:CancelConversionTask",
        "ec2:CancelExportTask",
        "ec2:CreateImage",
        "ec2:CreateInstanceExportTask",
        "ec2:CreateTags",
        "ec2:DeleteTags",
        "ec2:DescribeConversionTasks",
        "ec2:DescribeExportTasks",
        "ec2:DescribeExportImageTasks",
        "ec2:DescribeInstanceAttribute",
        "ec2:DescribeInstanceStatus",
        "ec2:DescribeInstances",
        "ec2:DescribeTags",
        "ec2:ExportImage",
        "ec2:ImportInstance",
        "ec2:ImportVolume",
        "ec2:StartInstances",
        "ec2:StopInstances",
        "ec2:TerminateInstances",
        "ec2:ImportImage",
        "ec2:ImportSnapshot",
        "ec2:DescribeImportImageTasks",
        "ec2:DescribeImportSnapshotTasks",
        "ec2:CancelImportTask"
      ],
      "Resource": "*"
    }
  ]
}

権限がなければ、専用のIAMユーザを作成するのもありかと思います。
新規作成をした場合は、AWS CLIにこのユーザ情報を記載を忘れずに。。。

AWS CLIのインストール
作業用PCと同様にAWS CLI のインストールを参照してインストールします。

VMware Toolsをアンインストール
VMware Toolsをインストールしている場合は
以下の手順を参考にアンインストールしてください。 docs.vmware.com

静的IPアドレスを設定している場合はDHCPに設定に変更する
DHCPに設定していなければ以下の手順を参考に設定変更をしてください。 access.redhat.com

その他

  • CD-ROM ドライブを利用している場合は切断する必要があります。
  • VMウイルス対策ソフトウェアまたは侵入検出ソフトウェアを利用している場合、無効にする必要があります。
    • インポートプロセスが完了したら、これらのサービスを再度有効にすることができます。
Linux

リモートアクセスの設定

リモートアクセスの有効化をおこなっていない場合は
以下の手順を参考に必要な設定をしてください。 access.redhat.com

ホストのファイアウォールでリモートアクセスが許可されていなければ
以下の手順を参考に必要な設定をしてください。 access.redhat.com

公開鍵ベースのリモートアクセスが許可されていなければ
以下の手順を参考に必要な設定をしてください。 access.redhat.com

ブートローダーの確認

対象のブートローダーは以下の通りです。

以下のコマンドで対象のブートローダーを使用している確認します。

$ sudo dd if=/dev/sda count=1 | strings

ルートファイルシステムの確認
対象のルートファイルシステムは以下の通りです。

以下のコマンドで利用しているルートファイルシステムを確認します。

$ cat /etc/fstab

VMwareから必要イメージファイルをエクスポート

以下のVMwareサイトで利用しているVMwareの「OVAファイルをエクスポート」手順を検索し、その手順に従って作業をおこなえばエクスポートが可能です。 docs.vmware.com

VMイメージファイル格納用のS3バケット作成・アップロード

先ほど、エクスポートしたOVAファイルやVMDKファイルを格納するS3を
AWSコンソールまたは以下のAWS CLIコマンドで作成します。

$ aws s3 mb s3://bucket-name
make_bucket: bucket-name

$ aws s3 cp test.ovf s3://bucket-name/ 
upload: ./test.ovf to s3://bucket-name/test.ovf

$ aws s3 ls s3://bucket-name
2020-01-07 03:35:00        317 file.txt

VM Import/Export用のIAM ロール (vmimport) の作成

trust-policy.jsonという名前のファイルを作成しポリシーをファイルに追加します。

$ vim 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ロールを作成し、
ロールへのアクセス権を前の手順で作成したtrust-policy.jsonをもとに付与します。

$ aws iam create-role --role-name vmimport --assume-role-policy-document file://trust-poolicy.json
 {
     "Role": {
         "AssumeRolePolicyDocument": {
             "Version": "2012-10-17", 
             "Statement": [
                 {
                     "Action": "sts:AssumeRole", 
                     "Effect": "Allow", 
                     "Condition": {
                         "StringEquals": {
                             "sts:Externalid": "vmimport"
                         }
                     }, 
                     "Principal": {
                         "Service": "vmie.amazonaws.com"
                     }
                 }
             ]
         }, 
         "RoleId": "AROA2PLMIQDORKZYZRYOO", 
         "CreateDate": "2020-01-07T01:14:37Z", 
         "RoleName": "vmimport", 
         "Path": "/", 
         "Arn": "arn:aws:iam::xxxxxxxxxxxx:role/vmimport"
     }
 }

role-policy.jsonという名前のファイルを作成します。
disk-image-file-bucketバケットは先ほど作成したバケット名を指定します。

$ vim role-policy.json 
{
   "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コマンドを使用して上記で作成したvmimportロールにポリシーをアタッチします。

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

VMのインポート

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

単一ディスク(VMDKファイルが1つ)の場合

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

複数ディスク(VMDKファイルが複数)の場合

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

import-imageを使用してインポートタスクを作成します。

$ aws ec2 import-image --description "My server disks"--disk-containers file://containers..json
{
    "Status": "active", 
    "Description": "My server disks", 
    "SnapshotDetails": [
        {
            "UserBucket": {
                "S3Bucket": "my-import-bucket", 
                "S3Key": "my-server-vm-disk1.vmdk"
            }, 
            "DiskImageSize": 0.0, 
            "Format": "VMDK"
        }, 
        {
            "UserBucket": {
                "S3Bucket": "my-import-bucket", 
                "S3Key": "my-server-vm-disk2.vmdk"
            }, 
            "DiskImageSize": 0.0, 
            "Format": "VMDK"
        }
    ], 
    "Progress": "2", 
    "StatusMessage": "pending", 
    "ImportTaskId": "import-ami-xxxxxxxxxxxxx"
}

Progressが100になれば完了となります。
体感ですが結構待ちましたので気長に待ってください。

途中の進捗状況を確認はdescribe-import-image-tasksコマンドで可能です。

$ aws ec2 describe-import-image-tasks --import-task-ids import-ami-xxxxxxxxxxxxx
     "ImportImageTasks": [
         {
             "Status": "active", 
             "Description": "testcslabo48", 
             "SnapshotDetails": [
                 {
                     "Status": "completed", 
                     "UserBucket": {
                         "S3Bucket": "my-import-bucket", 
                         "S3Key": "my-server-vm-disk1.vmdk"
                     }, 
                     "DiskImageSize": 1932634112.0, 
                     "Description": "First disk", 
                     "Format": "VMDK"
                 }, 
                 {
                     "Status": "completed", 
                     "UserBucket": {
                         "S3Bucket": "my-import-bucket", 
                         "S3Key": "my-server-vm-disk2.vmdk"
                     }, 
                     "DiskImageSize": 76800.0, 
                     "Description": "Second disk", 
                     "Format": "VMDK"
                 }
             ], 
             "Progress": "20", 
             "StatusMessage": "updating", 
             "ImportTaskId": "import-ami-xxxxxxxxxxxxx"
         }
     ]
 }

途中でキャンセルする場合はcancel-import-taskコマンドを実行します。

$ aws ec2 cancel-import-task --import-task-id import-ami-xxxxxxxxxxxxx

StatuscompletedになればAMIが使用可能になります。

$ aws ec2 describe-import-image-tasks --import-task-ids import-ami-xxxxxxxxxxxxx 
{
     "ImportImageTasks": [
         {
             "Status": "completed", 
             "LicenseType": "BYOL", 
             "Description": "My server disks", 
             "ImageId": "ami-xxxxxxxxxxxx", 
             "Platform": "Linux", 
             "Architecture": "x86_64", 
             "SnapshotDetails": [
                 {
                     "Status": "completed", 
                     "DeviceName": "/dev/sda1", 
                     "Description": "First disk", 
                     "Format": "VMDK", 
                     "DiskImageSize": 1932634112.0, 
                     "UserBucket": {
                         "S3Bucket": "my-import-bucket",
                         "S3Key": "my-server-vm-disk1.vmdk"
                     }, 
                     "SnapshotId": "snap-xxxxxxxxxxxx"
                 }, 
                 {
                     "Status": "completed", 
                     "DeviceName": "/dev/sdf", 
                     "Description": "Second disk", 
                     "Format": "VMDK", 
                     "DiskImageSize": 76800.0, 
                     "UserBucket": {
                         "S3Bucket": "my-import-bucket",
                         "S3Key": "my-server-vm-disk2.vmdk"
                     }, 
                     "SnapshotId": "snap-xxxxxxxxxxxxx"
                 }
             ], 
             "ImportTaskId": "import-ami-xxxxxxxxxxxxx"
         }
     ]
 }

これでAMIが使えますのでAMIをもとにEC2を作成してみてください。

最後に

やってみた結果一番詰まるのは「VM Import/Exportの事前準備」かなと思います。
僕も実際にやったときはSSHユーザをつくり忘れてしまい
ログインも何もできないただの箱が出来上がりました。

VM Import/Exportの事前準備」は各環境で実行手順がまちまちですので、
サービスの環境などでおこなう際はしっかりと確認していただけたら幸いです。

VM環境からAWS環境へ移行の際に必要になる手順かと思いますので皆様も試してみてはいかがでしょうか?