Amazon EC2 via SDK: Your First Instance
Amazon EC2 gives you virtual machines you launch, use, and tear down on demand.
Busca en todas las páginas de la documentación
Amazon EC2 gives you virtual machines you launch, use, and tear down on demand.
This page runs the full lifecycle from code: launch one instance, wait until it is running, read its details, then terminate it. Both SDKs do the same four steps.
Quick-reference recipe card - copy-paste ready.
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2", region_name="us-east-1")
run = ec2.run_instances(
ImageId="ami-0abcdef1234567890", # a valid AMI in your region
InstanceType="t3.micro",
MinCount=1, MaxCount=1,
)
instance_id = run["Instances"][0]["InstanceId"]
print("launched", instance_id)// --- TypeScript (AWS SDK v3) ---
import { EC2Client, RunInstancesCommand } from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({ region: "us-east-1" });
const run = await ec2.send(new RunInstancesCommand({
ImageId: "ami-0abcdef1234567890", // a valid AMI in your region
InstanceType: "t3.micro",
MinCount: 1, MaxCount: 1,
}));
const instanceId = run.Instances?.[0].InstanceId;
console.log("launched", instanceId);When to reach for this:
Launch one instance, wait for it with a waiter, read its public details, then terminate it and wait for that too.
# --- Python (boto3) ---
import boto3
ec2 = boto3.client("ec2", region_name="us-east-1")
# 1. Launch
run = ec2.run_instances(
ImageId="ami-0abcdef1234567890",
InstanceType="t3.micro",
MinCount=1, MaxCount=1,
TagSpecifications=[{
"ResourceType": "instance",
"Tags": [{"Key": "Name", "Value": "first-instance"}],
}],
)
iid = run["Instances"][0]["InstanceId"]
# 2. Wait until it is running (no manual polling loop)
ec2.get_waiter("instance_running").wait(InstanceIds=[iid])
# 3. Read details
desc = ec2.describe_instances(InstanceIds=[iid])
inst = desc["Reservations"][0]["Instances"][0]
print(iid, inst["State"]["Name"], inst.get("PublicIpAddress"))
# 4. Terminate and wait for cleanup
ec2.terminate_instances(InstanceIds=[iid])
ec2.get_waiter("instance_terminated").wait(InstanceIds=[iid])
print("terminated", iid)// --- TypeScript (AWS SDK v3) ---
import {
EC2Client, RunInstancesCommand, DescribeInstancesCommand,
TerminateInstancesCommand, waitUntilInstanceRunning, waitUntilInstanceTerminated,
} from "@aws-sdk/client-ec2";
const ec2 = new EC2Client({ region: "us-east-1" });
// 1. Launch
const run = await ec2.send(new RunInstancesCommand({
ImageId: "ami-0abcdef1234567890",
InstanceType: "t3.micro",
MinCount: 1, MaxCount: 1,
TagSpecifications: [{
ResourceType: "instance",
Tags: [{ Key: "Name", Value: "first-instance" }],
}],
}));
const iid = run.Instances![0].InstanceId!;
// 2. Wait until it is running
await waitUntilInstanceRunning({ client: ec2, maxWaitTime: 300 }, { InstanceIds: [iid] });
// 3. Read details
const desc = await ec2.send(new DescribeInstancesCommand({ InstanceIds: [iid] }));
const inst = desc.Reservations![0].Instances![0];
console.log(iid, inst.State?.Name, inst.PublicIpAddress);
// 4. Terminate and wait for cleanup
await ec2.send(new TerminateInstancesCommand({ InstanceIds: [iid] }));
await waitUntilInstanceTerminated({ client: ec2, maxWaitTime: 300 }, { InstanceIds: [iid] });
console.log("terminated", iid);What this demonstrates:
RunInstances requires MinCount and MaxCount even for a single instance.TagSpecifications) let you find and clean up instances later.sleep loop.DescribeInstances returns instances nested inside Reservations, not a flat list.t3.micro, m5.large, and so on) sets CPU, memory, and network capacity.RunInstances returns immediately with the instance in pending state; it is not usable until it reaches running.DescribeInstances under the hood until the target state is reached or it times out, replacing hand-written polling.shutting-down to terminated.Hardcoding an AMI ID is fragile because they change and differ per region. Look one up at runtime instead.
# --- Python (boto3) ---
import boto3
# The current Amazon Linux 2023 AMI is published as an SSM public parameter.
ssm = boto3.client("ssm", region_name="us-east-1")
ami = ssm.get_parameter(
Name="/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64"
)["Parameter"]["Value"]
print(ami)// --- TypeScript (AWS SDK v3) ---
import { SSMClient, GetParameterCommand } from "@aws-sdk/client-ssm";
const ssm = new SSMClient({ region: "us-east-1" });
const out = await ssm.send(new GetParameterCommand({
Name: "/aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64",
}));
console.log(out.Parameter?.Value);Feed that value into RunInstances as ImageId so you always launch a current image.
You can pass a KeyName for SSH, but the modern default is to attach an IAM role and connect through Systems Manager Session Manager - no open port 22, no key files to manage. Pass an instance profile via the IamInstanceProfile parameter.
MinCount=1, MaxCount=1 for a single instance.RunInstances returns while the instance is still pending, with no public IP yet. Fix: wait on instance_running before reading details.finally block or cleanup script.SubnetId and SecurityGroupIds, or rely on the default VPC for a first test.stop keeps the instance and its EBS volume; terminate deletes it. Fix: terminate to fully clean up, stop only to pause a keeper.| Alternative | Use When | Don't Use When |
|---|---|---|
| EC2 via SDK (this page) | Dynamic, per-request instance lifecycle from code | Managing long-lived fleets that should be declarative |
| CloudFormation / CDK / Terraform | Provisioning stable infrastructure you version | You need imperative, one-off launches |
| Auto Scaling Groups | Fleets that scale on demand or heal themselves | A single short-lived instance |
| AWS Lambda | Event-driven or short tasks with no server to manage | Long-running or stateful processes |
| ECS / Fargate | Containerized workloads without managing hosts | You specifically need a full VM |
An AMI ID, an instance type, and MinCount/MaxCount. In a default VPC the SDK fills in the subnet and default security group for you.
A single RunInstances call is one reservation that can launch several instances, so the API groups instances under the reservation that created them. Iterate reservations, then instances.
Waiters implement the correct polling interval and timeout for the resource, and stop on the right terminal states. They are less code and less likely to hammer the API or hang forever.
Resolve it at runtime from an SSM public parameter such as the Amazon Linux 2023 path. Hardcoding an ID breaks across regions and over time as images are republished.
Stopping halts the instance but keeps it and its EBS volume so you can start it again. Terminating deletes the instance permanently. Terminate test instances to avoid ongoing charges.
Attach an IAM role with SSM permissions and use Systems Manager Session Manager. It gives you a shell with no open inbound port and no key files.
Yes. Set MaxCount above 1 (and MinCount to the least acceptable number). EC2 launches up to MaxCount, and the call returns all instances it started.
Usually the security group blocks the port, the subnet has no public route, or the instance has no public IP. Check the security group ingress and the subnet's route to an internet gateway.
Billing starts when the instance begins running and continues by the second until you stop or terminate it. A forgotten t3.micro still accrues charges, so always clean up.
For long-lived infrastructure, prefer IaC (CloudFormation, CDK, Terraform) so the desired state is versioned and reproducible. Use the SDK for dynamic, per-request lifecycle instead.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última actualización: 24 jul 2026