关于 ec2
面向云运维人员和开发者的 AWS EC2 参考技能,涵盖实例操作、安全、成本、可靠性与故障排查,并提供 CLI 和 boto3 示例。
主要功能
- 01实例类型与购买选项
- 02启动和管理实例
- 03配置安全组与 EBS
- 04应用安全、成本和可靠性实践
- 05诊断连接与实例故障
适用场景
- 01选择实例类型和购买选项
- 02通过 CLI 或 boto3 启动实例
- 03保护实例并优化成本
- 04排查 SSH 访问或启动故障
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ itsmostafa/ aws-agent-skills --skill ec2安装后在 Claude Code 中输入/ec2确认已加载。
附带文件evals/evals.jsoninstance-management.md
详细介绍
AWS EC2
Amazon Elastic Compute Cloud(EC2)在云端提供可调整规模的计算容量。
高级模式(Auto Scaling、Spot Fleets、Session Manager、Instance Connect、IMDS、Placement Groups、计划扩缩容):请参阅 instance-management.md。
目录
核心概念
实例类型
| 类别 | 示例 | 用例 |
|---|---|---|
| 通用型 | t3、m6i、t4g(Graviton) | Web 服务器、开发环境 |
| 计算优化型 | c6i、c7g(Graviton) | 批处理、游戏 |
| 内存优化型 | r6i、r7g(Graviton) | 数据库、缓存 |
| 存储优化型 | i3、d3 | 数据仓库 |
| 加速型 | p4d、g5 | ML、图形处理 |
对于性能相同的工作负载,Graviton(ARM)实例(t4g、m7g、c7g、r7g)比 x86 同等实例便宜约 20%——新工作负载值得考虑使用。
购买选项
| 选项 | 说明 |
|---|---|
| 按需 | 按小时/秒付费 |
| 预留 | 承诺使用 1-3 年,最高可享 72% 折扣 |
| Spot | 使用闲置容量,最高可享 90% 折扣——可能会提前 2 分钟收到通知后中断 |
| Savings Plans | 基于灵活承诺的折扣 |
AMI(Amazon Machine Image)
包含操作系统、软件和配置的模板,用于启动实例。使用 SSM Parameter Store 查找最新的官方 AMI,而不是将 ID 硬编码:
# Latest Amazon Linux 2 AMI
aws ssm get-parameter \
--name /aws/service/ami-amazon-linux-latest/amzn2-ami-hvm-x86_64-gp2 \
--query 'Parameter.Value' --output text
# Latest Amazon Linux 2023
aws ssm get-parameter \
--name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 \
--query 'Parameter.Value' --output text
# Latest Ubuntu 22.04
aws ssm get-parameter \
--name /aws/service/canonical/ubuntu/server/22.04/stable/current/amd64/hvm/ebs-gp2/ami-id \
--query 'Parameter.Value' --output text
安全组
用于控制入站和出站流量的虚拟防火墙。更改会立即生效——无需重启。
常见模式
启动实例
# Create key pair
aws ec2 create-key-pair \
--key-name my-key \
--query 'KeyMaterial' \
--output text > my-key.pem
chmod 400 my-key.pem
# Create security group
aws ec2 create-security-group \
--group-name web-server-sg \
--description "Web server security group" \
--vpc-id vpc-12345678
# Allow SSH and HTTP
aws ec2 authorize-security-group-ingress \
--group-id sg-12345678 \
--protocol tcp \
--port 22 \
--cidr 10.0.0.0/8
aws ec2 authorize-security-group-ingress \
--group-id sg-12345678 \
--protocol tcp \
--port 80 \
--cidr 0.0.0.0/0
# Launch instance
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type t3.micro \
--key-name my-key \
--security-group-ids sg-12345678 \
--subnet-id subnet-12345678 \
--associate-public-ip-address \
--tag-specifications 'ResourceType=instance,Tags=[{Key=Name,Value=web-server}]'
# Wait until running, then get IP
aws ec2 wait instance-running --instance-ids i-1234567890abcdef0
aws ec2 describe-instances \
--instance-ids i-1234567890abcdef0 \
--query 'Reservations[].Instances[].PublicIpAddress' --output text
boto3:
import boto3
ec2 = boto3.resource('ec2')
instances = ec2.create_instances(
ImageId='ami-0123456789abcdef0',
InstanceType='t3.micro',
KeyName='my-key',
SecurityGroupIds=['sg-12345678'],
SubnetId='subnet-12345678',
MinCount=1,
MaxCount=1,
TagSpecifications=[{
'ResourceType': 'instance',
'Tags': [{'Key': 'Name', 'Value': 'web-server'}]
}]
)
instance = instances[0]
instance.wait_until_running()
instance.reload()
print(f"Instance ID: {instance.id}")
print(f"Public IP: {instance.public_ip_address}")
用户数据脚本
操作系统包管理器说明:
- Amazon Linux 2:使用
amazon-linux-extras install nginx1 -y——yum install nginx会失败,因为默认的 AL2 软件仓库中没有 nginx- Amazon Linux 2023:使用
dnf install -y nginx- Ubuntu:使用
apt-get install -y nginx- Amazon Linux 2 / RHEL:始终可以通过
yum install -y httpd安装httpd(Apache)
# Amazon Linux 2 — nginx via amazon-linux-extras
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type t3.micro \
--key-name my-key \
--security-group-ids sg-12345678 \
--subnet-id subnet-12345678 \
--user-data '#!/bin/bash
amazon-linux-extras install nginx1 -y
systemctl start nginx
systemctl enable nginx
'
# Amazon Linux 2 — httpd (Apache, simpler alternative)
# --user-data '#!/bin/bash
# yum install -y httpd
# systemctl start httpd
# systemctl enable httpd
# echo "<h1>Hello from $(hostname -f)</h1>" > /var/www/html/index.html
# '
附加 IAM 角色
# Create instance profile
aws iam create-instance-profile \
--instance-profile-name web-server-profile
aws iam add-role-to-instance-profile \
--instance-profile-name web-server-profile \
--role-name web-server-role
# Launch with profile
aws ec2 run-instances \
--image-id ami-0123456789abcdef0 \
--instance-type t3.micro \
--iam-instance-profile Name=web-server-profile \
...
从实例创建 AMI
aws ec2 create-image \
--instance-id i-1234567890abcdef0 \
--name "my-custom-ami-$(date +%Y%m%d)" \
--description "Custom AMI with web server" \
--no-reboot
使用 Spot 的 Auto Scaling Group(现代方法)
在大规模使用 Spot 实例时,推荐的方法是通过采用混合实例策略的 Auto Scaling Group,而不是旧版的 request-spot-instances API。此方法支持实例多样化,以尽量减少中断。
完整设置请参阅 instance-management.md。快速示例:
# 1. Create launch template with IMDSv2
aws ec2 create-launch-template \
--launch-template-name my-lt \
--launch-template-data '{
"ImageId": "ami-0123456789abcdef0",
"SecurityGroupIds": ["sg-12345678"],
"IamInstanceProfile": {"Name": "my-profile"},
"MetadataOptions": {"HttpTokens": "required", "HttpEndpoint": "enabled"}
}'
# 2. Create ASG with mixed-instances (Spot + On-Demand diversification)
aws autoscaling create-auto-scaling-group \
--auto-scaling-group-name my-asg \
--min-size 0 --max-size 20 --desired-capacity 2 \
--vpc-zone-identifier "subnet-111,subnet-222" \
--mixed-instances-policy '{
"LaunchTemplate": {
"LaunchTemplateSpecification": {"LaunchTemplateName": "my-lt", "Version": "$Latest"},
"Overrides": [
{"InstanceType": "c5.xlarge"},
{"InstanceType": "c5.2xlarge"},
{"InstanceType": "c5a.xlarge"}
]
},
"InstancesDistribution": {
"OnDemandBaseCapacity": 0,
"OnDemandPercentageAboveBaseCapacity": 0,
"SpotAllocationStrategy": "capacity-optimized"
}
}'
EBS 卷管理
# Create volume
aws ec2 create-volume \
--availability-zone us-east-1a \
--size 100 \
--volume-type gp3 \
--iops 3000 \
--throughput 125 \
--encrypted
# Attach to instance
aws ec2 attach-volume \
--volume-id vol-12345678 \
--instance-id i-1234567890abcdef0 \
--device /dev/sdf
# Create snapshot
aws ec2 create-snapshot \
--volume-id vol-12345678 \
--description "Daily backup"
CLI 参考
实例管理
| 命令 | 说明 |
|---|---|
aws ec2 run-instances | 启动实例 |
aws ec2 describe-instances | 列出实例 |
aws ec2 start-instances | 启动已停止的实例 |
aws ec2 stop-instances | 停止运行中的实例 |
aws ec2 reboot-instances | 重启实例 |
aws ec2 terminate-instances | 终止实例 |
aws ec2 modify-instance-attribute | 修改实例设置 |
安全组
| 命令 | 说明 |
|---|---|
aws ec2 create-security-group | 创建安全组 |
aws ec2 describe-security-groups | 列出安全组 |
aws ec2 authorize-security-group-ingress | 添加入站规则 |
aws ec2 revoke-security-group-ingress | 移除入站规则 |
aws ec2 authorize-security-group-egress | 添加出站规则 |
AMI
| 命令 | 说明 |
|---|---|
aws ec2 describe-images | 列出 AMI |
aws ec2 create-image | 从实例创建 AMI |
aws ec2 copy-image | 将 AMI 复制到其他区域 |
aws ec2 deregister-image | 删除 AMI |
EBS 卷
| 命令 | 描述 |
|---|---|
aws ec2 create-volume | 创建 EBS 卷 |
aws ec2 attach-volume | 附加到实例 |
aws ec2 detach-volume | 从实例分离 |
aws ec2 create-snapshot | 创建快照 |
aws ec2 modify-volume | 调整大小/修改卷 |
最佳实践
安全性
- 使用 IAM 角色,而不是在实例上使用访问密钥
- 限制安全组——遵循最小权限原则
- 后端实例使用私有子网
- 启用 IMDSv2,以防止 SSRF 攻击
- 对 EBS 卷进行静态加密
# Require IMDSv2 on existing instance
aws ec2 modify-instance-metadata-options \
--instance-id i-1234567890abcdef0 \
--http-tokens required \
--http-endpoint enabled
性能
- 选择合适规格的实例——监控并调整
- 使用 EBS 优化型实例
- 选择合适的 EBS 卷类型(gp3 是不错的默认选择;高 IOPS 场景使用 io2)
- 使用置放群组实现低延迟网络(参见 instance-management.md)
成本优化
- 对可容错工作负载使用 Spot 实例(批处理、ML 训练、CI)
- 停止/终止未使用的实例
- 对稳定运行的工作负载使用预留实例或 Savings Plans
- 删除未使用的 EBS 卷和快照
- 考虑使用 Graviton(t4g、m7g、c7g)——相同性能下价格约低 20%
可靠性
- 使用 Auto Scaling 组实现高可用性(参见 instance-management.md)
- 跨多个 AZ 部署
- 使用 Elastic Load Balancer分配流量
- 实施运行状况检查
故障排除
无法通过 SSH 连接到实例
首先:识别错误类型——不同错误对应不同的根本原因:
| 错误 | 含义 | 主要疑因 |
|---|---|---|
Connection refused | 网络可达,但 SSH 守护进程未在侦听 | sshd 崩溃、未安装 sshd、操作系统防火墙(ufw/iptables)阻止连接、端口错误 |
Connection timed out | 数据包始终未能到达 | 安全组阻止端口 22、NACL 阻止流量、没有公有 IP、IP 地址错误 |
Permission denied | 已连接,但身份验证失败 | 密钥文件错误、用户名错误、密钥未获授权 |
各操作系统的常见用户名:
| 操作系统 | 默认 SSH 用户 |
|---|---|
| Amazon Linux 2 / 2023 | ec2-user |
| Ubuntu | ubuntu |
| Debian | admin |
| CentOS / RHEL | ec2-user 或 centos |
| Windows | Administrator |
诊断命令:
# 1. Check instance state and public IP
aws ec2 describe-instances \
--instance-ids i-1234567890abcdef0 \
--query "Reservations[].Instances[].{State:State.Name,PublicIP:PublicIpAddress,StatusChecks:State.Name}"
# 2. Check instance status (system + instance checks)
aws ec2 describe-instance-status --instance-ids i-1234567890abcdef0
# 3. Check security group rules for port 22
aws ec2 describe-security-groups \
--group-ids sg-12345678 \
--query "SecurityGroups[].IpPermissions[?ToPort==\`22\`]"
# 4. Get console output to see boot logs, sshd errors, OOM events
aws ec2 get-console-output \
--instance-id i-1234567890abcdef0 \
--latest \
--query Output --output text
如果连接被拒绝——通过 Session Manager 登录实例以修复 sshd:
# Requires SSM agent on instance + AmazonSSMManagedInstanceCore policy
aws ssm start-session --target i-1234567890abcdef0
# Once inside, diagnose:
systemctl status ssh # Ubuntu
systemctl status sshd # Amazon Linux
df -h # Check disk full
sudo sshd -t # Test sshd config for syntax errors
sudo journalctl -u ssh -n 50 # Recent sshd logs
使用 Session Manager 替代 SSH(无需开放端口,也无需密钥对):
aws ssm start-session --target i-1234567890abcdef0
# Port forwarding via SSM
aws ssm start-session \
--target i-1234567890abcdef0 \
--document-name AWS-StartPortForwardingSession \
--parameters '{"portNumber":["22"],"localPortNumber":["2222"]}'
实例无法启动
原因:
- 达到实例限制
- AZ 中容量不足
- EBS 卷问题
- AMI 无效
# Check instance state reason
aws ec2 describe-instances \
--instance-ids i-1234567890abcdef0 \
--query "Reservations[].Instances[].StateReason"
实例无法访问
# Check instance status
aws ec2 describe-instance-status \
--instance-ids i-1234567890abcdef0
# Get console output
aws ec2 get-console-output \
--instance-id i-1234567890abcdef0 \
--latest
# Get screenshot (for Windows/GUI issues)
aws ec2 get-console-screenshot \
--instance-id i-1234567890abcdef0
CPU/内存使用率高
# Enable detailed monitoring
aws ec2 monitor-instances \
--instance-ids i-1234567890abcdef0
# Check CloudWatch metrics (cross-platform date command)
START=$(date -u -v-1H +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u --date='1 hour ago' +%Y-%m-%dT%H:%M:%SZ)
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
--start-time "$START" \
--end-time "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \
--period 300 \
--statistics Average