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以瞭解更多信息。感謝閱讀,若有建議和意見,請寫在評論中。

這裏能夠找到全部代碼和配置文件。

相關文章
相關標籤/搜索