やりたいこと
EC2 インスタンスを AWS Backup から復旧させる場合、IP アドレスが変わらないようにしたい
AWS Backup から復旧させる場合、新しい EC2 インスタンスが正常に起動することを確認してから、古い EC2 インスタンスを削除するようにしたい
検証
EC2 インスタンスのネットワークインターフェイス 1 にプライマリ IP とセカンダリ IP を付与するが、Windows の設定でセカンダリ IP のみを利用し、プライマリ IP は使わないという選択肢です。
この場合、以下のような考慮が不要となる認識です。
- アプリケーション側で両方の IP を利用するのか、セカンダリ IP のみを利用するのか
- FW などでホストで穴あけをしていた場合、両方の IP を指定する必要がある
- リストア後に、Windows のネットワークの設定を変更しなくても良い
..etc
「リストア後に、Windows のネットワークの設定を変更しなくても良い」ことについて、もう少し書くと、
例えば、古い EC2 インスタンスで Windows のネットワークの設定を以下の通りとしたとします。
PS C:\Users\Administrator> ipconfig /all
イーサネット アダプター イーサネット 3:
IPv4 アドレス . . . . . . . . . . . .: 10.10.10.30(優先)
サブネット マスク . . . . . . . . . .: 255.255.255.0
IPv4 アドレス . . . . . . . . . . . .: 10.10.10.10(優先)
サブネット マスク . . . . . . . . . .: 255.255.255.0
デフォルト ゲートウェイ . . . . . . .: 10.10.10.1
DNS サーバー. . . . . . . . . . . . .: 10.10.0.2
古い EC2 インスタンスが削除されていない状態では、プライマリ IP はデタッチできないので、新しい EC2 インスタンスのプライマリ IP は変更するしかありません。そのため、次の通り新しい EC2 インスタンスを起動します。
- ネットワークインターフェイス 1
- プライマリ IP: 10.10.10.20
- セカンダリ IP: 10.10.10.30
しかし、先程の Windows のネットワークの設定では、10.10.10.30 と 10.10.10.10 が設定されているので、Windows のネットワークの設定も 10.10.10.10 を 10.10.10.20 に変更する必要が発生するということかなと思います。
ただし、古い EC2 インスタンスの Windows のネットワークの設定では、10.10.10.30 のみしか設定されていないため、セカンダリ IP をデタッチ後は一切接続できなくなります。
古い EC2 インスタンスの起動
基本的には、ネットワークインターフェイス 1 に、プライマリ IP と セカンダリ IP を付与して起動しておくだけです。
- ネットワークインターフェイス 1
- プライマリ IP: 10.10.10.10
- セカンダリ IP: 10.10.10.30
なお、ユーザデータで Powershell の New-NetIPAddress を利用して、IP アドレスを変更しようとしましたが、原則として IP アドレスへの変更はできないようです。(試してみましたが、実際にできなく、調べたらこのようでした。違ったらすいません。。。)
RDP 接続し、ipconfig /all
で現在のネットワークを確認しておきます。
当然ですが、プライマリ IP: 10.10.10.10 のみしか認識していません。
PS C:\Users\Administrator> ipconfig /all
イーサネット アダプター イーサネット 3:
IPv4 アドレス . . . . . . . . . . . .: 10.10.10.10(優先)
サブネット マスク . . . . . . . . . .: 255.255.255.0
デフォルト ゲートウェイ . . . . . . .: 10.10.10.1
DNS サーバー. . . . . . . . . . . . .: 10.10.0.2
セカンダリ IP: 10.10.10.30 が認識するように、Windows のネットワークの設定を変更していきます。
現在は、プライマリ IP: 10.10.10.10 で接続しているため、再度 RDP で接続し直し、再度ipconfig /all
で現在のネットワークを確認しておきます。
PS C:\Users\Administrator> ipconfig /all
イーサネット アダプター イーサネット 3:
IPv4 アドレス . . . . . . . . . . . .: 10.10.10.30(優先)
サブネット マスク . . . . . . . . . .: 255.255.255.0
デフォルト ゲートウェイ . . . . . . .: 10.10.10.1
DNS サーバー. . . . . . . . . . . . .: 10.10.0.2
セカンダリ IP のデタッチ
旧 EC2 を停止し、セカンダリ IP: 10.10.10.30 をデタッチします。
aws ec2 stop-instances --instance-ids $(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=ec2" \
--query "Reservations[].Instances[].InstanceId" \
--output text)
aws ec2 unassign-private-ip-addresses \
--network-interface-id $(aws ec2 describe-instances \
--filters "Name=tag:Name,Values=ec2" \
--query "Reservations[].Instances[].NetworkInterfaces[].NetworkInterfaceId" \
--output text) \
--private-ip-addresses 10.10.10.30
念の為、AWS コンソールからもセカンダリ IP: 10.10.10.30 がデタッチされていることを確認しておきましょう。
AWS Backup からの復元
aws backup list-recovery-points-by-backup-vault
で、「RecoveryPointArn」を確認します。
aws backup list-recovery-points-by-backup-vault \
--backup-vault-name [backup-vault-name] \
| jq '.RecoveryPoints[] | {RecoveryPointArn, Status, CreationDate, CompletionDate, ResourceName}'
{
"RecoveryPointArn": "arn:aws:ec2:ap-northeast-1::image/ami-0cde33f354e4ddba7",
"Status": "COMPLETED",
"CreationDate": "2024-12-01T21:00:00+09:00",
"CompletionDate": "2024-12-01T21:20:47.607000+09:00",
"ResourceName": "ec2"
}
{
"RecoveryPointArn": "arn:aws:ec2:ap-northeast-1::image/ami-0af302fc13f009a61",
"Status": "COMPLETED",
"CreationDate": "2024-11-30T21:00:00+09:00",
"CompletionDate": "2024-11-30T21:20:21.768000+09:00",
"ResourceName": "ec2"
}
aws backup get-recovery-point-restore-metadata
で、バックアップの作成に使用されたメタデータを取得します。
この時に以下の処理をします。
- メタデータの RestoreMetadata のみを取得
- CpuOptions, SecurityGroupIds, SubnetId を削除
- NetworkInterfaces
- NetworkInterfaceId, PrivateIpAddresses, SecondaryPrivateIpAddressCount を削除
- AssociatePublicIpAddress を false に編集
- PrivateIpAddress 10.10.10.10 を 10.10.10.20 に置き換え
これにより、新しい EC2 の IP アドレスは以下の通りとなります。
- ネットワークインターフェイス 1
- プライマリ IP: 10.10.10.20
- セカンダリ IP: 10.10.10.30
backup_vault_name="Default"
RecoveryPointArn="arn:aws:ec2:ap-northeast-1::image/ami-0cde33f354e4ddba7"
old_ip="10.10.10.10"
new_ip="10.10.10.20"
aws backup get-recovery-point-restore-metadata \
--backup-vault-name "$backup_vault_name" \
--recovery-point-arn "$RecoveryPointArn" \
| jq --arg oldIp "$old_ip" \
--arg newIp "$new_ip" '
.RestoreMetadata
| del(.CpuOptions)
| del(.SecurityGroupIds)
| del(.SubnetId)
| .NetworkInterfaces |= (
fromjson
| map(
del(.NetworkInterfaceId)
| del(.PrivateIpAddress)
| del(.SecondaryPrivateIpAddressCount)
| (.AssociatePublicIpAddress = false)
| (.PrivateIpAddresses |= map(
if .PrivateIpAddress == $oldIp then
.PrivateIpAddress = $newIp
else
.
end
))
)
| tojson
)
' > restore_metadata.json
コマンド実行後のメタデータは以下の通りです。
{
"Architecture": "x86_64",
"CapacityReservationSpecification": "{\"CapacityReservationPreference\":\"open\"}",
"CreditSpecification": "{\"CpuCredits\":\"unlimited\"}",
"DisableApiTermination": "false",
"EbsOptimized": "true",
"EnaSupport": "true",
"HibernationOptions": "{\"Configured\":false}",
"IamInstanceProfileName": "AmazonSSMRoleForInstancesQuickSetup",
"InstanceInitiatedShutdownBehavior": "stop",
"InstanceType": "t3.small",
"KeyName": "windows",
"Monitoring": "{\"State\":\"disabled\"}",
"NetworkInterfaces": "[{\"AssociatePublicIpAddress\":false,\"DeleteOnTermination\":true,\"Description\":\"\",\"DeviceIndex\":0,\"Groups\":[\"sg-0ab05c4d4946e22ee\"],\"Ipv6AddressCount\":0,\"Ipv6Addresses\":[],\"PrivateIpAddresses\":[{\"Primary\":true,\"PrivateIpAddress\":\"10.10.10.20\"},{\"Primary\":false,\"PrivateIpAddress\":\"10.10.10.30\"}],\"SubnetId\":\"subnet-0d6ec4e42c29ea23b\",\"InterfaceType\":\"interface\",\"Ipv4Prefixes\":[],\"Ipv6Prefixes\":[]}]",
"Placement": "{\"AvailabilityZone\":\"ap-northeast-1a\",\"GroupName\":\"\",\"Tenancy\":\"default\"}",
"Platform": "windows",
"RequireIMDSv2": "false",
"RootDeviceType": "ebs",
"VirtualizationType": "hvm",
"VpcId": "vpc-05d96ee40d75582bc",
"aws:backup:request-id": "f577d135-1fc9-480c-9cb2-2a7883ae02f0"
}
では、復元の準備が整いましたので実行してみますが、メタデータファイルを用意して、CLI から実行する場合、AWS Backup の IAM ロールに iam:PassRole
を付与してあげる必要があるようです。
{
"Version": "2012-10-17",
"Statement": [
{
"Action": "iam:PassRole",
"Resource": "*",
"Effect": "Allow"
}
]
}
aws backup start-restore-job
で復元してみます。今回 AWS CLI は 1 つずつ実行していってますが、スクリプトにしても良いと思います。
aws backup start-restore-job --region ap-northeast-1 \
--recovery-point-arn "$RecoveryPointArn" \
--iam-role-arn "arn:aws:iam::123456789012:role/service-role/AWSBackupDefaultServiceRole" \
--metadata file://restore_metadata.json \
--copy-source-tags-to-restored-resource
{
"RestoreJobId": "EE682088-127A-5D7C-7573-B2AEB43A00C4"
}
数分後、ジョブの実行が完了しているか確認します。ジョブの実行が完了するまでに数分かかるので、スクリプトで実装するのであれば、数分おきに Status が COMPLETED なっているか確認するようにすれば良いと思います。
aws backup describe-restore-job \
--region ap-northeast-1 \
--restore-job-id "EE682088-127A-5D7C-7573-B2AEB43A00C4" \
--query "Status" \
--output text
COMPLETED
新しい EC2 インスタンスの動作確認
AWS コンソールから、以下の IP アドレスになっていることを確認します。
- ネットワークインターフェイス 1
- プライマリ IP: 10.10.10.20
- セカンダリ IP: 10.10.10.30
RDP で接続し、ipconfig /all で現在のネットワークを確認し、セカンダリ IP: 10.10.10.30 のままであれば成功です。
PS C:\Users\Administrator> ipconfig /all
イーサネット アダプター イーサネット 3:
IPv4 アドレス . . . . . . . . . . . .: 10.10.10.30(優先)
サブネット マスク . . . . . . . . . .: 255.255.255.0
デフォルト ゲートウェイ . . . . . . .: 10.10.10.1
DNS サーバー. . . . . . . . . . . . .: 10.10.0.2