暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

基于AWS EKS的K8S实践 - 日志方案解决

640



Hi~朋友,关注置顶防止错过消息


基于AWS EKS的K8S实践系列文章是基于企业级的实战文章,一些设置信息需要根据公司自身要求进行设置,如果大家有问题讨论或咨询可以加我微信(公众号后台回复 程序员修炼笔记 可获取联系方式)。

当前日志的解决方案

  1. 传统 EFK

  2. 云供应商提供的日志平台(比如阿里的 SLS 、 CloudWatch)

云供应商的平台一般都可以通过 SDK 的方式进行投递解决,所以其实无关乎我们的应用部署方式,只要按照云供应商的所需配置进行配置即可。

今天我们主要说一下如果是自建的 ES 的日志的收集方案的解决。

Kubernetes的日志收集的集中方案

  1. 在每个节点上运行一个收集的agent,该agent负责采集节点上的所有日志,这种通常就是DaemonSet

  2. Sidecar容器:为每个Pod运行一个日志代理容器,该Agent容器只负责当前Pod内的业务日志的收集

  3. 直接将应用程序的日志推送到采集后端

关于第一种方案这种方案虽然可以降低资源的消耗(无需为每个 Pod 配置一个 Sidecar 容器),但是他的灵活程度比较低,因为在我们实际的使用场景中,每个日志推送到es 的 index 名称往往不同,并且日志保存周期也可能不同,而 Sidecar 可以根据每个 Pod 进行定制化相对灵活,当然最灵活的方式还是第三种,这种方式无关乎你的底层服务架构,都是基于 HTTP 或者 RPC 进行的数据的直接推送。

Sidecar 容器的解决方案

  1. 准备我们filebeat的配置文件,这里我们通过 ConfigMap准备,如下:

  1. kind: ConfigMap

  2. apiVersion: v1

  3. metadata:

  4. name: xxx-internal-filebeat-config

  5. namespace: application-test

  6. data:

  7. filebeat.yml: |

  8. filebeat.inputs:

  9. - type: filestream

  10. paths:

  11. - "/docker/log/*.log"

  12. parsers:

  13. - multiline:

  14. type: pattern

  15. pattern: '^\d{4}-\d{2}-\d{2}\s\d{2}\:\d{2}\:\d{2}\.\d{3}'

  16. negate: true

  17. match: after

  18. fields:

  19. project: xxx-internal

  20. env: test

  21. pipeline: ys-application-log-pipeline

  22. output.elasticsearch:

  23. hosts: ["test.es.xxx.com:9200"]

  24. indices:

  25. - index: "%{[fields.project]}-%{[fields.env]}-%{+yyyy.MM.dd}"

  • paths: 收集的 log 日志文件的路径

  • multiline:确保将多行日志(如堆栈异常)作为一个完整文档发送

  • multiline.pattern:用来指定要匹配的正则表达式模式,根据你配置其他多行选项的方式,与指定正则表达式匹配的行将被视为上一行的延续或新多行事件的开始

  • multiline.negate:定义是否为否定模式,也就是和上面定义的模式相反,默认为false

  • multiline.match: 指定Filebeat如何将匹配的行组合到事件中,设置在之后(after)或之前(before)

我上面的配置的含义就是代表了我的日志开头是个时间戳,在logback中的配置是%d{yyyy-MM-dd HH:mm:ss.SSS},如果不以yyyy-MM-dd HH:mm:ss.SSS开始的连续行将会被追加到匹配的前一行。

  • fields:指定添加一些其他属性,这里我增加了project和 env

  • pipeline:用于指定Ingest pipeline,这里会在日志投递到 es 之前对日志进行清洗过滤转换,Ingest pipeline会在 ES 的 Ingest Node 上进行处理

Ingest Node相比 LogStash 的缺点主要是他的输出只能到 ES(不能再输出到 Kafka 队列),没有缓冲机制,不像 LogStash 有缓冲机制在一定程度上可以防止数据的丢失,其次是他支持的 Processor 相对较少,没有 LogStash 种类丰富,但在我们的使用场景下,日志量没有明显的波峰,而且我们的日志写到 es的情况下我这里就直接利用Ingest pipeline进行处理,这样也会少一个 LogStash 组件的维护,这里牵涉到一个技术选型的核心思想:在你的人力和基础系统不够扎实的前提下,一定要将你的技术架构简单化,组件越少越好,以最低成本的最合适的方式满足你的当下需求,整的花里胡哨没用只是皮毛而且也会增加运维人员开发人员的负担,系统先跑起来,其次稳下来,最后投入一定的人力开发基础系统(包含 DevOps 、监控),这些支持系统虽然不能为公司带来明面上的收益,但是他是提高研发效率,保障系统跑的快跑的好提高问题排查效率的关键。

  • output.elasticsearch.indices:指定我们投递到 es的 index 名称

ys-application-log-pipeline用做什么?

es 的里面的时间默认是 filebeat 投递日志的时间,不是日志里面的时间,我们的有些应用对这个时间比较敏感,必须是日志里面的时间,因此ys-application-log-pipeline主要做的就是将日志里面的时间取出来,单独再存储到一个field 中,方便进行排序查询。

  1. PUT _ingest/pipeline/ys-application-log-pipeline

  2. {

  3. "processors": [

  4. {

  5. "grok": {

  6. "field": "message",

  7. "patterns": [

  8. "%{MY_DATETIME:log_time}"

  9. ],

  10. "pattern_definitions": {

  11. "MY_DATE": "%{YEAR}[/-]%{MONTHNUM}[/-]%{MONTHDAY}",

  12. "MY_TIME": "[0-9][0-9]:[0-9][0-9]:[0-9][0-9].[0-9][0-9][0-9]",

  13. "MY_DATETIME": "%{MY_DATE} %{MY_TIME}"

  14. }

  15. }

  16. },

  17. {

  18. "date": {

  19. "field": "log_time",

  20. "formats": [

  21. "yyyy-MM-dd HH:mm:ss.SSS"

  22. ],

  23. "target_field": "log_time",

  24. "output_format": "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

  25. }

  26. },

  27. {

  28. "script": {

  29. "lang": "painless",

  30. "source": "String datetime = ctx.log_time;\nZonedDateTime zdt = ZonedDateTime.parse(datetime);\nzdt = zdt.minusHours(7);\nctx.log_time = zdt;"

  31. }

  32. },

  33. {

  34. "date": {

  35. "field": "log_time",

  36. "formats": [

  37. "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"

  38. ],

  39. "target_field": "log_time",

  40. "output_format": "yyyy-MM-dd HH:mm:ss.SSS"

  41. }

  42. }

  43. ]

  44. }

Deployments配置

  1. apiVersion: apps/v1

  2. kind: Deployment

  3. metadata:

  4. namespace: application-test

  5. name: xxx-internal

  6. labels:

  7. app: xxx-internal

  8. spec:

  9. ...

  10. template:

  11. metadata:

  12. labels:

  13. app: xxx-internal

  14. spec:

  15. restartPolicy: Always

  16. containers:

  17. - name: xxx-internal

  18. image: DEPLOY_IMAGE

  19. imagePullPolicy: Always

  20. ....

  21. volumeMounts:

  22. - mountPath: /docker/log

  23. name: application-log

  24. - name: filebeat

  25. image: docker.elastic.co/beats/filebeat:8.6.1

  26. imagePullPolicy: Always

  27. volumeMounts:

  28. - name: application-log

  29. mountPath: /docker/log

  30. - name: filebeat-config

  31. mountPath: /usr/share/filebeat/filebeat.yml

  32. subPath: filebeat.yml

  33. volumes:

  34. - name: application-log

  35. emptyDir: {}

  36. - name: filebeat-config

  37. configMap:

  38. name: xxx-internal-filebeat-config

  39. items:

  40. - key: filebeat.yml

  41. path: filebeat.yml

可以看到在我们的 Pod 中我们除了本身的业务应用容器,我们还启动了一个fielbeat 容器专门用来收集我们的业务日志,具体的关于 Volume 的挂载后续我这边有时间单独写,这里就不专门写了,熟悉 Kubernetes 的同学肯定不会陌生,经过上述配置我们的业务日志就会被投递到我们的 es 中。


【知识星球招募】

  知识星球正在初期搭建中,在星球中可以互相提问,分享经验,我也会在星球中分享基础技术架构的全流程搭建,包括但不仅限于DevOps,监控、Flink开发,Java开发(JVM、多线程、MySQL数据库)等相关技术类文章,期待大家的加入




文章转载自程序员修炼笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论