介绍
只有应用正确初始化,运行中的实例才能发挥作用。你将使用 Terraform 读取已准备好的应用 AMI,在提供的网络中启动 EC2 实例,并通过 User Data 配置应用。
你应已了解 Terraform 变量和资源引用、公有子网路由、安全组以及 EC2 启动基础知识。此全新环境提供 AMI、密钥对、网络和一个独立的参考应用。你将创建并删除自己的应用实例。
与认证考试的关联
| 认证 | 考试任务 | 实践内容 |
|---|---|---|
| Cloud Practitioner (CLF-C02) | 任务 3.1 | 通过基础设施即代码部署已初始化的 EC2 应用,并使用 AWS CLI 检查其部署状态。 |
实验概览

读取 AMI 并启动应用
在这一步中,你将把已准备好的 AMI、网络输入和 User Data 连接到 Terraform EC2 资源,然后验证应用初始化后的响应。
打开 Terminal 和 AWS View。参考服务器已经运行。应用网络已就绪,但尚无 application-server。本实验不会复用之前实验的虚拟机或资源。
进入工作目录,检查已准备好的输入值:
cd /home/labex/project/application-launch
cat terraform.tfvars.json
这些值标识提供的 AMI、子网和安全组。网络已配置为在启动时分配公网 IP,具有互联网路由,并允许 User 客户端访问应用端口 8081。Terraform 已为课程环境准备就绪;无需个人凭据。
通过独立的 AWS 查询找到提供的应用镜像。AMI 描述创建实例时使用的镜像;读取现有 AMI 不会创建新镜像。
aws ec2 \
describe-images \
--filters Name=name,Values=report-server-ubuntu-2204 \
--query 'Images[].{Image:ImageId,Name:Name,Architecture:Architecture}'
名称为 report-server-ubuntu-2204,架构为 x86_64,ID 与 ami_id 输入一致。Terraform 数据源读取现有对象;资源管理对象的生命周期。你将通过 data.aws_ami.application 读取此 AMI,再通过 aws_instance.application 创建实例。
创建 application.tf。带引号的外层 heredoc 写入 HCL,不进行 shell 展开。在 HCL 内,${...} 对 Terraform 表达式进行插值,jsonencode 将消息转换为有效 JSON。当 User Data 在新实例内部运行时,带引号的内层 CONFIG heredoc 会将该 JSON 写入预先准备好的应用配置。
cat > application.tf <<'HCL'
data "aws_ami" "application" {
most_recent = true
filter {
name = "image-id"
values = [var.ami_id]
}
}
resource "aws_instance" "application" {
ami = data.aws_ami.application.id
instance_type = "t3.micro"
key_name = "report-key"
subnet_id = var.subnet_id
vpc_security_group_ids = [var.security_group_id]
user_data_replace_on_change = true
user_data = <<-SCRIPT
#!/bin/bash
set -eu
cat > /etc/report-app/config.json <<'CONFIG'
${jsonencode({ message = var.message })}
CONFIG
SCRIPT
tags = {
Name = "application-server"
}
}
output "instance_id" {
value = aws_instance.application.id
}
output "image_id" {
value = data.aws_ami.application.id
}
HCL
实例引用 AMI 数据源,而不是复制镜像 ID。提供的子网和安全组输入将它连接到已准备好的网络。User Data 在首次启动时运行以配置应用;它不是交互式登录命令。默认 message 输入为 Terraform report application。user_data_replace_on_change 使后续启动配置变更明确触发实例替换;你将在后面的实验中探索这种发布行为。
初始化、格式化并验证:
terraform init
terraform fmt
terraform validate
如果 init 显示 Incomplete lock file information for providers,它描述的是其他平台的校验和。已准备好的虚拟机使用 linux_amd64;初始化和验证成功后即可继续。
审查计划。它读取提供的 AMI,并提出创建一个 EC2 实例。它不得替换参考服务器或创建新 AMI。
terraform plan
应用配置,并在提示时输入 yes:
terraform apply
保存并显示生成的实例和镜像 ID:
INSTANCE_ID=$(terraform output -raw instance_id)
echo "$INSTANCE_ID"
IMAGE_ID=$(terraform output -raw image_id)
echo "$IMAGE_ID"
独立查询实例。将它的运行状态、镜像、子网和安全组与预先准备的输入进行核对。
aws ec2 \
describe-instances \
--instance-ids "$INSTANCE_ID" \
--query 'Reservations[].Instances[].{ID:InstanceId,State:State.Name,Image:ImageId,Subnet:SubnetId,Groups:SecurityGroups[].GroupId,PublicIP:PublicIpAddress}'
在 AWS View 中,选择 application-server、User · 198.51.100.10 和 Application · 8081,然后点击 Send request。预期看到 Connected · 200 和 Terraform report application。实际应用响应证明启动配置已作用于工作负载;仅有 running 不能证明这一结果。

示例检查点:AWS View 显示运行中的应用及其实际初始化消息。各虚拟机中的资源 ID 和地址会有所不同。
检查 Terraform 映射并确认收敛:
terraform state list
terraform plan
状态包含 AMI 数据源和实例资源;计划显示 No changes.。
删除实例并保留提供的基础设施
在这一步中,你将仅销毁 Terraform 管理的应用实例,同时保留其源镜像、已准备好的网络和参考应用。
数据源不拥有它读取的镜像。VPC、子网、路由、安全组和密钥对也均在此状态之外提供。批准删除之前,先审查删除范围:
terraform plan -destroy
预期销毁一个受管理实例。然后执行删除,并输入 yes:
terraform destroy
查询同一个实例 ID。其状态应为 terminated;请求失败不能证明实例已终止。
aws ec2 \
describe-instances \
--instance-ids "$INSTANCE_ID" \
--query 'Reservations[].Instances[].{ID:InstanceId,State:State.Name}'
预先准备的镜像必须仍然存在,并保持原始 ID:
aws ec2 \
describe-images \
--image-ids "$IMAGE_ID" \
--query 'Images[].{Image:ImageId,Name:Name}'
检查剩余状态:
terraform state list
不应再有受管理的应用资源。在 AWS View 中,已终止的实例不再是可选择的运行目标。选择 reference-server、User 来源和端口 8081,发送请求。响应必须仍为 Connected · 200,内容为 Reference application。
保留 HCL 文件以供审阅。之后再执行普通计划时,保留的配置会提出创建新实例;这并不表示销毁操作失败。
总结
你区分了 AMI 数据源与 EC2 资源,连接了提供的网络输入,通过 User Data 初始化应用,并验证了实际响应。你确认计划没有变更,且仅删除了受管理的实例,保留了镜像、网络和参考应用。



