借助 Google Distributed Cloud (GDC) 网闸隔离配置中的日志查询功能,您可以在收集日志后,检查项目工作负载中的操作和审核事件。您可以使用日志查询语言 (LogQL) 表达式在 Grafana 日志面板中过滤、直观呈现和导出日志流。对于程序化工作流,请按照标准 API 访问方法,通过 HTTP 或 gRPC 查询组织的 Log Query API。
准备工作
如需查询和直观呈现日志,您必须拥有必要的权限。
申请 IAM 组织角色
请与您的 IAM 组织管理员联系,申请获得以下角色:
- Organization Grafana Viewer (
organization-grafana-viewer):在 Grafana 监控实例的信息中心内直观呈现与组织相关的可观测数据。 - Log Querier (
log-query-api-querier-pa):访问 Log Query API,以查询platform-obs项目中的平台日志。
申请 IAM 项目角色
请与您的 IAM 项目管理员联系,申请获得以下角色:
- Project Grafana Viewer (
project-grafana-viewer):在项目命名空间中的 Grafana 监控实例的信息中心内直观呈现与项目相关的可观测数据。 - Log Querier (
log-query-api-querier):访问 Log Query API 以查询项目命名空间中的应用日志。
下表总结了 PA 和 AO 身份角色的 Role 要求:
| 角色 | 对象 | 集群 | 角色 | 命名空间 | 群组/用户 |
|---|---|---|---|---|---|
| PA | grafana |
管理 API 服务器 | project-grafana-viewer |
platform-obs |
群组 |
| PA | log-query-api |
管理 API 服务器 | log-query-api-querier-pa |
platform-obs |
群组 |
| PA | grafana |
管理 API 服务器 | project-grafana-viewer |
platform-obs |
用户 |
| PA | log-query-api |
管理 API 服务器 | log-query-api-querier-pa |
platform-obs |
用户 |
| AO | grafana |
管理 API 服务器 | project-grafana-viewer |
PROJECT_NAMESPACE |
群组 |
| AO | log-query-api |
管理 API 服务器 | log-query-api-querier |
PROJECT_NAMESPACE |
群组 |
| AO | grafana |
管理 API 服务器 | project-grafana-viewer |
PROJECT_NAMESPACE |
用户 |
| AO | log-query-api |
管理 API 服务器 | log-query-api-querier |
PROJECT_NAMESPACE |
用户 |
选择以下配置之一,以向 Management API 服务器上的用户组 (Config 1) 或个人用户 (Config 2) 授予 Grafana 访问权限。对于每种配置,您可以运行 kubectl 命令直接创建 RoleBinding,也可以将 RoleBinding YAML 清单保存到指定的基础设施即代码 (IaC) 文件路径,以便通过 GitOps 应用:
配置 1
此配置会向用户群组授予对管理 API 服务器上的 PA 和 AO Grafana 的访问权限。完成此配置后,请参阅本文档的 Grafana 信息中心部分,在 Grafana 上查看日志。
kubectl 命令
运行以下命令,直接创建
RoleBinding:kubectl --kubeconfig KUBECONFIG create rolebinding RULE_NAME -n platform-obs --group=GROUP_NAME --role=project-grafana-viewer示例:
kubectl --kubeconfig KUBECONFIG_PATH create rolebinding project-grafana-viewers-binding --role=project-grafana-viewer --group=my-team --namespace=platform-obsIaC 文件路径
或者,如需使用 IaC 管理
RoleBinding,请在以下路径中创建 YAML 文件:/infrastructure/zonal/zones/ZONE/org-admin/rolebindings/GROUP_NAME/YAML_FILEYAML 文件
将以下
RoleBinding清单保存在 IaC 文件路径中的 YAML 文件中:apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: RULE_NAME namespace: platform-obs subjects: - kind: Group name: GROUP_NAME apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: project-grafana-viewer apiGroup: rbac.authorization.k8s.io
配置 2
此配置会向用户授予在管理 API 服务器上访问 PA 和 AO Grafana 的权限。设置此配置后,请参阅本文档的 Grafana 信息中心部分,以在 Grafana 上查看日志。
kubectl 命令
运行以下命令,直接创建
RoleBinding:kubectl --kubeconfig KUBECONFIG create rolebinding RULE_NAME -n platform-obs --user=EMAIL_ADDRESS --role=project-grafana-viewer示例:
kubectl --kubeconfig KUBECONFIG_PATH create rolebinding project-grafana-viewers-binding --role=project-grafana-viewer --user=my-email@example.com --namespace=platform-obsIaC 文件路径
或者,如需使用 IaC 管理
RoleBinding,请在以下路径中创建 YAML 文件:/infrastructure/zonal/zones/ZONE/org-admin/rolebindings/EMAIL_ADDRESS/YAML_FILEYAML 文件
将以下
RoleBinding清单保存在 IaC 文件路径中的 YAML 文件中:apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: RULE_NAME namespace: platform-obs subjects: - kind: User name: EMAIL_ADDRESS apiGroup: rbac.authorization.k8s.io roleRef: kind: Role name: project-grafana-viewer apiGroup: rbac.authorization.k8s.io
替换以下内容:
KUBECONFIG:特定集群的 kubeconfig 文件的路径,该集群包含应用此RoleBinding的NAMESPACE。KUBECONFIG_PATH:示例命令中 kubeconfig 文件的路径。RULE_NAME:此RoleBinding资源在命名空间中的唯一名称,例如pa-project-grafana-viewer。NAMESPACE:在其中创建和应用此RoleBinding的 Kubernetes 命名空间。请查看上表中的Namespace列。EMAIL_ADDRESS:被授予该角色的用户的标识符,例如application-operator@example.com。ROLE:包含您要授予用户的权限的Role的名称。请在上表中查找可用角色。GROUP_NAME:PA 用户所属的Group的名称,例如pa-group。ZONE:区域的名称。YAML_FILE:RoleBinding资源的 YAML 文件的名称。
如需详细了解这些角色,请参阅准备 IAM 权限。
查询和过滤日志
选择以下方法之一,以构建查询并过滤项目工作负载中的日志:
Grafana 日志面板
本部分介绍如何使用 Grafana 中的“日志”面板访问日志。
确定 Grafana 端点
以下网址是项目的 Grafana 实例的端点:
https://GDC_URL/PROJECT_NAMESPACE/grafana
替换以下内容:
GDC_URL:GDC 中组织的网址。PROJECT_NAMESPACE:您的项目命名空间。例如,
org-1组织中platform-obs项目的 Grafana 端点为https://org-1/platform-obs/grafana。
在 Grafana 界面中查看日志
在 Grafana 界面中查询日志:
- 在 GDC 控制台中,选择您的项目。
- 在导航菜单中,依次选择运维 > Logging。
点击在 Grafana Loki 中查看全部。
系统会打开一个新页面,其中显示您的 Grafana 端点和界面。
在界面上,点击导航菜单中的探索 探索,打开探索页面。
在探索栏的菜单中,根据您的 Universe 类型选择一个数据源来检索日志:
单可用区 Universe:选择以下数据源之一,以显示 Universe 的单个可用区中的日志记录数据:
- 运维日志:显示运维日志。
- 审核日志:显示审核日志。
多可用区 Universe:Grafana 可以连接到不同的可用区并显示跨可用区数据。选择以下数据源之一,以显示来自宇宙中任何可用区的日志记录数据,无论您登录的是哪个可用区:
- 运维日志 ZONE_NAME:显示特定可用区的运维日志。
- 审核日志 ZONE_NAME:显示特定可用区的审核日志。
此外,如需在单个信息中心内实现跨可用区数据可视化,并向查询添加多个可用区,请选择混合作为数据源。
输入查询,使用 LogQL(日志查询语言)表达式从“日志”面板中搜索日志。您可以通过以下任一方式执行此步骤:
- 使用交互式查询构建器界面。然后,点击运行查询。
- 直接在文本字段中输入查询,然后按 Shift+Enter 运行查询。
该页面会显示与您的查询匹配的日志。查询日志后,您可以将其导出。点击导出,以纯文本或 CSV 格式下载日志。您还可以为日志选择时间范围。

图 1. 用于从 Grafana 界面查询审核日志的菜单选项。
在图 1 中,审核日志选项会显示一个界面,您可以通过该界面从 Grafana 构建查询来检索审核日志。
如需查看用于查询不同日志的标签和值示例,请参阅示例查询和标签。
为日志选择时间范围
如需查询某个时间范围内的日志,请按以下步骤操作:
点击 Grafana 中的 时间选择器菜单。
从菜单中,执行以下操作之一:
- 选择相对时间范围选项,例如过去 30 分钟。
- 通过从日历中选择特定日期和时间,然后点击应用时间范围,设置自定义绝对时间范围。
(可选)点击更改时间设置,通过时间范围控件更改时区和财年设置。
时间设置会按信息中心保存。如需详细了解一段时间内的查询,请参阅 https://grafana.com/docs/loki/latest/reference/api/#query-loki-over-a-range-of-time。
Log Query API
本部分介绍了如何使用 Log Query API 访问日志。
确定 Log Query API 端点
Log Query API 公开了以下两个端点,用于查询审核日志和操作日志:
审核日志端点:
audit-log-query-api.ORG_DOMAIN操作日志端点:
operational-log-query-api.ORG_DOMAIN
将 ORG_DOMAIN 替换为组织的域名。您可以使用 gdcloud config list 命令查看此属性。域名必须遵循语法 org-name.zone.google.gdch.com。例如,在 zone1 区域和测试环境中,名为 org-1 的组织具有类似于 org-1.zone1.google.gdch.test 的网域。
Log Query API 具有以下三个端点选项:
- labels:列出项目的所有标签。
- labels/labels/LABEL/values:列出项目的特定标签值。
- logs:列出特定项目的日志。
如需了解详情,请参阅 API 文档。
发送查询
使用 HTTP 或 gRPC 客户端向 Log Query API 端点发送查询。
HTTP
按照说明使用 HTTP 客户端直接访问 API。
您可以依靠 kubectl 来管理身份验证,也可以自行处理身份验证。
使用 curl、wget 等 HTTP 客户端或您创建和管理的 HTTP 客户端查询 Log Query API。以下示例使用 curl 工具查询 API,您可以对 wget 命令使用类似的格式:
对 cURL 请求进行身份验证:
- 下载并安装 gdcloud CLI。
设置 gdcloud
core/organization_console_url属性:gdcloud config set core/organization_console_url https://GDC_URL将
GDC_URL替换为 GDC 中组织的网址。-
gdcloud auth login 使用您的用户名和密码进行身份验证并登录。
将指定账号的身份令牌导出到环境变量:
export TOKEN="$($HOME/gdcloud auth print-identity-token --audiences=https://LOG_QUERY_API_ENDPOINT)"将
LOG_QUERY_API_ENDPOINT替换为您要从中查询日志的日志查询 API 端点以及您要连接到的网域。因此,audiences标志的值可以是https://operational-log-query-api.org-1.zone1.google.gdch.test。登录成功后,您可以通过
gdcloud auth print-identity-token命令在 cURL 请求中使用授权标头。如需了解详情,请参阅 gdcloud auth print-identity-token。
如果您想列出项目的所有标签,请发送以下查询:
curl -H "Authorization: Bearer ${TOKEN}" \ https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels \ -H "Content-Type: application/json" -v替换以下内容:
LOG_QUERY_API_ENDPOINT:您要从中查询日志的日志查询 API 端点。PROJECT_NAMESPACE:您的项目命名空间。
如果您想列出项目的特定标签值,请发送以下查询:
curl -H "Authorization: Bearer ${TOKEN}" \ https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/labels/labels/LABEL/values \ -H "Content-Type: application/json" -v替换以下内容:
LOG_QUERY_API_ENDPOINT:您要从中查询日志的日志查询 API 端点。PROJECT_NAMESPACE:您的项目命名空间。LABEL:您要查询其值的特定标签。
如果您想查询特定项目的日志,请构建
logs_filter查询并将其添加到请求正文中:curl -X GET -H "Authorization: Bearer ${TOKEN}" \ https://LOG_QUERY_API_ENDPOINT/v1/projects/PROJECT_NAMESPACE/logs \ -H "Content-Type: application/json" -d \ '{"logs_filter": {"labels_equal": {"LABEL": "LABEL_VALUE"}}}' -v替换以下内容:
LOG_QUERY_API_ENDPOINT:您要从中查询日志的日志查询 API 端点。PROJECT_NAMESPACE:您的项目命名空间。LABEL:您要查询其日志的特定标签。LABEL_VALUE:要查询其日志的标签值。
请参阅 API 文档,了解构建
logs_filter查询的所有选项。
gRPC
gRPC 在各种编程语言中都得到了广泛支持,与 HTTP 客户端相比,它提供了更高效的通信方法。
如需使用 gRPC 查询日志,您必须满足以下前提条件:
- 基于 Google 提供的协议缓冲区创建您自己的客户端库。
- 在客户端中实现身份验证。
- 实现重试。
如需了解协议缓冲区,请参阅 API 文档。
以下示例展示了如何使用未经身份验证的 gRPC 客户端从 Go 程序查询日志。该示例假设您创建了一个 golang 软件包,其中包含用于导入代码依赖项的 Bazel build 文件:
将以下代码保存到名为
client.go的 Go 程序中:package main import ( "context" "crypto/tls" "flag" "fmt" "google.golang.org/grpc/credentials" "google.golang.org/grpc/metadata" pb "<import path to generated log query api protos>/pkg/apis/public/logging/v1/proto" "google.golang.org/grpc" ) var serverAddr = flag.String("server", "localhost:8080", "server address") func main() { flag.Parse() tc := credentials.NewTLS(&tls.Config{InsecureSkipVerify: true}) conn, err := grpc.Dial(*serverAddr, grpc.WithTransportCredentials(tc)) if err != nil { panic(error.Error(fmt.Errorf("create client connection failed: %v", err))) } defer conn.Close() c := pb.NewLogsClient(conn) md := metadata.Pairs("clienttest", "test") ctx := metadata.NewOutgoingContext(context.Background(), md) err = listLabels(ctx, c, "project-foo") if err != nil { panic(error.Error(err)) } if err := listLabelValues(ctx, c, "project-foo", "resource-bar"); err != nil { panic(error.Error(err)) } if err := listLogs(ctx, c, "project-foo", &pb.ListLogsFilter{ LabelsEqual: map[string]string{"resource-bar": "resource-bar-value"}, OrderAscending: true, }); err != nil { panic(error.Error(err)) } } // List all labels for a project. func listLabels(ctx context.Context, c pb.LogsClient, project string) error { lbr := &pb.ListLabelsRequest{ Parent: project, PageSize: 1000, // PageSize can be configured to limit the number of responses per page. } resp, err := c.ListLabels(ctx, lbr) if err != nil { return fmt.Errorf("list labels: %v", err) } fmt.Printf("%v", resp) return nil } // List specific label values for a project. func listLabelValues(ctx context.Context, c pb.LogsClient, project string, label string) error { lbr := &pb.ListLabelValuesRequest{ Parent: project, Label: label, PageSize: 1000, // PageSize can be configured to limit the number of responses per page. } resp, err := c.ListLabelValues(ctx, lbr) if err != nil { return fmt.Errorf("list label values: %v", err) } fmt.Printf("%v", resp) return nil } // List logs for a specific project. func listLogs(ctx context.Context, c pb.LogsClient, project string, lf *pb.ListLogsFilter) error { lbr := &pb.ListLogsRequest{ Parent: project, LogsFilter: lf, PageSize: 5, // PageSize can be configured to limit the number of responses per page. } resp, err := c.ListLogs(ctx, lbr) if err != nil { return fmt.Errorf("list logs: %v", err) } fmt.Printf("logs: %v", resp) return nil }运行 Go 程序:
go run PATH_TO_API/client.go -server=LOG_QUERY_API_ENDPOINT:443替换以下内容:
PATH_TO_API:API 文件的路径。LOG_QUERY_API_ENDPOINT:您要从中查询日志的日志查询 API 端点。
如果未指定服务器标志,则默认请求会发送到
localhost。
示例查询和标签
以下是可用于查询日志的一些默认标签:
cluster:集群的名称。namespace:您的项目命名空间。node:节点名称。pod:Pod 名称。container:容器名称。
以下代码示例展示了如何使用标签和值来查询不同的日志:
选择服务器日志:
{cluster="admin", namespace="kube-system", resources="k8s_container", container="kube-apiserver"}选择集群审核日志:
{cluster="admin", resources="k8s_audit"}