集群上云使用了ACK,但以前的fluentd服务没有同步过来,现在在跑的只有filebeat。
初步思路,k8s的日志采集,也使用filebeat。
搞懂k8s的日志机制:
日志路径
找了一些filebeat的样例,使用的日志路径为 /var/log/containers/*.log
/var/log/containers的日志通过 软链接到了 /var/log/pods
[ecs-user@ack-node3 social-production]$ ls -lh /var/log/containers/social-production-5c487869c4-5jvtn_c-production_social-production-f44276e7ea227b2b8508f794b16a4c66b44e4cf143d89412038a9e122b3e5a47.log
lrwxrwxrwx 1 root root 122 Oct 10 21:12 /var/log/containers/social-production-5c487869c4-5jvtn_c-production_social-production-f44276e7ea227b2b8508f794b16a4c66b44e4cf143d89412038a9e122b3e5a47.log -> /var/log/pods/c-production_social-production-5c487869c4-5jvtn_fd30b753-0d57-4584-9e54-fe610d9917a1/social-production/0.log
[ecs-user@ack-node3 social-production]$ ls -lh /var/log/pods/c-production_social-production-5c487869c4-5jvtn_fd30b753-0d57-4584-9e54-fe610d9917a1/social-production/0.log
-rw-r----- 1 root root 74M Nov 1 16:26 /var/log/pods/c-production_social-production-5c487869c4-5jvtn_fd30b753-0d57-4584-9e54-fe610d9917a1/social-production/0.log还有一个重要的目录 /var/lib/container/log ,应该是containerd使用的日志目录,rotation由kubelet的两个配置参数containerLogMaxSize和containerLogMaxFiles控制。
具体策略还不清楚:
1. 问:maxSize默认10M指的是压缩后的文件大小?
2. 问:0.log进行切换的时候,如何保证日志不丢失,是原子性操作吗?
答:猜测相当于 mv 操作,不会丢失日志,inode也不会变。
[ecs-user@ack-node3 social-production]$ pwd
/var/lib/container/log/c-production_social-production-5c487869c4-5jvtn_fd30b753-0d57-4584-9e54-fe610d9917a1/social-production
[ecs-user@ack-node3 social-production]$ ls -lh
total 203M
-rw-r----- 1 root root 74M Nov 1 16:44 0.log
-rw-r--r-- 1 root root 9.3M Oct 17 08:22 0.log.20231013-084315.gz
-rw-r--r-- 1 root root 9.8M Oct 23 00:22 0.log.20231017-082217.gz
-rw-r--r-- 1 root root 9.9M Oct 28 10:12 0.log.20231023-002200.gz
-rw-r----- 1 root root 101M Oct 28 10:12 0.log.20231028-101228有一个问题就是,filebeat会不会重复采集,或者是在日志文件切换时,漏掉日志。 从官方文档得知:Filebeat identifies files by inode and device name.
感觉如果使用/var/log/containers,发生 0.log 并未被采集完就切换的情况,就丢日志了。 如果使用/var/lib/container/log则能规避这个问题。 因为用的inode,即使rotate,只要不删除或者重建文件,不会出现采集丢失的情况。可能出现的问题是Pod被驱逐。
containerd的日志形式,跟docker 不一样:
[ecs-user@ack-node3 ~]$ sudo tail -n 2 /var/log/containers/apollon-backend-production-86ddd8c57b-8rdbt_c-production_apollon-backend-production-1a67bfa1c3ef7a11f28fb956a8290bd7178ae3de31d43737824c7c1839e223e9.log
// 日志格式
2023-11-10T16:51:33.889404488+08:00 stdout F 1752ms - GET - /api/student-tasks?studentId=50137
2023-11-10T16:51:39.298739524+08:00 stdout F 0ms - GET - /api调整filebeat采集多个数据源✅
inputs和autodiscover能不能共用? 应该是可以共用,测试过了inputs也会发现新创建的文件。autodiscover可能更方便container的追踪。
如何测试,比如只采集某个特定Pod的日志?
可以使用fields添加字段,添加后如:
{"@timestamp":"2023-11-10T10:15:34.174Z","@metadata":{"beat":"filebeat","type":"_doc","version":"8.11.0"},"fields":{"app_id":"someid","namespace":"c-prodoction"},"ecs":{"version":"8.0.0"},"host":{"name":"2ef45dfce8c5"},"agent":{"ephemeral_id":"f893dfef-df5d-4b4f-875a-b1f8a7ff8a10","id":"c4c236ad-06f1-42d8-965d-413ac2be431b","name":"2ef45dfce8c5","type":"filebeat","version":"8.11.0"},"log":{"offset":0,"file":{"device_id":"64513","inode":"1273469","path":"/home/edc/zk_logs/2.log"}},"message":"2","input":{"type":"filestream"}}用fields_under_root可以提到上层,测试没有效果。
遇到一个问题,filebeat日志实时滚动正常,logstash虽然日志没实时滚动,但是没有报错,但是在kibana没有发现新的indice。 受chatgpt提示,去检查了logstash的配置,路径在 /mnt/ELKStack/docker-compose-files/logstash/conf,发现3个配置文件,input.conf, output.conf, filter.conf。在这个目录,所有文件都会生效,所以.bak备份文件要放在别的目录。
output.conf定义了根据规则将日志输送到什么indice,目前的配置是,未找到json.model字段的,全丢到了一个miscellaneous的indice了。这次修改判断fields.source=ack(在filebeat的configmap添加的自定义字段),则按namespace进行分片推送。
filter.conf是定义各种规则的,这次加了prune的白名单和mutate修改字段名。之前完整的字段日志,留了一个[[ack-log_before_logstash_filter]]
奇怪的事发生了:
if [fields][source] =~ "ack" {
prune {
whitelist_names => ["message", "stream", "@timestamp"]
}
}
上边这个配置是生效的。
下边的配置,没有生效:
if [fields][source] =~ "ack" {
prune {
whitelist_names => ["message", "[kubernetes][deployment][name]", "[kubernetes][replicaset][name]", "[host][hostname]", "[fields][source]", "stream", "@timestamp"]
}
}经多方查证,是elasticsearch不接受”.“的问题: https://discuss.elastic.co/t/field-name-cannot-contain/33251/2 https://github.com/elastic/elasticsearch/pull/12068
顺便发现,因为logstash启动参数带了--config.reload.automatic,更改配置文件后,程序会自动pipeline,无需重启docker(重启JVM太慢了)。
调试后,把带”.“的field name都重命名了,然后只取部分字段。
if [fields][source] == "ack" {
#filter之后,若字段包含"."的话,无法被elk接收, 所以进行rename
mutate {
rename => {
"[kubernetes][deployment][name]" => "deployment"
"[kubernetes][replicaset][name]" => "replicaset"
"[kubernetes][namespace]" => "namespace"
"[host][hostname]" => "hostname"
"[fields][source]" => "fields_source"
}
}
prune {
whitelist_names => ["namespace", "message", "deployment", "replicaset", "hostname", "fields_source", "stream", "@timestamp"]
#whitelist_names => ["message", "stream", "@timestamp"]
#blacklist_names => ["host\.ip", "host\.ip\.keyword"]
}
}接下来是filebeat从5.2.2版本升级到8.10.4版本如何操作。记录offset的文件格式不一样,还有5版本的config路径是在/mnt/zk_logs/filebeat-data,也就是说,每个node上的filebeat用的是同一个文件,需要考证一下新版本,是不是可以这么用,是否合理。