Troubleshooting Windows EC2 instance user-data

Infrastructure Developer
Search for a command to run...

Infrastructure Developer
No comments yet. Be the first to comment.
Prerequisite Install AWS Load Balancer Controller: This controller is essential for managing AWS load balancers in a Kubernetes environment. Step 1: Enable Proxy Protocol in NLB Target Group Add the following annotation to your NLB Target Group to...

AWS Managed NAT Gateway is a widely-used service that provides seamless internet access for resources within a private VPC subnet. However, its cost structure has been a pain point for many AWS users, with high fees for both hourly usage and data pro...
Configure NTP in timesyncd.conf echo "NTP=169.254.169.123" | sudo tee -a /etc/systemd/timesyncd.conf cat /etc/systemd/timesyncd.conf Enable the timesyncd.service sudo systemctl unmask systemd-timesyncd.service sudo apt install systemd-timesyncd ...

Error waiting to create Instance: Error waiting for Creating Instance: Error code 7, message: Required 'compute.subnetworks.use' permission for

automating time tracking for a more accurate record of time spent on projects

Often while we are troubleshooting for EC2 user data, we want to have visibility to what happens to the script at launch. Whether it failed or which line of code is not executing by the instance.
We usually have to RDP to see the log itself or use Session Manager to connect to the instance. But we often found the SSM agent is not running. It is quite frustrating and time-consuming to fix every hurdle to get to the log file.
So in this article, I'd like to share my user-data by utilizing the CloudWatch agent to push the user-data log to CloudWatch Logs.
This example will install Python and AWS CLIV2 in Windows EC2 instance.
<powershell>
$instanceId = (invoke-webrequest http://169.254.169.254/latest/meta-data/instance-id -UseBasicParsing).content
$config = '{
"logs":{
"logs_collected":{
"files":{
"collect_list":[
{
"file_path":"C:\\ProgramData\\Amazon\\EC2-Windows\\Launch\\Log\\UserdataExecution.log",
"log_group_name":"UserdataExecution.log",
"log_stream_name":"{instance_id}"
}
]
}
}
},
"metrics":{
"append_dimensions":{
"AutoScalingGroupName":"${aws:AutoScalingGroupName}",
"ImageId":"${aws:ImageId}",
"InstanceId":"${aws:InstanceId}",
"InstanceType":"${aws:InstanceType}"
},
"metrics_collected":{
"LogicalDisk":{
"measurement":[
"% Free Space"
],
"metrics_collection_interval":60,
"resources":[
"*"
]
},
"Memory":{
"measurement":[
"% Committed Bytes In Use"
],
"metrics_collection_interval":60
},
"statsd":{
"metrics_aggregation_interval":60,
"metrics_collection_interval":10,
"service_address":":8125"
}
}
}
}'
mkdir C:\Downloads\Amazon\AmazonCloudWatchAgent
powershell -Command "(New-Object Net.WebClient).DownloadFile('https://s3.amazonaws.com/amazoncloudwatch-agent/windows/amd64/latest/amazon-cloudwatch-agent.msi','C:\Downloads\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent.msi')"
do{
C:\Downloads\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent.msi
Start-Sleep 2
$config | Set-Content 'C:\Downloads\Amazon\AmazonCloudWatchAgent\config.json'
& "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a fetch-config -m ec2 -s -c file:"C:\Downloads\Amazon\AmazonCloudWatchAgent\config.json"
$agent_status = & "C:\Program Files\Amazon\AmazonCloudWatchAgent\amazon-cloudwatch-agent-ctl.ps1" -a status | ConvertFrom-Json
$agent_status
}
until($agent_status.status -eq "running")
Restart-Service AmazonSSMAgent
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls, [Net.SecurityProtocolType]::Tls11, [Net.SecurityProtocolType]::Tls12, [Net.SecurityProtocolType]::Ssl3
[Net.ServicePointManager]::SecurityProtocol = "Tls, Tls11, Tls12, Ssl3"
iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
choco install python -y
$dlurl = "https://awscli.amazonaws.com/AWSCLIV2.msi"
$installerPath = Join-Path $env:TEMP (Split-Path $dlurl -Leaf)
Invoke-WebRequest $dlurl -OutFile $installerPath
Start-Process -FilePath msiexec -Args "/i $installerPath /passive" -Verb RunAs -Wait
Remove-Item $installerPath
</powershell>