prometheus-基于http_sd_configs的服务发现

说明

暂时不考虑写prometheus的搭建章(单机搭建太简单了。。。),后续可能会考虑写prometheus的集群、prometheus的外部存储等文章

这文章需要一定的GO基础,如果只是直接尝试使用,无所谓

这文章只是测试而已,真实使用还需要根据实际环境修改使用

Prometheus 服务发现机制概述

Prometheus数据源的配置主要分为静态配置和动态发现, 常用的为以下几类:

  1. static_configs: #静态服务发现
  2. file_sd_configs: #文件服务发现
  3. dns_sd_configs: #DNS 服务发现
  4. kubernetes_sd_configs: #Kubernetes 服务发现
  5. consul_sd_configs: #Consul 服务发现
  6. http_sd_configs: #自建API 服务发现

http_sd_configs实验

竟然是服务自动发现,那么就不能有手动写入的情况发生

官方相关文档:

1. https://prometheus.io/docs/prometheus/latest/configuration/configuration/#http_sd_config
 2. https://prometheus.io/docs/prometheus/latest/http_sd/#comparison-between-file-based-sd-and-http-sd

流程:

  1. Prometheus-server配置加上http_sd_configs配置
  2. node_exporter添加一个获取IP、主机名、机器唯一ID发给节点API的功能
  3. 节点API有二个接口
        1. 一个接收node_exporter启动发过来的数据
        2. 一个等待Prometheus来调用获取节点数据列表

数据格式

[
  {
    "targets": [ "<host>", ... ],
    "labels": {
      "<labelname>": "<labelvalue>", ...
    }
  },
  ...
]

流程1

在Prometheus-server添加http_sd_configs配置

scrape_configs
  - job_name: httpsd
    http_sd_configs:
      - url: "http://127.0.0.1:8080/authentication"

流程二

在node_exporter主代码文件中添加

// 以下是自定义功能
func init() {
    ip, err := GetIP(); if err != nil {
        return
    }
    authenticationhttp(ip)
}
// 发送http验证信息
func authenticationhttp(ip string) {
    // 获取主机名
    hostname, _ := os.Hostname()
    authenticationtextr := map[string]string{"ip": ip, "hostname":hostname}
    j, _ := json.Marshal(authenticationtextr)
    resp, err := http.Post("http://127.0.0.1:8080/authentication", "application/json", strings.NewReader(string(j))); if err != nil {
        return
    }
    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body); if err != nil {
        return
    }
    fmt.Println(string(body))

}
// 获取内网IP
func GetIP() (string, error) {
    addr, err := net.InterfaceAddrs()
    if err != nil {
        return "0", fmt.Errorf("获取IP失败")
    }
    for _, address := range addr {
        // 检查ip地址判断是否回环地址
        if ipnet, ok := address.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
            if ipnet.IP.To4() != nil {
                return ipnet.IP.String(), nil
            }
        }
    }
    return "0", fmt.Errorf("获取IP失败")
}
// 以上是自定义功能

流程三

API脚本

package main

import (
    "github.com/gin-gonic/gin"
    "fmt"
)

type authentication struct {
    Ip string `json:"ip"`
    Hostname string `json:"hostname"`
}

var data []interface{} // 因为测试没有用持久化存储,所以暂时使用脚本内部缓存存储

func main()  {
    r := gin.Default()
    r.POST("/authentication", func(c *gin.Context) {
        authenticationr := authentication{}
        c.BindJSON(&authenticationr)
        da := map[string]interface{}{
            "targets": [1]string{fmt.Sprintf("%v:9100", authenticationr.Ip)},
            "labels": map[string]string{
                "hostname": authenticationr.Hostname,
            },
        }
        data = append(data, da)
        fmt.Println(data)
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })

    r.GET("/authentication", func(c *gin.Context) {
        c.JSON(200, data)
    })
    r.Run() // 监听并在 0.0.0.0:8080 上启动服务
}

总结

  1. 使用http_sd_configs有一定的风险,因为数据都是存在API方的
  2. 可以把思路转换一下,可以用file_sd_configs的方式,只需要将API改动一下,每次获取到机器信息,就进行写入指定文件,那么file_sd_configs检测到文件发生变化,就会重新加载文件
  3. http_sd_configs如果读取失败,会使用上一次完成获取到的API结果,所以需要对结果进行持久化存储不建议文件

博主的想法是,将节点API归于OPS平台的一个API,如果有多云的情况下,那么每个云中每个区域,单独放一个节点API,用于Prometheus的调用,以及Prometheus之node节点的上报,后续还会深度学习Prometheus,重点在于node,因为想把node二开成平台的node


   转载规则


《prometheus-基于http_sd_configs的服务发现》 江松泉 采用 知识共享署名 4.0 国际许可协议 进行许可。
 上一篇
计算机组成原理-CPU集合篇(持续更新) 计算机组成原理-CPU集合篇(持续更新)
说明||| 代表个人想法 参考学习: ​ 1. 极客时间专栏-深入浅出计算机组成原理 性能指标之 计算机的计时单位 - CPU时钟虽然时间是一个很自然的用来衡量性能的指标,但是用时间来衡量时,有两个问题。 第一个就是时间不“准”。如果
下一篇 
gitlab的不中断业务升级 gitlab的不中断业务升级
背景今早一个需求就扔到我头上,差点爆炸 gitlab升级要求不停业务,就代表升级过程中,开发还是可以提交代码,拉取代码。。。。。。 虽然想吐槽一下,不过吃人家饭,需求要硬也得搞,方法总比问题多嘛 方案怎么实现业务不中断,突然想到了gitla
2021-10-14
  目录