grafana+prometheus实现云主机监控

配置 Prometheus

1
2
3
4
5
mkdir prometheus

cd prometheus

vim prometheus.yml
  1. 编写 prometheus 配置文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
global:
scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute.
evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute.

alerting:
alertmanagers:
- static_configs:
- targets:
scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']
- job_name: 'node'
static_configs:
- targets: ['<你的ip>:9100']
  1. 启动 prometheus
1
docker run -p 9090:9090 -d --rm --name prometheus -v /root/app/prometheus/:/etc/prometheus/ prom/prometheus
配置 Node Exporter 采集服务器数据
  1. 启动 node exporter
1
2
docker run -d --name node-exporter -p 9100:9100 -v "/root/app/prometheus/proc:/host/proc:ro" -v "/root/app/prometheus/sys:/host/sys:ro" -v "/root/app/prometheus:/rootfs:ro" prom/node-exporter

  1. 查看 node exporter

浏览器打开 http://<你的服务器 ip>:9100/metrics

  1. 查看数据源

浏览器打开 http://<服务器 ip>:9090

点击后就能看到你配置的数据源了

配置 Grafana

  1. 启动 grafana
1
docker run --rm --name grafana -p 30001:3000 -d grafana/grafana
  1. 配置数据源

打开 http://<服务器 ip>:3001

配置数据源

勾选 prometheus

然后再将刚刚的 prometheus 网址输入进去然后点击 Save & test 然后在导入一个别人已经布置好的 dashboard https://grafana.com/grafana/dashboards/8919 输入编号 8919

然后就大功告成啦!

注:grafana 首次登入的账号密码是 admin 进去后会修改密码

webhook搭建

webhook搭建

WebHook

网页开发中的网络钩子(Webhook)是一种通过自定义回调函数来增加或更改网页表现的方法。这些回调可被可能与原始网站或应用相关的第三方用户及开发者保存、修改与管理。术语“网络钩子”由杰夫·林德塞(Jeff Lindsay)于 2007 年通过给计算机编程术语“钩子”(Hook)加上前缀得来

为什么我需要搭建一个 webhook

那可要从搭建这个博客系统说起了,由于该博客使用 hexo 搭建,所以每次更新博客需要部署一下然后才能生效。而我又不愿意每次写完都去部署,这样就埋下了一个 webhook 的坑!其实 webhook 就是一个回调地址每次推送都访问下那个地址然后做部署

搭建 webhook

其实搭建这个有很多第三方的库已经支持了,但是偏偏我选择了 gitee(可恶啊!!!)

1. 设置 gitee 的签名


如果你是 java 或者 python 搭建 webhoook gitee 有事例代码
下面使用 go 语言实现

1
2
3
4
5
6
7
8
9
// Sign secret 为你在gitee设置的秘钥,time为请求头中的X-Gitee-Timestamp 也可以用当前收到请求的时间戳 但与请求调用时间误差不能超过1小时
func Sign(secret string, time string) string {
stringToSign := time + "\n" + secret
key := []byte(secret)
h := hmac.New(sha256.New, key)
h.Write([]byte(stringToSign))
signData := h.Sum(nil)
return base64.StdEncoding.EncodeToString(signData)
}

2. 搭建后端服务

使用 gin 搭建 webhook 的后端服务

1
2
3
4
5
func main() {
r := gin.Default()
router.RegisterRouter(r) // 就是你需要注册的路由
r.Run(":3000") // 监听并在 0.0.0.0:8080 上启动服务
}

router 中的代码以及目录结构

其实我就是简单的分了一下目录结构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
webhook
├─Dockerfile // 打包
├─Makefile // 部署
├─boot.sh // sh脚本
├─main.go // 程序入口
├─utils
| ├─response // 通用响应体
├─internal
| ├─router
| | ├─gitee.go // gitee 的路由
| | └router.go // 总路由
| ├─handler // 处理函数
| | ├─blog.go
| | └webhook.go
├─gitee
| ├─errors.go // 错误常量码
| ├─event.go //一些事件的常量
| ├─gitee.go //gitee包
| ├─push_event_payload.go //推送事件的请求数据结构体
| ├─sign //签名包

3. 编写处理函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
type GiteeService struct {
hook *gitee.Webhook
}

// New 创建一个新的服务
func NewGitee() *GiteeService {
hook, _ := gitee.New(gitee.WithSecret(GITEESECRET))
return &GiteeService{
hook: hook,
}
}

func (g *GiteeService) Blog(c *gin.Context) {
payload, err := g.hook.Parse(c.Request, gitee.PushEvents)
if err != nil {
if err == gitee.ErrEventNotFound {
// ok event wasn;t one of the ones asked to be parsed
fmt.Printf("ErrEventNotFound %s\n", err)
response.Err(c, err)
return
}
// ok event wasn;t one of the ones asked to be parsed
fmt.Printf("unkonw error %s\n", err)
response.Err(c, err)
return
}
switch payload.(type) {
case gitee.PushEventPayload:
//release := payload.(gitee.PushEventPayload)
go func() {
cmd := exec.Command("sh", "/root/app/blog/webhook.sh")
output, err := cmd.CombinedOutput()
if err != nil {
fmt.Println(string(output))
fmt.Printf("command error %s\n", err)
response.Err(c, err)
return
}
fmt.Println(string(output))
}()
response.Ok(c, nil)
}

}

上面就是一个简单的处理函数,但是值得说的一个点是 为什么需要使用携程去处理 由于打包部署的时间比较久但是 gitee 的 webhook 请求时长为 5s
所以我们这个请求得开一个携程去处理否则请求将请求超时

4. 部署 webhook

由于我需要执行其他需要自动部署的 app 的 shell 脚本,然而我有不想讲整个目录软连接进去所以我就直接二进制部署了就没有使用 docker, 可以看到 Dockerfile 都还在 呜呜呜

下面是我的部署 shell 脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#!/bin/bash
path=/root/app/webhooks

cd $path
git pull

port=3000
# 找到占用 3000 端口的进程 ID
pid=$(lsof -t -i:$port)

if [ -n "$pid" ]; then
# 杀死进程
echo "Killing process $pid"
kill -9 $pid
fi

outlog="$path/out.log"
if [ -e "$outlog" ]; then
rm "$outlog"
fi

rm -rf $path/main
go build -o $path/main .
nohup $path/main >> $outlog &

先将之前的服务停止,然后再将日志清除,最后再后台运行。

5. gitee 配置 webhook

这个就简单了就将你的后台路由填进去然后测试一把就行

总结
以上就是搭建 webhook 的整个流程咯,实际上就是写个后端服务,然后当你出发 git 某个操作就会请求这个 url 然后执行你需要执行的代码。

easegress

easegress

Easegress

官方架构
Easegress 是一个全功能型的流量调度和编排系统,通过 API 网关技术,可以在不改一行代码的情况下,最大限度的帮助后台服务扩大系统可用性和稳定性,并且可以增加整体的性能。其可以让企业在快速业务增长的同时不用对整个技术架构进行大改造,以赢得并抓住稍瞬即逝的商业机会。官方文档

在这里插入图片描述
官方文档上的介绍以及架构图。

1. 下载源码

1
git clone https://github.com/megaease/easegress.git

源码中有一个 server 端和一个命令行工具
easegress的服务端和命令行启动程序

我们首先得需要编译命令行工具形成一个可执行的二进制文件,之后再用这个可执行文件去对服务端进行操作。当然你如果不需要 debug 的话你也可以编译 server 端。接下来我们直接就编译成两个二进制文件

2. 编译

里面有个 Makefile 文件,我们只需在最外层目录下执行

1
make build

然后他就会给你下载依赖并且编译,会在文件中生成 bin 文件夹,里面会有两个二进制文件

1
2
easegress-server 	//服务端
egctl //命令行工具

二进制文件

3. 运行

1
./easegress-server	//运行服务端

启动
启动成功后我们就需要创建 httpserver 了,这个就是用来对于流量的控制。

4. 创建一个 HttpServer

以下一切操作都在在 bin 目录下。

1
2
3
4
5
6
7
8
9
10
11
12
13
echo '
kind: HTTPServer
name: server-demo
port: 10080
keepAlive: true
https: false
rules:
- paths:
- pathPrefix: /pipeline
backend: pipeline-demo
- pathRegexp: ^/user/(.*)$
rewriteTarget: /$1
backend: test-demo '| ./egctl object create

以上的操作是创建了一个 httpserver 监听 10080 端口,并且有两个服务,一个是以/pipeline 为前缀的服务的流量直接打到 pipeline-demo 这个命名的后端上(虽然现在还未创建,我知道你很急,但是你先别急)下面的另一个服务就是 path 是一个正则表达式,所有匹配上的流量都会被打到 test-demo 服务上,rewriteTarget 为啥是/$1 呢,请看下面图片,
在这里插入图片描述
在这里插入图片描述
看官是否能看懂?也就是说这个路径重写是用了 go 标准库中的 ReplaceAllString 方法,然后这个$1 的话就是匹配到的字符串(这个话题就不延伸了,不然我怎么水博客🤪,可能某天就把这个坑填上了)

5. 创建服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
echo '
name: pipeline-demo
kind: Pipeline
flow:
- filter: proxy
filters:
- name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:9095
- url: http://127.0.0.1:9096
- url: http://127.0.0.1:9097
loadBalance:
policy: roundRobin' | ./egctl object create

请听我解释: - servers 你部署的后端服务 (为啥有三个呢?) 你流量大需要分流呗 - loadBalance 你分流总得有个策略吧 - flow 就是 api 编排流量进来会根据你编排的顺序去走相应的流程
好吧下面我要装一波了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
echo '
name: test-demo2
kind: Pipeline
flow:
- filter: proxy
jumpIf:
failureCode: failResponse
- filter: failResponse
- filter: successResponse
filters:
- name: successResponse
kind: ResponseBuilder
protocol: http
template: |
statusCode: 200
headers:
"Content-Type": ["application/json"]
body: "{{.responses.DEFAULT.Body}}"
- name: failResponse
kind: ResponseBuilder
protocol: http
template: |
statusCode: 200
headers:
"Content-Type": ["application/json"]
body: |
{
"code": -1
"data": null
"message": "{{.responses.DEFAULT.JSONBody.message}}"
}
- name: proxy
kind: Proxy
pools:
- servers:
- url: http://127.0.0.1:8001
failureCodes: [400, 404, 408, 429, 500, 501, 503, 504]
loadBalance:
policy: roundRobin' | ./egctl object create

怎么样?是不是脑瓜子嗡嗡的,上面就是对数据的返回格式做了统一。
flow 中有个 jumpIf 这个就是当 failureCode 等于 failureCodes 中的某个值时就直接跳转到 failResponse 过滤器。好了好了我们启动一下看一下吧!

6. 启动

终于启动了

在这里插入图片描述
成功了 xdm,官方文档还有很多操作,比如说 ip 限制啊,跨域啊,鉴权等等…他还支持 K8s Ingress Controller 是不是值得一学?虽然小编学不会k8s但是或许某天我更新了k8s文章可别喷我!!!