Skip to content
On this page

当 PromQL 遇上 SQL:用混合查询解锁 Kubernetes 监控分析

学习如何在 GreptimeDB 中使用 TQL 和 CTE 将 PromQL 时序聚合与 SQL 分析能力结合,实现高级 Kubernetes 监控分析。

Kubernetes 监控早已是标配。Prometheus + Grafana 的组合用了这么多年,PromQL 写得溜的工程师一抓一大把。但想把 CPU 使用率和请求量做关联分析,或根据资源使用情况做动态分类时,PromQL 就开始别扭了。

PromQL 擅长时序聚合,但不擅长复杂 JOIN、条件分支等能力,聚合与窗口函数的表达能力也很受限——而这些恰恰是 SQL 的强项。把两者结合起来,很多复杂分析就能变得简单直接。

GreptimeDB 的 TQL(Telemetry Query Language)正是为此设计:在 SQL 中直接嵌入 PromQL,用 CTE 组合多个查询,实现真正的混合分析。

TQL:在 SQL 中执行 PromQL

TQL 是 GreptimeDB 对 SQL 的扩展,让你在 SQL 环境里直接执行 PromQL。基本语法:

sql
TQL EVAL (start, end, step) promql_expression

startend 支持多种时间表达式:

  • now() — 当前时间
  • now() - interval '1' hour — 1 小时前
  • date_trunc('day', now()) — 今天零点
  • '2024-01-01T00:00:00Z' — RFC3339 格式

查询过去一小时的 CPU 使用率:

sql
TQL EVAL (now() - interval '1' hour, now(), '5m')
    sum by (namespace, pod) (rate(container_cpu_usage_seconds_total[5m]))

AS 给结果列起别名,方便后续 SQL 处理:

sql
TQL EVAL (now() - interval '1' hour, now(), '5m')
    sum by (namespace, pod) (rate(container_cpu_usage_seconds_total[5m])) AS cpu_cores

结果列名变成 cpu_cores,SQL 引用更方便。

执行环境

TQL 是 SQL 扩展,任何能连 GreptimeDB 执行 SQL 的地方都能用:

  • 命令行:MySQL CLI (mysql -h host -P 4002) 或 PostgreSQL CLI (psql -h host -p 4003)
  • 编程语言:JDBC、Python DB-API、Go database/sql 等标准接口
  • 可视化工具:Grafana(MySQL/PostgreSQL 数据源)、DBeaver、DataGrip
  • HTTP API/v1/sql 端点

K8s 监控最常见的用法是在 Grafana 中配置 MySQL 数据源指向 GreptimeDB(默认端口 4002),在 Dashboard 查询编辑器里写 TQL。PromQL 的时序能力加上 SQL 的分析能力,结果直接可视化。

如何接入 K8s 指标? 参考官方教程 Kubernetes Cluster Metrics Monitoring,了解如何通过 Prometheus Remote Write 将集群指标写入 GreptimeDB。

CTE + TQL:混合查询的核心模式

TQL 的真正威力在于和 CTE(Common Table Expression)配合。CTE 是临时结果集,可以在主查询中引用,把复杂查询拆成可读的小块。

基本模式:

sql
WITH metrics_cte AS (
    TQL EVAL (start, end, step) promql_expression AS value_alias
)
SELECT * FROM metrics_cte WHERE value_alias > threshold;

几个要点:

  1. 时间列名取决于数据来源:Prometheus Remote Write 写入的数据用 greptime_timestamp;自定义表可能是 ts 或其他名字
  2. 建议用 AS 别名:显式指定列名比依赖自动生成更可靠
  3. 只支持 TQL EVAL:CTE 中不能用 TQL EXPLAINTQL ANALYZE

完整例子——找出 CPU 使用超过 0.5 核的 Pod,按使用量排序。

注意这里的 container_cpu_usage_seconds_total 是 Prometheus counter 类型,记录的是累计 CPU 秒数,必须用 rate() 转换成每秒使用率才有意义。纯 SQL 没法处理 counter 的速率计算,纯 PromQL 的过滤排序又不够灵活——这正是混合查询的用武之地:

sql
WITH cpu_usage AS (
    TQL EVAL (now() - interval '1' hour, now(), '5m')
    sum by (namespace, pod) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
    AS cpu_cores
)
SELECT
    greptime_timestamp as ts,
    namespace,
    pod,
    cpu_cores
FROM cpu_usage
WHERE cpu_cores > 0.5
ORDER BY cpu_cores DESC
LIMIT 20;

PromQL 计算 CPU 使用率,SQL 过滤排序。纯 PromQL 也能实现,但 SQL 语法更直观,尤其条件复杂时。

实战场景一:资源使用分级告警

根据资源使用情况设置不同告警级别。纯 PromQL 需要多条规则,SQL 的 CASE WHEN 一步到位:

sql
WITH cpu_usage AS (
    TQL EVAL (now() - interval '1' hour, now(), '5m')
    sum by (namespace, pod) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
    AS cpu_cores
)
SELECT
    greptime_timestamp as ts,
    namespace,
    pod,
    ROUND(cpu_cores, 3) as cpu_cores,
    CASE
        WHEN cpu_cores > 2 THEN 'critical'
        WHEN cpu_cores > 1 THEN 'warning'
        ELSE 'normal'
    END as alert_level
FROM cpu_usage
WHERE cpu_cores > 0.1
ORDER BY cpu_cores DESC;

一个查询搞定分级,critical 排在前面。

实战场景二:跨指标关联分析

想知道每个服务单位请求消耗多少 CPU?用来评估代码效率或做容量规划。

把 CPU 数据和请求量关联起来,纯 PromQL 比较绕,CTE + JOIN 很自然(这里用 http_requests_total,你的集群可能是其他指标名,按实际情况替换):

sql
WITH
    cpu_data AS (
        TQL EVAL (now() - interval '1' hour, now(), '5m')
        sum by (pod) (rate(container_cpu_usage_seconds_total{container!=""}[5m]))
        AS cpu_cores
    ),
    request_data AS (
        TQL EVAL (now() - interval '1' hour, now(), '5m')
        sum by (pod) (rate(http_requests_total[5m]))
        AS req_per_sec
    )
SELECT
    c.greptime_timestamp as ts,
    c.pod,
    ROUND(c.cpu_cores, 3) as cpu_cores,
    ROUND(r.req_per_sec, 1) as req_per_sec,
    ROUND(c.cpu_cores / r.req_per_sec * 1000, 2) as cpu_per_1k_requests
FROM cpu_data c
JOIN request_data r
    ON c.greptime_timestamp = r.greptime_timestamp
    AND c.pod = r.pod
WHERE r.req_per_sec > 1
ORDER BY cpu_per_1k_requests DESC;

计算每 1000 个请求消耗的 CPU。数值越高,服务越"吃"资源,可能需要优化。

提示:JOIN 条件除了时间戳,还要匹配标签(这里是 pod)。确保两个 TQL 的聚合维度一致,否则 JOIN 结果会出错。

实战场景三:API 响应时间 P99 分析

SLO 监控是业界通用实践。找出 P99 延迟最高的接口,PromQL 的 histogram_quantile 算分位数,SQL 做排序过滤更方便。

这里用 http_request_duration_seconds_bucket,这是 Prometheus 社区的标准命名。如果你用的是 Istio、Nginx Ingress 等,指标名可能不同,按实际情况替换。

sql
WITH latency_p99 AS (
    TQL EVAL (now() - interval '1' hour, now(), '5m')
    histogram_quantile(0.99, sum by (service, endpoint, le) (rate(http_request_duration_seconds_bucket[5m])))
    AS p99_seconds
)
SELECT
    greptime_timestamp as ts,
    service,
    endpoint,
    ROUND(p99_seconds * 1000, 1) as p99_ms,
    CASE
        WHEN p99_seconds > 1 THEN 'SLO violated'
        WHEN p99_seconds > 0.5 THEN 'at risk'
        ELSE 'healthy'
    END as slo_status
FROM latency_p99
WHERE p99_seconds IS NOT NULL
ORDER BY p99_seconds DESC
LIMIT 20;

找出 P99 最高的 20 个接口,标注 SLO 状态。超 1 秒直接标记 SLO violated,快速定位问题。

实战场景四:Pod 重启异常检测

Pod 频繁重启是危险信号。TQL 统计重启次数,SQL 聚合做异常检测:

sql
WITH restart_counts AS (
    TQL EVAL (now() - interval '6' hour, now(), '30m')
    sum by (namespace, pod) (increase(kube_pod_container_status_restarts_total[30m]))
    AS restarts
)
SELECT
    namespace,
    pod,
    CAST(SUM(restarts) AS INT) as total_restarts,
    CAST(MAX(restarts) AS INT) as max_per_30m,
    CAST(AVG(restarts) AS INT) as avg_per_30m
FROM restart_counts
WHERE restarts > 0
GROUP BY namespace, pod
HAVING SUM(restarts) >= 3
ORDER BY total_restarts DESC;

HAVING 过滤偶发重启,聚焦真正有问题的 Pod。

最佳实践

1. 用 AS 别名让列名可预测

PromQL 自动生成的列名可能很长,且不同版本间可能变化。显式命名更健壮。

2. 写 JOIN 时确认时间列名

前面提过,Prometheus Remote Write 数据用 greptime_timestamp,自定义表可能不同。JOIN 时别写错。

3. 保持聚合维度一致

JOIN 多个 TQL CTE 时,确保 by (...) 维度一致,否则可能产生笛卡尔积或空结果。

4. 合理设置查询范围

(start, end, step) 影响数据量和性能。实时监控用短范围小 step;趋势分析用长范围大 step。

5. 善用 GreptimeDB 的 SQL 能力

GreptimeDB 基于 Apache DataFusion,提供丰富的内置函数:

  • 聚合SUMAVGMINMAXCOUNT
  • 窗口ROW_NUMBERRANKLAGLEAD
  • 数学ROUNDABSFLOORCEILCLAMP
  • 时间date_truncdate_adddate_formatto_unixtime
  • 条件CASE WHENCOALESCENULLIF

完整列表见 GreptimeDB SQL Functions

小结

PromQL 擅长时序聚合,SQL 擅长关联分析和条件处理。TQL + CTE 让你:

  1. 用 PromQL 做时序聚合(rate、histogram_quantile、increase 等)
  2. 用 SQL 做过滤、JOIN、条件分支、窗口分析
  3. 把复杂分析拆成可读的小块

对于 K8s 监控,很多以前需要应用层处理的分析,现在可以直接在数据库层完成。

下次遇到复杂监控分析,试试混合查询。

参考链接

加入我们的社区

获取 Greptime 最新更新,并与其他用户讨论。