Terraform 自动化管理云监控与日志服务:构建 CI/CD 全链路可观测性闭环

📅 · 海外服务器线路与网络实测 - ChengziCloud

一句话结论

> 从一个告警到根因定位只需 3 分钟——用 Terraform 统一管理 CloudMonitor 告警规则、SLS 日志采集与 Grafana 大盘,实现 DevOps 可观测性即代码

本文要点
  • 引言:当告警响起时,你在哪里?
  • 核心概念:什么是可观测性即代码?
  • 实战:用 Terraform 管理 CloudMonitor 告警
  • SLS 日志服务:从采集到分析的全流程自动化
  • CI/CD 流水线集成:让可观测性随应用一起交付
  • Grafana 大盘:Terraform 自动化的最后一公里

从一个告警到根因定位只需 3 分钟——用 Terraform 统一管理 CloudMonitor 告警规则、SLS 日志采集与 Grafana 大盘,实现 DevOps 可观测性即代码

引言:当告警响起时,你在哪里?

凌晨两点,手机震动。一条来自云监控的告警:「生产环境 API 网关 5xx 错误率超过 5%」。你打开笔记本电脑,登录云控制台,点开云监控页面查看告警详情,再切到日志服务(SLS)查询对应时间段的错误日志,最后去 Grafana 大盘里对比上下游服务的指标变化——整个过程下来,十五分钟过去了。

这不是个别现象。在传统运维模式下,监控配置、日志采集、告警规则、可视化大盘往往分散在不同的控制台里,由不同的人在不同的时间手动创建。当系统出问题时,运维人员需要在多个工具之间反复切换,信息碎片化严重拖慢了故障响应速度。

本文将介绍一种「可观测性即代码」(Observability as Code)的实践方案:用 Terraform 统一管理阿里云 CloudMonitor 告警规则、SLS 日志采集配置和 Grafana 监控大盘,并将其嵌入 CI/CD 流水线,实现基础设施、应用部署和可观测性配置的同步交付。

一、核心概念:什么是可观测性即代码?

在深入实践之前,我们先厘清几个关键概念:

1.1 监控 vs 可观测性

维度传统监控(Monitoring)可观测性(Observability)
数据来源预定义的指标(CPU、内存、QPS)指标 + 日志 + 链路追踪(Metrics, Logs, Traces)
问题发现基于已知阈值的告警能够探索未知问题
配置方式手动在控制台创建代码化声明式管理
典型工具Zabbix、NagiosPrometheus + Grafana + Loki + Tempo
变更追踪无版本控制Git 版本控制,可审计、可回滚

可观测性即代码的核心思想是:把监控配置当作基础设施的一部分,用 Terraform 或 ROS(资源编排服务)来声明和管理,享受与应用程序代码一样的版本控制、代码审查和 CI/CD 自动化。

1.2 为什么选择 Terraform?

在阿里云生态中,管理云资源有两种主流选择:

  1. ROS(资源编排服务):阿里云原生,JSON/YAML 模板,与阿里云资源深度集成
  2. Terraform:HashiCorp 出品,HCL 语言,多云支持,社区 Provider 丰富

对于可观测性场景,Terraform 的优势在于:

  • 多云统一:如果一个团队同时使用阿里云和 AWS,Terraform 可以用同一套语法管理两边的监控资源
  • Provider 生态:Terraform 的 alicloud provider 已经支持 CloudMonitor、SLS 等服务的完整资源管理
  • 模块化:可以将告警规则封装成可复用的 Terraform Module,团队之间共享

二、实战:用 Terraform 管理 CloudMonitor 告警

2.1 基础架构:创建告警联系人与联系人组

告警的第一要素是「通知给谁」。我们用 Terraform 来声明告警联系人和联系人组:


# 创建告警联系人
resource "alicloud_cms_alarm_contact" "oncall" {
  alarm_contact_name = "oncall-engineer"
  describe           = "值班工程师"
  channels_mail      = "[email protected]"
  channels_sms       = "13800138000"
  channels_ding_webhook = "https://oapi.dingtalk.com/robot/send?access_token=xxx"
}

# 创建联系人组
resource "alicloud_cms_alarm_contact_group" "prod_oncall" {
  alarm_contact_group_name = "prod-oncall-group"
  describe                 = "生产环境值班组"
  contacts                 = [alicloud_cms_alarm_contact.oncall.alarm_contact_name]
}

2.2 核心监控:ECS 与 SLB 指标告警

对于云服务器和负载均衡,以下是生产环境必须配置的基础告警:


# ECS CPU 使用率告警
resource "alicloud_cms_alarm" "ecs_cpu" {
  name    = "ecs-cpu-high-${var.env}"
  project = "acs_ecs_dashboard"
  metric  = "CPUUtilization"
  period  = 60
  statistics = "Average"

  resources {
    dimensions = {
      instanceId = var.ecs_instance_id
    }
  }

  operator       = ">="
  threshold      = "80"
  triggered_count = 3
  contact_groups = [alicloud_cms_alarm_contact_group.prod_oncall.id]

  effective_interval = "00:00-23:59"
  silence_time       = 600  # 静默期 10 分钟,避免告警风暴
}

# SLB 后端 5xx 错误率告警
resource "alicloud_cms_alarm" "slb_5xx" {
  name    = "slb-backend-5xx-${var.env}"
  project = "acs_slb_dashboard"
  metric  = "Hecode5xx"
  period  = 120
  statistics = "Average"

  resources {
    dimensions = {
      instanceId = var.slb_instance_id
    }
  }

  operator         = ">="
  threshold        = "10"
  triggered_count  = 2
  contact_groups   = [alicloud_cms_alarm_contact_group.prod_oncall.id]
  silence_time     = 300
}

2.3 高级实践:复合告警与动态阈值

静态阈值告警容易产生误报——业务高峰期 80% 的 CPU 使用率可能是正常的。CloudMonitor 支持动态阈值和复合告警:


# 动态阈值告警(基于历史基线自动判断异常)
resource "alicloud_cms_alarm" "ecs_cpu_dynamic" {
  name       = "ecs-cpu-anomaly-${var.env}"
  project    = "acs_ecs_dashboard"
  metric     = "CPUUtilization"
  period     = 300
  statistics = "Average"

  # 使用动态阈值
  thresholds {
    level          = "P95"
    comparison_operator = ">="
    statistics     = "Average"
    threshold      = "0"  # 动态阈值模式下此值被忽略
  }

  contact_groups = [alicloud_cms_alarm_contact_group.prod_oncall.id]
}

实践建议:生产环境采用「静态阈值 + 动态阈值」双层告警策略。静态阈值设置宽松(如 CPU > 90%)作为兜底,动态阈值捕捉异常波动,两者结合可以显著降低误报率。

三、SLS 日志服务:从采集到分析的全流程自动化

3.1 日志采集配置:Logtail 的 Terraform 化管理

SLS 的核心组件是 Logtail——运行在 ECS 或容器上的日志采集 Agent。通过 Terraform,我们可以将 Project、Logstore、Logtail 配置全部代码化:


# 创建日志 Project
resource "alicloud_log_project" "app_logs" {
  name        = "app-logs-${var.env}"
  description = "应用日志项目 - ${var.env} 环境"
}

# 创建 Logstore(日志存储单元)
resource "alicloud_log_store" "app_access" {
  project               = alicloud_log_project.app_logs.name
  name                  = "access-log"
  shard_count           = 4
  auto_split            = true
  max_split_shard_count = 64
  retention_period      = 30  # 保留 30 天
  append_meta           = true
}

# 创建 Logtail 配置 — 采集 Nginx 访问日志
resource "alicloud_logtail_config" "nginx_access" {
  project      = alicloud_log_project.app_logs.name
  logstore     = alicloud_log_store.app_access.name
  name         = "nginx-access-config"
  input_type   = "file"
  output_type  = "LogService"

  input_detail {
    file_pattern     = "/var/log/nginx/access.log"
    log_type         = "common_reg_log"
    log_path         = "/var/log/nginx"
    topic_format     = "none"
    enable_tag       = true
    max_depth        = 5

    # 日志解析规则 — 正则表达式
    log_begin_regex  = "\\d+\\.\\d+\\.\\d+\\.\\d+.*"
    regex            = "(\\S+) \\S+ \\S+ \\[(.*?)\\] \"(\\S+)\" (\\d+) (\\d+).*"
    key              = ["remote_addr", "time_local", "request_uri", "status", "body_bytes_sent"]
    time_format      = "%d/%b/%Y:%H:%M:%S %z"
  }
}

3.2 应用日志采集:自定义 Log4j/Logback 格式

Java 应用的日志格式往往比较特殊。以下是一个采集 Spring Boot 应用 JSON 格式日志的配置示例:


resource "alicloud_logtail_config" "springboot_app" {
  project     = alicloud_log_project.app_logs.name
  logstore    = alicloud_log_store.app_log.name
  name        = "springboot-app-config"
  input_type  = "file"
  output_type = "LogService"

  input_detail {
    file_pattern = "/opt/app/logs/app-*.log"
    log_type     = "json_log"
    log_path     = "/opt/app/logs"
    topic_format = "group_topic"
    enable_tag   = true

    # JSON 模式自动提取字段,无需写正则
  }
}

3.3 SLS 告警:让日志主动发现问题

SLS 不仅存储日志,还具备强大的告警能力。以下配置实现「5 分钟内 5xx 错误超过 100 次」的日志告警:


resource "alicloud_log_alert" "high_5xx_rate" {
  project      = alicloud_log_project.app_logs.name
  name         = "high-5xx-rate-alert"
  display_name = "Nginx 5xx 错误率过高"
  description  = "当 5 分钟内 Nginx 5xx 错误超过 100 次时触发告警"

  schedule {
    type     = "FixedRate"
    interval = "5m"
  }

  query {
    store       = alicloud_log_store.app_access.name
    store_type  = "log"
    query       = "status: 5* | SELECT count(*) AS error_count"
    time_span_type = "Relative"
    start        = "-5m"
    end          = "now"
  }

  notification {
    type    = "SMS"
    content = "Nginx 5xx 错误告警:过去 5 分钟共发生 ${error_count} 次错误"
  }
}

四、CI/CD 流水线集成:让可观测性随应用一起交付

4.1 设计原则

可观测性配置应该与应用程序代码放在同一个 Git 仓库中,遵循「应用在哪里,监控就在哪里」的原则:


my-app/
├── src/                    # 应用源代码
├── Dockerfile
├── terraform/              # 可观测性配置
│   ├── main.tf             # CloudMonitor 告警 + SLS 采集配置
│   ├── variables.tf
│   └── dashboard.json      # Grafana 大盘 JSON
├── .github/workflows/
│   └── deploy.yml          # CI/CD 流水线
└── deploy.sh

4.2 GitLab CI 流水线配置

以下是一个完整的 GitLab CI 流水线,在部署应用的同时同步可观测性配置:


# .gitlab-ci.yml
stages:
  - build
  - deploy
  - observability

variables:
  ALICLOUD_ACCESS_KEY: ${CI_ALICLOUD_ACCESS_KEY}
  ALICLOUD_SECRET_KEY: ${CI_ALICLOUD_SECRET_KEY}
  TERRAFORM_VERSION: "1.5.0"

# 阶段一:构建 Docker 镜像
build:
  stage: build
  image: docker:latest
  script:
    - docker build -t registry.example.com/my-app:${CI_COMMIT_SHA} .
    - docker push registry.example.com/my-app:${CI_COMMIT_SHA}

# 阶段二:部署应用
deploy:
  stage: deploy
  image: alpine:latest
  script:
    - apk add --no-cache openssh-client sshpass
    - sshpass -p "${SSH_PASSWORD}" ssh -o StrictHostKeyChecking=no
      root@${SERVER_IP}
      "docker pull registry.example.com/my-app:${CI_COMMIT_SHA} &&
       docker stop my-app || true &&
       docker rm my-app || true &&
       docker run -d --name my-app
         -p 8080:8080
         registry.example.com/my-app:${CI_COMMIT_SHA}"
  needs: ["build"]

# 阶段三:部署可观测性配置
observability:
  stage: observability
  image: hashicorp/terraform:${TERRAFORM_VERSION}
  script:
    - cd terraform
    - terraform init
    - terraform plan -var="env=production"
    - terraform apply -auto-approve -var="env=production"
  needs: ["deploy"]
  only:
    - main  # 仅主分支触发可观测性配置变更

4.3 关键设计决策:为什么 observability 是独立 Stage?

有读者可能会问:为什么不把 Terraform apply 放在 deploy 阶段一起运行?

答案是职责分离和失败隔离:

场景observability 失败不影响应用observability 与应用耦合
Terraform state lock 冲突应用正常部署 ✅应用部署被阻塞 ❌
CloudMonitor API 限流应用正常部署 ✅应用部署失败 ❌
告警规则配置错误应用正常,修复后重试 ✅回滚整个部署 ❌

监控配置的失败不应该阻止应用部署——这是我们在生产环境中用血的教训换来的经验。

五、Grafana 大盘:Terraform 自动化的最后一公里

5.1 通过 Terraform 管理 Grafana Dashboard

如果你的团队使用 Grafana 做可视化,可以通过 Terraform 的 Grafana Provider 管理大盘:


# 配置 Grafana Provider
provider "grafana" {
  url  = "https://grafana.example.com"
  auth = var.grafana_api_key
}

# 从 JSON 文件创建 Dashboard
resource "grafana_dashboard" "app_overview" {
  config_json = file("${path.module}/dashboards/app-overview.json")

  # 关联到指定文件夹
  folder = grafana_folder.app_services.id
}

resource "grafana_folder" "app_services" {
  title = "应用服务大盘"
}

5.2 阿里云 CloudMonitor + Grafana 数据源

在 Grafana 中接入阿里云 CloudMonitor 数据源后,所有的 Terraform 管理的告警规则指标都可以在 Grafana 中展示。推荐以下核心面板:

  1. 服务健康总览:各服务 HTTP 状态码分布、响应时间 P50/P95/P99
  2. 基础设施监控:ECS CPU/内存/磁盘、SLB QPS/并发连接数
  3. 日志趋势面板:通过 SLS 数据源展示错误日志趋势、Top N 错误来源
  4. 告警时间线:标注告警触发时间点,辅助根因分析

六、最佳实践与踩坑总结

6.1 Terraform State 管理

永远使用远程 State 存储,团队协作中最常见的翻车场景就是 State 文件不一致:


terraform {
  backend "oss" {
    bucket   = "terraform-state-prod"
    key      = "observability/terraform.tfstate"
    region   = "cn-hangzhou"
    access_key = var.alicloud_access_key
    secret_key = var.alicloud_secret_key
  }
}

6.2 告警静默期设置

告警风暴是生产环境中最令人头疼的问题之一。合理设置静默期(silence_time)可以避免同类告警在短时间内重复发送:


# 推荐配置
silence_time = 600  # 10 分钟静默期
# 配合 escalation 规则:如果 30 分钟内未恢复,升级通知

6.3 SLS 索引优化

日志量大时,SLS 的查询性能直接影响告警时效。建议:

  • 只对需要查询的字段建立索引,不要全字段索引
  • 分区键选择时间戳字段,避免全表扫描
  • Logstore 的 shard 数量根据写入吞吐量动态调整

6.4 CI/CD 集成的权限最小化

为 CI/CD 流水线使用独立的 RAM 子账号,只授予必要权限:


{
  "Statement": [
    {
      "Action": [
        "cms:PutResourceMetricRule",
        "cms:DeleteMetricRule",
        "log:CreateProject",
        "log:CreateLogStore",
        "log:CreateConfig"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ],
  "Version": "1"
}

6.5 变更审计与回滚

所有可观测性配置变更通过 Git 提交记录完整追踪。当告警配置被误修改导致误报或漏报时,只需一条命令即可回滚:


git log --oneline terraform/main.tf  # 查看变更历史
git revert <commit-hash>              # 回滚到上一个版本
terraform apply                       # 应用回滚

七、总结与展望

本文介绍了用 Terraform 统一管理 CloudMonitor、SLS 和 Grafana 的可观测性即代码方案。回顾要点:

  1. 监控告警代码化:CloudMonitor 告警规则、联系人组全部通过 Terraform 声明,告别手动点击
  2. 日志采集自动化:SLS Project、Logstore、Logtail 配置随应用一起部署,新服务上线即接入日志
  3. CI/CD 深度集成:可观测性配置作为独立 Stage 嵌入流水线,应用部署与监控配置同步交付
  4. 版本控制与审计:所有变更可追溯、可回滚,团队协作有据可依

未来,随着 OpenTelemetry 生态的成熟,Trace 数据的采集与分析也可以纳入可观测性即代码的范畴。同时,AI 驱动的根因分析(RCA)与自动化修复(Self-Healing)正在逐步落地——当系统检测到异常时,不仅能发出告警,还能自动执行预定义的修复脚本,真正实现从「监控」到「自治」的跨越。


技术栈速查表:

层级工具/服务用途
IaCTerraform / ROS声明式管理云资源与监控配置
监控告警CloudMonitor云资源指标监控与多渠道告警
日志服务SLS(日志服务)日志采集、存储、查询与分析
可视化Grafana多数据源统一监控大盘
流水线GitLab CI / GitHub Actions应用与可观测性配置同步交付
版本控制Git + OSS 远程 State配置变更审计与回滚

本文由 6.chengzicloud.cloud 提供,点击访问首页了解更多