我们知道 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实例,分别创建了一个Gauge和Counter类型的指标,其中第一个参数为指标名称,第二个参数为指标的注释信息,第三个参数为相关的标签,然后为不同的标签值设置不同的指标值,最后通过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_metric和another_metric这两个指标了。 Prometheus 会给每个抓取的指标附加一个job和instance的标签,job标签来自scrape配置,我们这里抓取 Pushgateway 的job标签为job=”pushgateway”,instance标签的值会自动设置为抓取目标的主机和端口,所以所有从 Pushgateway 抓取的指标都会有 Pushgateway 的主机和端口作为instance标签,但是这可能会和你附加推送到 Pushgateway 指标上的job和instance标签冲突,这个时候 Prometheus 会将这些标签重命名为exported_job和exported_instance。 但是,在抓取 Pushgateway 时,通常不希望出现这种行为。更多的时候你可能更希望保留推送到 Pushgateway 的指标的job和instance标签,这个时候我们只需要在 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 中的两个指标。 可以看到job和instance这两个标签变成了我们推送到 Pushgateway 中的标签值了,这个可能更符合我们的预期。 另外需要注意的是 Pushgateway 不提供任何强一致性保证,没有高可用的方案,它可以做的最好的事情就是将每个指定时间段的指标保存到磁盘了,总之不到万不得已的情况下最好别用 Pushgateway。
转载请注明:IT运维空间 » 运维技术 » 使用 Prometheus Pushgateway 推送监控指标
发表评论