参数化私有报告存储

AWSBeginner
立即练习

介绍

你的团队需要开发和预览两套报告存储,分别保存不同内容。你将复用一份配置,理解存储桶与对象之间的引用,并证明两个独立根目录分别管理不同的 AWS 资源。

本实验以第一个 AWS Terraform 实验及你已有的变量和输出知识为基础。工具、访问配置和 provider 连接已准备就绪;不会复用之前虚拟机中的资源。

与认证考试的关联

认证 考试任务 实践内容
Cloud Practitioner (CLF-C02) 任务 3.1 使用可重复的基础设施定义和运维资源查询。
Developer – Associate (DVA-C02) 任务 3.3,技能 3.3.4 部署基础设施定义的基础实践。
DevOps Engineer – Professional (DOP-C02) 任务 2.1 通过 IaC 定义管理资源的基础实践。

本实验实际资源及保留边界的概念总览。

部署开发环境存储

在这一步中,你将使用输入变量和资源引用,通过一份配置创建开发环境的报告存储。

已准备好的两个根目录 report-dev 和 report-preview 最初除 provider 连接文件外均为空。每个根目录将保存自己的本地状态。这与在单个根目录中更改输入不同:一个根目录仍然管理已记录在其状态中的资源。

进入开发环境根目录并创建资源模板。environment 和 report 变量是字符串输入。${var.environment} 将环境名称插入存储桶名称中。对象的 bucket 参数引用存储桶资源的 ID,因此 Terraform 能发现依赖关系并先创建存储桶。content_type 告知读取方如何解释这些字节。

cd /home/labex/project/report-dev
cat > main.tf <<'EOF'
variable "environment" { type = string }
variable "report" { type = string }

resource "aws_s3_bucket" "reports" {
  bucket = "terraform-reports-${var.environment}"
  tags = {
    Project     = "TerraformReports"
    Environment = var.environment
  }
}

resource "aws_s3_object" "report" {
  bucket       = aws_s3_bucket.reports.id
  key          = "reports/current.csv"
  content      = var.report
  content_type = "text/csv"
}

output "bucket_name" { value = aws_s3_bucket.reports.id }
output "report_key" { value = aws_s3_object.report.key }
EOF

为此环境创建一个变量文件。转义序列 \n 表示报告字符串中的换行符。将值单独保存,便于复用同一个资源模板。

cat > dev.tfvars <<'EOF'
environment = "dev"
report      = "orders,12\n"
EOF

初始化、验证并审查此根目录。-var-file 选择变量值文件;它不会选择不同的状态。

terraform init
terraform validate
terraform plan -var-file=dev.tfvars

预期新增两个资源:存储桶及其报告对象。应用相同的输入,并在提示时输入 yes:

terraform apply -var-file=dev.tfvars

输出值标识存储桶和对象键。使用 $(...) 保存并显示这些值,它会捕获命令输出。-raw 输出字符串时不带 Terraform 的引号。

BUCKET=$(terraform output -raw bucket_name)
echo "$BUCKET"
KEY=$(terraform output -raw report_key)
echo "$KEY"

通过 AWS 读取实际存储的报告,不要把输出值或状态条目当作数据存在的证明。响应包含 ContentType: text/csv;目标文件保存报告字节。

aws s3api \
  get-object \
  --bucket "$BUCKET" \
  --key "$KEY" \
  dev-downloaded.csv
cat dev-downloaded.csv

预期看到 orders,12。你也可以在 AWS View 中展开 terraform-reports-dev 内的 reports/current.csv。保持独立的团队参考报告不变。 部署后的 AWS View:实际创建的自有存储出现在保留的参考报告旁边。

使用独立状态复用模板

在这一步中,你将使用预览环境的输入部署同一个模板,同时保留开发环境存储。

仅将资源模板复制到已准备好的预览环境根目录。本练习只复制 main.tf,因为每个已准备好的根目录都会单独初始化。不要通过克隆 terraform.tfstate 或已初始化的 .terraform/ 目录来创建另一个环境:它们可能携带原始的资源或后端映射。依赖锁定文件 .terraform.lock.hcl 则不同:它记录 provider 版本和校验和,可以与配置一起共享或提交,不包含环境资源映射。预览环境根目录已有自己的 provider 连接文件。

cp /home/labex/project/report-dev/main.tf /home/labex/project/report-preview/main.tf
cd /home/labex/project/report-preview
cat > preview.tfvars <<'EOF'
environment = "preview"
report      = "orders,25\n"
EOF

初始化此根目录并审查预览环境的计划:

terraform init
terraform plan -var-file=preview.tfvars

预期同样新增两个资源,存储桶名称为 terraform-reports-preview。如果意外出现删除开发环境存储桶的计划,就说明你复用了错误的状态。应用配置并输入 yes:

terraform apply -var-file=preview.tfvars

读取预览环境的输出和报告。环境输入更改名称和标签;报告输入更改实际存储的字节。

BUCKET=$(terraform output -raw bucket_name)
echo "$BUCKET"
aws s3api \
  get-object \
  --bucket "$BUCKET" \
  --key reports/current.csv \
  preview-downloaded.csv
cat preview-downloaded.csv

预期看到 orders,25。使用 Terraform 的全局选项 -chdir 比较两个根目录的输出和状态列表;此选项在指定根目录中运行命令,不会更改 shell 当前所在目录:

terraform -chdir=/home/labex/project/report-dev output bucket_name
terraform -chdir=/home/labex/project/report-dev state list
terraform -chdir=/home/labex/project/report-preview output bucket_name
terraform -chdir=/home/labex/project/report-preview state list

两个根目录都有 aws_s3_bucket.reports 这样的地址,但各自映射到不同的 AWS 存储桶。确认开发环境的数据保持完好:

aws s3api \
  get-object \
  --bucket terraform-reports-dev \
  --key reports/current.csv \
  dev-retained.csv
cat dev-retained.csv

预期看到 orders,12。它们是独立的本地状态,并非工作区或共享后端。Terraform 输入变量文档更详细地介绍了变量文件的选择方式。 AWS View 显示两套独立的自有报告存储,旁边是保留的团队参考报告。

清理两套自有存储

在这一步中,你将销毁每个根目录的资源,同时保留团队参考报告。

销毁时,每个根目录都需要使用自己的输入。审查开发环境的删除计划,然后执行销毁并输入 yes。Terraform 知道对象与存储桶的依赖关系,因此会先删除对象,再删除存储桶。

terraform -chdir=/home/labex/project/report-dev plan -destroy -var-file=dev.tfvars
terraform -chdir=/home/labex/project/report-dev destroy -var-file=dev.tfvars

现在仅删除预览环境根目录的资源,再次输入 yes 确认:

terraform -chdir=/home/labex/project/report-preview destroy -var-file=preview.tfvars

每次销毁都应报告移除了两个资源。验证两份状态映射均为空,且无关的参考报告仍然存在:

terraform -chdir=/home/labex/project/report-dev state list
terraform -chdir=/home/labex/project/report-preview state list
aws s3api \
  list-buckets \
  --query 'Buckets[].Name'
aws s3api \
  head-object \
  --bucket team-reference-reports \
  --key keep.txt \
  --query ContentLength

只剩下参考存储桶。经过身份验证且成功返回的列表能证明目标资源已不存在;访问或网络失败则不能。保留预先配置的凭据,直到最终检查完成。

总结

你使用两个变量文件复用了存储桶和对象模板,读取了实际报告字节和 Content-Type,保持各根目录的状态相互独立,并且仅清理了自己的两个环境。