在 Google Cloud Platform 上运行 Promtail 客户端
本文档解释了如何设置 Google Cloud Platform 将特定 GCP 项目的云资源日志转发到 Google Pubsub Topic 中,以便 Promtail 可以消费。
注意
Promtail 已被弃用,并且将通过 2026 年 2 月 28 日进入长期支持 (LTS) 阶段。Promtail 将于 2026 年 3 月 2 日达到生命周期结束 (EOL)。您可以在此处找到迁移资源。
本文档假定读者已安装 gcloud
并拥有所需的权限(如“角色和权限”部分所述)。
有两种配置方式
- 拉取模式订阅:Promtail 从 GCP PubSub topic 拉取日志条目
- 推送模式订阅:GCP 将日志条目发送到 Promtail 监听的 Web 服务器
总体而言,GCP、Promtail 和 Loki 之间的设置如下图所示

角色和权限
用户需要拥有以下角色才能完成设置。
- “roles/pubsub.editor”
- “roles/logging.configWriter”
设置 Pubsub Topic
Google Pubsub Topic 将作为队列来持久化日志消息,然后 Promtail 可以从中读取。
$ gcloud pubsub topics create $TOPIC_ID
例如
$ gcloud pubsub topics create cloud-logs
设置日志路由器
我们创建一个日志接收器 (log sink) 将云日志转发到我们刚刚创建的 pubsub topic 中。
$ gcloud logging sinks create $SINK_NAME $SINK_LOCATION $OPTIONAL_FLAGS
例如
$ gcloud logging sinks create cloud-logs pubsub.googleapis.com/projects/my-project/topics/cloud-logs \
--log-filter='resource.type=("gcs_bucket")' \
--description="Cloud logs"
上述命令还添加了 log-filter
选项,用于表示哪些类型的日志应该进入目标 pubsub
topic。有关添加 log-filter
的更多信息,请参阅此文档
我们在下方介绍更高级的 log-filter
授予日志接收器 pubsub publisher 角色
查找刚刚创建的日志接收器的写入者身份服务账号
gcloud logging sinks describe \
--format='value(writerIdentity)' $SINK_NAME
例如
gcloud logging sinks describe \
--format='value(writerIdentity)' cloud-logs
创建 IAM 策略绑定,允许日志接收器向该 topic 发布消息
gcloud pubsub topics add-iam-policy-binding $TOPIC_ID \
--member=$WRITER_IDENTITY --role=roles/pubsub.publisher
例如
gcloud pubsub topics add-iam-policy-binding cloud-logs \
--member=serviceAccount:pxxxxxxxxx-xxxxxx@gcp-sa-logging.iam.gserviceaccount.com --role=roles/pubsub.publisher
为 Grafana Loki 创建 Pubsub 订阅
拉取
我们为上面创建的 pubsub topic 创建订阅,Promtail 使用此订阅来消费日志消息。
$ gcloud pubsub subscriptions create cloud-logs --topic=$TOPIC_ID \
--ack-deadline=$ACK_DEADLINE \
--message-retention-duration=$RETENTION_DURATION \
例如
$ gcloud pubsub subscriptions create cloud-logs --topic=projects/my-project/topics/cloud-logs \
--ack-deadline=10 \
--message-retention-duration=7d
有关更精细的选项,请参阅 gcloud pubsub subscriptions --help
推送
由于 GCP PubSub 推送订阅是一项相对较新的服务,在某些情况下,需要授予 Google 权限。首先,检查 GCP 项目的创建日期
> gcloud projects describe $GCP_PROJECT_ID
createTime: 'some date'
...
projectId: $GCP_PROJECT_ID
projectNumber: '$GCP_PROJECT_NUMBER'
如果 createTime
早于 2021 年 4 月 8 日,请跳过以下步骤。否则,您需要将 iam.serviceAccountTokenCreator
角色授予 Google 管理的服务账号
PUBSUB_SERVICE_ACCOUNT="service-${GCP_PROJECT_NUMBER}@gcp-sa-pubsub.iam.gserviceaccount.com"
gcloud projects add-iam-policy-binding ${GCP_PROJECT_ID} \
--member="serviceAccount:${PUBSUB_SERVICE_ACCOUNT}"\
--role='roles/iam.serviceAccountTokenCreator'
已使用 GCP Logs Push 目标配置了 Promtail,该目标托管在面向互联网且启用 HTTPS 的部署中,我们可以继续创建推送订阅。
gcloud pubsub subscriptions create cloud-logs \
--topic=$TOPIC_ID \
--push-endpoint=$HTTPS_PUSH_ENDPOINT_URI
使用 Terraform 设置
您还可以选择使用 Terraform 创建 GCP 日志收集所需的资源。首先,以下代码段将添加拉取和推送两种方式所需的资源。
如何使用 Terraform 超出本指南的范围。您可以参考此教程了解如何使用 Terraform 和 GCP。
// Provider module
provider "google" {
project = "$GCP_PROJECT_ID"
}
// Topic
resource "google_pubsub_topic" "main" {
name = "cloud-logs"
}
// Log sink
variable "inclusion_filter" {
type = string
description = "Optional GCP Logs query which can filter logs being routed to the pub/sub topic and promtail"
}
resource "google_logging_project_sink" "main" {
name = "cloud-logs"
destination = "pubsub.googleapis.com/${google_pubsub_topic.main.id}"
filter = var.inclusion_filter
unique_writer_identity = true
}
resource "google_pubsub_topic_iam_binding" "log-writer" {
topic = google_pubsub_topic.main.name
role = "roles/pubsub.publisher"
members = [
google_logging_project_sink.main.writer_identity,
]
}
然后,根据选择拉取或推送方式,需要添加另一个代码段。
拉取
以下代码段配置了 Promtail 将订阅的 pub/sub topic 的订阅。
// Subscription
resource "google_pubsub_subscription" "main" {
name = "cloud-logs"
topic = google_pubsub_topic.main.name
}
然后,填写所需的变量后,运行以下代码段以创建新资源。
terraform apply \
-var="inclusion_filter=<GCP Logs query of what logs to include>"
推送
以下代码段配置了向 Promtail 转发日志的 pub/sub topic 的推送订阅。
// Subscription
variable "push_endpoint_url" {
type = string
description = "Public URL where Promtail is hosted."
}
resource "google_pubsub_subscription" "main" {
name = "cloud-logs"
topic = google_pubsub_topic.main.name
push_config {
push_endpoint = var.push_endpoint_url
attributes = {
x-goog-version = "v1"
}
}
}
要创建新资源,填写所需的变量后,运行以下代码段。
terraform apply \
-var="push_endpoint_url=<Promtail public URL>" \
-var="inclusion_filter=<GCP Logs query of what logs to include>"
Promtail 的 ServiceAccount
我们需要一个具有以下权限的服务账号
- pubsub.subscriber
这使得 Promtail 能够从之前创建的 pubsub 订阅中读取日志条目。
您可以在此处找到 gcplog
的 Promtail scrape config 示例
如果您正在从多个 GCP 项目中抓取日志,则此服务账号应该在您尝试抓取的所有项目中拥有上述权限。
操作
有时,您可能希望清除包含日志的待处理 pubsub 队列。
这些消息会一直留在 Pubsub 订阅中,直到它们被确认。以下命令将移除日志消息,而无需通过 Promtail 或任何其他 pubsub 消费者进行消费。
gcloud pubsub subscriptions seek <subscription-path> --time=<yyyy-mm-ddThh:mm:ss>
要删除截止目前所有旧消息,请将 --time
设置为当前时间。
gcloud pubsub subscriptions seek projects/my-project/subscriptions/cloud-logs --time=$(date +%Y-%m-%dT%H:%M:%S)
高级日志过滤器
到目前为止,我们已经介绍了如何将 GCS 存储桶日志导入 Grafana Loki,但通常可能需要添加多个云资源日志,也可能需要排除不必要的日志。以下是一个更复杂的示例。
我们使用 log-filter
选项包含日志,使用 exclusion
选项排除特定日志。
用例
包含以下云资源日志
- GCS 存储桶
- Kubernetes
- IAM
- HTTP 负载均衡器
我们还根据负载内容和状态码排除特定的 HTTP 负载均衡器日志。
$ gcloud logging sinks create cloud-logs pubsub.googleapis.com/projects/my-project/topics/cloud-logs \
--log-filter='resource.type=("gcs_bucket OR k8s_cluster OR service_account OR iam_role OR api OR audited_resource OR http_load_balancer")' \
--description="Cloud logs" \
--exclusion='name=http_load_balancer,filter=<<EOF
resource.type="http_load_balancer"
(
(
jsonPayload.statusDetails=("byte_range_caching" OR "websocket_closed")
)
OR
(
http_request.status=(101 OR 206)
)
)
EOF