Terraform 自动化管理云监控与日志服务:构建 CI/CD 全链路可观测性闭环
> 从一个告警到根因定位只需 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、Nagios | Prometheus + Grafana + Loki + Tempo |
| 变更追踪 | 无版本控制 | Git 版本控制,可审计、可回滚 |
可观测性即代码的核心思想是:把监控配置当作基础设施的一部分,用 Terraform 或 ROS(资源编排服务)来声明和管理,享受与应用程序代码一样的版本控制、代码审查和 CI/CD 自动化。
1.2 为什么选择 Terraform?
在阿里云生态中,管理云资源有两种主流选择:
- ROS(资源编排服务):阿里云原生,JSON/YAML 模板,与阿里云资源深度集成
- 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 中展示。推荐以下核心面板:
- 服务健康总览:各服务 HTTP 状态码分布、响应时间 P50/P95/P99
- 基础设施监控:ECS CPU/内存/磁盘、SLB QPS/并发连接数
- 日志趋势面板:通过 SLS 数据源展示错误日志趋势、Top N 错误来源
- 告警时间线:标注告警触发时间点,辅助根因分析
六、最佳实践与踩坑总结
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 的可观测性即代码方案。回顾要点:
- 监控告警代码化:CloudMonitor 告警规则、联系人组全部通过 Terraform 声明,告别手动点击
- 日志采集自动化:SLS Project、Logstore、Logtail 配置随应用一起部署,新服务上线即接入日志
- CI/CD 深度集成:可观测性配置作为独立 Stage 嵌入流水线,应用部署与监控配置同步交付
- 版本控制与审计:所有变更可追溯、可回滚,团队协作有据可依
未来,随着 OpenTelemetry 生态的成熟,Trace 数据的采集与分析也可以纳入可观测性即代码的范畴。同时,AI 驱动的根因分析(RCA)与自动化修复(Self-Healing)正在逐步落地——当系统检测到异常时,不仅能发出告警,还能自动执行预定义的修复脚本,真正实现从「监控」到「自治」的跨越。
技术栈速查表:
| 层级 | 工具/服务 | 用途 |
|---|---|---|
| IaC | Terraform / ROS | 声明式管理云资源与监控配置 |
| 监控告警 | CloudMonitor | 云资源指标监控与多渠道告警 |
| 日志服务 | SLS(日志服务) | 日志采集、存储、查询与分析 |
| 可视化 | Grafana | 多数据源统一监控大盘 |
| 流水线 | GitLab CI / GitHub Actions | 应用与可观测性配置同步交付 |
| 版本控制 | Git + OSS 远程 State | 配置变更审计与回滚 |
本文由 6.chengzicloud.cloud 提供,点击访问首页了解更多