「可观测性与运维自动化」

把 Terraform 纳入日常运维体系:变更审计与审批留痕、Slack 与 Webhook 通知集成、定时 plan 做漂移巡检、带安全边界的自动化修复,以及运行手册与运维度量指标建设。

1. 为什么 IaC 也需要可观测性

一句话总结: Terraform 管的是「期望状态」,但期望与现实之间会因手工改动、外部事件而漂移,没有持续观测就无法知道基础设施是否还符合代码描述。

写完代码、跑通 apply 之后,工作并没有结束。真正的问题是:三个月后,线上的基础设施还和代码一致吗? 有人手工开了安全组、自动伸缩调整了实例数、云厂商改动了默认行为——这些都让 state 与现实的差距逐渐扩大。

# 一次 plan 就能暴露全部差异
terraform plan -detailed-exitcode
# 退出码 0 = 无变更,1 = 报错,2 = 有变更

可观测性覆盖四个维度:

维度问题手段
变更审计谁在何时改了哪条资源审批记录 + 日志
通知变更发生时谁知道Slack / Webhook
漂移现实是否偏离代码定时 plan
健康系统是否在预期状态指标 + 运行手册

一句话:Terraform 的可观测性不是「看 Terraform 本身的日志」,而是「用 Terraform 持续回答基础设施是否符合预期」。

2. 变更审计与审批

一句话总结: 审计回答「谁在什么策略版本下、基于哪份 plan、改了哪些资源」,审批回答「关键变更是否有人放行」,二者共同构成变更的可追溯链条。

# 从 plan 中提取本次变更的完整清单
terraform show -json plan.tfplan | \
  jq -c '[.resource_changes[]
          | select(.change.actions != ["no-op"])
          | {address, actions: .change.actions}]'
# 留存审计证据:plan 哈希 + 变更清单 + 审批记录
sha256sum plan.tfplan > audit/plan-$(date +%Y%m%d-%H%M%S).sha256
git rev-parse HEAD > audit/commit.txt

在 CI 中用 environment 保护 apply 阶段,强制人工放行:

# .github/workflows/apply.yml
jobs:
  plan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: terraform init && terraform plan -out=plan.tfplan
      - uses: actions/upload-artifact@v4
        with:
          name: tfplan
          path: plan.tfplan

  apply:
    needs: plan
    runs-on: ubuntu-latest
    environment: production   # 需人工审批
    steps:
      - uses: actions/download-artifact@v4
        with: { name: tfplan }
      - run: terraform init && terraform apply plan.tfplan
审计对象留存物用途
代码版本git commit / tag回溯当时配置
计划快照plan.tfplan + sha256复核实际变更
审批记录PR 评论 / 审批人责任可追溯
应用日志apply 输出事后对账
策略版本策略仓库 tag当时的门禁规则

一句话:审计不是「不信任工程师」,而是「让每一次变更都能被复盘」——事故之后能快速定位,本身就是可靠性的组成部分。

3. 通知集成

一句话总结: 把 plan 摘要、apply 结果、漂移告警推送到 Slack 或 Webhook,让团队在变更发生时立刻知情,而不是等到出事才发现。

# 把 plan 摘要格式化成 Slack 消息
terraform show -json plan.tfplan | jq -r '
  "计划变更: \(.resource_changes | map(select(.change.actions != ["no-op"])) | length) 个资源\n" +
  (.resource_changes
   | map(select(.change.actions != ["no-op"]))
   | map("• \(.address) [\(.change.actions | join(","))]")
   | join("\n"))' > summary.txt
curl -s -X POST -H 'Content-type: application/json' \
  --data "$(jq -n --rawfile s summary.txt '{
    text: ("Terraform 计划摘要\n" + $s)
  }')" \
  "$SLACK_WEBHOOK_URL"
# 通用 Webhook 通知(适用于 Teams / 钉钉 / 自建服务)
- name: Notify
  if: always()
  run: |
    curl -s -X POST "$WEBHOOK_URL" \
      -H "Content-Type: application/json" \
      -d "{\"status\":\"${{ job.status }}\",\"commit\":\"$GITHUB_SHA\"}"

通知内容的设计原则:

事件通知渠道内容要点
plan 完成PR 评论变更数量、销毁资源、成本增量
apply 成功Slack 频道环境、变更数、执行人
apply 失败Slack + 值班错误摘要、日志链接
漂移检测Slack 告警频道漂移资源清单、首次发现时间
高危变更Slack + @审批人销毁/替换类操作重点标记

一句话:通知的价值在「信噪比」——只推值得打断人的事件,否则频道会被静音,告警就失效了。

4. 漂移巡检与定时 plan

一句话总结: 用定时任务周期性执行 terraform plan -detailed-exitcode,把漂移从「某天偶然发现」变成「每天自动上报」。

# .github/workflows/drift.yml
name: drift-detection

on:
  schedule:
    - cron: "0 6 * * *"   # 每天 UTC 06:00
  workflow_dispatch:

jobs:
  drift:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        stack: [network, data, app]
    steps:
      - uses: actions/checkout@v4
      - uses: hashicorp/setup-terraform@v3
      - run: terraform init
        working-directory: stacks/${{ matrix.stack }}
      - name: Detect drift
        id: plan
        continue-on-error: true
        run: terraform plan -detailed-exitcode -no-color
        working-directory: stacks/${{ matrix.stack }}
      - name: Report
        if: steps.plan.outputs.exitcode == '2'
        run: |
          echo "检测到漂移: ${{ matrix.stack }}"
          # 推送到告警频道
# 本地或定时任务中手工执行
terraform plan -detailed-exitcode -refresh-only
echo "exit=$?"

# 只看漂移的资源
terraform show -json drift.tfplan | \
  jq '[.resource_changes[] | select(.change.actions != ["no-op"]) | .address]'

4.1 漂移的三种处置

漂移类型例子处置
预期内自动伸缩调整了实例数更新 ignore_changes 或配置
意外手工改动控制台开了安全组端口回滚或纳管
外部系统改动云厂商改了默认参数更新 Provider 或接受差异

一句话:漂移巡检的关键不是「发现差异」,而是「分类差异」——不是所有差异都该被自动抹平。

5. 自动化修复与安全边界

一句话总结: 自动修复能收敛简单漂移,但必须先划定安全边界:只允许白名单资源、只允许幂等操作、必须留痕并可回滚。

# 自动化修复脚本:仅处理白名单内的漂移资源
DRIFT=$(terraform show -json drift.tfplan | \
  jq -r '.resource_changes[]
         | select(.change.actions != ["no-op"])
         | .address')

ALLOWED='aws_cloudwatch_log_group|aws_s3_bucket_lifecycle|aws_ssm_parameter'

if echo "$DRIFT" | grep -vqE "^($ALLOWED)"; then
  echo "存在白名单外的漂移,跳过自动修复,转人工处理"
  exit 1
fi

terraform apply -auto-approve -refresh-only

自动修复的安全边界清单:

边界规则
资源范围白名单,排除有状态资源
操作类型只做 refresh / 幂等收敛,不做删除
环境范围仅 dev / stg,prod 一律人工
执行留痕每次自动修复写审计日志
熔断机制单次修复超过 N 个资源则中止
回滚预案修复前 state 备份
# 用 prevent_destroy 从代码层面挡住最危险的操作
resource "aws_db_instance" "main" {
  lifecycle {
    prevent_destroy = true
  }
}

一句话:自动化修复的原则是「能自动收敛的自动收敛,可能造成破坏的一律转人工」——省下的人力不值得用事故来换。

6. 运行手册与故障响应

一句话总结: 运行手册把「出事时该做什么」写成可执行的步骤,让任何值班同学都能在压力下按图索骥,而不是依赖某个人的记忆。

运行手册:Terraform apply 失败

[现象]
apply 中断,报错 ResourceInUse / DependencyViolation

[处理步骤]
1. 确认是否有并发 apply:检查锁状态
2. 查看具体失败资源:terraform show plan.tfplan | grep 资源名
3. 判断是否部分成功:terraform state list 对比期望清单
4. 若部分成功:修正配置后重新 apply(Terraform 幂等)
5. 若状态损坏:从备份 state push 恢复
6. 记录事件:时间、影响范围、根因、后续动作

[升级路径]
15 分钟未恢复 → 通知平台负责人
涉及生产数据 → 立即拉群并冻结相关流水线
# 手册中常用的诊断命令
terraform state list
terraform state show aws_instance.web
terraform providers
terraform version
故障场景首要动作禁止动作
锁残留确认后 force-unlock未确认直接强解
apply 部分成功修正后重跑手工在控制台补资源
状态损坏从备份恢复手工编辑 tfstate
误删资源用备份/快照恢复反复重试 apply
凭证失效刷新凭证提交凭证到仓库

一句话:运行手册的价值在「把人从恐慌中拉回流程」——事故现场最缺的不是聪明,而是秩序。

7. 度量指标与持续改进

一句话总结: 用少量关键指标衡量 IaC 运维的健康度:漂移数量、apply 成功率、变更前置时间、自动修复占比,指标驱动改进而非感觉驱动。

# 从历史 apply 日志中统计成功率
grep -c "Apply complete" apply-*.log
grep -c "Error:" apply-*.log

# 统计当前漂移资源数
terraform show -json drift.tfplan | \
  jq '[.resource_changes[] | select(.change.actions != ["no-op"])] | length'
# 把关键指标推送到 CloudWatch,纳入统一看板
resource "aws_cloudwatch_metric_alarm" "drift_count" {
  alarm_name          = "terraform-drift-count"
  comparison_operator = "GreaterThanThreshold"
  evaluation_periods  = 1
  metric_name         = "DriftResourceCount"
  namespace           = "TerraformOps"
  period              = 86400
  statistic           = "Maximum"
  threshold           = 5
  alarm_description   = "漂移资源数超过 5 个,需要人工收敛"
}
指标含义目标
漂移资源数现实偏离代码的规模趋近于 0
apply 成功率流水线稳定性> 95%
变更前置时间从提交到上线逐季缩短
自动修复占比自动化成熟度稳步提升
回滚次数变更质量逐季下降

一句话:指标的意义是「让改进可衡量」——没有指标的运维改进,最后都变成「感觉比以前好了」。

8. 总结

可观测性与运维自动化把 Terraform 从「一次性工具」变成「持续运行的控制面」:

环节手段关键点
审计plan 快照 + 审批记录每次变更可复盘
审批environment 保护关键变更人工放行
通知Slack / Webhook高信噪比,只推值得打断的
漂移巡检定时 plan + detailed-exitcode每日自动上报
漂移分类预期内 / 手工 / 外部分类后再决定处置
自动修复白名单 + 熔断 + 留痕破坏性操作转人工
运行手册步骤化 + 升级路径值班可独立处置
度量漂移数 / 成功率 / 前置时间指标驱动改进

一句话收尾:Terraform 的终局不是「写完代码」,而是「持续保证现实与代码一致」。从审计留痕到通知推送,从每日漂移巡检到带边界的自动修复,再到手册化的故障响应与指标化的持续改进,基础设施才真正从「一次交付」变成了「可运营的系统」。

延伸阅读

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「terraform」更多文章

  1. Helm Provider 与应用发布:值注入与回滚
  2. 模块注册表与分发:版本、文档与测试
  3. DNS 与证书编排:托管区域与自动验证