Envoy service mesh、Prometheus和Grafana下的微服务监控(翻译)

原文连接:medium.com/@dnivra26/m…python

若是你刚接触“Service Mesh“和“Envoy”,我这里有一篇文章能够帮你入门。nginx

这是Envoy service mesh下的可观测性系列的第二篇文章,你能够在这里阅读第一篇关于分布式追踪的文章。git

在微服务中谈及监控时,你可不能被蒙在鼓里,至少要知道问题出在哪儿了。github

让咱们看看Envoy是怎样帮助咱们了解咱们的服务运行情况的。在service mesh下,全部的通讯都会经过mesh,这意味着没有任何服务会与其它服务直接通讯,服务向Envoy发起调用请求,而后Envoy将调用请求路由到目标服务,因此Envoy将持有传入和传出流量的上下文。Envoy一般提供关于传入请求、传出请求和Envoy实例状态的指标。redis

准备

这是咱们将要构建的系统概览。docker

overall setup

Statsd

Envoy支持经过两到三种格式来暴露指标,但本文中咱们将使用statsd格式。shell

因此流程将是这样,首先Envoy推送指标到statsd,而后咱们用prometheus(一个时序数据库)从statsd拉取指标,最后经过grafana可视化这些指标。数据库

在准备概览图中,我提到了statsd exporter而不是statsd,这是由于咱们并不会直接使用statsd,而是使用一个接收statsd格式数据,并将其以prometheus格式输出的转换器(服务)。下面让咱们来搞定它吧。json

Envoy的指标主要分为两类:后端

  1. Counter(计数器):一个只增不减的指标。如:请求总数
  2. Gauge(量表):一个可增可减的指标,相似于一个瞬时值。如:当前CPU使用量

让咱们看一个包含stats sink的Envoy配置

---
admin:
 access_log_path: "/tmp/admin_access.log"
 address: 
 socket_address: 
 address: "127.0.0.1"
 port_value: 9901
stats_sinks:
 -
 name: "envoy.statsd"
 config:
 tcp_cluster_name: "statsd-exporter"
 prefix: front-envoy    
static_resources: 
 listeners:
 - 
 name: "http_listener"
 address: 
 socket_address: 
 address: "0.0.0.0"
 port_value: 80
 filter_chains:
 filters: 
 - 
 name: "envoy.http_connection_manager"
 config:
 use_remote_address: true
 add_user_agent: true
 access_log:
 - name: envoy.file_access_log
 config:
 path: /dev/stdout
 format: "[ACCESS_LOG][%START_TIME%] \"%REQ(:METHOD)% %REQ(X-ENVOY-ORIGINAL-PATH?:PATH)% %PROTOCOL%\" %RESPONSE_CODE% %RESPONSE_FLAGS% %BYTES_RECEIVED% %BYTES_SENT% %DURATION% %RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)% \"%REQ(X-FORWARDED-FOR)%\" \"%REQ(USER-AGENT)%\" \"%REQ(X-REQUEST-ID)%\" \"%REQ(:AUTHORITY)%\" \"%UPSTREAM_HOST%\" \"%DOWNSTREAM_REMOTE_ADDRESS_WITHOUT_PORT%\"\n"
 stat_prefix: "ingress_443"
 codec_type: "AUTO"
 generate_request_id: true
 route_config: 
 name: "local_route"
 virtual_hosts: 
 - 
 name: "http-route"
 domains: 
 - "*"
 routes: 
 - 
 match: 
 prefix: "/"
 route:
 cluster: "service_a"
 http_filters:
 - 
 name: "envoy.router"
 clusters:
 -
 name: "statsd"
 connect_timeout: "0.25s"
 type: "strict_dns"
 lb_policy: "ROUND_ROBIN"
 hosts:
 -
 socket_address:
 address: "statsd_exporter"
 port_value: 9125
 - 
 name: "service_a"
 connect_timeout: "0.25s"
 type: "strict_dns"
 lb_policy: "ROUND_ROBIN"
 hosts:
 - 
 socket_address: 
 address: "service_a_envoy"
 port_value: 8786
复制代码

第8-13行告诉Envoy咱们须要statsd格式的指标、咱们的统计信息前缀(一般是你的服务名)是什么和statsd sink的地址。

第55-63行配置了咱们的环境中的statsd sink。

这就是让Envoy输出统计信息所须要的全部配置。如今让咱们来看看第2-7行作了哪些事情:

  1. Envoy在9901端口暴露了一个管理端,你能够经过它动态地改变日志级别,查看当前配置、统计数据等
  2. Envoy也能够生成与nginx相似的访问日志,你能够经过它了解服务间的通讯情况。访问日志的格式也是可配置的,如第29-33行

你须要将相同的配置添加到系统中的其它Envoy sidecar上(是的,每一个服务都有本身的Envoy sidecar)。

这些服务自己是用go写的,它们作的事情很简单,仅仅是经过Envoy调用其它服务。你能够在这里查看服务和Envoy的配置。

如今,虽然咱们只有图中的statsd exporter,但有了它,若是咱们运行docker容器(docker-compose build & docker-compose up),而后向Front Envoy(localhost:8080)发送一些流量,Envoy 将把这些流量的指标发送到statsd exporter,随后statsd exporter会把这些指标转换成prometheus格式,并将其暴露在9102端口。

Statsd exporter中的统计信息格式以下图所示

来自statsd exporter的prometheus格式的指标

这里边将有上百个指标,同时,在上面的截图中咱们能看到Service A和Service B之间的通讯延迟指标。上图的指标是遵循prometheus格式的

metric_name ["{" label_name "=" `"` label_value `"` { "," label_name "=" `"` label_value `"` } [ "," ] "}"] value [ timestamp ]
复制代码

你能够在这里了解更多。

Prometheus

咱们将使用Prometheus做为时序数据库来保存咱们的指标。Prometheus不只是一个时序数据库,它自己仍是一个监控系统,但本文咱们只用它来存储指标数据。须要注意的是,prometheus是一个经过主动拉取来获取指标的系统,这意味着你必须告诉prometheus从何处拉取指标,在咱们的例子中是从statsd exporter处拉取。

将Prometheus添加到系统中很是简单而又直接,咱们只须要将拉取目标(statsd exporter)做为配置文件传递给Prometheus就能够了。配置看起来是这样的

global:
 scrape_interval:  15s
scrape_configs:
 - job_name: 'statsd'
 scrape_interval: 5s
 static_configs:
 - targets: ['statsd_exporter:9102']
 labels:
 group: 'services'
复制代码

scrape_interval的值表示Prometheus从目标处拉取配置的频率。

如今启动Prometheus,里面应该有一些数据了。让咱们打开localhost:9090来看一看

prometheus查询页面

如图所示,能够看到咱们的指标。你能作的可不单单是选择已有的指标,从这里能够阅读关于prometheus查询语言的更多信息。它还能够基于查询结果绘制图表,除此以外还有一个报警系统。

若是咱们打开prometheus的targets页面,将能看到全部的拉取目标和它们的健康状态

prometheus目标

Grafana

Grafana是一个很棒的监控可视化解决方案,它支持Prometheus,Graphite,InfluxDB,ElasticSearch等多种后端。

Grafana有两大主要组件须要咱们配置

  1. 数据源(Datasource):指定grafana从哪一个后端获取指标。你能够经过配置文件来配置数据源,代码以下所示

    apiVersion: 1
    
    datasources:
     - name: prometheus
     type: prometheus
     access: Server
     url: http://prometheus:9090
     editable: true
     isDefault:
    复制代码
  2. 仪表盘(Dashboard):你能够从仪表盘查看来自数据源的指标。Grafana支持多种可视化元素,如Graphs,Single Stats,Heatmaps……你能够继承这些元素并使用插件来构造本身的元素。

我在使用Grafana时遇到的惟一一个问题是,缺乏一种标准的方法来用代码开发那些仪表盘。所幸有一些第三方的库提供了支持,咱们将使用来自weaveworks的grafanalib

下面是咱们经过 python 代码尝试构建的一个仪表盘

from grafanalib.core import *
import os
dashboard = Dashboard(
    title="Services Dashboard",
    templating=Templating(
        [
            Template(
                name="source",
                dataSource="prometheus",
                query="metrics(.*_cluster_.*_upstream_rq_2xx)",
                regex="/(.*)_cluster_.*_upstream_rq_2xx/",
                default="service_a"
            ),
            Template(
                name="destination",
                dataSource="prometheus",
                query="metrics(.*_cluster_.*_upstream_rq_2xx)",
                regex="/.*_cluster_(.*)_upstream_rq_2xx/",
                default="service_b"
            )
        ]
    ),
    rows=[
        Row(
            panels=[
                Graph(
                    title="2XX",
                    transparent=True,
                    dataSource="prometheus",
                    targets=[
                        Target(
                            expr="[[source]]_cluster_[[destination]]_upstream_rq_2xx - [[source]]_cluster_[[destination]]_upstream_rq_2xx offset $__interval",
                            legendFormat="2xx"
                        )
                    ]
                ),
                Graph(
                    title="5XX",
                    transparent=True,
                    dataSource="prometheus",
                    targets=[
                        Target(
                            expr="[[source]]_cluster_[[destination]]_upstream_rq_5xx - [[source]]_cluster_[[destination]]_upstream_rq_5xx offset $__interval",
                            legendFormat="5xx"
                        ),
                    ]
                ),
                Graph(
                    title="Latency",
                    transparent=True,
                    dataSource="prometheus",
                    targets=[
                        Target(
                            expr="[[source]]_cluster_[[destination]]_upstream_rq_time",
                            legendFormat="{{quantile}}"
                        )
                    ]
                )
            ]
        ),
    ]
).auto_panel_ids()
复制代码

在这段代码中,咱们为2xx,5xx和延迟数据构建了图表。其中第5-22行很重要,它从咱们的设置中提取可用的service names做为grafana的变量,为咱们建立一个动态的仪表盘,这意味着咱们可以选择性地查看特定源服务和目标服务的统计数据。若是想了解更多关于变量的内容请参考这里

你须要经过grafanalib命令来从上述python文件生成仪表盘

generate-dashboard -o dashboard.json service-dashboard.py
复制代码

注意这里生成的dashboard.json可不容易阅读。

因此,启动Grafana时咱们只须要传递仪表盘和数据源就行了。当访问http:localhost:3000时,你将看到:

grafana仪表盘

如今你应该能看到2xx,5xx和延迟的图表,同时还能看到一个下拉菜单,你能够经过它选择源服务和目标服务。关于Grafana还有许多内容咱们没有讨论到,包括强大的查询编辑器和告警系统。更重要的是,这一切都是能够经过插件和应用扩展的,能够参考这里的例子。若是你正想可视化常见服务如redis,rabbitmq等的指标,grafana有一个公共仪表盘库,你只须要导入它们就能够使用了。使用Grafana 还有一个好处,你能够经过配置文件和代码建立和管理全部东西,而不须要过多地经过UI来操做。

我建议你试用一下prometheus和grafana以了解更多信息。感谢阅读,若有建议和意见,请写在评论中。

这里能够找到全部代码和配置文件。

相关文章
相关标签/搜索