利用Prometheus 打造企業分佈式監控平臺(2)--服務發現

prome02.png

服務發如今Wikipedia的描述是:
Service discovery is the automatic detection of devices and services offered by these devices on a computer network.git

換句話說,它容許應用程序動態發現服務,而不是在應用程序配置中靜態定義服務。github

對於Prometheus,可使用多種方法進行服務發現,包括雲提供商API(例如AWS,Azure,GCE,Openstack),基於DNS的發現(使用SRV記錄)以及查詢Kubernetes API中正在運行的服務。web

可想而知,在目前雲原生環境下,應用具有高度彈性,經過靜態配置監控目標的行爲是多麼的低效。json

Hotreload

固然Prometheus 提供了Hotreload機制,在配置文件變動的時候,能夠通知Prometheus進行reload。並且在reload的過程當中,服務不會停機後端

熱更新的加載方法有兩種:服務器

固然新版本的Prometheus 的熱加載功能默認是關閉的,你須要在Prometheus的啓動參數中,添加以下參數:架構

--web.enable-lifecycleapp

可是這種方式,並非最優雅的,你須要維護整個配置文件。負載均衡

服務發現

除靜態配置以外,Prometheus 已經支持了以下的服務發現方式:curl

# List of Azure service discovery configurations.
azure_sd_configs:
  [ - <azure_sd_config> ... ]

# List of Consul service discovery configurations.
consul_sd_configs:
  [ - <consul_sd_config> ... ]

# List of DNS service discovery configurations.
dns_sd_configs:
  [ - <dns_sd_config> ... ]

# List of EC2 service discovery configurations.
ec2_sd_configs:
  [ - <ec2_sd_config> ... ]

# List of OpenStack service discovery configurations.
openstack_sd_configs:
  [ - <openstack_sd_config> ... ]

# List of file service discovery configurations.
file_sd_configs:
  [ - <file_sd_config> ... ]

# List of GCE service discovery configurations.
gce_sd_configs:
  [ - <gce_sd_config> ... ]

# List of Kubernetes service discovery configurations.
kubernetes_sd_configs:
  [ - <kubernetes_sd_config> ... ]

# List of Marathon service discovery configurations.
marathon_sd_configs:
  [ - <marathon_sd_config> ... ]

# List of AirBnB's Nerve service discovery configurations.
nerve_sd_configs:
  [ - <nerve_sd_config> ... ]

# List of Zookeeper Serverset service discovery configurations.
serverset_sd_configs:
  [ - <serverset_sd_config> ... ]

# List of Triton service discovery configurations.
triton_sd_configs:
  [ - <triton_sd_config> ... ]

下圖是一個Prometheus + consul sd 的架構。對於線上環境咱們可能會劃分爲:dev, stage, prod不一樣的集羣。每個集羣運行多個主機節點,每一個服務器節點上運行一個Node Exporter實例。Node Exporter實例會自動註冊到Consul中,而Prometheus則根據Consul返回的Node Exporter實例信息動態的維護Target列表,從而向這些Target輪詢監控數據。

bolg_sd_mutil_cluster.png

固然目前官方對於增長新的服務發現方式比較慎重,與Alertmanager 通知類型狀況相似,官方不但願新的不穩定服務發現方式會影響Prometheus自身的穩定性。

可以與其餘SD機制(例如Docker Swarm)集成是源源不斷的需求。爲了解決這個問題,最近,Prometheus存儲庫中的文檔目錄進行了一些小的代碼更改,並提供了一個示例,以實現自定義服務發現集成,而無需將其合併到Prometheus主分支中。

例如,我在實際落地Prometheus的工程中,增長了下面兩種服務發現方式:

  • 基於負載均衡器服務自動發現:根據負載均衡器的地址,獲取後端服務器組。在Cloud上,後端服務器組大多要配置HPA,決定了須要動態的發現。
  • 基於自動伸縮組的服務自動發現:有些任務型工做負載,根據工做負載來擴縮worker節點數,好比根據消息隊列的消息堆積數,來擴縮消費者的數量。此時根據自動伸縮組,獲取實際運行的Worker節點。

如何實現自定義服務發現?

官方推薦的方式:按照官方的接口約定,實現新的服務發現方式,將發現的目標和標籤寫到文件中,而後結合prometheus自己支持的file_sd方式。Prometheus會按期到指定文件中獲取最新的目標。

以下所示:

scrape_configs:
  - job_name: "custom-sd"
    scrape_interval: "15s"
    file_sd_configs:
    - files:
      - /path/to/custom_sd.json

Adapter

首先了解一下adapter.go文件,您能夠複製此文件以實現自定義SD實現。

// Adapter runs an unknown service discovery implementation and converts its target groups
// to JSON and writes to a file for file_sd.
type Adapter struct {
    ctx     context.Context
    disc    discovery.Discoverer
    groups  map[string]*customSD
    manager *discovery.Manager
    output  string
    name    string
    logger  log.Logger
}

// Run starts a Discovery Manager and the custom service discovery implementation.
func (a *Adapter) Run() {
    go a.manager.Run()
    a.manager.StartCustomProvider(a.ctx, a.name, a.disc)
    go a.runCustomSD(a.ctx)
}

Adapter利用Discovery.Manager在goroutine中啓動自定義SD提供程序的Run函數。Manager有一個通道,自定義SD將向其發送更新。這些更新包含SD目標。groups字段包含全部目標和標籤。

type customSD struct {
    Targets []string          `json:"targets"`
    Labels  map[string]string `json:"labels"`
}

存在這個customSD結構主要是爲了幫助咱們將內部Prometheus targetgroup.Group結構轉換爲JSON以用於file_sd格式。

運行時,Adapter將在通道上監聽來自咱們的自定義SD實現的更新,接收到更新後,它將解析targetgroup.Groups到另外一個映射[string]* customSD中,並將其存儲在Adapter,若是二者不一樣,咱們將新組分配給Adapter結構,並將它們做爲JSON寫入輸出文件中。

自定義SD實現

如今咱們要實際使用Adapter來實現咱們本身的自定義SD。完整的工做示例位於此處的examples目錄中。

在這裏,您能夠看到咱們導入Adapter代碼「 github.com/prometheus/prometheus/documentation/examples/custom-sd/adapter」以及其餘一些Prometheus庫。爲了編寫自定義SD,咱們須要一個實現Discoverer接口:

// Discoverer provides information about target groups. It maintains a set
// of sources from which TargetGroups can originate. Whenever a discovery provider
// detects a potential change, it sends the TargetGroup through its channel.
//
// Discoverer does not know if an actual change happened.
// It does guarantee that it sends the new TargetGroup whenever a change happens.
//
// Discoverers should initially send a full set of all discoverable TargetGroups.
type Discoverer interface {
    // Run hands a channel to the discovery provider(consul,dns etc) through which it can send
    // updated target groups.
    // Must returns if the context gets canceled. It should not close the update
    // channel on returning.
    Run(ctx context.Context, up chan<- []*targetgroup.Group)
}

咱們實際上只須要實現一個函數 Run(ctx context.Context,up chan <-[] * targetgroup.Group)。這是Adapter代碼中的管理器將在goroutine中調用的函數。Run函數包含了知道什麼時候退出的上下文,並傳遞了用於發送目標組更新的通道。

查看提供的示例中的Run函數,咱們能夠看到在另外一個SD的實現中須要作的一些關鍵事情。

總結

若是實際場景中,公司已經有統一的服務註冊中心或是配置中心,那麼徹底能夠自定義SD,這樣的好處是,利用了現有的基礎設施,實現無縫對接。

另一點是,Prometheus 中kubernetes SD的方式,對於容器化部署的業務,更加簡單。

相關文章
相關標籤/搜索