SQL API

# 1. 简介

提供统一的 SQL 接口查询所有类型的观测数据,可作为 Grafana 的 DataSource,或基于此实现自己的 GUI。

# 2. SQL 服务端点

获取服务端点端口号:

port=$(kubectl get --namespace deepflow -o jsonpath="{.spec.ports[0].nodePort}" services deepflow-server)
1

# 3. SQL 查询语句

# 3.1 获取所有数据库

SQL 语句:

show databases
1

API 调用方式:

curl -XPOST "http://${deepflow_server_node_ip}:${port}/v1/query/" \
    --data-urlencode "sql=show databases"
1
2

# 3.2 获取指定数据库的所有表

SQL 语句:

show tables
1

API 调用方式:

curl -XPOST "http://${deepflow_server_node_ip}:${port}/v1/query/" \
    --data-urlencode "db=${db_name}" \
    --data-urlencode "sql=show tables"
1
2
3

# 3.3 获取指定数据表中的 Tag

SQL 语句:

show tags from ${table_name}
1

API 调用方式:

curl -XPOST "http://${deepflow_server_node_ip}:${port}/v1/query/" \
    --data-urlencode "db=${db_name}" \
    --data-urlencode "sql=show tags from ${table_name}"
1
2
3

输出示例:

{
    "OPT_STATUS": "SUCCESS",
    "DESCRIPTION": "",
    "result": {
        "columns": [
          "name",
          "client_name",
          "server_name",
          "display_name",
          "type" // int, int_enum, string, string_enum, resource_name, resource_id, ip
        ],
        "values": [
            [
              "chost",
              "chost_0",
              "chost_1",
              "云服务器",
              "resource_id"
            ],
            [
              "chost_name",
              "chost_name_0",
              "chost_name_1",
              "云服务器名称",
              "resource_name"
            ]
        ]
    }
}
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

# 3.4 获取指定 Tag 的取值

# 3.4.1 获取 Tag 的所有取值

SQL 语句:

show tag ${tag_name} values from ${table_name}
1

上述语句也可通过 limitoffset 关键词减少返回的取值数量:

show tag ${tag_name} values from ${table_name} limit 100 offset 100
1

API 调用方式:

curl -XPOST "http://${deepflow_server_node_ip}:${port}/v1/query/" \
    --data-urlencode "db=${db_name}" \
    --data-urlencode "sql=show tag ${tag_name} values from ${table_name}"
1
2
3

输出示例:

{
    "OPT_STATUS": "SUCCESS",
    "DESCRIPTION": "",
    "result": {
        "columns": [
          "value",
          "display_name",
          "uid"
        ],
        "values": [
            [
                348,
                "deepflow",
                "i-2ze3bpa0o5cy8edplozi"
            ],
        ]
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

# 3.4.2 使用 Tag 自身名称过滤

注意到上述 Tag 的取值会返回三列:valuedisplay_nameuid。我们可以利用这些信息进行过滤,例如:

show tag ${tag_name} values from ${table_name} where display_name like '*abc*'
1

API 调用方式和输出示例同上。

# 3.4.3 使用其他 Tag 关联过滤

有时候我们希望使用 Tag 进行关联过滤,减少候选项取值范围。这个时候我们可以选择查询某个数据表,对 Tag1 进行过滤的同时对 Tag2 进行聚合。例如,我们希望查询所有 pod_cluster="cluster1" 中的 pod 名称:

SELECT pod FROM `vtap_flow_port.1m` WHERE pod_cluster = 'cluster1' GROUP BY pod
1

以上语句会利用 flow_metrics 数据库中的 vtap_flow_port.1m 表中的 pod_cluster 字段对 pod 的候选项进行过滤和分组。当然我们也可通过查询 DeepFlow 中的任意表来实现此需求,但应尽量避免使用数据量很大的表。另外,我们也可在 SQL 中加入时间等其他维度来加速查找:

SELECT pod FROM `vtap_flow_port.1m` WHERE pod_cluster = 'cluster1' AND time > 1234567890 GROUP BY pod
1

注意:仅当 pod 中曾经有流量(且不使用 HostNetwork 时)才能在 flow_metrics 中查到数据。当我们在集成 Prometheus 或 Telegraf 数据以后,也可借用这其中恒定存在的指标来辅助获取 Tag 取值。例如,我们可使用 ext_metrics 中的 Prometheus 指标实现上述需求:

SELECT pod FROM `prometheus.kube_pod_start_time` WHERE pod_cluster = 'cluster1' GROUP BY pod
1

在 Grafana 中,我们也可利用上述能力实现 Variable 候选项的联动过滤,例如我们使用一个自定义的 Variable $cluster 和内置的 Variable $__from、$__to (opens new window) 对另一个 Variable pod 进行联动过滤:

  • cluster 的值为 id 时, 使用 $cluster:

    cluster = [1, 2]
    result: 1, 2
    
    1
    2
    // Add 5 minutes before and after the time range to avoid frequent changes of candidates
    SELECT pod_id as `value`, pod as `display_name` FROM `vtap_flow_port.1m` WHERE pod_cluster IN ($cluster) AND time >= ${__from:date:seconds}-500 AND time <= ${__to:date:seconds}+500 GROUP BY `value`
    
    1
    2
  • cluster 的值为 name 时, 使用 ${cluster:singlequote}:

    cluster = [deepflow-a, deepflow-b]
    result: 'deepflow-a', 'deepflow-b'
    
    1
    2
    SELECT pod as `value`, pod as `display_name` FROM `vtap_flow_port.1m` WHERE pod_cluster IN (${cluster:singlequote}) AND  time >= ${__from:date:seconds}-500 AND time <= ${__to:date:seconds}+500 GROUP BY `value`
    
    1

# 3.5 获取指定数据表中的 Metrics

SQL 语句:

show metrics from ${table_name}
1

API 调用方式:

curl -XPOST "http://${deepflow_server_node_ip}:${port}/v1/query/" \
    --data-urlencode "db=${db_name}" \
    --data-urlencode "sql=show metrics from ${table_name}"
1
2
3

# 3.6 查询观测数据

SQL 语句:

SELECT col_1, col_2, col_3 \
FROM   tbl_1 \
WHERE  col_4 = y \
GROUP BY col_1, col_2 \
HAVING   col_5 > 100 \
ORDER BY col_3 \
LIMIT 100
1
2
3
4
5
6
7

API 调用方式:

curl -XPOST "http://${deepflow_server_node_ip}:${port}/v1/query/" \
    --data-urlencode "db=${db_name}" \
    --data-urlencode "sql=${sql}"
1
2
3

db=flow_metric时,需要通过--data-urlencode "data_precision=${data_precision}"指定数据精度,data_precision的可选值为1m1s

# 4. SQL 查询函数

# 4.1 Tag 支持的函数

  • enum
    • 说明:enum(tap_side) 将枚举字段转化为值
    • 示例:SELECT enum(tap_side) ...... WHERE enum(tap_side) = 'xxx' ...
    • 注意:仅string_enumint_enum类型的Tag支持

# 4.2 Metrics 支持的函数

执行如下 SQL 语句可获取所有的函数:

show metric function
1

API 调用方式:

curl -XPOST "http://${deepflow_server_node_ip}:${port}/v1/query/" \
    --data-urlencode "sql=show metric function"
1
2

# 5. SQL 语法

  • 左值不支持空格、单引号、反引号
  • 右值中的单引号,需要使用转义符 \ 进行转义