Prometheus 提供了 官方版 Golang 库 用于采集并暴露监控数据,本文为您介绍如何使用官方版 Golang 库来暴露 Golang runtime 相关的数据,以及其它一些基本简单的示例,并使用 Prometheus监控服务来采集指标展示数据等。

说明:

Golang Client API 相关的文档详见 GoDoc

安装

通过 go get 命令来安装相关依赖,示例如下:

go get github.com/prometheus/client_golang/prometheus
go get github.com/prometheus/client_golang/prometheus/promauto
go get github.com/prometheus/client_golang/prometheus/promhttp

开始(运行时指标)

  1. 准备一个 HTTP 服务,路径通常使用 /metrics。可以直接使用 prometheus/promhttp 里提供的 Handler 函数。如下是一个简单的示例应用,通过 http://localhost:2112/metrics 暴露 Golang 应用的一些默认指标数据(包括运行时指标、进程相关指标以及构建相关的指标):

    package main
    
    import (
            "net/http"
    
            "github.com/prometheus/client_golang/prometheus/promhttp"
    )
    
    func main() {
            http.Handle("/metrics", promhttp.Handler())
            http.ListenAndServe(":2112", nil)
    }
    
  2. 执行以下命令启动应用:

    go run main.go
    
  3. 执行以下命令,访问基础内置指标数据:

    curl <http://localhost:2112/metrics>
    

应用层面指标

  1. 上述示例仅仅暴露了一些基础的内置指标。应用层面的指标还需要额外添加(后续我们将提供一些 SDK 方便接入)。如下示例暴露了一个名为 myapp_processed_ops_total 的 计数类型 指标,用于对目前已经完成的操作进行计数。如下每两秒操作一次,同时计数器加1:

    package main
    
    import (
            "net/http"
            "time"
    
            "github.com/prometheus/client_golang/prometheus"
            "github.com/prometheus/client_golang/prometheus/promauto"
            "github.com/prometheus/client_golang/prometheus/promhttp"
    )
    
    func recordMetrics() {
            go func() {
                    for {
                            opsProcessed.Inc()
                            time.Sleep(2 * time.Second)
                    }
            }()
    }
    
    var (
            opsProcessed = promauto.NewCounter(prometheus.CounterOpts{
                    Name: "myapp_processed_ops_total",
                    Help: "The total number of processed events",
            })
    )
    
    func main() {
            recordMetrics()
    
            http.Handle("/metrics", promhttp.Handler())
            http.ListenAndServe(":2112", nil)
    }
    
  2. 执行以下命令启动应用:

    go run main.go
    
  3. 执行以下命令,访问暴露的指标:从输出结果我们可以看到 myapp_processed_ops_total 计数器相关的信息,包括帮助文档、类型信息、指标名和当前值,如下所示:

    curl <http://localhost:2112/metrics>
    
    # HELP myapp_processed_ops_total The total number of processed events
    # TYPE myapp_processed_ops_total counter
    myapp_processed_ops_total 666
    

使用 Prometheus 监控服务

上述我们提供了两个示例展示如何使用 Prometheus Golang 库来暴露应用的指标数据,但暴露的监控指标数据为文本类型,需要搭建维护额外的 Prometheus 服务来抓取指标,可能还需要额外的 Grafana 来对数据进行可视化展示。

打包部署应用

  1. Golang 应用一般可以使用如下形式的 Dockerfile(按需修改):

    FROM golang:alpine AS builder
    RUN apk add --no-cache ca-certificates \\
            make \\
            git
    COPY . /go-build
    RUN cd /go-build && \\
            export GO111MODULE=on && \\
            export GOPROXY=https://goproxy.io && \\
            go build -o 'golang-exe' path/to/main/
    
    FROM alpine
    RUN apk add --no-cache tzdata
    COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs
    COPY --from=builder /go-build/golang-exe /usr/bin/golang-exe
    ENV TZ Asia/Shanghai
    CMD ["golang-exe"]
    
  2. 镜像可以使用自有镜像仓库。

  3. 需要根据应用类型定义一个 Kubernetes 的资源,这里我们使用 Deployment,示例如下:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: golang-app-demo
      labels:
        app: golang-app-demo
    spec:
      replicas: 3
      selector:
        matchLabels:
          app: golang-app-demo
      template:
        metadata:
          labels:
            app: golang-app-demo
        spec:
          containers:
          - name: golang-exe-demo:v1
            image: nginx:1.14.2
            ports:
            - containerPort: 80
    
  4. 同时需要 Kubernetes Service 做服务发现和负载均衡。

    apiVersion: v1
    kind: Service
    metadata:
      name: golang-app-demo
    spec:
      selector:
        app: golang-app-demo
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    

    注意

    必须添加一个 Label 来标明目前的应用,Label 名不一定为 app,但是必须有类似含义的 Label 存在,其它名字的 Label 我们可以在后面添加数据采集任务的时候做 relabel 来达成目的。