说明
暂时不考虑写prometheus的搭建章(单机搭建太简单了。。。),后续可能会考虑写prometheus的集群、prometheus的外部存储等文章
这文章需要一定的GO基础,如果只是直接尝试使用,无所谓
这文章只是测试而已,真实使用还需要根据实际环境修改使用
Prometheus 服务发现机制概述
Prometheus数据源的配置主要分为静态配置和动态发现, 常用的为以下几类:
- static_configs: #静态服务发现
- file_sd_configs: #文件服务发现
- dns_sd_configs: #DNS 服务发现
- kubernetes_sd_configs: #Kubernetes 服务发现
- consul_sd_configs: #Consul 服务发现
- 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 上启动服务
}
总结
- 使用http_sd_configs有一定的风险,因为数据都是存在API方的
- 可以把思路转换一下,可以用file_sd_configs的方式,只需要将API改动一下,每次获取到机器信息,就进行写入指定文件,那么file_sd_configs检测到文件发生变化,就会重新加载文件
- http_sd_configs如果读取失败,会使用上一次完成获取到的API结果,所以需要对结果进行持久化存储不建议文件
博主的想法是,将节点API归于OPS平台的一个API,如果有多云的情况下,那么每个云中每个区域,单独放一个节点API,用于Prometheus的调用,以及Prometheus之node节点的上报,后续还会深度学习Prometheus,重点在于node,因为想把node二开成平台的node