AWS の EC2 インスタンスをローカルの Proxmox でそのまま実行できないか試行錯誤したときのメモ

大きく分けて以下のステップを踏む

  1. EC2 コンテナの AMI 作成
  2. AMI から S3 にエクスポート
  3. ローカル PC にダウンロード
  4. Proxmox が起動できるように変換
  5. 起動

移行した直後は SSH できない場合があるので、ID/Pass を設定しておくと安全

AWS Cloudshell (admin ユーザー)での作業

S3 Bucket の作成

# バケット名を定義
BUCKET_NAME="ami-export-$(date +%Y%m%d%H%M%S)"
REGION=ap-northeast-1

# バケットを作成
aws s3 mb s3://$BUCKET_NAME --region $REGION

vmimport ロールの作成

# vmimport ロールを作成
cat > trust-policy.json <<'JSON'
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": { "Service": "vmie.amazonaws.com" },
    "Action": "sts:AssumeRole",
    "Condition": { "StringEquals": { "sts:Externalid": "vmimport" } }
  }]
}
JSON
aws iam create-role --role-name vmimport \
  --assume-role-policy-document file://trust-policy.json

# vmimport ロールに必要権限を付与
cat > vmimport-inline.json <<'JSON'
{
  "Version":"2012-10-17",
  "Statement":[
    { "Effect":"Allow",
      "Action":[ "s3:GetBucketLocation","s3:GetObject","s3:ListBucket","s3:PutObject","s3:GetBucketAcl" ],
      "Resource":["*"]
    },
    { "Effect":"Allow",
      "Action":[ "ec2:ModifySnapshotAttribute","ec2:CopySnapshot","ec2:RegisterImage","ec2:Describe*" ],
      "Resource":"*"
    }
  ]
}
JSON
aws iam put-role-policy \
  --role-name vmimport \
  --policy-name AllowS3AndEC2ForExport \
  --policy-document file://vmimport-inline.json

EC2 から AMI を作成

INSTANCE_ID の部分を自分ものに置き換える

INSTANCE_ID=i-xxxxxxxxxxxxxxxxx

AMI_ID=$(aws ec2 create-image \
  --instance-id "$INSTANCE_ID" \
  --name "ami-from-$INSTANCE_ID" \
  --description "AMI created from $INSTANCE_ID" \
  --no-reboot \
  --query 'ImageId' --output text)
echo "AMI_ID=$AMI_ID"

AMI を S3 にエクスポート

PREFIX="exports"
EXPORT_TASK_ID=$(aws ec2 export-image \
  --image-id "$AMI_ID" \
  --disk-image-format VMDK \
  --s3-export-location S3Bucket=$BUCKET_NAME,S3Prefix=${PREFIX}/ \
  --role-name vmimport \
  --query 'ExportImageTaskId' --output text)
echo "EXPORT_TASK_ID=$EXPORT_TASK_ID"

進捗確認(すこし時間がかかる)

aws ec2 describe-export-image-tasks

ダウンロード用 IAM ユーザー作成

S3 に転送したイメージをダウンロードするために IAM ユーザーを作成し、ローカル PC に AWS CLI をセットアップする

すでにセットアップ済みであれば「イメージをダウンロード」までスキップ

# ユーザー作成
USER_NAME=export-user
aws iam create-user --user-name $USER_NAME

# アクセスキー発行 (AccessKeyIdとSecret をメモする)
aws iam create-access-key --user-name $USER_NAME

# S3へのRead権限を付与
cat > s3-readonly.json <<JSON
{
  "Version": "2012-10-17",
  "Statement": [
    { "Effect": "Allow",
      "Action": "s3:ListAllMyBuckets",
      "Resource": "*"
    },
    { "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::$BUCKET_NAME"
    },
    { "Effect": "Allow",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::$BUCKET_NAME/*"
    }
  ]
}
JSON
aws iam put-user-policy \
  --user-name $USER_NAME \
  --policy-name S3ReadOnlySpecificBucket \
  --policy-document file://s3-readonly.json

# もしフルアクセスを与える場合は以下のコマンド(非推奨)
# aws iam attach-user-policy --user-name $USER_NAME --policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess

ローカル PC での作業

AWS CLI 設定

AWS CLI のインストール方法については こちらを参照

USER_NAME=export-user
REGION=ap-northeast-1
export AWS_PAGER=""
aws configure --profile $USER_NAME   # ここでさっきメモしたAccesskeyIdとSecretを入力
export AWS_PROFILE=$USER_NAME
aws configure set region $REGION --profile $USER_NAME

イメージをダウンロード

# すべてのバケットを表示
aws s3 ls

# バケット選んで中身を表示
aws s3 ls s3://ami-export-xxxxxxxxxxxxxx/

# バケット内のコンテンツをすべてダウンロード
aws s3 cp --recursive s3://ami-export-xxxxxxxxxxxxxx/ ./

VMDK から QCOW2/RAW に変換

qemu-utils をインストール

sudo apt update
sudo apt install qemu-utils
# 変換
qemu-img convert -f vmdk -O qcow2 export-ami-xxxxxxxxxxxxxxxxx.vmdk disk.qcow2
# 確認
qemu-img info disk.qcow2

Proxmox での作業

空の VM を作成

GUI からだと

  1. “Create VM”
  2. OS: “Do not use any media”
  3. System - BIOS: SeaBIOS
  4. Disks: すべての Disk を削除

Proxmox のホストに SSH してディスクをアタッチ

VM を作成後、VMID を GUI から確認して、変数を定義しておく

VMID=111
qm importdisk $VMID ./disk.qcow2 local --format qcow2

# ディスクを VM に接続:
qm set $VMID --scsihw virtio-scsi-pci --scsi0 local:$VMID/vm-$VMID-disk-0.qcow2
qm set $VMID --boot order=scsi0

# ネットワーク設定で、最初は互換性の高い e1000 を指定する

qm set $VMID --net0 e1000,bridge=vmbr0

# シリアル出力を有効化。
qm set $VMID --serial0 socket --vga serial0

VM 起動

qm start $VMID

# ターミナルに接続
qm terminal $VMID

起動できると、cloud-init のタイムアウトが発生した後、login を求められる (タイムアウトを待っているので多分 2 分くらいかかる)

[   63.982952] cloud-init[1308]: 2025-09-20 14:42:15,253 - url_helper.py[WARNING]: Calling 'http://169.254.169.254/2009-04-04/meta-data/instance-id' failed [49/120s]: request error [HTTPConnectionPool(host='169.254.169.254', port=80): Read timed out. (read timeout=50.0)]
...
...
...
[  OK  ] Started Execute cloud user/final scripts.
[  OK  ] Reached target Cloud-init target.

Ubuntu 16.04.7 LTS ip-172-31-35-185 ttyS0

ip-172-31-35-185 login:

(余談) ID/Pass がわからない場合

ID/Pass がわからないかつ IP がその VM に割り振られていない場合はパスワードを変更してシリアルコンソールからログインできるようにする必要がある。

AWS のインスタンスは grub が無効化されている場合が多いので、以下の手順を踏んでパスワードをリセットする

  1. VM を一度シャットダウン or STOP
  2. 以下のコマンドで一度 VGA に戻す
    qm set $VMID --delete serial0 && qm set $VMID --vga std
  3. Ubuntu Server の iso イメージを Hardware -> “CD/DVD Drive” -> “Use CD/DVD disk image file (iso)” に接続
  4. Options -> Boot Order から Disk を一番先頭に持ってくる
  5. 起動して GUI から Console を開く
  6. (Ubuntu Server の場合)Help -> Enter Shell
  7. fdisk -lで対象のデバイスを確認後、mount /dev/sda1 /mntで/mnt にマウント
  8. chroot /mnt
  9. passwd rootでパスワード変更
  10. SELinux が有効になっている場合はラベルを修復
    getenforce # 結果が"Enforcing"の場合は続けて以下のコマンドを実行
    restorecon -Rv /etc
  11. VM STOP 後、GUI から Hardware -> “CD/DVD Drive” -> “Do not use any media"を選択しディスクを外す
  12. VM を起動

起動後の調節

Cloud Init の無効化 (EC2 で設定されている Cloud Init が EC2 コンテナ管理用のエンドポイントにアクセスを試みて起動が遅くなるため)

sudo apt purge cloud-init
sudo rm -rf /etc/cloud/ /var/lib/cloud/

hosts に hostname を追加 (sudo コマンドの実行が極端に遅くなるため)

echo "127.0.1.1 $(hostname)" | sudo tee -a /etc/hosts