关于 aws-ec2
面向管理生产、预发布或开发工作负载的团队,提供部署和运维 Amazon EC2 实例的技能。内容包括重复部署、扩缩容、Spot 实例、AMI 管理和常见故障排查。
主要功能
- 01启动和管理 EC2 实例
- 02配置启动模板和用户数据
- 03设置 Auto Scaling 组
- 04申请和配置 Spot 实例
- 05创建和管理 AMI
- 06排查启动与连接问题
适用场景
- 01为应用环境启动计算实例
- 02构建可复用的黄金 AMI
- 03在负载均衡器后扩展实例
- 04调查 SSH 或实例启动故障
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ bagelhole/ devops-security-agent-skills --skill aws-ec2安装后在 Claude Code 中输入/aws-ec2确认已加载。
附带文件references/ec2-operations.md
详细介绍
AWS EC2
部署和管理 Amazon EC2 计算实例,以承载生产、预发布和开发工作负载。
适用场景
- 启动新的计算实例以托管应用
- 构建黄金 AMI,实现一致的部署
- 在负载均衡器后配置自动扩缩组
- 将工作负载迁移到 Spot 实例以节省成本
- 排查实例连接、性能或启动故障
- 创建启动模板,实现可重复的基础设施部署
前提条件
- 已安装并配置 AWS CLI v2(
aws configure) - IAM 权限:
ec2:*、autoscaling:*、elasticloadbalancing:*、iam:PassRole - 已有包含子网的 VPC(参见 aws-vpc)
- 已创建 SSH 密钥对(
aws ec2 create-key-pair --key-name my-key --query 'KeyMaterial' --output text > my-key.pem)
实例类型选择指南
| 类别 | 类型 | 用例 |
|---|---|---|
| 通用型 | t3、t3a、m6i、m7g | Web 服务器、小型数据库、开发/测试 |
| 计算优化型 | c6i、c7g | 批处理、媒体编码、机器学习推理 |
| 内存优化型 | r6i、r7g、x2idn | 内存缓存、大型数据库 |
| 存储优化型 | i3、i4i、d3 | 数据仓库、分布式文件系统 |
| 加速型 | p4d、g5、inf2 | 机器学习训练、GPU 渲染、推理 |
| 突增型 | t3.micro-t3.2xlarge | 稳定负载较低、偶尔需要突增的场景 |
启动实例
# Launch a production web server
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.medium \
--key-name my-key \
--security-group-ids sg-12345678 \
--subnet-id subnet-12345678 \
--iam-instance-profile Name=EC2AppProfile \
--metadata-options "HttpTokens=required,HttpEndpoint=enabled" \
--block-device-mappings '[{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": 30,
"VolumeType": "gp3",
"Iops": 3000,
"Throughput": 125,
"Encrypted": true
}
}]' \
--tag-specifications 'ResourceType=instance,Tags=[
{Key=Name,Value=web-server-01},
{Key=Environment,Value=production},
{Key=Team,Value=platform}
]' \
--user-data file://userdata.sh
# Launch with IMDSv2 required (security best practice)
aws ec2 run-instances \
--image-id ami-0abcdef1234567890 \
--instance-type t3.micro \
--metadata-options "HttpTokens=required,HttpPutResponseHopLimit=1,HttpEndpoint=enabled" \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=secure-instance}]'
用户数据脚本
#!/bin/bash
# userdata.sh - Bootstrap a web server on Amazon Linux 2023
set -euxo pipefail
# System updates
dnf update -y
# Install and start web server
dnf install -y nginx
systemctl enable nginx
systemctl start nginx
# Install CloudWatch agent
dnf install -y amazon-cloudwatch-agent
/opt/aws/amazon-cloudwatch-agent/bin/amazon-cloudwatch-agent-ctl \
-a fetch-config -m ec2 \
-s -c ssm:AmazonCloudWatch-linux
# Install CodeDeploy agent
dnf install -y ruby wget
cd /home/ec2-user
wget https://aws-codedeploy-us-east-1.s3.us-east-1.amazonaws.com/latest/install
chmod +x ./install
./install auto
# Signal CloudFormation (if launched via CFN)
# /opt/aws/bin/cfn-signal -e $? --stack ${AWS::StackName} --resource ASG --region ${AWS::Region}
启动模板
# Create a launch template with full configuration
aws ec2 create-launch-template \
--launch-template-name web-server-template \
--version-description "v1 - AL2023 with nginx" \
--launch-template-data '{
"ImageId": "ami-0abcdef1234567890",
"InstanceType": "t3.medium",
"KeyName": "my-key",
"SecurityGroupIds": ["sg-12345678"],
"IamInstanceProfile": {"Name": "EC2AppProfile"},
"MetadataOptions": {
"HttpTokens": "required",
"HttpEndpoint": "enabled"
},
"BlockDeviceMappings": [{
"DeviceName": "/dev/xvda",
"Ebs": {
"VolumeSize": 30,
"VolumeType": "gp3",
"Encrypted": true
}
}],
"TagSpecifications": [{
"ResourceType": "instance",
"Tags": [
{"Key": "Environment", "Value": "production"},
{"Key": "ManagedBy", "Value": "launch-template"}
]
}],
"Monitoring": {"Enabled": true},
"UserData": "'"$(base64 -w0 userdata.sh)"'"
}'
# Create a new version of the launch template
aws ec2 create-launch-template-version \
--launch-template-name web-server-template \
--source-version 1 \
--version-description "v2 - updated AMI" \
--launch-template-data '{"ImageId": "ami-0newami1234567890"}'
# Set the default version
aws ec2 modify-launch-template \
--launch-template-name web-server-template \
--default-version 2
自动扩缩组
# Create ASG with mixed instances (on-demand + spot)
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name web-asg \
--mixed-instances-policy '{
"LaunchTemplate": {
"LaunchTemplateSpecification": {
"LaunchTemplateName": "web-server-template",
"Version": "$Default"
},
"Overrides": [
{"InstanceType": "t3.medium"},
{"InstanceType": "t3a.medium"},
{"InstanceType": "m5.large"}
]
},
"InstancesDistribution": {
"OnDemandBaseCapacity": 2,
"OnDemandPercentageAboveBaseCapacity": 25,
"SpotAllocationStrategy": "capacity-optimized"
}
}' \
--min-size 2 --max-size 10 --desired-capacity 4 \
--vpc-zone-identifier "subnet-aaa,subnet-bbb" \
--target-group-arns "arn:aws:elasticloadbalancing:us-east-1:123456789012:targetgroup/web-tg/abc123" \
--health-check-type ELB \
--health-check-grace-period 300 \
--tags '[
{"Key":"Name","Value":"web-asg","PropagateAtLaunch":true},
{"Key":"Environment","Value":"production","PropagateAtLaunch":true}
]'
# Create target tracking scaling policy (target 60% CPU)
aws autoscaling put-scaling-policy \
--auto-scaling-group-name web-asg \
--policy-name cpu-target-tracking \
--policy-type TargetTrackingScaling \
--target-tracking-configuration '{
"PredefinedMetricSpecification": {
"PredefinedMetricType": "ASGAverageCPUUtilization"
},
"TargetValue": 60.0,
"ScaleInCooldown": 300,
"ScaleOutCooldown": 60
}'
# Create scheduled scaling for known traffic patterns
aws autoscaling put-scheduled-update-group-action \
--auto-scaling-group-name web-asg \
--scheduled-action-name scale-up-morning \
--recurrence "0 8 * * MON-FRI" \
--min-size 4 --max-size 20 --desired-capacity 8
aws autoscaling put-scheduled-update-group-action \
--auto-scaling-group-name web-asg \
--scheduled-action-name scale-down-evening \
--recurrence "0 20 * * MON-FRI" \
--min-size 2 --max-size 10 --desired-capacity 2
Spot 实例
# Request Spot instances
aws ec2 request-spot-instances \
--spot-price "0.05" \
--instance-count 3 \
--type "one-time" \
--launch-specification '{
"ImageId": "ami-0abcdef1234567890",
"InstanceType": "c5.xlarge",
"KeyName": "my-key",
"SecurityGroupIds": ["sg-12345678"],
"SubnetId": "subnet-12345678"
}'
# Check current Spot prices
aws ec2 describe-spot-price-history \
--instance-types t3.medium t3a.medium m5.large \
--availability-zone us-east-1a \
--product-descriptions "Linux/UNIX" \
--start-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--query "SpotPriceHistory[].{Type:InstanceType,Price:SpotPrice,AZ:AvailabilityZone}" \
--output table
# Create a Spot Fleet request
aws ec2 request-spot-fleet \
--spot-fleet-request-config '{
"IamFleetRole": "arn:aws:iam::123456789012:role/aws-ec2-spot-fleet-role",
"TargetCapacity": 10,
"SpotPrice": "0.10",
"AllocationStrategy": "capacityOptimized",
"LaunchSpecifications": [
{"ImageId": "ami-xxx", "InstanceType": "c5.xlarge", "SubnetId": "subnet-aaa"},
{"ImageId": "ami-xxx", "InstanceType": "c5a.xlarge", "SubnetId": "subnet-bbb"}
]
}'
AMI 管理
# Create an AMI from a running instance
aws ec2 create-image \
--instance-id i-0abc123def456 \
--name "web-server-$(date +%Y%m%d)" \
--description "Web server golden AMI" \
--no-reboot \
--tag-specifications 'ResourceType=image,Tags=[
{Key=Name,Value=web-server-golden},
{Key=Version,Value=2026.03.24}
]'
# Copy AMI to another region for disaster recovery
aws ec2 copy-image \
--source-image-id ami-0abcdef1234567890 \
--source-region us-east-1 \
--region us-west-2 \
--name "web-server-dr-copy"
# Deregister old AMIs and delete associated snapshots
aws ec2 deregister-image --image-id ami-old123
aws ec2 delete-snapshot --snapshot-id snap-old123
# Share AMI with another AWS account
aws ec2 modify-image-attribute \
--image-id ami-0abcdef1234567890 \
--launch-permission "Add=[{UserId=987654321098}]"
实例管理
# List running instances with key details
aws ec2 describe-instances \
--filters "Name=instance-state-name,Values=running" \
--query "Reservations[].Instances[].{ID:InstanceId,Type:InstanceType,IP:PrivateIpAddress,Name:Tags[?Key=='Name']|[0].Value,State:State.Name}" \
--output table
# Stop and start instances
aws ec2 stop-instances --instance-ids i-0abc123def456
aws ec2 start-instances --instance-ids i-0abc123def456
# Resize an instance (stop first)
aws ec2 stop-instances --instance-ids i-0abc123def456
aws ec2 wait instance-stopped --instance-ids i-0abc123def456
aws ec2 modify-instance-attribute \
--instance-id i-0abc123def456 \
--instance-type '{"Value": "t3.large"}'
aws ec2 start-instances --instance-ids i-0abc123def456
# Get console output for debugging boot issues
aws ec2 get-console-output --instance-id i-0abc123def456
# Get instance screenshot (helps debug GUI issues)
aws ec2 get-console-screenshot --instance-id i-0abc123def456
使用 Terraform 配置 EC2 自动扩缩
resource "aws_launch_template" "web" {
name_prefix = "web-"
image_id = data.aws_ami.amazon_linux.id
instance_type = "t3.medium"
iam_instance_profile {
name = aws_iam_instance_profile.web.name
}
metadata_options {
http_tokens = "required"
http_endpoint = "enabled"
}
block_device_mappings {
device_name = "/dev/xvda"
ebs {
volume_size = 30
volume_type = "gp3"
encrypted = true
}
}
user_data = base64encode(file("userdata.sh"))
tag_specifications {
resource_type = "instance"
tags = {
Name = "web-server"
Environment = "production"
}
}
}
resource "aws_autoscaling_group" "web" {
name = "web-asg"
min_size = 2
max_size = 10
desired_capacity = 4
vpc_zone_identifier = [aws_subnet.private_a.id, aws_subnet.private_b.id]
target_group_arns = [aws_lb_target_group.web.arn]
health_check_type = "ELB"
launch_template {
id = aws_launch_template.web.id
version = "$Latest"
}
tag {
key = "Name"
value = "web-asg"
propagate_at_launch = true
}
}
resource "aws_autoscaling_policy" "cpu" {
name = "cpu-target-tracking"
autoscaling_group_name = aws_autoscaling_group.web.name
policy_type = "TargetTrackingScaling"
target_tracking_configuration {
predefined_metric_specification {
predefined_metric_type = "ASGAverageCPUUtilization"
}
target_value = 60.0
}
}
故障排查
| 问题 | 原因 | 解决方法 |
|---|---|---|
实例卡在 pending 状态 | 容量不足 | 尝试其他可用区或实例类型 |
| 无法通过 SSH 连接实例 | 安全组或 NACL 阻止了 22 端口 | 检查 SG 入站规则和路由表 |
| 实例立即终止 | EBS 卷限制或 AMI 问题 | 使用 describe-instances 检查 StateReason |
| IMDSv1 弃用警告 | 未设置元数据选项 | 在启动模板中设置 HttpTokens=required |
| 用户数据未运行 | 脚本缺少 shebang 或未进行 Base64 编码 | 确认存在 #!/bin/bash 文件头;检查 /var/log/cloud-init-output.log |
| Spot 实例已终止 | AWS 收回了容量 | 使用容量优化型分配策略并选择多种实例类型 |
| ASG 未替换运行状况不佳的实例 | 运行状况检查宽限期太短 | 延长宽限期,使其覆盖应用启动时间 |
| EBS 吞吐量成为瓶颈 | gp2 卷太小,无法提供所需 IOPS | 迁移到 gp3 并明确设置 IOPS/吞吐量 |
相关技能
- aws-vpc - VPC 网络、子网和安全组
- aws-iam - 实例配置文件和角色
- aws-cost-optimization - 合理调整资源规格和 Spot 策略
- terraform-aws - 使用基础设施即代码进行部署
- cloudformation - AWS 原生 IaC 模板
评论
支持 Markdown