欢迎光临

Google Cloud Monitoring 与 Cloud Logging 生产级实战:从指标采集到告警策略与SLO管理

在现代云原生架构中,可观测性(Observability)是保障服务可靠性的基石。Google Cloud 提供了强大的 Cloud Monitoring 和 Cloud Logging 服务,帮助团队从指标采集、日志分析到告警策略构建完整的运维闭环。本文将从实际生产场景出发,深入讲解如何搭建一套生产级的监控与日志体系,涵盖自定义指标采集、日志结构化与查询优化、告警策略设计、SLO/SLI 管理,以及与 Terraform 的基础设施即代码实践。

Google Cloud Monitoring Dashboard

一、Cloud Monitoring 核心架构与概念

Cloud Monitoring(前身为 Stackdriver Monitoring)是 GCP 原生的指标监控服务。它采用指标-时间序列-告警的三层模型:指标(Metric)描述了要观测的对象,时间序列(Time Series)记录了指标随时间的变化,告警策略(Alerting Policy)定义了何时触发通知。

1.1 指标类型与资源层级

GCP 的指标体系围绕受监控资源(Monitored Resource)组织。每个指标都绑定到特定的资源类型,如

1
gce_instance

1
k8s_container

1
cloud_function

等。理解资源层级是构建有效监控的前提:

  • 系统指标:GCP 服务自动采集,如 CPU 利用率、请求延迟、错误率
  • 自定义指标:用户通过 API 或 OpenTelemetry 上报的业务指标
  • 日志指标:基于日志内容提取的派生指标(Distribution 或 Delta 类型)

查看所有可用的指标类型,可以使用 gcloud 命令:


1
2
3
4
5
# 列出所有可用的指标描述符
gcloud monitoring metrics list --filter="metricType=starts_with('custom.')"

# 查看特定指标的详细信息
gcloud monitoring metrics describe compute.googleapis.com/instance/cpu/usage_time

1.2 时间序列数据模型

每条时间序列由以下要素唯一标识:

要素 说明 示例
指标类型 指标的完整路径
1
loadbalancing.googleapis.com/https/request_count
受监控资源 资源类型 + 标签
1
https_lb_rule

+

1
url_map_name=my-lb
指标标签 维度切分
1
response_code_class=2xx

这种多维数据模型允许我们按不同维度聚合和切分,比如按区域、服务版本、HTTP 状态码等维度分析延迟分布。

二、自定义指标采集:从 OpenTelemetry 到 API 直推

系统指标只能覆盖基础设施层面,业务可观测性依赖自定义指标。GCP 提供了两种主要上报方式:OpenTelemetry Collector 集成和直接 API 推送。

2.1 OpenTelemetry Collector 集成

OpenTelemetry 已成为云原生可观测性的事实标准。通过 Google Cloud 的 OTLP Exporter,可以将应用指标无缝推送到 Cloud Monitoring:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# otel-collector-config.yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

processors:
  batch:
    send_batch_size: 1024
    timeout: 5s
  resourcedetection:
    detectors: [gcp]

exporters:
  googlecloud:
    metric:
      prefix: "custom.googleapis.com/opentelemetry/"
      resource_filters:
        - prefix: "cloud.resource_id"
    project: my-gcp-project

service:
  pipelines:
    metrics:
      receivers: [otlp]
      processors: [batch, resourcedetection]
      exporters: [googlecloud]

在 GKE 中部署 Collector 时,建议使用 Sidecar 模式确保每个 Pod 的指标独立采集,或者使用 DaemonSet 模式集中收集节点级指标。关键配置项包括

1
send_batch_size

(控制 API 调用频率)和

1
resourcedetection

(自动注入 GCP 资源标签)。

2.2 直接 API 推送自定义指标

对于不支持 OpenTelemetry 的遗留系统或需要精细控制的场景,可以直接使用 Monitoring API 推送指标。首先需要创建指标描述符:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from google.cloud import monitoring_v3
from google.api import metric_pb2, label_pb2
import time

client = monitoring_v3.MetricServiceClient()
project_name = f"projects/my-gcp-project"

# 创建自定义指标描述符
descriptor = metric_pb2.MetricDescriptor()
descriptor.type = "custom.googleapis.com/payment/transaction_latency"
descriptor.metric_kind = metric_pb2.MetricDescriptor.DISTRIBUTION
descriptor.value_type = metric_pb2.MetricDescriptor.DOUBLE
descriptor.description = "Payment transaction latency distribution"
descriptor.display_name = "Payment Latency"

label = label_pb2.LabelDescriptor()
label.key = "payment_method"
label.value_type = label_pb2.LabelDescriptor.STRING
label.description = "Payment method (credit_card, alipay, wechat_pay)"
descriptor.labels.append(label)

descriptor = client.create_metric_descriptor(
    name=project_name, metric_descriptor=descriptor
)
print(f"Created metric descriptor: {descriptor.name}")

指标描述符创建后,即可上报时间序列数据。注意 DISTRIBUTION 类型的指标需要构建

1
Distribution

对象:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# 上报分布类型指标
from google.api import distribution_pb2

series = monitoring_v3.TimeSeries()
series.metric.type = "custom.googleapis.com/payment/transaction_latency"
series.metric.labels["payment_method"] = "credit_card"

series.resource.type = "gce_instance"
series.resource.labels["instance_id"] = "123456789"
series.resource.labels["zone"] = "asia-east1-a"

point = monitoring_v3.Point()
point.interval.end_time.seconds = int(time.time())

dist = distribution_pb2.Distribution()
dist.mean = 245.5
dist.count = 1000
dist.sum_of_squared_deviation = 1500000.0
dist.bucket_options.explicit.bounds.extend([50, 100, 200, 500, 1000, 2000])
dist.bucket_counts.extend([50, 120, 280, 350, 150, 50, 0])

point.value.distribution_value.CopyFrom(dist)
series.points.append(point)

client.create_time_series(name=project_name, time_series=[series])

最佳实践:使用 DISTRIBUTION 类型而非 GAUGE 记录延迟数据,因为分布指标天然支持百分位数查询(p50、p95、p99),这对 SLO 监控至关重要。

三、Cloud Logging 结构化日志与查询优化

Cloud Logging(前身为 Stackdriver Logging)不仅是日志存储服务,更是日志分析和可观测性的核心组件。在海量日志场景下,结构化日志和高效查询是运维效率的关键。

Cloud Logging Analysis

3.1 结构化日志最佳实践

JSON 格式的结构化日志可以被 Cloud Logging 自动解析为字段,支持精确的字段级查询。以下是 Python 应用的推荐日志格式:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
import json
import logging
import datetime

class StructuredLogger:
    def __init__(self, service_name, version="1.0.0"):
        self.service_name = service_name
        self.version = version
        self.logger = logging.getLogger(service_name)
        handler = logging.StreamHandler()
        handler.setFormatter(logging.Formatter('%(message)s'))
        self.logger.addHandler(handler)
        self.logger.setLevel(logging.INFO)

    def _log(self, level, message, **kwargs):
        entry = {
            "severity": level,
            "timestamp": datetime.datetime.utcnow().isoformat() + "Z",
            "service": self.service_name,
            "version": self.version,
            "message": message,
            **kwargs
        }
        self.logger.log(getattr(logging, level), json.dumps(entry))

    def info(self, message, **kwargs):
        self._log("INFO", message, **kwargs)

    def error(self, message, **kwargs):
        self._log("ERROR", message, **kwargs)

    def request_log(self, method, path, status_code, latency_ms,
                    user_id=None, trace_id=None):
        self._log("INFO", f"{method} {path} {status_code}",
            http_request={
                "request_method": method,
                "request_path": path,
                "status": status_code,
                "latency": f"{latency_ms}ms"
            },
            user_id=user_id,
            trace_id=trace_id
        )

# 使用示例
logger = StructuredLogger("payment-service", version="2.3.1")
logger.request_log("POST", "/api/v2/charge", 200, 145.3,
                   user_id="u_8x9a2b", trace_id="trace_abc123")
logger.error("Database connection pool exhausted",
             db_host="db-primary", pool_size=50, active=50, waiting=23)

关键设计要点:

  • http_request 字段:使用 Cloud Logging 的保留字段名,可被自动识别为 HTTP 请求日志
  • trace_id 字段:与 Cloud Trace 集成,实现日志与链路追踪的关联
  • severity 字段:使用 Cloud Logging 标准的 severity 级别(DEBUG、INFO、WARNING、ERROR、CRITICAL)
  • 避免嵌套过深:查询时深层嵌套字段语法繁琐,建议将关键字段平铺在顶层

3.2 高效日志查询语法

Cloud Logging 使用 Lucene 风格的查询语言,支持字段精确匹配、正则表达式和范围查询。以下是生产环境常用的查询模式:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# 查找支付服务最近1小时的错误日志
severity>=ERROR
resource.type="gce_instance"
jsonPayload.service="payment-service"
timestamp>="2026-08-06T00:00:00Z"

# 按 HTTP 状态码过滤
jsonPayload.http_request.status>=500
jsonPayload.http_request.status<600

# 按追踪ID关联查找
jsonPayload.trace_id="trace_abc123"

# 正则匹配错误模式
jsonPayload.message=~"connection.*timeout|pool.*exhausted"

# 聚合查询:统计每个错误码的出现次数
# 使用 Log Analytics (BigQuery SQL)
SELECT
  jsonPayload.http_request.status AS status_code,
  COUNT(*) AS error_count
FROM `my-project.logging_analytics._Default`
WHERE severity >= "ERROR"
  AND timestamp >= TIMESTAMP_SUB(CURRENT_TIMESTAMP(), INTERVAL 1 HOUR)
GROUP BY status_code
ORDER BY error_count DESC

3.3 日志路由与长期存储

Cloud Logging 默认保留 30 天日志。对于合规审计或长期分析需求,需要配置日志接收器(Sink)将日志导出到 Cloud Storage 或 BigQuery:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# Terraform: 日志路由到 BigQuery 用于长期分析
resource "google_logging_project_sink" "bigquery_sink" {
  name        = "prod-logs-to-bigquery"
  destination = "bigquery.googleapis.com/projects/my-project/datasets/logging_analytics"

  filter = <<EOF
    severity >= WARNING
    resource.type = ("gce_instance" OR "k8s_container")
  EOF

  # 使用 BigQuery 分区表优化查询成本
  bigquery_options {
    use_partitioned_tables = true
  }

  unique_writer_identity = true
}

# 授予 Sink 服务账号 BigQuery 写入权限
resource "google_project_iam_binding" "bigquery_writer" {
  role = "roles/bigquery.dataEditor"
  members = [
    google_logging_project_sink.bigquery_sink.writer_identity
  ]
}

四、告警策略设计:从阈值到多条件组合

告警策略的质量直接决定了 On-Call 工程师的生活质量。一个好的告警系统应该具有高信噪比——真故障立即触发,正常波动绝不误报。

4.1 告警策略的黄金法则

在设计告警策略之前,请牢记以下原则:

  • 基于症状告警:告警用户可感知的问题(错误率上升、延迟增加),而非根因(CPU 高、内存不足)。CPU 高本身不是问题,只有当它导致服务降级时才需要告警
  • 设置合理的窗口:单次异常不告警,使用滑动窗口(如”5 分钟内持续”)过滤噪声
  • 多条件组合:组合多个指标(如错误率 > 1% 请求量 > 100/s)降低误报
  • 分级通知:P0 级立即电话/PagerDuty,P1 级 Slack 通知,P2 级仅记录工单

4.2 Terraform 管理告警策略

以下是一个生产级的告警策略配置,监控 HTTP 服务的错误率和延迟:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# 错误率告警
resource "google_monitoring_alert_policy" "high_error_rate" {
  display_name = "High Error Rate - Payment Service"
  combiner     = "AND"
  enabled      = true

  conditions {
    display_name = "Error rate exceeds 1% for 5 minutes"

    condition_threshold {
      filter     = <<-EOF
        resource.type="gce_instance"
        AND metric.type="loadbalancing.googleapis.com/https/request_count"
        AND resource.label."url_map_name"="payment-lb"
      EOF

      duration   = "300s"  # 持续5分钟
      comparison = "COMPARISON_GT"

      # 计算错误率:5xx 占总请求的比例
      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "ALIGN_RATE"
        group_by_fields    = ["resource.label.url_map_name"]
      }

      threshold_value = 0.01  # 1%
    }
  }

  conditions {
    display_name = "Request volume above minimum threshold"

    condition_threshold {
      filter     = <<-EOF
        resource.type="gce_instance"
        AND metric.type="loadbalancing.googleapis.com/https/request_count"
        AND resource.label."url_map_name"="payment-lb"
      EOF

      duration   = "300s"
      comparison = "COMPARISON_GT"

      aggregations {
        alignment_period   = "60s"
        per_series_aligner = "ALIGN_RATE"
      }

      threshold_value = 100  # 最少100 req/s,避免低流量误报
    }
  }

  notification_channels = [
    google_monitoring_notification_channel.pagerduty.id,
    google_monitoring_notification_channel.slack.id
  ]

  documentation {
    content   = <<-DOC
      ## 故障排查步骤
      1. 查看 Logging: `severity>=ERROR jsonPayload.service="payment-service"`
      2. 检查最近部署: `gcloud run revisions list --service=payment-service`
      3. 检查数据库连接池状态
      4. 联系 On-Call: @payment-team-oncall
    DOC
    mime_type = "text/markdown"
  }
}

# 通知渠道:Slack
resource "google_monitoring_notification_channel" "slack" {
  display_name = "Payment Team Slack"
  type         = "slack"

  labels = {
    channel_name = "#payment-alerts"
  }

  sensitive_labels {
    auth_token = var.slack_auth_token
  }
}

4.3 MQL 高级告警查询

对于复杂的监控需求,Monitoring Query Language(MQL)提供了比标准过滤器更强大的表达力。例如,计算 p99 延迟的同比环比变化:


1
2
3
4
5
6
7
8
9
# MQL: 当 p99 延迟比上周同期增长 50% 以上时告警
fetch https_lb_rule
| metric 'loadbalancing.googleapis.com/https/total_latencies'
| filter metric.response_code_class = '2xx'
| align delta(5m)
| group_by [resource.url_map_name],
    percentile(value, 99)
| condition val() > prev(val(), 7d) * 1.5 [AND]
    val() > 500  # 且绝对值超过 500ms

五、SLO/SLI 管理:用错误预算驱动可靠性决策

SLO(Service Level Objective)是可观测性的终极目标——它将运维从被动响应转变为主动管理。Cloud Monitoring 原生支持 SLO 监控,配合错误预算(Error Budget)可以科学地平衡可靠性与迭代速度。

SLO Monitoring Dashboard

5.1 定义 SLI 指标

SLI(Service Level Indicator)是衡量服务水平的具体指标。常见的 SLI 类型有两种:

  • 可用性 SLI:成功请求 / 总请求
  • 延迟 SLI:满足延迟阈值的请求 / 总请求

使用 Terraform 创建 SLO:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
# 支付服务可用性 SLO: 99.9% (月度错误预算 ~43分钟)
resource "google_monitoring_slo" "payment_availability" {
  service       = google_monitoring_service.payment.service_id
  slo_id        = "payment-availability-slo"
  display_name  = "Payment Service Availability - 99.9%"

  goal          = 0.999
  rolling_period_days = 30

  basic_sli {
    availability {
      enabled = true
    }
  }
}

# 支付服务延迟 SLO: 99% 的请求在 500ms 内完成
resource "google_monitoring_slo" "payment_latency" {
  service       = google_monitoring_service.payment.service_id
  slo_id        = "payment-latency-slo"
  display_name  = "Payment Service Latency - p99 &lt; 500ms"

  goal          = 0.99
  rolling_period_days = 30

  request_based_sli {
    good_total_ratio {
      good_service_filter = join(" AND ", [
        "resource.type="gce_instance"",
        "metric.type="loadbalancing.googleapis.com/https/total_latencies"",
        "metric.response_code_class = "2xx"",
      ])
      total_service_filter = join(" AND ", [
        "resource.type="gce_instance"",
        "metric.type="loadbalancing.googleapis.com/https/total_latencies"",
      ])
    }
  }
}

5.2 错误预算告警

当错误预算消耗过快时,应该触发预警。Cloud Monitoring 支持基于 SLO 的告警策略——在错误预算消耗达到特定阈值时通知团队:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
# 错误预算消耗速率告警
resource "google_monitoring_alert_policy" "error_budget_burn_rate" {
  display_name = "Payment SLO - Error Budget Burning Too Fast"
  combiner     = "OR"
  enabled      = true

  conditions {
    display_name = "Error budget burn rate exceeds 14.4x (will exhaust in &lt; 2 hours)"

    condition_monitoring_query_language {
      query = <<-MQL
        fetch cloud_monitoring_slo
        | metric 'monitoring.googleapis.com/slo/error_budget_burn_rate'
        | filter resource.slo_id = '${google_monitoring_slo.payment_availability.slo_id}'
        | value(val() > 14.4)
      MQL
      duration = "600s"
    }
  }

  notification_channels = [
    google_monitoring_notification_channel.pagerduty.id
  ]

  documentation {
    content = "支付服务 SLO 错误预算消耗速率异常,预计 2 小时内耗尽。请立即排查。"
  }
}

常用的错误预算告警速率阈值:

燃烧速率 含义 建议操作
1x 30 天内恰好耗尽 无需操作,正常消耗
6x 5 天内耗尽 Slack 通知,安排排查
14.4x 2 天内耗尽 PagerDuty 告警,优先处理
43.2x 6 小时内耗尽 紧急响应,可能需要回滚

六、Dashboard 构建与信息辐射

好的 Dashboard 是团队共享运维状态的信息辐射器。Cloud Monitoring Dashboard API 允许通过代码定义和部署仪表盘:


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# Terraform: 生产级监控仪表盘
resource "google_monitoring_dashboard" "payment_service" {
  dashboard_json = jsonencode({
    displayName = "Payment Service - Production"
    mosaicLayout = {
      tiles = [
        # 错误率折线图
        {
          width  = 6
          height = 4
          widget = {
            title = "Error Rate by Endpoint"
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = join(" AND ", [
                      "resource.type="gce_instance"",
                      "metric.type="loadbalancing.googleapis.com/https/request_count"",
                      "metric.response_code_class!="2xx""
                    ])
                    aggregation = {
                      alignmentPeriod    = "60s"
                      perSeriesAligner   = "ALIGN_RATE"
                      groupByFields      = ["metric.response_code_class"]
                    }
                  }
                }
              }]
            }
          }
        },
        # 延迟热力图
        {
          width  = 6
          height = 4
          widget = {
            title = "Request Latency Heatmap"
            xyChart = {
              dataSets = [{
                timeSeriesQuery = {
                  timeSeriesFilter = {
                    filter = join(" AND ", [
                      "resource.type="gce_instance"",
                      "metric.type="loadbalancing.googleapis.com/https/total_latencies""
                    ])
                    aggregation = {
                      alignmentPeriod  = "60s"
                      perSeriesAligner = "ALIGN_DELTA"
                    }
                  }
                }
                plotType = "HEATMAP"
              }]
            }
          }
        }
      ]
    }
  })
}

七、成本优化与最佳实践总结

监控和日志本身也可能成为成本黑洞。以下是控制成本的关键策略:

  • 日志采样:对高吞吐量、低价值的日志(如健康检查)在应用层做采样,仅记录 1%-10%
  • 排除过滤器:使用日志接收器的排除过滤器在入口处丢弃不需要的日志,避免写入计费
  • BigQuery 分区:导出到 BigQuery 时使用分区表和聚簇表,查询时始终带时间范围条件
  • 自定义指标降采样:在本地聚合后再上报,减少 API 调用次数
  • SLO 精简:只为关键服务定义 SLO,每个服务不超过 2-3 个 SLO

1
2
3
4
5
6
7
8
9
10
# 日志排除过滤器:丢弃健康检查日志
resource "google_logging_project_exclusion" "health_check" {
  name        = "exclude-health-checks"
  description = "Exclude load balancer health check logs"
  filter      = <<-EOF
    resource.type="http_load_balancer"
    jsonPayload.request_path="/healthz"
    severity="INFO"
  EOF
}

生产环境检查清单

在将监控体系推向生产之前,请确认以下事项:

  • 所有关键服务已配置结构化日志输出
  • 自定义指标使用 Distribution 类型记录延迟
  • 告警策略包含多条件组合,避免单指标误报
  • 错误预算告警已启用(6x 和 14.4x 两级)
  • 日志接收器已配置 BigQuery 长期存储
  • 排除过滤器已配置,减少无效日志写入
  • Dashboard 已部署,团队可快速查看服务健康状态
  • 所有监控配置使用 Terraform 管理,纳入 GitOps 流程

Cloud Monitoring 和 Cloud Logging 的组合为 Google Cloud 用户提供了从指标采集到告警响应的完整可观测性方案。通过结构化日志、自定义指标、SLO 管理和基础设施即代码实践,团队可以构建一套既全面又经济的监控体系。记住,监控的目标不是收集尽可能多的数据,而是在故障发生时快速定位问题、在故障发生前提前预警——质量永远胜过数量。

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » Google Cloud Monitoring 与 Cloud Logging 生产级实战:从指标采集到告警策略与SLO管理
分享到: 更多 (0)