刚刚从loki的promtail client坑中爬出来
问题
在promtail官方提供的作用于kubernetes数据源的配置文件中,在loki中展示是这样的

grafana格式化json后,也不是很方便,如下图:

如果使用官方原版的日志格式,肯定是无法快速排查问题的,日志看着很乱,所以需要调整下日志输出格式,调整后如下图:

那么在遇到这个问题后,我都做了那些操作呢
爬坑
首先我看了一下,这些数据都是怎么来的,日志为什么会是一段json,我打开rancher查看日志,格式并不是这样的呀,如下图:

虽然疑惑,但是我没有深究,我发现日志确实跟rancher中是同步的,rancher每刷新出新日志,loki中也会跟着出现,这时我知道,是promtail官方的promtail配置文件,已经为我们接入了kubernetespod的日志,但是输出的东西似乎有点问题,我开始看promtail配置,我是了解loki之后,才了解promtail的,之前也没玩过promtail,所以刚看promtail配置文件的时候,有点困难,原版如下:
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
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
|
server:
log_level: info
http_listen_port: 3101
clients:
- url: http://loki-loki-distributed-gateway/loki/api/v1/push
positions:
filename: /run/promtail/positions.yaml
scrape_configs:
# See also https://github.com/grafana/loki/blob/master/production/ksonnet/promtail/scrape_config.libsonnet for reference
- job_name: kubernetes-pods
pipeline_stages:
- cri: {}
kubernetes_sd_configs:
- role: pod
relabel_configs:
- source_labels:
- __meta_kubernetes_pod_controller_name
regex: ([0-9a-z-.]+?)(-[0-9a-f]{8,10})?
action: replace
target_label: __tmp_controller_name
- source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_name
- __meta_kubernetes_pod_label_app
- __tmp_controller_name
- __meta_kubernetes_pod_name
regex: ^;*([^;]+)(;.*)?$
action: replace
target_label: app
- source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_instance
- __meta_kubernetes_pod_label_release
regex: ^;*([^;]+)(;.*)?$
action: replace
target_label: instance
- source_labels:
- __meta_kubernetes_pod_label_app_kubernetes_io_component
- __meta_kubernetes_pod_label_component
regex: ^;*([^;]+)(;.*)?$
action: replace
target_label: component
- action: replace
source_labels:
- __meta_kubernetes_pod_node_name
target_label: node_name
- action: replace
source_labels:
- __meta_kubernetes_namespace
target_label: namespace
- action: replace
replacement: $1
separator: /
source_labels:
- namespace
- app
target_label: job
- action: replace
source_labels:
- __meta_kubernetes_pod_name
target_label: pod
- action: replace
source_labels:
- __meta_kubernetes_pod_container_name
target_label: container
- action: replace
replacement: /var/log/pods/*$1/*.log
separator: /
source_labels:
- __meta_kubernetes_pod_uid
- __meta_kubernetes_pod_container_name
target_label: __path__
- action: replace
regex: true/(.*)
replacement: /var/log/pods/*$1/*.log
separator: /
source_labels:
- __meta_kubernetes_pod_annotationpresent_kubernetes_io_config_hash
- __meta_kubernetes_pod_annotation_kubernetes_io_config_hash
- __meta_kubernetes_pod_container_name
target_label: __path__
|
第一次动这个配置文件,还是url地址不对,修改了下地址。
简单看了下配置文件,relabel_configs部分大致看明白了,是从元数据中提取组合形成新的target_label,例如:
1
2
3
4
5
6
7
|
- action: replace
replacement: $1
separator: /
source_labels:
- namespace
- app
target_label: job
|
这一段意思是:将原数据中的两个labelnamespace和app用/连接,形成新的target_labeljob: namespace/app。
那么剩下的配置文件,查阅官网文档后大致了解:
1
2
3
4
5
6
7
8
9
10
11
12
13
|
server: # promtail 基础配置
log_level: info
http_listen_port: 3101
clients: # 客户端连接地址,用于推送日志给loki
- url: http://loki-loki-distributed-gateway/loki/api/v1/push
positions: # 用于记录读取位置,promtail重启后仍然可以继续读取
filename: /run/promtail/positions.yaml
scrape_configs: # 配置任务
- job_name: kubernetes-pods
pipeline_stages: # 管道步骤,可以对元数据进行处理。
- cri: {} # 类似于装饰器,官方写好了针对于kubernetes日志格式的处理,也是本次坑需要修改的地方。
kubernetes_sd_configs: # 如何自动发现新的日志
- role: pod # 官方提供的
|
了解完配置文件后,就发现了突破口,需要在promtail中修改管道步骤pipeline_stages,如何修改呢,查阅了官方文档 大致了解了下如何操作元数据,主要有下面几种:

那么对于我这个问题,应该怎么修改呢,我找了下,原配置文件中的cri: {},是个什么意思,在文档中显示:

这一段确实难住我了,这几个stage我都了解是啥意思,但是组合到一起,我就不知道了。特别是正则这段,似乎不是我认识的正则表达式。翻了翻 正则表达式官方文档 也没看懂,当我要尝试写一下正则的时候,发现,怎么写都不对,根本没有效果,而且无论loki,还是promtail,都没有error日志,就是这里,给我整蒙了。又研究了一半天,发现,正则写不对原因竟然是元数据格式给弄错了。
前面提到过,rancher中的日志,和grafana展示的日志不太一样,原因是,rancher读取日志后做了格式化,原日志格式本来就是json,如下图:

格式化后:
1
2
3
4
5
|
{
"log": "2022/08/30 16:17:56.466 \u001b[1;44m[D]\u001b[0m [server.go:2868] | 10.0.0.29|\u001b[97;43m 400 \u001b[0m| 6.757592ms| match|\u001b[97;46m POST \u001b[0m /user/login r:/user/login\n",
"stream": "stdout",
"time": "2022-08-30T08:17:56.466188101Z"
}
|
kubernetes存储的日志存储在node节点的/var/log/containers目录下,直接cat就可以了。
有了元数据后,就可以好好写一下正则了,不过这个正则确实写不明白,我就换了种方式,我看到官网文档中有一个json的stage,于是将- cri: {}改为了:
1
2
3
4
5
|
- json:
expressions:
output: log
- output:
source: output
|
重启后可以看到这段日志变成了:

到此就完成了loki日志的格式化