AWS AmazonECS documentation change
Summary
Added documentation for using warm pools with Windows instances, including IAM policy requirements, lifecycle hook configuration, and user data script implementation to ensure proper initialization before instance stop.
Security assessment
The change adds security documentation through required IAM permissions for lifecycle actions and secure metadata token usage in IMDSv2 calls. However, it doesn't address any existing security vulnerability but rather provides operational guidance for Windows warm pools.
Diff
diff --git a/AmazonECS/latest/developerguide/using-warm-pool.md b/AmazonECS/latest/developerguide/using-warm-pool.md index 0ca345f33..e2014bada 100644 --- a//AmazonECS/latest/developerguide/using-warm-pool.md +++ b//AmazonECS/latest/developerguide/using-warm-pool.md @@ -6,0 +7,2 @@ +Using warm pools with Amazon ECS Windows instances + @@ -17 +19 @@ To use warm pools with your Amazon ECS cluster, set the `ECS_WARM_POOLS_CHECK` a -The following shows an example of how the agent configuration variable can be specified in the **User data** field of an Amazon EC2 launch template. Replace `MyCluster` with the name our your cluster. +The following shows an example of how the agent configuration variable can be specified in the **User data** field of an Amazon EC2 launch template for Linux instances. Replace `MyCluster` with the name of your cluster. For Windows instances, see Using warm pools with Amazon ECS Windows instances. @@ -27,0 +30,75 @@ The `ECS_WARM_POOLS_CHECK` variable is only supported on agent versions `1.59.0` +## Using warm pools with Amazon ECS Windows instances + +When using warm pools with the **Stopped** pool state on Windows instances, use Amazon EC2 Auto Scaling lifecycle hooks to ensure user data execution completes before the instance is stopped. Without lifecycle hooks, the instance may be stopped before Amazon ECS initialization finishes. + +To configure lifecycle hooks for Windows warm pool instances: + + 1. Add the following IAM policy to your container instance role to allow the instance to complete the lifecycle action: + + { + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "autoscaling:CompleteLifecycleAction" + ], + "Resource": "*" + } + ] + } + + 2. Add a lifecycle hook to your Auto Scaling group on _Instance Launching_ with `ABANDON` as the default result and a heartbeat timeout that allows enough time for Amazon ECS initialization (for example, 10 minutes). For more information, see [Add lifecycle hooks](https://docs.aws.amazon.com/autoscaling/ec2/userguide/adding-lifecycle-hooks.html) in the _Amazon EC2 Auto Scaling User Guide_. + + 3. Use the following user data that creates a scheduled task to complete the lifecycle action after a delay. The delay ensures EC2Launch finishes saving its state before the instance is stopped. Replace `MyCluster`, `my-lifecycle-hook`, and `my-asg-name` with your values. + + <powershell> + $lifecycleHookName = "my-lifecycle-hook" + $autoScalingGroupName = "my-asg-name" + + $scriptContent = @' + $token = Invoke-RestMethod -Method Put -Uri http://169.254.169.254/latest/api/token -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} + $instanceId = Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/meta-data/instance-id -Headers @{"X-aws-ec2-metadata-token" = $token} + $region = Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/meta-data/placement/region -Headers @{"X-aws-ec2-metadata-token" = $token} + $lifecycleHookName = "my-lifecycle-hook" + $autoScalingGroupName = "my-asg-name" + Complete-ASLifecycleAction -LifecycleHookName $lifecycleHookName -AutoScalingGroupName $autoScalingGroupName -InstanceId $instanceId -LifecycleActionResult 'CONTINUE' -Region $region + '@ + Set-Content -Path "C:\ProgramData\Amazon\ECS\complete-lifecycle.ps1" -Value $scriptContent + + try + { + [Environment]::SetEnvironmentVariable("ECS_WARM_POOLS_CHECK", "true", "Machine") + Import-Module ECSTools + Initialize-ECSAgent -Cluster MyCluster -EnableTaskIAMRole + + $taskAction = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-NoProfile -ExecutionPolicy Bypass -File C:\ProgramData\Amazon\ECS\complete-lifecycle.ps1" + $taskTrigger = New-ScheduledTaskTrigger -Once -At ((Get-Date).AddSeconds(60)) + $settings = New-ScheduledTaskSettingsSet -StartWhenAvailable + $taskPrincipal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount -RunLevel Highest + Register-ScheduledTask -TaskName "CompleteLifecycleHook" -Action $taskAction -Trigger $taskTrigger -Principal $taskPrincipal -Settings $settings -Force + } + catch + { + $token = Invoke-RestMethod -Method Put -Uri http://169.254.169.254/latest/api/token -Headers @{"X-aws-ec2-metadata-token-ttl-seconds" = "21600"} + $INSTANCE = Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/meta-data/instance-id -Headers @{"X-aws-ec2-metadata-token" = $token} + $region = Invoke-RestMethod -Method Get -Uri http://169.254.169.254/latest/meta-data/placement/region -Headers @{"X-aws-ec2-metadata-token" = $token} + Complete-ASLifecycleAction -InstanceId $INSTANCE -LifecycleHookName $lifecycleHookName -AutoScalingGroupName $autoScalingGroupName -LifecycleActionResult ABANDON -Region $region + } + </powershell> + <persist>true</persist> + + + + +This user data script does the following: + + * Initializes the Amazon ECS agent with the warm pools check enabled. + + * Creates a scheduled task that waits 30 seconds after user data completes, then signals the lifecycle hook to proceed. The delay allows EC2Launch to save its state so that user data re-runs correctly on subsequent boots. + + * If initialization fails, the lifecycle action is completed with `ABANDON` so the instance is terminated and replaced. + + + +