使用 Prometheus Pushgateway 推送监控指标

k8s技术圈

共 11874字,需浏览 24分钟

 · 2022-07-13

我们知道 Prometheus 采用的 pull 模式,但是某些网络场景下面(比如不在一个子网或者防火墙),Prometheus 无法直接拉取监控指标数据,这个时候我们可能就需要一种能够主动 push 的模式了。而 Pushgateway 就是 Prometheus 生态中来解决这个问题的一个工具。

但是 Pushgateway 也不是万能的,其本身也存在一些弊端:

  • 将多个节点数据汇总到 pushgateway, 如果 pushgateway 挂了,受影响范围更大
  • Prometheus 拉取状态 up 只针对 pushgateway, 无法做到对每个目标有效

由于 Pushgateway 可以持久化推送给它的所有监控数据,所以即使你的监控已经下线,Prometheus 还会拉取到旧的监控数据,需要手动清理 Pushgateway 不要的数据。

Pushgateway 的存在是为了允许临时和批处理作业向 Prometheus 暴露其指标。由于这些类型的任务可能存在的时间不够长而无法被抓取,因此他们可以将指标推送到 Pushgateway,然后 Pushgateway 将这些指标暴露给 Prometheus。有一点我们需要明白的是 Pushgateway 不是将指标主动 push 给 Prometheus,而是通过脚本将指标数据主动 push 给 Pushgateway 后,Prometheus 仍然通过 pull 模式去抓取指标

前面我们也介绍过 node-exporter 中的 textfile 收集器也可以用来采集指标,似乎和 Pushgateway 比较相似,这二者有什么区别吗?textfile 通常是用于节点级别的指标,而 Pushgateway 是用于服务级别的指标。

安装

同样要安装 Pushgateway 也非常简单,直接从 Release 页面 下载适用于你平台的二进制版本并解压即可使用。如果你想从源码自行编译,可以在代码根目录下面直接执行 make 命令即可编译。

直接执行 Pushgateway 二进制文件即可启动了,要更改监听的地址,可以通过 --web.listen-address 标志(例如0.0.0.0:9091:9091)指定。默认情况下 Pushgateway 不保留指标。但是 --persistence.file 标志允许我们指定一个文件,将推送的指标保存在其中,这样当 Pushgateway 重新启动后指标仍然存在。

此外当然我们也可以直接使用 Docker 镜像来进行启动:

docker run -d -p 9091:9091 prom/pushgateway

同样我们这里还是将 Pushgateway 部署在 Kubernetes 集群中,对应的资源清单文件如下所示:

# pushgateway.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pushgateway-data
  namespace: kube-mon
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 2Gi
  storageClassName: local-path
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pushgateway
  namespace: kube-mon
  labels:
    app: pushgateway
spec:
  selector:
    matchLabels:
      app: pushgateway
  template:
    metadata:
      labels:
        app: pushgateway
    spec:
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pushgateway-data
      containers:
        - name: pushgateway
          image: prom/pushgateway:v1.4.3
          imagePullPolicy: IfNotPresent
          args:
            - "--persistence.file=/data"
          ports:
            - containerPort: 9091
              name: http
          volumeMounts:
            - mountPath: "/data"
              name: data
          resources:
            requests:
              cpu: 100m
              memory: 500Mi
            limits:
              cpu: 100m
              memory: 500Mi
---
apiVersion: v1
kind: Service
metadata:
  name: pushgateway
  namespace: kube-mon
  labels:
    app: pushgateway
spec:
  selector:
    app: pushgateway
  type: NodePort
  ports:
    - name: http
      port: 9091
      targetPort: http

这里我们 --persistence.file 指定了持久化的文件,然后通过一个 Service 来暴露了服务,直接应用上面的资源清单文件即可:

☸ ➜ kubectl apply -f https://p8s.io/docs/pushgateway/manifests/pushgateway.yaml
☸ ➜ kubectl get pods -n kube-mon -l app=pushgateway
NAME                           READY   STATUS    RESTARTS   AGE
pushgateway-7684cbb67d-6mbjn   1/1     Running   0          99s
☸ ➜ kubectl get svc -n kube-mon -l app=pushgateway
NAME          TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)          AGE
pushgateway   NodePort   10.106.136.207   <none>        9091:30893/TCP   107s

默认情况下 Pushgateway 会提供一个简单的 Web 页面,可以查看当前具有哪些指标。

基本使用

Pushgateway 的数据推送支持两种方式,Prometheus Client SDK 推送和 API 推送。

Client SDK 推送

Prometheus 本身提供了支持多种语言的 SDK,可通过 SDK 的方式,生成相关的数据,并推送到 Pushgateway,当然这种方式需要客户端代码支持,这也是官方推荐的方案。目前的 SDK 覆盖语言有官方的:

  • Go
  • Java or Scala
  • Python
  • Ruby

也有许多第三方的库,详情可参见此链接:https://prometheus.io/docs/instrumenting/clientlibs/

这里我们以 Python 为例进行说明。

首先安装 Prometheus 的 Python SDK:

☸ ➜ pip install prometheus-client

然后创建一个名为 app.py 的文件,内容如下所示:

from prometheus_client import CollectorRegistry, Counter, Gauge, push_to_gateway

registry = CollectorRegistry()

g = Gauge('container_memory''Container memory data', ['node'], registry=registry)
g.labels(node='node1').inc()      # +1
g.labels(node='node2').dec(10)    # -10
g.labels(node='node3').set(4.2)   # 4.2

c = Counter('my_requests_total''HTTP requests total', ['method''endpoint'], registry=registry)
c.labels(method='get', endpoint='/').inc()
c.labels(method='post', endpoint='/submit').inc()

push_to_gateway('192.168.0.106:30893', job='batchA', registry=registry)

首先引入了 Prometheus 的 Python SDK,然后创建了一个 CollectorRegistry 实例,分别创建了一个 GaugeCounter 类型的指标,其中第一个参数为指标名称,第二个参数为指标的注释信息,第三个参数为相关的标签,然后为不同的标签值设置不同的指标值,最后通过 push_to_gateway 函数将指标数据发送到指定的 Pushgateway 服务上去。

直接执行上面的 Python 文件即可将数据推送到 Pushgateway:

☸ ➜ python app.py

API 推送

此外使用 Prometheus 文本协议,推送指标也是非常简单的,无需提供单独的 CLI。只需使用 curl 之类的命令行工具即可。

不过需要注意,在文本协议中,每一行都必须以换行符结尾('LF''\n'),以其他方式结束一行,例如使用 'CR''\r')、'CRLF''\r\n')或只是数据包的结尾,将导致协议错误。

推送的指标按组进行管理,由任意数量的标签组成的分组键识别,其中第一个必须是 job 标签。

比如我们现在将单个样本推送到由 {job="some_job"} 标识的组中:

☸ ➜ echo "some_metric 3.14" | curl --data-binary @- http://192.168.0.106:30893/metrics/job/some_job

需要注意由于没有提供类型信息, 所以这里的 some_metric 将是 UNTYPED 无类型的。

上面的命令执行完后我们可以重新前往 Pushgateway 的 Web 页面查看。

可以看到页面中就出现了上面我们推送的 some_metric 这个指标,而且位于 job="some_job" 这个分组下面。

接下来我们再推送一些相对复杂的指标,推到 {job="some_job",instance="some_instance"} 标识的分组中去,继续之前记得将上面的分组删除,然后执行下面的命令:

☸ ➜ cat <<EOF | curl --data-binary @- http://192.168.0.106:30893/metrics/job/some_job/instance/some_instance
  # TYPE some_metric counter
  some_metric{label="val1"} 42
  # TYPE another_metric gauge
  # HELP another_metric Just an example.
  another_metric 2398.283
EOF

该命令会将指标推送到 {job="some_job",instance="some_instance"} 标识的分组中去,要注意指标内容中是如何提供类型信息和帮助信息的,这里我们的指标是都具有类型了。

在 Web 界面中就可以看到上面推送的两个指标了,一个是 COUNTER 类型,一个是 GAUGE 类型。

如果你想删除某个分组下面的所有指标,我们也可以通过 curl 命令来实现。比如删除由 {job="some_job",instance="some_instance"} 标识的分组中的所有指标,可以通过下面的命令来实现:

☸ ➜ curl -X DELETE http://192.168.0.106:30893/metrics/job/some_job/instance/some_instance

这里需要注意的是删除是根据分组标识进行删除的,比如我们要删除由 {job="some_job"} 标识的分组中的所有指标,那么可以用下面的命令来实现:

☸ ➜ curl -X DELETE http://192.168.0.106:30893/metrics/job/some_job

但是需要注意这里是不包括上面示例 {job="some_job",instance="some_instance"} 分组中的指标的,即使这些指标具有相同的 job 标签,这点非常重要。

如果你想删除所有组中的所有指标,可以使用下面的命令来实现:

☸ ➜ curl -X PUT http://192.168.0.106:30893/api/v1/admin/wipe

但是需要注意需要通过 Pushgateway 的命令行标志 --web.enable-admin-api 来启用管理 API。

抓取指标

现在我们需要将 Pushgateway 的指标配置到 Prometheus 中去,让 Prometheus 去主动抓取 Pushgateway 的指标数据,我们当然也可以使用服务发现的方式,这里我们单独为 Pushgateway 创建一个抓取任务,在 Prometheus 中添加如下所示的抓取配置:

scrape_configs:
  - job_name: "pushgateway"
    kubernetes_sd_configs:
      - role: endpoints
    relabel_configs:
      - source_labels:
          [__meta_kubernetes_namespace, __meta_kubernetes_service_name]
        action: keep
        regex: kube-mon;pushgateway
# 省略其他配置......

我们这里同样采用基于 endpoints 的自动发现的方式来进行配置,去匹配 kube-mon 这个命名空间下名为 pushgateway 的服务即可。正常更新上面的配置后 Prometheus 就会自动去发现 Pushgateway 这个服务了。

现在我们重新推送下面的指标:

☸ ➜ cat <<EOF | curl --data-binary @- http://192.168.0.106:30893/metrics/job/some_job/instance/some_instance
  # TYPE some_metric counter
  some_metric{label="val1"} 42
  # TYPE another_metric gauge
  # HELP another_metric Just an example.
  another_metric 2398.283
EOF

推送完成后我们就可以在 Prometheus 中去查询 some_metricanother_metric 这两个指标了。

Prometheus 会给每个抓取的指标附加一个 jobinstance 的标签,job 标签来自 scrape 配置,我们这里抓取 Pushgateway 的 job 标签为 job="pushgateway"instance 标签的值会自动设置为抓取目标的主机和端口,所以所有从 Pushgateway 抓取的指标都会有 Pushgateway 的主机和端口作为 instance 标签,但是这可能会和你附加推送到 Pushgateway 指标上的 jobinstance 标签冲突,这个时候 Prometheus 会将这些标签重命名为 exported_jobexported_instance

但是,在抓取 Pushgateway 时,通常不希望出现这种行为。更多的时候你可能更希望保留推送到 Pushgateway 的指标的 jobinstance 标签,这个时候我们只需要在 Pushgateway 的抓取配置中设置 honor_labels: true 即可,我们重新更新 Prometheus 的配置:

scrape_configs:
  - job_name: "pushgateway"
    honor_labels: true
    kubernetes_sd_configs:
      - role: endpoints
    relabel_configs:
      - source_labels:
          [__meta_kubernetes_namespace, __meta_kubernetes_service_name]
        action: keep
        regex: kube-mon;pushgateway
# 省略其他配置......

上面抓取 Pushgateway 的任务中我们新增了一个 honor_labels: true 的配置,更新后我们重新去查询推送到 Pushgateway 中的两个指标。

可以看到 jobinstance 这两个标签变成了我们推送到 Pushgateway 中的标签值了,这个可能更符合我们的预期。

另外需要注意的是 Pushgateway 不提供任何强一致性保证,没有高可用的方案,它可以做的最好的事情就是将每个指定时间段的指标保存到磁盘了,总之不到万不得已的情况下最好别用 Pushgateway。

对 Prometheus 感兴趣的朋友也可以关注下我们的《Prometheus入门到实战》的课程,现在属于上新优惠价格,已经更新了80小节内容,还在持续更新中......

浏览 29
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报