菜单
开源 RSS

在 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 可以从中读取。

bash
$ gcloud pubsub topics create $TOPIC_ID

例如

bash
$ gcloud pubsub topics create cloud-logs

设置日志路由器

我们创建一个日志接收器 (log sink) 将云日志转发到我们刚刚创建的 pubsub topic 中。

bash
$ gcloud logging sinks create $SINK_NAME $SINK_LOCATION $OPTIONAL_FLAGS

例如

bash
$ 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 角色

查找刚刚创建的日志接收器的写入者身份服务账号

bash
gcloud logging sinks describe \
 --format='value(writerIdentity)' $SINK_NAME

例如

bash
gcloud logging sinks describe \
 --format='value(writerIdentity)' cloud-logs

创建 IAM 策略绑定,允许日志接收器向该 topic 发布消息

bash
gcloud pubsub topics add-iam-policy-binding $TOPIC_ID \
--member=$WRITER_IDENTITY --role=roles/pubsub.publisher

例如

bash
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 使用此订阅来消费日志消息。

bash
$ gcloud pubsub subscriptions create cloud-logs --topic=$TOPIC_ID \
--ack-deadline=$ACK_DEADLINE \
--message-retention-duration=$RETENTION_DURATION \

例如

bash
$ 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 项目的创建日期

bash
> gcloud projects describe $GCP_PROJECT_ID

createTime: 'some date'
...
projectId: $GCP_PROJECT_ID
projectNumber: '$GCP_PROJECT_NUMBER'

如果 createTime 早于 2021 年 4 月 8 日,请跳过以下步骤。否则,您需要将 iam.serviceAccountTokenCreator 角色授予 Google 管理的服务账号

bash
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 的部署中,我们可以继续创建推送订阅。

bash
gcloud pubsub subscriptions create cloud-logs \
--topic=$TOPIC_ID \
--push-endpoint=$HTTPS_PUSH_ENDPOINT_URI

使用 Terraform 设置

您还可以选择使用 Terraform 创建 GCP 日志收集所需的资源。首先,以下代码段将添加拉取和推送两种方式所需的资源。

如何使用 Terraform 超出本指南的范围。您可以参考此教程了解如何使用 Terraform 和 GCP。

terraform
// 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 的订阅。

terraform
// Subscription
resource "google_pubsub_subscription" "main" {
  name  = "cloud-logs"
  topic = google_pubsub_topic.main.name
}

然后,填写所需的变量后,运行以下代码段以创建新资源。

bash
terraform apply \
    -var="inclusion_filter=<GCP Logs query of what logs to include>"

推送

以下代码段配置了向 Promtail 转发日志的 pub/sub topic 的推送订阅。

terraform
// 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"
    }
  }
}

要创建新资源,填写所需的变量后,运行以下代码段。

bash
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 消费者进行消费。

bash
gcloud pubsub subscriptions seek <subscription-path> --time=<yyyy-mm-ddThh:mm:ss>

要删除截止目前所有旧消息,请将 --time 设置为当前时间。

bash
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