简介
负载均衡器可以避开故障应用,但本身不会创建替代服务器。本实验将创建启动模板和 Auto Scaling 组,保持两台应用实例。你将让一个应用故障,观察自动替换产生的新实例 ID,并验证新服务器真正处理请求。
你应已理解 EC2 User Data、ALB 目标组和应用健康检查。本次全新环境提供网络、应用镜像、密钥对,以及带 HTTP 监听器的空 ALB 目标组,没有现成的应用实例池。AWS CLI 和连接文件独立于前面的实验准备。
认证考点关联
本实验为以下认证考点提供入门实践。
- Solutions Architect – Associate (SAA-C03) · 任务 2.1:启动模板、Auto Scaling 组容量和负载均衡集成;任务 2.2:通过替换故障后端支持可用性。
- CloudOps Engineer – Associate (SOA-C03) · 任务 2.1:使用 Auto Scaling 保持 EC2 容量;任务 2.2:通过应用健康状态识别并替换不健康后端。
创建应用启动模板
本步骤定义 Auto Scaling 启动每台应用服务器时使用的配置。
进入工作目录,加载已准备好的网络变量:
cd /home/labex/project
source launch.env
启动模板保存 AMI、实例类型、安全组和启动配置等实例设置。查看已提供的配置:
cat launch-template.json
cat application-user-data.sh
JSON 选择了已准备好的 AMI、t3.micro、report-key 和应用安全组。UserData 包含另行展示的启动脚本的 base64 编码。脚本创建初始配置,将消息设为 Application ready、healthy 设为 true。Auto Scaling 每次启动都必须应用该配置,让替代实例就绪;只在某台旧服务器内部手动修改不会改变模板。
创建模板。file:// 告诉 AWS CLI 将 JSON 文件内容作为参数值:
LT_ID=$(aws ec2 \
create-launch-template \
--launch-template-name application-template \
--launch-template-data file://launch-template.json \
--query 'LaunchTemplate.LaunchTemplateId' \
--output text)
模板具有编号的版本。查看组将显式使用的版本 1:
aws ec2 \
describe-launch-template-versions \
--launch-template-id "$LT_ID" \
--versions 1 \
--query 'LaunchTemplateVersions[].{Version:VersionNumber,AMI:LaunchTemplateData.ImageId,Type:LaunchTemplateData.InstanceType,Key:LaunchTemplateData.KeyName,Groups:LaunchTemplateData.SecurityGroupIds}'
创建模板不会启动实例。打开 AWS View:已提供的 ALB 和目标组存在,但尚无已注册应用目标。
启动并连接应用实例池
本步骤创建 Auto Scaling 组,将其真实应用实例连接到已提供的 ALB。
Auto Scaling 组在最小和最大容量范围内保持期望实例数量。期望容量是组要维持的数量,不是请求吞吐量的度量。最小 2、期望 2、最大 3 表示初始两台服务器,并允许增加一台。
保存已提供目标组的 ARN 和负载均衡器的 DNS 名称:
TG_ARN=$(aws elbv2 \
describe-target-groups \
--names application-targets \
--query 'TargetGroups[0].TargetGroupArn' \
--output text)
LB_DNS=$(aws elbv2 \
describe-load-balancers \
--names application-alb \
--query 'LoadBalancers[0].DNSName' \
--output text)
使用模板版本 1 和两个已准备好的子网创建组。--target-group-arns 自动将组实例注册到 ALB。--health-check-type ELB 将负载均衡健康状态纳入替换判断;仅靠 EC2 检查无法发现所有应用故障。宽限期给新实例留出启动时间,之后应用健康状态才会导致替换。本练习使用 30 秒,生产值应匹配应用启动行为:
aws autoscaling \
create-auto-scaling-group \
--auto-scaling-group-name application-fleet \
--launch-template "LaunchTemplateId=$LT_ID,Version=1" \
--min-size 2 \
--max-size 3 \
--desired-capacity 2 \
--vpc-zone-identifier "$SUBNET_ID,$SECOND_SUBNET_ID" \
--target-group-arns "$TG_ARN" \
--health-check-type ELB \
--health-check-grace-period 30
查看组及其实例 ID:
aws autoscaling \
describe-auto-scaling-groups \
--auto-scaling-group-names application-fleet \
--query 'AutoScalingGroups[].{Min:MinSize,Desired:DesiredCapacity,Max:MaxSize,HealthCheck:HealthCheckType,Grace:HealthCheckGracePeriod,Instances:Instances[].InstanceId}'
等待应用就绪,再查看 ALB 目标:
aws elbv2 \
wait target-in-service \
--target-group-arn "$TG_ARN"
aws elbv2 \
describe-target-health \
--target-group-arn "$TG_ARN" \
--query 'TargetHealthDescriptions[].{Instance:Target.Id,Health:TargetHealth.State}' \
--output table
预期为两个健康 ID。发送六个请求,将响应 ID 与组实例对照:
for request in 1 2 3 4 5 6; do
curl --config client.conf -sS "http://$LB_DNS/health"
echo
done
打开 AWS View。确认期望容量 2、两个健康目标,并通过 Send request 观察两个 ID 的真实 200 响应。子网和可用区标签表示配置,本练习不测量实际跨可用区容灾能力。
观察自动故障替换
本步骤让应用故障,并由组替换该实例,而不是手动修复。
选择一个当前组实例,保存其用于 SSH 的公网地址:
OLD_ID=$(aws autoscaling \
describe-auto-scaling-groups \
--auto-scaling-group-names application-fleet \
--query 'AutoScalingGroups[0].Instances[0].InstanceId' \
--output text)
OLD_IP=$(aws ec2 \
describe-instances \
--instance-ids "$OLD_ID" \
--query 'Reservations[0].Instances[0].PublicIpAddress' \
--output text)
只修改 healthy,让应用返回 503。与上一个实验一样,使用临时 JSON 文件避免读取时覆盖:
ssh -F ssh_config "ubuntu@$OLD_IP" \
'sudo jq ".healthy = false" /etc/report-app/config.json > /tmp/report-config.json && sudo install -m 644 /tmp/report-config.json /etc/report-app/config.json'
ssh -F ssh_config "ubuntu@$OLD_IP" \
'curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:8081/health'
预期为 503。应用故障时实例仍在运行。ALB 检测健康检查失败;启动宽限期结束后,组会替换不健康实例以恢复期望容量。相同启动模板会让替代实例以健康配置启动。
保持 AWS View 打开,观察 ID 和健康状态变化。检测后会紧接着替换,不健康状态可能很短;新目标也可能先显示 initial,再变为健康。不要手动修复,也不要额外执行 run-instances。
等待旧实例终止,并等待目标组健康:
aws ec2 \
wait instance-terminated \
--instance-ids "$OLD_ID"
aws elbv2 \
wait target-in-service \
--target-group-arn "$TG_ARN"
查看旧实例和当前组:
aws ec2 \
describe-instances \
--instance-ids "$OLD_ID" \
--query 'Reservations[].Instances[].{Instance:InstanceId,State:State.Name}'
aws autoscaling \
describe-auto-scaling-groups \
--auto-scaling-group-names application-fleet \
--query 'AutoScalingGroups[].{Desired:DesiredCapacity,Instances:Instances[].InstanceId}'
旧 ID 应为 terminated。期望容量仍为 2,新 ID 替代了旧 ID。替代实例是重新初始化的服务器;只在旧服务器内部进行的修改不会自动保留。
再次发送六个请求:
for request in 1 2 3 4 5 6; do
curl --config client.conf -sS "http://$LB_DNS/health"
echo
done
查找两个当前组 ID,包括替代实例,且不应出现旧 ID。在 AWS View 中确认两个健康目标,并通过 Send request 观察替代实例真正响应。仅有原生资源数量还不能证明新应用可用。

示例:期望容量保持为两台,新创建的实例返回 HTTP 200。你的实例 ID 会不同。
删除实例池和启动模板
本步骤删除你的组、实例和启动模板,保留已提供的 ALB 和网络。
用 --force-delete 删除组,即使最小容量为 2,也终止其实例。仅删除模板不会停止运行中的实例:
aws autoscaling \
delete-auto-scaling-group \
--auto-scaling-group-name application-fleet \
--force-delete
aws ec2 \
wait instance-terminated \
--filters "Name=tag:aws:autoscaling:groupName,Values=application-fleet"
aws ec2 \
delete-launch-template \
--launch-template-id "$LT_ID"
等待器通过 Auto Scaling 自动添加的标签选择本组实例,包括先前被替换的旧实例,并等待所有选中实例终止。检查组已不存在、模板列表和目标注册:
aws autoscaling \
describe-auto-scaling-groups \
--auto-scaling-group-names application-fleet \
--query 'AutoScalingGroups[].AutoScalingGroupName'
aws ec2 \
describe-launch-templates \
--query 'LaunchTemplates[].LaunchTemplateName'
aws elbv2 \
describe-target-health \
--target-group-arn "$TG_ARN" \
--query 'TargetHealthDescriptions[].Target.Id'
三个列表都应为 []。目标取消注册可能需要时间;如果仍在进行,稍等并重复最后的查询。AWS View 应保留 ALB 和目标组,但不显示实例池和已注册应用目标。保留已提供的网络、AMI 和密钥对。
总结
你创建了带版本的启动模板和 Auto Scaling 组,保持两台真实应用服务器。你将 ALB 健康检查纳入替换判断,制造应用故障,并验证新实例 ID 真正处理请求。最后,你删除了组、实例和模板,保留了已提供的负载均衡器和网络。
下一个实验将通过简单扩缩策略改变期望容量,并测试组的上下限。



