协调两个 Terraform 工作目录

AWSBeginner
立即练习

介绍

两名维护者各有同一环境的工作副本。你将观察实际写入共享状态的进程、因其原生锁而被拒绝的竞争计划,以及正常释放锁后从另一个目录成功执行的操作。

你需要了解远端 S3 状态和常规 Terraform 计划及应用操作。此全新环境提供两个已初始化的工作副本、一项受控的定时变更、报告存储和财务参考报告;无需之前的虚拟机或个人 AWS 账户。

与认证考试的关联

认证 考试任务 实践内容
CloudOps Engineer – Associate (SOA-C03) 任务 3.1,技能 3.1.6 Terraform 基础实践:通过经过审查的配置和状态变更维护基础设施,同时保留正在使用的资源。

实验概览

概念图:维护任务保留配置、状态与现有报告存储之间的关系。

识别同一环境的两个副本

在这一步中,确认两个工作目录有意管理同一个环境。它们并非独立的 dev 和 preview 部署:两个后端配置均选择 coordination-team-state 中的 reports/shared.tfstate。

cd /home/labex/project/shared-state-operators
cat operator-a/shared.s3.tfbackend
cat operator-b/shared.s3.tfbackend

两者均使用 use_lockfile = true。写入进程操作期间,Terraform 会在此状态旁创建一个原生 S3 锁对象,以防另一个写入进程依据存在冲突的快照进行操作。

terraform -chdir=operator-a state show aws_s3_bucket.reports
terraform -chdir=operator-b state show aws_s3_bucket.reports

两者均标识 coordinated-daily-reports。读取其中的实际报告,并保持财务参考报告不变:

aws s3 \
  cp s3://coordinated-daily-reports/report.txt -

预期看到 Daily sales: 120 orders。检查提供的受控变更:

cat operator-a/pending-change.tf

仅为本练习,一个 terraform_data 资源会通过 local-exec 在创建过程中暂停 30 秒。该暂停使实际写入进程的锁可被观察到。普通资源更新也会持有锁;人为添加 sleep 并非生产部署建议。两个配置中都包含这项受控状态变更,但尚未应用。

观察实际争用和正常释放

在这一步中,运行一个实际写入进程,并从第二个目录运行与之竞争的计划。将下面整个代码块作为一次操作执行,以免阅读停顿消耗观察窗口。

& 在后台启动操作方 A;$! 捕获其进程 ID。它的输出写入日志,便于阅读第二个操作方的错误。有次数上限的循环等待实际 S3 锁出现,而不假定固定的启动时间。if 语句让你能够检查预期失败的计划,wait 返回写入进程的实际完成状态。即使从同一个 Terminal 启动,它们也是两个独立的 Terraform 进程。

terraform -chdir=operator-a apply -auto-approve > /tmp/operator-a.log 2>&1 &
WRITER_PID=$!
echo "$WRITER_PID"
for attempt in $(seq 1 60); do
  if aws s3api head-object \
    --bucket coordination-team-state \
    --key reports/shared.tfstate.tflock > /dev/null 2>&1; then
    break
  fi
  sleep 1
done
aws s3api get-object \
  --bucket coordination-team-state \
  --key reports/shared.tfstate.tflock \
  /tmp/current-lock.json
cat /tmp/current-lock.json
if terraform -chdir=operator-b plan -lock-timeout=0s; then
  echo 'Unexpected: the competing plan acquired the lock.'
  false
else
  PLAN_EXIT=$?
  echo "$PLAN_EXIT"
fi
wait "$WRITER_PID"
cat /tmp/operator-a.log

竞争计划必须以 1 退出,并显示 Error acquiring the state lock。身份验证或连接错误不能证明发生了锁争用。锁信息属于实际写入进程;上传一个与锁同名的文件,不能证明写入进程之间实现了协调。

操作方 A 应成功完成受控创建,并正常释放锁。不要禁用锁定、删除活动写入进程的锁,或使用 force-unlock 让第二个操作方继续执行。在 AWS View 中,报告存储始终可用;锁协调的是管理操作,而不是报告读取权限。

释放后从另一个工作副本继续

在这一步中,在写入进程完成后,让操作方 B 正常获取后端访问锁。第二个工作副本现在应读取更新后的共享状态,而不是独立创建另一套资源。

terraform -chdir=operator-b plan -lock-timeout=5s

预期看到 No changes。写入期间被阻止的同一个命令,现在可以正常获取和释放锁。

从两个目录检查完成后的状态:

terraform -chdir=operator-a state list
terraform -chdir=operator-b state list

两者都列出 aws_s3_bucket.reports 和 terraform_data.coordination。它们对应同一环境和共享管理记录,并非两套部署。

aws s3 \
  cp s3://coordinated-daily-reports/report.txt -

原始文本仍可读取。检查状态版本历史:

aws s3api \
  list-object-versions \
  --bucket coordination-team-state \
  --prefix reports/shared.tfstate

实际状态具有历史记录,当前对象清单中不应再存在活动的 .tflock。历史锁版本或删除标记并不是活动写入进程的锁。

terraform -chdir=operator-a plan

此处也预期看到 No changes。后台检查会区分实际 Terraform 进程争用与手动提供的锁,并验证原始报告版本、正常释放以及后续成功访问。为各自所有者保留共享存储和后端。

总结

你区分了同一环境的两个工作副本与独立环境,观察了实际的原生锁争用,并在写入进程正常释放锁后安全继续操作,没有删除活动锁。