基于 Prometheus 和 Grafana 的分布式爬虫监控方案
在上一节中,我们已经实现了 Scrapy 分布式爬虫的数据统计,这些统计数据可以通过 Redis 共享以实现数据的集中化存储和同步。
接下来,我们可能想做的就是基于这些数据,将其可视化出来,比如我们想要的结果可能是这样的。
-
不用太多复杂的编程或配置就可以搭建一个高性能、高可用、实用又美观的数据可视化面板,面板中可以实时显示爬虫的各个指标的状态。
-
当某项指标异常的时候,可以通过各个方式通知我们,以便及时调整和修复。
以上的两个需求其实就恰好对标了监控的两大核心问题一一可视化+告警,这两个功能是监控系统的核心重点。
本节中,我们要介绍的就是一个企业级监控数据的监控方案一—Prometheus+Grafana,其中前者可以实现流式监控数据的收集、存储、查询、告警,后者可以实现强大又精美的可视化面板,同时也配备了告警功能。二者经常放在一起使用,同时二者还是云原生的重要部件,与 Kubernetes 结合起来可以实现全方位的数据监控和告警系统。
下面我们就来介绍 Prometheus 和 Grafana,并介绍如何将二者与 Scrapy 爬虫结合来实现数据监控。
Prometheus
Prometheus 是一个开源的服务监控系统和时间序列数据库,用于存储一些时序数据,比如某个时刻的各个指标数据等。它可以从一些HTTP页面来拉取符合格式的时间序列数据,同时也支持通过中间网关来推送数据。另外,它还支持灵活的查询语言 PromQL。利用 PromQL,我们可以非常方便地查询和分析某个时间段内的各项指标数据。另外,它提供了可视化UI,还支持告警配置等功能。
Prometheus 在记录纯数字时间序列方面表现非常好。它既适用于面向服务器等硬件指标的监控也适用于高动态的面向服务架构的监控。对于现在流行的微服务,Prometheus 的多维度数据收集和数据筛选查询语言也是非常强大的。
图17-26 说明了 Prometheus 的整体架构,以及生态中一些组件的作用。
图17-26 Prometheus 的整体架构
Grafana
Grafana 是一个开源的、拥有丰富 Dashboard 和图表编辑的指标分析平台,它专注于时序类图表分析,而且支持多种数据源,如 Prometheus、Graphite、InfluxDB、Elasticsearch、MySQL、Kubernetes、Zabbix 等。
Grafana 的一个最大特点就是,界面非常酷炫!非常接近于一些企业级可视化大屏的效果。图 17-27 就是用 Grafana 做的可视化监控面板。
Grafana 对 Prometheus 有非常好的支持。在 Grafana 中,可以添加 Prometheus 的数据源,同时支持调试、查询和可视化展示。
准备工作
在开始学习接下来的内容之前,请确保你已经完成了上一节的内容,能将 Scrapy 爬虫项目在 Kubernetes 上运行起来。
另外,我们还需要安装另一个 Kubernetes 套件 Helm,利用它我们可以快速部署一些 Kubernetes 服务,安装流程可以参考: https://setup.scrape.center/helm 。
做好如上准备工作之后,我们就可以开始实现 Scrapy 与 Prometheus+Grafana 监控系统的对接了。
要想完成这个工作,有三步需要做:第一步便是生成Scrapy的Exporter,用于收集统计数据;第二步便是将Grafana与Prometheus对接起来,构建可视化面板;第三步便是配置告警。
图17-27 用Grafana做的可视化监控面板
Scrapy Exporter
接下来,我们首先来看看怎么将Scrapy的数据对接到Prometheus,这就需要生成一个Scrapy的 Data Exporter。
我们首先来看看Exporter大约是什么样子的,如图17-28所示。
可以看到,这就是一个HTTP网页,网页内容遵循一定格式,这个格式可以被Prometheus自动解析并存储下来。我们需要做的就是为Scrapy生成这样一个网页,然后将这个网页的地址告诉 Prometheus,Prometheus便会每隔一段时间来抓取这个页面,从而获取到Scrapy的各个指标数据了。
图 17-28 Exporter
那么,Scrapy 怎么生成这个页面呢?它不是用来爬取数据的吗?生成 HTTP 页面不又需要一个 HTTP 服务器吗?这又是怎么实现的呢?其实,Scrapy 的功能十分强大。Scrapy 确实主要用来爬取数据,但这并不妨碍同时提供一个 HTTP 服务,而且 HTTP 服务可以和 Scrapy 本身关联起来,比如读取到 Scrapy 的各项统计指标,然后将数据展示在网页之中,这是完全可以做到的。
怎么实现的呢?其实还是借助子 Scrapy 的 Extension。关于 Extension 的更多知识,请参考前文内容。另外,我们还需要借助一个开源工具,叫作 prometheus\_client,利用它可以我们通过传入一些参数构造不同的指标数据,生成 Exporter 格式的内容。
关于 Exporter 的实现原理,这里就不展开讲解了,我们可以直接借助一个开源库 GerapyPrometheus-Exporter 来实现。
安装方式很简单: pip3 install gerapy-prometheus-exporter
安装完成之后,需要在 settings.py 里面配置并启用:
EXTENSIONS = {
'gerapy_prometheus_exporter.extension.WebService': 500,
}
配置完成之后,我们可以在本地启动一下 Scrapy 爬虫,这时候我们就可以在本地 http://localhost:9410/metrics 看到类似图 17-28 的结果,比如其中有一些指标如下:
# TYPE scrapy_items_scraped gauge
scrapy_items_scraped{spider="scrapycompositedemo"} 174.0
# HELP scrapy_items_dropped Spider items dropped
# TYPE scrapy_items_dropped gauge
scrapy_items_dropped{spider="scrapycompositedemo"} 0.0
# HELP scrapy_response_received Spider responses received
# TYPE scrapy_response_received gauge
# HELP scrapy_opened Spider opened
# TYPE scrapy_opened gauge
scrapy_opened{spider="scrapycompositedemo"} 1.0
# HELP scrapy_closed Spider closed
# TYPE scrapy_closed gauge
# HELP scrapy_downloader_request_bytes ...
# TYPE scrapy_downloader_request_bytes gauge
scrapy_downloader_request_bytes{spider="scrapycompositedemo"} 616407.0
scrapy_items_scraped 就是一项 Prometheus 指标名称,其中有一个 spider 属性叫作 scrapycompositedemo,其值是 174。这代表已经爬取了 174 条数据。另外还有其他的指标,比如 scrapy_downloader_request_bytes 就代表 downloader 请求的字节数,值为 616407.0。
随着 Scrapy 的运行,爬虫的各项指标肯定会变化的,我们可以隔一段时间刷新下刚才的页面:
# TYPE scrapy_items_scraped gauge
scrapy_items_scraped{spider="scrapycompositedemo"} 509.0
# HELP scrapy_items_dropped Spider items dropped
# TYPE scrapy_items_dropped gauge
scrapy_items_dropped{spider="scrapycompositedemo"} 0.0
# HELP scrapy_response_received Spider responses received
# TYPE scrapy_response_received gauge
# HELP scrapy_opened Spider opened
# TYPE scrapy_opened gauge
scrapy_opened{spider="scrapycompositedemo"} 1.0
# HELP scrapy_closed Spider closed
# TYPE scrapy_closed gauge
# HELP scrapy_downloader_request_bytes ...
# TYPE scrapy_downloader_request_bytes gauge
scrapy_downloader_request_bytes{spider="scrapycompositedemo"} 930501.0
就是这样一个网页,在原来的基础上,Scrapy 爬虫提供了 HTTP 服务,并在 9410 端口上运行了此服务。
接下来,我们就重新把这个 Scrapy 项目部署到 Kubernetes 上,并通过 Service 将 9410 端口暴露出来。首先,需要重新构建 Docker 镜像并更新。当然,也可以使用我已经构建好的镜像 germey/scrapycompositedemo。
修改 kubernetes/scrapycompositedemo/deployment.yaml 文件,添加 containerPort 的配置,最终修改结果如下:
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: scrapycompositedemo
name: scrapycompositedemo
namespace: crawler
spec:
replicas: 1
selector:
matchlabels:
app: scrapycompositedemo
template:
metadata:
labels:
app: scrapycompositedemo
spec:
containers:
- env:
- name: ACCOUNTPOOL_URL
value: 'http://accountpool.crawler.svc.cluster.local:6777/antispider?/random'
- name: PROXYPOOL_URL
value: 'http://proxypool.crawler.svc.cluster.local:5555/random'
- name: REDIS_URL
value: 'redis://redis.crawler.svc.cluster.local:6379'
image: germey/scrapycompositedemo
name: scrapycompositedemo
resources:
limits:
memory: "500Mi"
cpu: "300m"
requests:
memory: "200Mi"
cpu: "100m"
ports:
- containerPort: 9410
这里就将 9410 端口暴露出来了,其他配置保持不变。注意,此处如果使用你自己的镜像的话,需要把 image 参数换一下。
同时新建一个 kubernetes/scrapycompositedemo/service.yaml 文件,内容如下:
apiVersion: v1
kind: Service
metadata:
labels:
app: scrapycompositedemo
name: scrapycompositedemo
namespace: crawler
spec:
ports:
- name: "9410"
port: 9410
targetPort: 9410
selector:
app: scrapycompositedemo
重新运行部署:
kubectl apply -f kubernetes/scrapycompositedemo
结果如下:
deployment.apps/scrapycompositedemo configured
service/scrapycompositedemo created
这样就成功了。
然后我们可以看下 Web 服务有没有运行成功:
kubectl port-forward svc/scrapycompositedemo 9410:9410 -n crawler
这时候重新打开 http://localhost:9410/metrics,如果能看到如图 17-28 所示的页面,就说明已经部署成功了,而且通过 9410 端口就能获取到 Scrapy 分布式爬虫的运行状态统计。
Prometheus 对接
接下来,我们需要做的就是将上文实现的 Exporter 和 Prometheus 进行对接,也就是将 HTTP 页面配置到 Prometheus 里面,这样 Prometheus 就会定时抓取这些指标并存储下来了。
由于 Scrapy 爬虫项目是部署在 Kubernetes 上的,对于 Prometheus 来说,当然同样要部署到 Kubernetes 里面才能访问了。
安装 Prometheus 时,我推荐使用 Helm 来安装,安装方法可以参考 https://github.com/prometheus-community/helm-charts/tree/main/charts/kube-prometheus-stack 。kube-prometheus-stack 是一个 Prometheus 和 Grafana 的套件,安装此套件可以同时安装好 Prometheus 和 Grafana,非常方便。
个人推荐将 Prometheus 单独安装到一个新的 Namespace 下面,比如新建一个 Namespace,叫作 monitor:
kubectl create namespace monitor
然后利用 Helm 来安装对应的 Repo 信息:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
这一步相当于把一些配置文件添加到 Helm 中,这样 Helm 才能对其进行安装。
接下来,我们可以运行如下命令安装:
helm install prometheus-stack prometheus-community/kube-prometheus-stack -n monitor
运行成功后,可能会得到如下信息:
NAME: prometheus-stack
LAST DEPLOYED: Sun Mar 28 22:27:37 2021
NAMESPACE: monitor
STATUS: deployed
REVISION: 1
NOTES:
kube-prometheus-stack has been installed. Check its status by running:
kubectl --namespace monitor get pods -l "release=prometheus-stack"
...
如果看到如上结果,就证明已经安装成功了。
接下来,我们重新进入 Dashboard,查看 Prometheus 套件的运行情况。运行 Dashboard 的流程见 17.8 节。
进入 Dashboard 之后,切换到 Monitor 命名空间,你可能看到如图 17-29 所示的运行结果,一些状态还是红色或者黄色,不用担心,目前还处在初始化的过程中,耐心等待一段时间,等待全部配置完成之后,就好了。
图17-29 运行结果
另外,每个 Chart 预留了一些配置项,这些配置项在 values.yaml 里面是可以复写、修改的,具体的配置可以查看 https://github.com/prometheus-community/helm-charts/blob/main/charts/kube-prometheus-stack/values.yaml 文件。比如,通过修改 Prometheus 的配置项,就能达到修改 scrape\_configs 的目的,这项配置叫作 prometheusOperator.prometheusSpec.additionalScrapeConfigs。
注意 此配置项的名称可能会随着当前 Helm Chart 的修改而不同,主要是明白其原理,具体的配置需要以官方文档为准。
这时候我们可以将此项配置进行修改:
prometheusOperator:
# 此处省略其他配置项
prometheusSpec:
# 此处省略其他配置项
additionalScrapeConfigs:
- job_name: scrapycompositedemo
static_configs:
- labels:
app: scrapycompositedemo
targets:
- scrapycompositedemo.crawler.svc.cluster.local:9410
这里我们添加了刚才的 Scrapy 爬虫的配置,指定了 labels 和 targets,具体的配置格式可以参考 https://prometheus.io/docs/prometheus/latest/configuration/configuration/\#scrape\_config]。
其中值得注意的是,我们将 targets 配置为 scrapycompositedemo.crawler.svc.cluster.local:9410,可以通过此 Host 在 Kubernetes 中访问到对应的服务。
配置完成之后,可以通过如下命令应用此更新:
helm upgrade -f values.yaml prometheus-stack prometheus-community/kube-prometheus-stack -n monitor
如果出现类似下面的输出结果:
Release "prometheus-stack" has been upgraded. Happy Helming!
NAME: prometheus-stack
LAST DEPLOYED: Sun Mar 28 23:22:44 2021
NAMESPACE: monitor
STATUS: deployed
REVISION: 2
NOTES:
kube-prometheus-stack has been installed. Check its status by running:
kubectl --namespace monitor get pods -l "release=prometheus-stack"
...
就证明更新生效了。
Grafana 配置
接下来,我们再回到 Grafana 的配置中,我们可以依然在本地通过 kubectl port-forward 将服务转发到本地:
kubectl port-forward svc/prometheus-stack-grafana 3000:80 -n monitor
|
这里服务的名称可能随着 Helm Chart 的修改而不同,主要是明白其原理,具体的配置需要以官方文档为准。 |
这里我们将 Grafana 从 80 转发到本地 3000 端口,这时候我们在本地浏览器上打开 http://localhost:3000/ ,就能看到如图 17-30 所示的结果。
图17-30 欢迎界面
进入了Grafana的欢迎界面,但是并不知道用户名和密码是什么,这时候密码会存在对应的Secrets 文件中。在此HelmChart中,它存在一个叫作prometheus-stack-grafana的Secret中,通过Dashboard我们可以清楚地看到用户名和密码,如图17-31所示。
图17-31 用户名和密码
可以看到,初始用户名就是admin,密码就是prom-operator。在Grafana欢迎界面中输入用户名和密码,我们便可以进入控制面板了,如图17-32所示。
图17-32 Grafana 控制面板
接下来,我们切换到 Explore 页面,可以看到已经配置好的 Prometheus 数据源,如图 17-33 所示。
图17-33 Explore页面
如果上文所述的 scrapeconfig 配置成功的话,此时在这里我们可以搜索到scrapy相关的指标,如图17-34所示。
图17-34 搜索scrapy相关的指标
比如此时我们输入scrapy_items_scraped,即抓取数据的条数,然后将时间范围设置为5min,点击右上角的RunQuery按钮,可以得到如图17-35所示的图表。
图17-35 搜索结果
这里我们就可以观察在过去五分钟内抓取到的数据量的变化情况了。当然,上面的页面仅仅是调试用的,我们可以试着创建一个Dashboard。
点击+号并选择创建Dashboard,创建一个Dashboard,如图17-36所示。
然后点击Addnewpanel按钮,创建一个新面板,如图17-37所示。
图17-36 创建一个Dashboard
图17-37 包创建新面板
这里我们可以按照如下情况配置,如图17-38所示。
-
Metrics:可以任意选择,比如这里依然选择scrapy_items_scraped,代表已经爬取到的数据条数。
-
Legend:图例名称,这里我们可以直接使用app来获取其中的属性。因为该条统计信息的app的属性就是scrapycompositedemo,所以这里图例的名称就叫作scrapycompositedemo。口Format:保持默认值Timesseries即可,即按照时间序列显示。
-
右侧的一些样式配置可以自行选择,比如配置面板标题、选择连线样式、是否显示数据点、预警值等。
图17-38 配置面板
配置完成之后,点击右上角的Apply按钮,保存该配置面板。另外,还可以继续增加其他面板。配置好了之后,将整个仪表盘保存下来。
比如,最后可以配置成类似图17-39所示的页面,这样我们就可以一目了然地看到爬虫的爬取状态了。
图17-39 仪表盘
另外,我们还可以设置告警,它既可以在Grafana里面使用内置的Alert设置,也可以使用Alert Manager设置。前者配置更加简单、方便,后者功能更为灵活、强大,可以根据个人偏好进行选择。
具体设置方式可以参考如下内容。
-
Grafana Alert 配置: https://grafana.com/docs/grafana/latest/alerting/create-alerts/ 。
-
Prometheus Stack Alert 配置: https://github.com/prometheus-operator/prometheus-operator 。