このトピックでは、Alibaba Cloud CLI を使用して Elastic Compute Service (ECS) インスタンスをあるリージョンから別のリージョンに移行する方法について説明します。このプロセスでは、ソースインスタンスのカスタムイメージを作成し、そのイメージをターゲットリージョンにコピーしてから、コピーしたイメージから新しいインスタンスを起動します。
仕組み
クロスリージョン移行プロセスでは、カスタムイメージを使用して、新しいリージョンにご利用の ECS インスタンスのディスクのレプリカを作成します。
カスタムイメージの作成:ソースインスタンスからカスタムイメージを作成します。これにより、すべてのディスク上のオペレーティングシステム、アプリケーション、およびデータがキャプチャされます。
カスタムイメージのコピー:カスタムイメージをターゲットリージョンにコピーします。
新しいインスタンスの作成:コピーしたイメージからターゲットリージョンに新しいインスタンスを作成します。
新しいインスタンスの検証:新しいインスタンスを検証し、すべてのアプリケーションとサービスが期待どおりに機能することを確認します。
ソースリソースのリリース:不要なコストが発生しないように、ソースリソースをリリースします。
事前準備
制限事項
ローカルディスクのスナップショットは作成できないため、この方法ではローカルディスクを使用するインスタンスはサポートされていません。
この方法では、ローカル SSD を搭載したインスタンスから、システムディスクとデータディスクのスナップショットを含むイメージを作成することはサポートされていません。詳細については、「ローカル SSD を搭載したインスタンスファミリー (i シリーズ)」をご参照ください。
ソースインスタンスはクラシックネットワークまたは VPC に配置できますが、宛先インスタンスは VPC にのみ作成できます。
新しいインスタンスのインスタンスタイプは、ターゲットゾーンで利用可能である必要があります。
課金
カスタムイメージの一部として作成されるスナップショットに対して課金されます。詳細については、「スナップショットの課金」をご参照ください。
計画に関する考慮事項
開始する前に、ターゲットリージョンに VPC、vSwitch、およびセキュリティグループが作成されていることを確認してください。
新しいインスタンスは、新しいインスタンス ID、プライベート IP アドレス、MAC アドレスなど、異なるメタデータを持ちます。このメタデータに依存するアプリケーションやスクリプトを更新してください。たとえば、MAC アドレスに関連付けられたソフトウェアライセンスを再バインドしたり、クラスター構成の IP アドレスを更新したりする必要がある場合があります。詳細については、「インスタンスのメタデータ」をご参照ください。
前提条件
ステップ 1: ソースインスタンスからのカスタムイメージの作成
CreateImage オペレーションを呼び出して、ソースインスタンスのカスタムイメージを作成します。詳細については、「インスタンスからのカスタムイメージの作成」をご参照ください。
ソースインスタンスが実行中の場合、この操作ではスナップショットのデータ整合性を確保するために、インスタンスが数分間停止します。
aliyun ecs CreateImage \
--RegionId 'cn-hangzhou' \
--ImageName 'source-image-for-migration' \
--InstanceId 'i-bp1g6zv0ce8oghu7****'成功した応答は、新しいイメージの ID を返します。
{
"ImageId": "m-bp146shijn7hujku****",
"RequestId": "C8B26B44-0189-443E-9816-*******"
}ImageId を保存します。これは次のステップで必要になります。
ステップ 2: ターゲットリージョンへのイメージのコピー
イメージをコピーする前に、そのステータスが Available になるまで待つ必要があります。ステータスは、DescribeImages 操作を呼び出すことで確認できます。
CopyImage オペレーションを呼び出して、イメージをターゲットリージョンにコピーします。次の例では、イメージを中国 (杭州) から中国 (北京) にコピーします。
aliyun ecs CopyImage \
--RegionId 'cn-hangzhou' \
--ImageId 'm-bp146shijn7hujku****' \
--DestinationRegionId 'cn-beijing' \
--DestinationImageName 'migrated-image-beijing'応答は、ターゲットリージョンにコピーされたイメージの新しい ImageId を返します。
{
"ImageId": "m-bp1h46wfpjsjastd****",
"RequestId": "473469C7-AA6F-4DC5-B3DB-A3DC0DE3C83E"
}この新しい ImageId を次のステップのために保存します。
ステップ 3: 宛先インスタンスの作成
RunInstances オペレーションを呼び出して、ターゲットリージョンにコピーされたイメージから新しいインスタンスを作成します。詳細については、「カスタム起動による ECS インスタンス」をご参照ください。
aliyun ecs RunInstances \
--RegionId 'cn-beijing' \
--ImageId 'm-bp1h46wfpjsjastd****' \
--InstanceType 'ecs.g6.large' \
--SecurityGroupId 'sg-2zea9dbddva****' \
--VSwitchId 'vsw-2zep7vc25mjc1****' \
--InstanceName 'migrated-instance-beijing' \
--PasswordInherit true \
--InternetChargeType 'PayByTraffic' \
--SystemDisk.Size '40' \
--SystemDisk.Category 'cloud_essd' \
--InstanceChargeType 'PostPaid' \
--InternetMaxBandwidthOut '10'この例では、PasswordInherit が true に設定されているため、ソースインスタンスと同じパスワードを使用して新しいインスタンスにログインできます。 パラメーターの完全なリストについては、API リファレンスをご参照ください。
成功した応答は、新しいインスタンスの ID を返します。
{
"RequestId": "473469C7-AA6F-4DC5-B3DB-A3DC0DE3****",
"InstanceIdSets": {
"InstanceIdSet": [
"i-bp67acfmxazb4pd2****"
]
}
}ステップ 4: 宛先インスタンスの検証
新しいインスタンスが実行されたら、それに接続して次の確認を行います:
システムディスクとデータディスク上のファイルシステムとデータがソースインスタンスと同一であることを確認します。
アプリケーションとサービスを起動して、それらが完全に機能することを確認します。
IP アドレスや MAC アドレスなど、インスタンスのメタデータに依存するリソースの関連付けを更新します。
ステップ 5: ソースリソースのリリース
新しいインスタンスが正しく動作していることを確認した後、不要な料金を避けるために元のリソースをリリースします。
インスタンスのリリース、イメージとスナップショットの削除は元に戻せない操作です。続行する前に、データが正常に移行および検証されていることを確認してください。
ソースインスタンスのリリース:DeleteInstance オペレーションを呼び出します。詳細については、「インスタンスのリリース」をご参照ください。
aliyun ecs DeleteInstance --InstanceId 'i-bp1g6zv0ce8oghu7****' --Force trueカスタムイメージの削除:ソースイメージとコピーされたイメージの両方に対して DeleteImage オペレーションを呼び出します。詳細については、「カスタムイメージの削除」をご参照ください。
# ソースリージョンのイメージを削除 aliyun ecs DeleteImage --RegionId 'cn-hangzhou' --ImageId 'm-bp146shijn7hujku****' # ターゲットリージョンのイメージを削除 aliyun ecs DeleteImage --RegionId 'cn-beijing' --ImageId 'm-bp1h46wfpjsjastd****'関連スナップショットの削除:イメージ作成プロセスで作成された各スナップショットに対して DeleteSnapshot オペレーションを呼び出します。
aliyun ecs DeleteSnapshot --SnapshotId 's-bp1c0doj0taqyzzl****'
スクリプトによる移行の自動化
コマンドラインスクリプトを使用して、移行プロセスを自動化できます。以下の例は、ニーズに合わせて適応できる基本的なフレームワークを提供します。
スクリプト例:
Bash
このスクリプトを実行するには、jq ツールがインストールされている必要があります。
#!/usr/bin/env bash
# ソースインスタンス ID
SRC_INSTANCE_ID="i-bp1g6zv0ce8oghu7****"
# ソースインスタンスのリージョン ID
SRC_REGION_ID="cn-hangzhou"
# ターゲットリージョン ID
DST_REGION_ID="cn-beijing"
# ターゲットインスタンスのゾーン ID
DST_ZONE_ID="cn-beijing-h"
# ソースインスタンスのタイプ
SRC_INSTANCE_TYPE="ecs.e-c1m1.large"
# ソースインスタンスのシステムディスクカテゴリ
SRC_SYSTEM_DISK_CATEGORY="cloud_auto"
# ソースインスタンスのシステムディスクサイズ
SRC_SYSTEM_DISK_SIZE=40
# ログの出力
function log {
local level="$1"
local message="$2"
echo "$(date +'%Y-%m-%d %H:%M:%S') [$level] $message"
}
# Alibaba Cloud CLI のラップ
function invoke_aliyun_command() {
local service="$1"
local action="$2"
shift 2
local -a params=("$@")
response=$(aliyun "$service" "$action" "${params[@]}")
exit_code=$?
if [ $exit_code -eq 0 ]; then return 0; fi
log "ERROR" "Failed to invoke aliyun command: aliyun $service $action ${params[*]}"
exit 1
}
# リソースが利用可能になるまで待機
function wait_resource_available() {
local service="$1"
local action="$2"
local region_id="$3"
local resource_type="$4"
local resource_id="$5"
local -a params=(
"--region" "$region_id"
"--RegionId" "$region_id"
"--${resource_type}Id" "$resource_id"
)
if [ "$resource_type" == "Image" ]; then
params+=("--Status" "Creating,Waiting,Available")
fi
local current_status
local current_progress
local timeout=1200
local interval=20
local end_time=$(( $(date +%s) + timeout ))
while (( $(date +%s) < end_time )); do
invoke_aliyun_command "$service" "$action" "${params[@]}"
current_status=$(echo "$response" | jq -r '.. | .Status? // empty' | head -n1)
current_progress=$(echo "$response" | jq -r '.. | .Progress? // empty' | head -n1)
log "INFO" "${resource_type} status: $current_status"
if [[ -n "$current_progress" ]]; then
log "INFO" "Creation progress: $current_progress"
fi
if [[ "$current_status" == "Available" ]]; then return 0; fi
sleep "$interval"
done
}
# イメージの作成
log "INFO" "Creating source image from instance '$SRC_INSTANCE_ID'"
src_img_params=(
"--region" "$SRC_REGION_ID"
"--RegionId" "$SRC_REGION_ID"
"--InstanceId" "$SRC_INSTANCE_ID"
"--ImageName" "cli-src-img"
)
invoke_aliyun_command ecs CreateImage "${src_img_params[@]}"
src_img_id=$(echo "$response" | jq -r .ImageId)
wait_resource_available ecs DescribeImages "$SRC_REGION_ID" "Image" "$src_img_id"
log "INFO" "Source image created: '$src_img_id'"
# ターゲットリージョンへのイメージのコピー
log "INFO" "Copying image to region: '$DST_REGION_ID'"
dst_img_params=(
"--region" "$SRC_REGION_ID"
"--RegionId" "$SRC_REGION_ID"
"--DestinationRegionId" "$DST_REGION_ID"
"--ImageId" "$src_img_id"
"--DestinationImageName" "cli-dst-img"
)
invoke_aliyun_command ecs CopyImage "${dst_img_params[@]}"
dst_img_id=$(echo "$response" | jq -r .ImageId)
wait_resource_available ecs DescribeImages "$DST_REGION_ID" "Image" "$dst_img_id"
log "INFO" "Destination image copied: '$dst_img_id'"
# VPC の作成
log "INFO" "Creating VPC"
dst_vpc_params=(
"--region" "$DST_REGION_ID"
"--RegionId" "$DST_REGION_ID"
"--CidrBlock" "10.0.0.0/8"
"--VpcName" "cli-dst-vpc"
)
invoke_aliyun_command ecs CreateVpc "${dst_vpc_params[@]}"
dst_vpc_id=$(echo "$response" | jq -r .VpcId)
wait_resource_available "Vpc" "DescribeVpcAttribute" "$DST_REGION_ID" "Vpc" "$dst_vpc_id"
log "INFO" "VPC created: '$dst_vpc_id'"
# vSwitch の作成
log "INFO" "Creating VSwitch"
dst_vsw_params=(
"--region" "$DST_REGION_ID"
"--RegionId" "$DST_REGION_ID"
"--ZoneId" "$DST_ZONE_ID"
"--VpcId" "$dst_vpc_id"
"--CidrBlock" "10.1.1.0/24"
)
invoke_aliyun_command vpc CreateVSwitch "${dst_vsw_params[@]}"
dst_vsw_id=$(echo "$response" | jq -r .VSwitchId)
wait_resource_available "vpc" "DescribeVSwitchAttributes" "$DST_REGION_ID" "VSwitch" "$dst_vsw_id"
log "INFO" "VSwitch created: '$dst_vsw_id'"
# セキュリティグループの作成
log "INFO" "Creating security group"
dst_sg_params=(
"--region" "$DST_REGION_ID"
"--RegionId" "$DST_REGION_ID"
"--SecurityGroupName" "cli-dst-sg"
"--VpcId" "$dst_vpc_id"
"--SecurityGroupType" "normal"
)
invoke_aliyun_command ecs CreateSecurityGroup "${dst_sg_params[@]}"
dst_sg_id=$(echo "$response" | jq -r .SecurityGroupId)
log "INFO" "Security group created: '$dst_sg_id'"
# ターゲットリージョンに従量課金制の ECS インスタンスを作成
log "INFO" "Creating ECS instance in zone: '$DST_ZONE_ID'"
dst_instance_params=(
"--region" "$DST_REGION_ID"
"--RegionId" "$DST_REGION_ID"
"--ImageId" "$dst_img_id"
"--SecurityGroupId" "$dst_sg_id"
"--VSwitchId" "$dst_vsw_id"
"--InstanceType" "$SRC_INSTANCE_TYPE"
"--InstanceName" "cli-dst-ecs"
"--PasswordInherit" "true"
"--SystemDisk.Category" "$SRC_SYSTEM_DISK_CATEGORY"
"--SystemDisk.Size" "$SRC_SYSTEM_DISK_SIZE"
"--InstanceChargeType" "PostPaid"
)
invoke_aliyun_command ecs RunInstances "${dst_instance_params[@]}"
dst_instance_id=$(echo "$response" | jq -r '.InstanceIdSets.InstanceIdSet[0]')
log "INFO" "ECS instance created: '$dst_instance_id'"Powershell
# エラー終了ポリシーの設定
$ErrorActionPreference = "Stop"
# 文字コードの設定
chcp 65001 | Out-Null
[System.Console]::OutputEncoding = [System.Text.Encoding]::UTF8
# ソースインスタンス ID
$SRC_INSTANCE_ID = "i-bp1g6zv0ce8oghu7****"
# ソースインスタンスのリージョン ID
$SRC_REGION_ID = "cn-hangzhou"
# ターゲットリージョン ID
$DST_REGION_ID = "cn-beijing"
# ターゲットインスタンスのゾーン ID
$DST_ZONE_ID = "cn-beijing-h"
# ソースインスタンスのタイプ
$SRC_INSTANCE_TYPE = "ecs.e-c1m1.large"
# ソースインスタンスのシステムディスクカテゴリ
$SRC_SYSTEM_DISK_CATEGORY = "cloud_auto"
# ソースインスタンスのシステムディスクサイズ
$SRC_SYSTEM_DISK_SIZE = 40
# ログの出力
function Log {
param ([string]$Level, [string]$Message)
Write-Host "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') [$Level] $Message"
}
# Alibaba Cloud CLI のラップ
function Invoke-AliyunCommand {
param ([string]$Service, [string]$Action, [array]$Params)
$response = aliyun $Service $Action $Params
if ($LASTEXITCODE -eq 0) { return $response | ConvertFrom-Json }
Log "ERROR" "Failed to call aliyun command: aliyun $Service $Action $Params"
exit 1
}
# ネストされたプロパティ値の取得
function Get-NestedPropertyValue {
param (
[object]$Object,
[string]$PropertyPath
)
$parts = $PropertyPath -split '\.'
$value = $Object
foreach ($part in $parts) {
$value = $value.$part
}
return $value
}
# リソースが利用可能になるまで待機
function Wait-ResourceAvailable {
param (
[string]$Service,
[string]$Action,
[object]$Params,
[string]$StatusPath,
[string]$ProgressPath
)
$timeout = 1200
$interval = 20
$endTime = (Get-Date).AddSeconds($timeout)
while ((Get-Date) -lt $endTime) {
$response = Invoke-AliyunCommand $Service $Action $Params
$currentStatus = Get-NestedPropertyValue $response $StatusPath
Log "INFO" "Resource status: $currentStatus"
if ($ProgressPath) {
$currentProgress = Get-NestedPropertyValue $response $ProgressPath
Log "INFO" "Creation progress: $currentProgress"
}
if ("Available" -eq $currentStatus) { return }
Start-Sleep -Seconds $interval
}
}
# イメージの作成
Log "INFO" "Creating source image from instance '$SRC_INSTANCE_ID'"
$srcImgId = (Invoke-AliyunCommand -Service "ecs" -Action "CreateImage" -Params @(
"--region", $SRC_REGION_ID,
"--RegionId", $SRC_REGION_ID,
"--InstanceId", $SRC_INSTANCE_ID,
"--ImageName", "cli-src-img"
)).ImageId
Wait-ResourceAvailable -Service "ecs" -Action "DescribeImages" -Params @(
"--region", $SRC_REGION_ID,
"--RegionId", $SRC_REGION_ID,
"--ImageId", $srcImgId,
"--Status", "Creating,Waiting,Available"
) -StatusPath "Images.Image.Status" -ProgressPath "Images.Image.Progress"
Log "INFO" "Source image created: '$srcImgId'"
# ターゲットリージョンへのイメージのコピー
Log "INFO" "Copying image to region: '$DST_REGION_ID'"
$dstImgId = (Invoke-AliyunCommand -Service "ecs" -Action "CopyImage" -Params @(
"--region", $SRC_REGION_ID,
"--RegionId", $SRC_REGION_ID,
"--DestinationRegionId", $DST_REGION_ID,
"--ImageId", $srcImgId,
"--DestinationImageName", "cli-dst-img"
)).ImageId
Wait-ResourceAvailable -Service "ecs" -Action "DescribeImages" -Params @(
"--region", $DST_REGION_ID,
"--RegionId", $DST_REGION_ID,
"--ImageId", $dstImgId,
"--Status", "Creating,Waiting,Available"
) -StatusPath "Images.Image.Status" -ProgressPath "Images.Image.Progress"
Log "INFO" "Destination image copied: '$dstImgId'"
# VPC の作成
Log "INFO" "Creating VPC"
$dstVpcId = (Invoke-AliyunCommand -Service "vpc" -Action "CreateVpc" -Params @(
"--region", $DST_REGION_ID,
"--RegionId", $DST_REGION_ID,
"--CidrBlock", "10.0.0.0/8",
"--VpcName", "cli-dst-vpc"
)).VpcId
Wait-ResourceAvailable -Service "Vpc" -Action "DescribeVpcAttribute" -Params @(
"--region", $DST_REGION_ID,
"--RegionId", $DST_REGION_ID,
"--VpcId", $dstVpcId
) -StatusPath "Status"
Log "INFO" "VPC created: '$dstVpcId'"
# vSwitch の作成
Log "INFO" "Creating VSwitch"
$dstVSwitchId = (Invoke-AliyunCommand vpc CreateVSwitch @(
"--region", $DST_REGION_ID,
"--RegionId", $DST_REGION_ID,
"--ZoneId", $DST_ZONE_ID,
"--VpcId", $dstVpcId,
"--CidrBlock", "10.1.1.0/24"
)).VSwitchId
Wait-ResourceAvailable -Service "Vpc" -Action "DescribeVSwitchAttributes" -Parameters @(
"--region", $DST_REGION_ID,
"--RegionId", $DST_REGION_ID,
"--VSwitch", $dstVSwitchId
) -StatusPath "Status"
Log "INFO" "VSwitch created: '$dstVSwitchId'"
# セキュリティグループの作成
Log "INFO" "Creating security group"
$dstSecurityGroupId = (Invoke-AliyunCommand ecs CreateSecurityGroup @(
"--region", $DST_REGION_ID,
"--RegionId", $DST_REGION_ID,
"--SecurityGroupName", "cli-dst-sg",
"--VpcId", $dstVpcId,
"--SecurityGroupType", "normal"
)).SecurityGroupId
Log "INFO" "Security group created: '$dstSecurityGroupId'"
# ターゲットリージョンに従量課金制の ECS インスタンスを作成
Log "INFO" "Creating ECS instance in zone: '$DST_ZONE_ID'"
$dstInstanceId = (Invoke-AliyunCommand ecs RunInstances @(
"--region", $DST_REGION_ID,
"--RegionId", $DST_REGION_ID,
"--ImageId", $dstImgId,
"--SecurityGroupId", $dstSecurityGroupId,
"--VSwitchId", $dstVSwitchId,
"--InstanceType", $SRC_INSTANCE_TYPE,
"--InstanceName", "cli-dst-ecs",
"--PasswordInherit", "true",
"--SystemDisk.Category", $SRC_SYSTEM_DISK_CATEGORY,
"--SystemDisk.Size", $SRC_SYSTEM_DISK_SIZE,
"--InstanceChargeType", "PostPaid"
)).InstanceIdSets.InstanceIdSet[0]
Log "INFO" "ECS instance created: '$dstInstanceId'"
Log "INFO" "Script execution completed successfully."参考資料
カスタムイメージを使用したクロスリージョンインスタンスのレプリケーション (コンソールベースの方法)