aws ec2 run-instances: Launch EC2 Instances in CI
aws ec2 run-instances launches EC2 instances from a specified AMI, instance type, and network configuration, returning the new instance IDs.
Pipelines spin up EC2 for ephemeral test rigs or self-hosted runners. run-instances is the launch primitive; the key is making it non-interactive and tagging on create so cleanup jobs can find what they made.
What it does
aws ec2 run-instances provisions EC2 instances from --image-id with the requested --instance-type and count. It returns a Reservation JSON containing the InstanceId(s). You attach networking, key pair, security groups, IAM instance profile, and user-data bootstrap script at launch.
Common usage
aws ec2 run-instances \
--image-id ami-0abcd1234ef567890 \
--instance-type t3.micro \
--count 1 \
--subnet-id subnet-0123456789abcdef0 \
--security-group-ids sg-0123456789abcdef0 \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=ci-runner},{Key=ci,Value=true}]' \
--query 'Instances[0].InstanceId' --output textOptions
| Flag | What it does |
|---|---|
| --image-id <ami> | AMI to launch from (required) |
| --instance-type <type> | Instance type, e.g. t3.micro |
| --count <n> | Number of instances (or min:max) |
| --subnet-id / --security-group-ids | VPC placement and firewall |
| --iam-instance-profile Name=<x> | Attach an instance profile for role creds |
| --user-data file://boot.sh | Bootstrap script run at first boot |
| --tag-specifications | Tag the instance atomically at creation |
| --dry-run | Check permissions without launching |
In CI
Tag on create with --tag-specifications (not a later create-tags) so a crashed job never leaves an untagged, unfindable instance. Pull the ID with --query "Instances[0].InstanceId" --output text and store it for the teardown step. Prefer OIDC role assumption over long-lived keys for the runner credentials.
Common errors in CI
"An error occurred (UnauthorizedOperation) when calling the RunInstances operation" means the role lacks ec2:RunInstances; note --dry-run also returns UnauthorizedOperation when denied and DryRunOperation when allowed. "InvalidAMIID.NotFound" means the AMI does not exist in this region. "InstanceLimitExceeded" or "VcpuLimitExceeded" means you hit an account quota. "InvalidParameterValue: Value () for parameter groupId is invalid" usually means an empty security-group variable.