经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Elasticsearch » 查看文章
日志采集/分析
来源:cnblogs  作者:FuShudi  时间:2024/7/1 11:27:05  对本文有异议

EFK

这是一个日志收集系统,日志收集属于可观测性体系

可观测性体系

  • 监控

    • 基础设施的维度
      • USE方法
        • CPU:
          • 利用率
          • 负载
        • 内存:
          • 利用率
          • 饱和度
          • 错误率
        • 网卡:
          • 利用率
          • 饱和度
          • 错误率
    • 应用程序的维度
      • RED方法
  • 日志

    • 操作系统维度
    • 应用维度
      • 通过日志的错误进一步完善监控
      • 通过日志排查问题
      • 行为分析
  • 链路追踪

1. 日志系统

  1. ELK
    • ElasticSearch :日志存储系统
    • LogStash:日志采集器
    • Kibana:日志查询分析系统

ELK现在用的少,原因是

  1. jruby(java+ruby)
  2. 语法复杂:重量级日志采集
  3. 性能差
  1. EFK

    • ElasticSearch
    • Fluneted:日志采集器
    • Kibana
  2. PLG

    • Promtail :日志采集器
    • Loki:日志存储系统
    • Grafana:日志查询分析系统

我们这里部署的架构是

ilogtail ---> kafka ---> logstash ---> elasticsearch ---> kibana

使用ilogtail采集日志写入到kafka消息队列里,再由logstash从消息队列里读取日志写入到 es,最后再由kibana做展示

至于第三个环节为什么是logstash而不是ilogtail是因为,ilogtail要往es里面写日志会需要配置es的认证密码,但我们是没有给es配置用户名和密码的,所以采用logstash

2. 部署ElasticSearch

2.1 创建handless服务

  1. [root@master EFK]# vim es-svc.yaml
  2. kind: Service
  3. apiVersion: v1
  4. metadata:
  5. name: elasticsearch
  6. namespace: logging
  7. labels:
  8. app: elasticsearch
  9. spec:
  10. selector:
  11. app: elasticsearch
  12. clusterIP: None
  13. ports:
  14. - port: 9200
  15. name: rest
  16. - port: 9300
  17. name: inter-node

2.2 创建sts

  1. [root@master EFK]# vim es-sts.yaml
  2. apiVersion: apps/v1
  3. kind: StatefulSet
  4. metadata:
  5. name: es
  6. namespace: logging
  7. spec:
  8. serviceName: elasticsearch
  9. replicas: 1
  10. selector:
  11. matchLabels:
  12. app: elasticsearch
  13. template:
  14. metadata:
  15. labels:
  16. app: elasticsearch
  17. spec:
  18. initContainers:
  19. - name: initc1
  20. image: busybox
  21. command: ["sysctl","-w","vm.max_map_count=262144"]
  22. securityContext:
  23. privileged: true
  24. - name: initc2
  25. image: busybox
  26. command: ["sh","-c","ulimit -n 65536"]
  27. securityContext:
  28. privileged: true
  29. - name: initc3
  30. image: busybox
  31. command: ["sh","-c","chmod 777 /data"]
  32. volumeMounts:
  33. - name: data
  34. mountPath: /data
  35. containers:
  36. - name: elasticsearch
  37. image: swr.cn-east-3.myhuaweicloud.com/hcie_openeuler/elasticsearch:7.17.1
  38. resources:
  39. limits:
  40. cpu: 1000m
  41. requests:
  42. cpu: 100m
  43. ports:
  44. - containerPort: 9200
  45. name: rest
  46. protocol: TCP
  47. - containerPort: 9300
  48. name: inter-node
  49. protocol: TCP
  50. volumeMounts:
  51. - name: data
  52. mountPath: /usr/share/elasticsearch/data
  53. env:
  54. - name: cluster.name
  55. value: k8s-logs
  56. - name: node.name
  57. valueFrom:
  58. fieldRef:
  59. fieldPath: metadata.name
  60. - name: cluster.initial_master_nodes
  61. value: "es-0"
  62. - name: discovery.zen.minimum_master_nodes
  63. value: "2"
  64. - name: discovery.seed_hosts
  65. value: "elasticsearch"
  66. - name: ES_JAVA_OPTS
  67. value: "-Xms512m -Xmx512m"
  68. - name: network.host
  69. value: "0.0.0.0"
  70. volumeClaimTemplates:
  71. - metadata:
  72. name: data
  73. labels:
  74. app: elasticsearch
  75. spec:
  76. accessModes: ["ReadWriteOnce"]
  77. resources:
  78. requests:
  79. storage: 10Gi

应用yaml文件

  1. [root@master EFK]# kubectl create ns logging
  2. [root@master EFK]# kubectl apply -f .
  3. service/elasticsearch create
  4. statefulset.apps/es create
  5. [root@master EFK]# kubectl get pods -n logging
  6. NAME READY STATUS RESTARTS AGE
  7. es-0 1/1 Running 0 46s

pod显示running就是部署好了

3. 部署kibana

我直接将所有需要的资源放在一个yaml文件里面

  1. apiVersion: v1
  2. kind: ConfigMap
  3. metadata:
  4. namespace: logging
  5. name: kibana-config
  6. labels:
  7. app: kibana
  8. data:
  9. kibana.yml: |
  10. server.name: kibana
  11. server.host: "0.0.0.0"
  12. i18n.locale: zh-CN
  13. elasticsearch:
  14. hosts: ${ELASTICSEARCH_HOSTS}
  15. ---
  16. apiVersion: v1
  17. kind: Service
  18. metadata:
  19. name: kibana
  20. namespace: logging
  21. labels:
  22. app: kibana
  23. spec:
  24. ports:
  25. - port: 5601
  26. type: NodePort
  27. selector:
  28. app: kibana
  29. ---
  30. apiVersion: apps/v1
  31. kind: Deployment
  32. metadata:
  33. name: kibana
  34. namespace: logging
  35. labels:
  36. app: kibana
  37. spec:
  38. selector:
  39. matchLabels:
  40. app: kibana
  41. template:
  42. metadata:
  43. labels:
  44. app: kibana
  45. spec:
  46. containers:
  47. - name: kibana
  48. image: swr.cn-east-3.myhuaweicloud.com/hcie_openeuler/kibana:7.17.1
  49. imagePullPolicy: IfNotPresent
  50. resources:
  51. limits:
  52. cpu: 1
  53. requests:
  54. cpu: 1
  55. env:
  56. - name: ELASTICSEARCH_URL
  57. value: http://elasticsearch:9200 # 写handless的名字
  58. - name: ELASTICSEARCH_HOSTS
  59. value: http://elasticsearch:9200 # 写handless的名字
  60. ports:
  61. - containerPort: 5601
  62. volumeMounts:
  63. - name: config
  64. mountPath: /usr/share/kibana/config/kibana.yml
  65. readOnly: true
  66. subPath: kibana.yml
  67. volumes:
  68. - name: config
  69. configMap:
  70. name: kibana-config

查看端口并访问

  1. [root@master EFK]# kubectl get svc
  2. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  3. elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 17m
  4. kibana NodePort 10.104.94.122 <none> 5601:30980/TCP 4m30s

kibana的nodeport端口是30980,我们来访问

这样就算部署好了,接下来需要部署日志采集工具

4. 部署ilogtail(docker-compose)

因为Fluentd配置复杂,所以我这里采用ilogtail来采集日志

  • ilogtail配置简单
  • 阿里开源,界面中文

我们先使用docker-compose的方式部署,最后整个平台搭建起来之后我们再将ilogtail部署到k8s集群里

4.1 编写docker-compose

  1. [root@master ilogtail]# vim docker-compose.yaml
  2. version: "3"
  3. services:
  4. ilogtail:
  5. container_name: ilogtail
  6. image: sls-opensource-registry.cn-shanghai.cr.aliyuncs.com/ilogtail-community-edition/ilogtail:2.0.4
  7. network_mode: host
  8. volumes:
  9. - /:/logtail_host:ro
  10. - /var/run:/var/run
  11. - ./checkpoing:/usr/local/ilogtail/checkpoint
  12. - ./config:/usr/local/ilogtail/config/local
  • /:我们将宿主机的整个 / ,目录挂载到容器里面,方便容器读取日志
  • checkpoint:这个相当于一个指针,指向当前读取到哪一行日志了,如果ilogtail被重启了它可以根据这个checkpoint来回到上一次读取的地方
  • config:这个就是放采集的配置文件的

启动容器

  1. [root@master ilogtail]# docker-compose up -d
  2. [root@master ilogtail]# docker ps |grep ilogtail
  3. eac545d4da87 sls-opensource-registry.cn-shanghai.cr.aliyuncs.com/ilogtail-community-edition/ilogtail:2.0.4 "/usr/local/ilogtail…" 10 seconds ago Up 9 seconds ilogtail

这样容器就启动了

4.2 配置ilogtail采集

  1. [root@master ilogtail]# cd config/
  2. [root@master config]# vim sample-stdout.yaml
  3. enable: true
  4. inputs:
  5. - Type: input_file # 文件输入类型
  6. FilePaths:
  7. - /logtail_host/var/log/messages
  8. flushers:
  9. - Type: flusher_stdout # 标准输出流输出类型
  10. OnlyStdout: true
  11. [root@master config]# docker restart ilogtail
  • /logtail_host/var/log/messages:这里是这个地址的原因是我们将宿主机的/,挂载到了容器内的logtail_host,所以我们宿主机产生的日志会在容器的/logtail_host/var/log/messages这个目录下

  • 配置文件写好之后我们还需要重启容器让他读取配置,所以有一个restart

4.3 查看容器采集的日志

  1. [root@master config]# docker logs ilogtail
  2. 2024-06-30 11:16:25 {"content":"Jun 30 19:16:22 master dockerd[1467]: time=\"2024-06-30T19:16:22.251108165+08:00\" level=info msg=\"handled exit event processID=9a8df40981b3609897794e50aeb2bde805eab8a75334266d7b5c2899f61d486e containerID=61770e8f88e3c6a63e88f2a09d2683c6ccce1e13f6d4a5b6f79cc4d49094bab4 pid=125402\" module=libcontainerd namespace=moby","__time__":"1719746182"}
  3. 2024-06-30 11:16:25 {"content":"Jun 30 19:16:23 master kubelet[1468]: E0630 19:16:23.594557 1468 kubelet_volumes.go:245] \"There were many similar errors. Turn up verbosity to see them.\" err=\"orphaned pod \\\"9d5ae64f-1341-4c15-b70f-1c8f71efc20e\\\" found, but error not a directory occurred when trying to remove the volumes dir\" numErrs=2","__time__":"1719746184"}

可以看到,宿主机的日志已经被成功采集了,宿主机的日志会被封装到content里,如果没有看到输出的日志的话,需要进入到容器内部查看一个叫做ilogtail.LOG的文件,而不能使用docker logs ilogtail

4.4 采集容器标准输出日志(可选)

  1. [root@master config]# cp sample-stdout.yaml docker-stdout.yaml
  2. # 为了避免同时输出到标准输出而导致的日志杂乱,我们临时将sample-stdout关掉
  3. [root@master config]# cat sample-stdout.yaml
  4. enable: false # 将这里改为false
  5. inputs:
  6. - Type: input_file # 文件输入类型
  7. FilePaths:
  8. - /logtail_host/var/log/messages
  9. flushers:
  10. - Type: flusher_stdout # 标准输出流输出类型
  11. OnlyStdout: true
  12. [root@master config]# cat docker-stdout.yaml
  13. enable: true
  14. inputs:
  15. - Type: service_docker_stdout
  16. Stdout: true # 采集标准输出
  17. Stderr: false # 不采集错误输出
  18. flushers:
  19. - Type: flusher_stdout
  20. OnlyStdout: true
  21. [root@master config]# docker restart ilogtail
  22. ilogtail

4.5 查看采集的容器日志

  1. 2024-06-30 11:24:13 {"content":"2024-06-30 11:24:10 {\"content\":\"2024-06-30 11:24:07 {\\\"content\\\":\\\"2024-06-30 11:24:04.965 [INFO][66] felix/summary.go 100: Summarising 12 dataplane reconciliation loops over 1m3.4s: avg=3ms longest=12ms ()\\\",\\\"_time_\\\":\\\"2024-06-30T11:24:04.965893702Z\\\",\\\"_source_\\\":\\\"stdout\\\",\\\"_container_ip_\\\":\\\"192.168.200.200\\\",\\\"_image_name_\\\":\\\"calico/node:v3.23.5\\\",\\\"_container_name_\\\":\\\"calico-node\\\",\\\"_pod_name_\\\":\\\"calico-node-hgqzr\\\",\\\"_namespace_\\\":\\\"kube-system\\\",\\\"_pod_uid_\\\":\\\"4d0d950c-346a-4f81-817c-c19526700542\\\",\\\"__time__\\\":\\\"1719746645\\\"}\",\"_time_\":\"2024-06-30T11:24:07.968118197Z\",\"_source_\":\"stdout\",\"_container_ip_\":\"192.168.200.200\",\"_image_name_\":\"sls-opensource-registry.cn-shanghai.cr.aliyuncs.com/ilogtail-community-edition/ilogtail:2.0.4\",\"_container_name_\":\"ilogtail\",\"__time__\":\"1719746647\"}","_time_":"2024-06-30T11:24:10.971474647Z","_source_":"stdout","_container_ip_":"192.168.200.200","_image_name_":"sls-opensource-registry.cn-shanghai.cr.aliyuncs.com/ilogtail-community-edition/ilogtail:2.0.4","_container_name_":"ilogtail","__time__":"1719746650"}

能够正常看见日志就说明日志采集没有问题,接下来我们部署kafka,用来接收ilogtail的日志,注意将日志采集关掉,不然你的虚拟机磁盘很快就会满

5. 部署kafka

kafka作为消息队列,会有消费者和生产者,生产者在这里就是ilogtail,也就是将日志写入到kafka,消费者就是logstash,从kafka里面读取日志写入到es

5.1 kafka介绍

Apache kafka是分布式的,基于发布/订阅的容错消息系统,主要特性如下

  • 高吞吐,低延迟:可以做到每秒百万级的吞吐量,并且延迟低(其他的消息队列基本也都可以)

  • 持久性,可靠性:消息会被持久化到本地磁盘,支持数据备份防止数据丢失,并且可以配置消息有效期,以便消费者可以多次消费

  • kafka官方不支持docker部署,我们可以使用第三方的镜像

5.2 部署kafka(docker-compose)

  1. version: '3'
  2. services:
  3. zookeeper:
  4. image: quay.io/3330878296/zookeeper:3.8
  5. network_mode: host
  6. container_name: zookeeper-test
  7. volumes:
  8. - zookeeper_vol:/data
  9. - zookeeper_vol:/datalog
  10. - zookeeper_vol:/logs
  11. kafka:
  12. image: quay.io/3330878296/kafka:2.13-2.8.1
  13. network_mode: host
  14. container_name: kafka
  15. environment:
  16. KAFKA_ADVERTISED_HOST_NAME: "192.168.200.200"
  17. KAFKA_ZOOKEEPER_CONNECT: "192.168.200.200:2181"
  18. KAFKA_LOG_DIRS: "/kafka/logs"
  19. volumes:
  20. - kafka_vol:/kafka
  21. depends_on:
  22. - zookeeper
  23. volumes:
  24. zookeeper_vol: {}
  25. kafka_vol: {}
  • KAFKA_LOG_DIRS: "/kafka/logs":这个地方需要注意,在kafka的名词里面,他把数据叫做日志,这个地方看似是定义的日志目录,其实是kafka的数据目录

5.3 部署kafdrop(kafka的web界面)

  1. [root@master kafka]# docker run -d --rm -p 9000:9000 -e KAFKA_BROKERCONNECT=192.168.200.200:9092 -e SERVER_SERVLET_CONTEXTPATH="/" quay.io/3330878296/kafdrop

部署好之后就可以使用web界面查看了,部署web界面的原因是我们将日志写入到kafka之后可以直接使用web界面查看也没有写入进去,比kafka命令行更加的直观

在浏览器输入ip:9000

5.4 ilogtail将日志写入到kafka

  1. [root@master config]# cd /root/ilogtail/config
  2. [root@master config]# cp sample-stdout.yaml kafka.yaml
  3. [root@master config]# vim kafka.yaml
  4. enable: true
  5. inputs:
  6. - Type: input_file
  7. FilePaths:
  8. - /logtail_host/var/log/messages
  9. flushers:
  10. - Type: flusher_kafka_v2
  11. Brokers:
  12. - 192.168.200.200:9092
  13. Topic: KafkaTopic
  14. [root@master config]# docker restart ilogtail
  15. ilogtail

这个时候我们再回到web界面就会出现一个topic

点进去可以查看有哪些日志被写入进去了

能看见日志就没问题了,接下来部署logstash

6. 部署logstash

logstash会从kafka读取消息然后写入到es里面去

6.1 部署logstash(docker-compose)

  1. [root@master ~]# mkdir logstash
  2. [root@master ~]# cd logstash
  3. [root@master logstash]# vim docker-compose.yaml
  4. version: '3'
  5. services:
  6. logstash:
  7. image: quay.io/3330878296/logstash:8.10.1
  8. container_name: logstash
  9. network_mode: host
  10. environment:
  11. LS_JAVA_OPTS: "-Xmx1g -Xms1g"
  12. volumes:
  13. - /etc/localtime:/etc/localtime:ro
  14. - /apps/logstash/config/logstash.yml:/usr/share/logstash/config/logstash.yml
  15. - /apps/logstash/pipeline:/usr/share/logstash/pipeline
  16. - /var/log:/var/log
  • config里面放的是logstash本身的配置文件
  • pipeline里面放的是采集/输出日志的规则

docker-compose写好之后先不要着急启动,因为我们给他挂载的配置文件还没有启动

现在编写配置文件

  1. [root@master logstash]# mkdir /apps/logstash/{config,pipeline}
  2. [root@master logstash]# cd /apps/logstash/config/
  3. [root@master config]# vim logstash.yml
  4. pipeline.workers: 2
  5. pipeline.batch.size: 10
  6. pipeline.batch.delay: 5
  7. config.reload.automatic: true
  8. config.reload.interval: 60s

写好这个文件之后我们启动这个logstash容器

  1. [root@master logstash]# /root/logstash
  2. [root@master logstash]# docker-compose up -d
  3. [root@master logstash]# docker ps |grep logstash
  4. 60dfde4df40d quay.io/3330878296/logstash:8.10.1 "/usr/local/bin/dock…" 2 minutes ago Up 2 minutes logstash

启动之后就没问题了

6.2 输出日志到es

Logstash官方文档地址

我们要使用logstash输出日志到es的话就需要到pipeline里面去写一些规则

  1. [root@master EFK]# cd /apps/logstash/pipeline/
  2. [root@master pipeline]# vim logstash.conf
  3. input {
  4. kafka {
  5. # 指定kafka地址
  6. bootstrap_servers => "192.168.200.200:9092"
  7. # 从哪些topic获取数据,要写已经存在topic
  8. topics => ["KafkaTopic"]
  9. # 从哪个地方开始读取,earliest是从头开始读取
  10. auto_offset_reset => "earliest"
  11. codec => "json"
  12. # 当一个logstash中有多个input插件时,建议每个插件定义一个id
  13. # id => "kubernetes"
  14. # group_id => "kubernetes"
  15. }
  16. }
  17. filter {
  18. json {
  19. source => "event.original"
  20. }
  21. mutate {
  22. remove_field => ["event.original","event"]
  23. }
  24. }
  25. output {
  26. elasticsearch {
  27. hosts => ["http://192.168.200.200:9200"]
  28. index => "kubernetes-logs-%{+YYYY.mm}"
  29. }
  30. }
  • ? hosts => ["http://192.168.200.200:9200"]:这个地方的9200,因为我们的logstash是用docker部署的,但是es是部署在k8s集群内部的,所以这个地方9200端口是通不了的,所以我们需要给k8s的es创建一个nodeport类型的svc,来让docker可以访问到
  1. [root@master EFK]# kubectl expose pod es-0 --type NodePort --port 9200 --target-port 9200
  2. service/es-0 exposed
  3. [root@master EFK]# kubectl get svc
  4. NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
  5. elasticsearch ClusterIP None <none> 9200/TCP,9300/TCP 3h38m
  6. es-0 NodePort 10.97.238.173 <none> 9200:32615/TCP 2s
  7. kibana NodePort 10.106.1.52 <none> 5601:30396/TCP 3h38m

这里他将9200映射到了本地的32615端口,所以我们将logstash的地址改到32615

  1. output {
  2. elasticsearch {
  3. hosts => ["http://192.168.200.200:32615"]
  4. index => "kubernetes-logs-%{+YYYY.mm}"
  5. }
  6. }

然后重启logstash

  1. [root@master pipeline]# docker restart logstash

6.3 到kibana查看

6.3.1 查看索引

  1. 点击stack management

  2. 点击索引管理,会看到有索引存在就是正常

  3. 点击索引模式,创建索引

  1. 进入discover

原文链接:https://www.cnblogs.com/fsdstudy/p/18277099

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号