SSM Automation Runbook "AWSEC2-CloneInstanceAndUpgradeWindows" 実行前の前提条件チェックスクリプトを作ってみた
はじめに
テクニカルサポートの 片方 です。
AWS Systems Manager Automation の Runbook である AWSEC2-CloneInstanceAndUpgradeWindows を利用すれば、EC2 インスタンス上の Windows Server OS を自動でインプレースアップグレードできます。
一方で、前提条件を満たしていない場合、Automation が途中で失敗してしまうこともあります。
例えば、ルート EBS ボリュームのディスク容量不足や時刻同期のずれなどが原因でインプレースアップグレードに失敗するケースがありました。
そこで今回は、AWSEC2-CloneInstanceAndUpgradeWindows 実行前の前提条件を確認するための事前チェック(スクリプト)を作成したのでご紹介します。
事前チェックの内容
今回作成した事前チェックでは、AWSEC2-CloneInstanceAndUpgradeWindows の公式ドキュメントに記載されている
前提条件および制限事項を中心に確認するようにしています。
また、公式ドキュメントには明示されていないものの、当サポート窓口でのお問い合わせ対応や検証の中で、実際にインプレースアップグレード失敗の原因になりやすかったポイントについても、ナレッジとしてチェック項目に含めています。
具体的には、以下のような項目を事前に確認します。
公式ドキュメントに記載されている主な前提条件・制限事項
- 対象の Windows Server バージョンがサポートされているか
(Windows Server 2008 R2 / 2012 R2 / 2016 / 2019) - 対象インスタンスが Domain Controller ではないか
- Remote Desktop Services のロール
(RDSH / RDCB / RDVH / RDWA)がインストールされていないか - PowerShell のバージョンが 3.0 以上であるか
- SSM Automation を実行するための IAM ロールが付与されているか
- インターネット(HTTPS/443)へのアウトバウンド通信が可能か
- ルートディスクに 20GB 以上の空き容量があるか
サポート窓口のナレッジとして追加しているチェック項目
公式ドキュメントの前提条件を満たしていても、環境によっては該当 Runbook の実行が失敗するケースがあります。
そのため、サポート対応の中で特に影響が大きかった以下の項目についても、事前チェックとして確認するようにしました。
-
時刻同期が正常に行われているか
時刻のずれが大きい場合、AWS API との通信に失敗する事例があります。 -
AWS ドライバー(PV / ENA / NVMe など)のバージョン情報
古い AWS ドライバーバージョンの場合、インプレースアップグレード中に問題が発生する事例があります。最新 Ver を利用中か確認することをお勧めします。
冒頭でお伝えした通り、事前チェックをすべてクリアした場合でも、AWSEC2-CloneInstanceAndUpgradeWindows の実行が必ず成功することを保証するものではありません。
しかしながら、事前に明らかな NG 条件や環境依存の問題を洗い出すことで、無駄な再実行や、原因調査・確認作業といった工程を減らすことが可能です。
実装してみた
前のセクションで整理したチェック項目をもとに、AWSEC2-CloneInstanceAndUpgradeWindows の実行前に前提条件を確認できる事前チェックを PowerShell スクリプトとして実装しました。
本事前チェックスクリプトは、AWS Systems Manager Run Command(AWS-RunPowerShellScript)から実行します。
実装手順
実装手順は以下のとおりです。
- AWS マネジメントコンソールから Systems Manager を開く
- Run Command を選択し、「Run Command (コマンドを実行)」 をクリック

- ドキュメントに AWS-RunPowerShellScript を選択

- コマンドのパラメータ 「Commands」 に、以下の PowerShell スクリプトを貼り付けて実行
Write-Output "=== AWSEC2-CloneInstanceAndUpgradeWindows PreCheck ==="
# 1. OS Version
try {
$os = Get-WmiObject Win32_OperatingSystem
$caption = $os.Caption
if ($caption -match "Windows Server 2008 R2|Windows Server 2012 R2|Windows Server 2016|Windows Server 2019") {
Write-Output "OSVersion | OK | $caption"
} else {
Write-Output "OSVersion | NG | Unsupported OS: $caption"
}
} catch {
Write-Output "OSVersion | NG | Unable to determine OS version"
}
# 2. Domain Controller
try {
$cs = Get-WmiObject Win32_ComputerSystem
if ($cs.DomainRole -eq 4 -or $cs.DomainRole -eq 5) {
Write-Output "DomainController | NG | This instance is a Domain Controller"
} else {
Write-Output "DomainController | OK | Not a Domain Controller"
}
} catch {
Write-Output "DomainController | NG | Unable to determine domain role"
}
# 3. RDS Roles
try {
$rds = Get-WmiObject Win32_ServerFeature | Where-Object { $_.Name -match "Remote Desktop" }
if ($rds) {
foreach ($f in $rds) {
Write-Output "RDSRole | NG | Installed: $($f.Name)"
}
} else {
Write-Output "RDSRole | OK | No RDS roles installed"
}
} catch {
Write-Output "RDSRole | NG | Unable to determine RDS roles"
}
# 4. PowerShell Version
try {
$psMajor = $PSVersionTable.PSVersion.Major
if ($psMajor -ge 3) {
Write-Output "PowerShell | OK | Version $psMajor"
} else {
Write-Output "PowerShell | NG | Version $psMajor"
}
} catch {
Write-Output "PowerShell | NG | Version check failed"
}
# 5. IAM Role (IMDSv2)
try {
$token = Invoke-RestMethod -Method PUT `
-Uri "http://169.254.169.254/latest/api/token" `
-Headers @{ "X-aws-ec2-metadata-token-ttl-seconds" = "21600" }
$iam = Invoke-RestMethod `
-Uri "http://169.254.169.254/latest/meta-data/iam/info" `
-Headers @{ "X-aws-ec2-metadata-token" = $token }
if ($iam.InstanceProfileArn) {
Write-Output "IAMRole | OK | $($iam.InstanceProfileArn)"
} else {
Write-Output "IAMRole | NG | No instance profile"
}
} catch {
Write-Output "IAMRole | NG | Unable to access instance metadata"
}
# 6. Time Sync
try {
$svc = Get-WmiObject Win32_Service -Filter "Name='w32time'"
if ($svc.State -ne "Running") {
Write-Output "TimeSync | NG | Windows Time Service not running"
} else {
$w32tm = w32tm /stripchart /computer:time.aws.com /dataonly /samples:1 2>$null
if ($w32tm -match "(-?\d+\.\d+)s") {
$offset = [math]::Abs([double]$matches[1])
if ($offset -le 300) {
Write-Output "TimeSync | OK | Offset ${offset}s"
} else {
Write-Output "TimeSync | NG | Offset ${offset}s"
}
}
}
} catch {
Write-Output "TimeSync | NG | Check failed"
}
# 7. Internet Access
try {
if (Test-NetConnection s3.amazonaws.com -Port 443 -InformationLevel Quiet) {
Write-Output "InternetAccess | OK | HTTPS(443) reachable"
} else {
Write-Output "InternetAccess | NG | HTTPS(443) not reachable"
}
} catch {
Write-Output "InternetAccess | NG | Connection check failed"
}
# 8. Disk Space
try {
$drive = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'"
$freeGB = [math]::Round($drive.FreeSpace / 1GB, 2)
if ($freeGB -ge 20) {
Write-Output "BootDiskFreeSpace | OK | $freeGB GB"
} else {
Write-Output "BootDiskFreeSpace | NG | $freeGB GB"
}
} catch {
Write-Output "BootDiskFreeSpace | NG | Check failed"
}
# 9. AWS Drivers (Info)
try {
$drivers = Get-WmiObject Win32_PnPSignedDriver |
Where-Object { $_.DeviceName -like "*AWS*" -or $_.DeviceName -like "*Amazon*" }
foreach ($d in $drivers) {
Write-Output "AWS-Driver | INFO | $($d.DeviceName) | Version $($d.DriverVersion)"
}
} catch {
Write-Output "AWS-Driver | WARN | Unable to list drivers"
}
Write-Output "=== PreCheck Finished ==="
※ 適宜修正してください。
- 対象の EC2 インスタンスを指定
- 下部へスクロールし「実行」 をクリック
これで以上です。お疲れさまでした。
確認してみた
作成した事前チェックスクリプトを、Windows Server 2019 および Windows Server 2016 の EC2 インスタンスで実際に実行してみました。
なお、Windows Server 2016 OS の EC2 インスタンスでは、ルート EBS ボリュームの空き容量が不足するように設定しています。


Run Command の実行が完了しましたので、確認します。

Windows Server 2019 の場合
この環境では、OS バージョンやロール構成、ディスク容量や時刻同期など、すべてのチェック項目が問題なくクリアされていることを確認できました。
=== AWSEC2-CloneInstanceAndUpgradeWindows PreCheck ===
OSVersion | OK | Microsoft Windows Server 2019 Datacenter
DomainController | OK | Not a Domain Controller
RDSRole | OK | No RDS roles installed
PowerShell | OK | Version 5
IAMRole | OK | arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCore
TimeSync | OK | Offset 0s
InternetAccess | OK | HTTPS(443) reachable
BootDiskFreeSpace | OK | 59.49 GB
AWS-Driver | INFO | Amazon Elastic Network Adapter | Version 2.11.0.0
AWS-Driver | INFO | AWS NVMe Elastic Block Storage Adapter | Version 1.7.0.39
=== PreCheck Finished ===
事前チェックの結果からは、AWSEC2-CloneInstanceAndUpgradeWindows を実行するための前提条件は満たしている状態であることが分かります。

Windows Server 2016 の場合
Windows Server 2016 が稼働している EC2 インスタンスでも同様に事前チェックを実行しています。
こちらの環境では、OS バージョンやロール構成自体は問題ありませんでしたが、想定通りにルート EBS ボリュームのディスク空き容量が不足していることが事前チェックで検出されました。
=== AWSEC2-CloneInstanceAndUpgradeWindows PreCheck ===
OSVersion | OK | Microsoft Windows Server 2016 Datacenter
DomainController | OK | Not a Domain Controller
RDSRole | OK | No RDS roles installed
PowerShell | OK | Version 5
IAMRole | OK | arn:aws:iam::123456789012:instance-profile/AmazonSSMManagedInstanceCore
TimeSync | OK | Offset 0s
InternetAccess | OK | HTTPS(443) reachable
BootDiskFreeSpace | NG | 7.25 GB
AWS-Driver | INFO | Amazon Elastic Network Adapter | Version 2.11.0.0
AWS-Driver | INFO | AWS NVMe Elastic Block Storage Adapter | Version 1.7.0.39
=== PreCheck Finished ===
このように、ディスク容量不足という明確な NG 条件を把握できたため、途中で失敗することを防ぐことができます。

まとめ
本ブログが誰かの参考になれば幸いです。
参考資料
- AWSEC2-CloneInstanceAndUpgradeWindows - AWS Systems Manager Automation Runbook Reference
- Use Automation runbooks to upgrade an EC2 Windows instance - Amazon Elastic Compute Cloud
- AWS Systems Manager Run Command - AWS Systems Manager
クラスメソッドオペレーションズ株式会社について
クラスメソッドグループのオペレーション企業です。
運用・保守開発・サポート・情シス・バックオフィスの専門チームが、IT・AIをフル活用した「しくみ」を通じて、お客様の業務代行から課題解決や高付加価値サービスまでを提供するエキスパート集団です。
当社は様々な職種でメンバーを募集しています。
「オペレーション・エクセレンス」と「らしく働く、らしく生きる」を共に実現するカルチャー・しくみ・働き方にご興味がある方は、クラスメソッドオペレーションズ株式会社 コーポレートサイト をぜひご覧ください。※2026年1月 アノテーション㈱から社名変更しました






