之前有写过elasticsearch集群和elk集群的博客, 都是基于docker的,使用docker-compose进行编排(K8S暂未掌握)

本文较长,上述两个博文中的内容本文都会重新讲解,建议收藏后进行阅读。本文包含了ELK + kafka(zookeeper) + filebeat整套方案的架构与实施

ELK介绍

       ELK = Elasticsearch, Logstash, Kibana 是一套实时数据收集,存储,索引,检索,统计分析及可视化的解决方案。最新版本已经改名为Elastic Stack,并新增了Beats项目。

  1. 通常当系统或者应用发生故障时,运维或者开发需要登录到各个服务器上,使用 grep / sed / awk Linux 脚本工具或vim打开文件的方式去日志里查找故障原因。
  2. 在没有日志系统的情况下,首先需要定位处理请求的服务器,如果这台服务器部署了多个实例,则需要去每个应用实例的日志目录下去找日志文件。
  3. 每个应用实例还会设置日志滚动策略(如:每天生成一个文件),还有日志压缩归档策略等。
  4. 这样一系列流程下来,对于我们排查故障以及及时找到故障原因,造成了比较大的麻烦,并且太靠人手工操作。
  5. 因此,如果我们能把这些日志集中管理,并提供集中检索功能,不仅可以提高诊断的效率,同时对系统情况有个全面的理解,还可以随时进行扩容,避免事后救火的被动。
  6. 总的来说有以下三点用途:
  7. 数据查找:通过检索日志信息,定位相应的 bug ,找出解决方案。
  8. 服务诊断:通过对日志信息进行统计、分析,了解服务器的负荷和服务运行状态
  9. 数据分析:可以做进一步的应用数据分析,当然需要更深入的数据分析,以便产生经济价值。
  10. (摘自:http://www.mamicode.com/info-detail-2741933.html)
  11. 当然elasticsearch除了用于ELK,还有许多其它用途, 我们用的只是它的一小部分功能:
  12. 分布式的搜索引擎和数据分析引擎
  13. 搜索:网站的站内搜索,IT系统的检索
  14. 数据分析:电商网站,统计销售排名前10的商家
  15. 全文检索,结构化检索,数据分析
  16. 全文检索:我想搜索商品名称包含某个关键字的商品
  17. 结构化检索:我想搜索商品分类为日化用品的商品都有哪些
  18. 数据分析:我们分析每一个商品分类下有多少个商品
  19. 对海量数据进行近实时的处理
  20. 分布式:ES自动可以将海量数据分散到多台服务器上去存储和检索
  21. 海联数据的处理:分布式以后,就可以采用大量的服务器去存储和检索数据,自然而然就可以实现海量数据的处理了
  22. 近实时:检索数据要花费1小时(这就不要近实时,离线批处理,batch-processing);在秒级别对数据进行搜索和分析
  23. (摘自:https://blog.csdn.net/paicmis/article/details/82535018)

       想必在平时工作学习中你也听到过elk或es(elasticsearch),本文为什么在ELK的基础上又使用了kafka(zookeeper)和filebeat呢?

  • 首先logstash具有日志采集、过滤、筛选等功能,功能完善但同时体量也会比较大,消耗系统资源自然也多。filebeat作为一个轻量级日志采集工具,虽然没有过滤筛选功能,但是仅仅部署在应用服务器作为我们采集日志的工具可以是说最好的选择了。但我们有些时候可能又需要logstash的过滤筛选功能,所以我们在采集日志时用filebeat,然后交给logstash过滤筛选。

  • 其次,logstash的吞吐量是有限的,一旦短时间内filebeat传过来的日志过多会产生堆积和堵塞,对日志的采集也会受到影响,所以在filebeat与logstash中间又加了一层kafka消息队列来缓存或者说解耦,当然redis也是可以的。这样当众多filebeat节点采集大量日志直接放到kafka中,logstash慢慢的进行消费,两边互不干扰。

  • 至于zookeeper,想必java的同学都知道,分布式服务管理神器,监控管理kafka的节点注册,topic管理等,同时弥补了kafka集群节点对外界无法感知的问题,kafka实际已经自带了zookeeper,但本教程将会使用独立的zookeeper进行管理,方便后期zookeeper集群的扩展。

ELK + kafka(zookeeper) + filebeat 的设计模型

ELK + kafka(zookeeper) + filebeat 的构建

首先说下准备工作

  • 1、服务器: 三台,内存最少4G,其中选择一台作为主节点,建议主节点8G内存。

    • PS:单台大内存服务器也可以,本教程为了更接近实际使用所以建议三台。

    • 如果资源有限,可以单独尝试文章开头的两篇博文,也可以尝试本教程,但不保证能所有的步骤都成功,可能会内存不足,内存低于4G不建议尝试)

  • 2、系统环境:linux内核不低于3.10.0

  • 3、安装docker环境以及docker-compose,详情见我的另一篇博文:https://www.cnblogs.com/lz0925/p/10985700.html

  • 4、首先在三台服务器上搭建es集群,然后选择在一个es节点上搭建ELK,然后在三个节点上安装kafka-zookeeper集群,最后filebeat,各个环节会进行各功能间的可用性测试。

  • 5、elk三个软件版本均为7.1.1,版本太低的话搭建完也该升级了,版本太高文档比较少,坑多,目前最新版本7.5.0,现阶段生产环境使用6.x.x的应该比较多,故选择7.1.1。

es集群的搭建

  1. - 基于单机搭建elasticsearch集群见官网 https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html

本文旨在三台不同的服务器,搭建elasticsearch集群,版本为7.1.1

  • 1、服务器列表即配置
  1. 172.168.50.408G), 172.168.50.41(16G), 172.168.50.240(8G)
  2. 服务器内存尽量不要低于4G
  3. 选用172.168.50.41作为master节点,
  • 2、建立存放yml文件的目录
  1. 建立文件夹,/root/elasticsearch(随意即可),用于存放启动elasticsearch容器的yml文件以及es的配置文件
  2. mkdir /root/elasticsearch
  • 3、创建docker-compose.yml文件
  1. cd /root/elasticsearch
  2. touch docker-compose.yml
  • 4、docker-compose.yml 的文件内容如下
  1. version: '3'
  2. services:
  3. elasticsearch: # 服务名称
  4. image: elasticsearch:7.1.1 # 使用的镜像
  5. container_name: elasticsearch # 容器名称
  6. restart: always # 失败自动重启策略
  7. environment:
  8. - node.name=node-41 # 节点名称,集群模式下每个节点名称唯一
  9. - network.publish_host=172.168.50.41 # 用于集群内各机器间通信,对外使用,其他机器访问本机器的es服务,一般为本机宿主机IP
  10. - network.host=0.0.0.0 # 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0,即本机
  11. - discovery.seed_hosts=172.168.50.40,172.168.50.240,172.168.50.41 # es7.0之后新增的写法,写入候选主节点的设备地址,在开启服务后,如果master挂了,哪些可以被投票选为主节点
  12. - cluster.initial_master_nodes=172.168.50.40,172.168.50.240,172.168.50.41 # es7.0之后新增的配置,初始化一个新的集群时需要此配置来选举master
  13. - cluster.name=es-cluster # 集群名称,相同名称为一个集群, 三个es节点须一致
  14. # - http.cors.enabled=true # 是否支持跨域,是:true // 这里设置不起作用,但是可以将此文件映射到宿主机进行修改,然后重启,解决跨域
  15. # - http.cors.allow-origin="*" # 表示支持所有域名 // 这里设置不起作用,但是可以将此文件映射到宿主机进行修改,然后重启,解决跨域
  16. - bootstrap.memory_lock=true # 内存交换的选项,官网建议为true
  17. - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # 设置内存,如内存不足,可以尝试调低点
  18. ulimits: # 栈内存的上限
  19. memlock:
  20. soft: -1 # 不限制
  21. hard: -1 # 不限制
  22. volumes:
  23. - /root/elasticsearch/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml # 将容器中es的配置文件映射到本地,设置跨域, 否则head插件无法连接该节点
  24. - esdata:/usr/share/elasticsearch/data # 存放数据的文件, 注意:这里的esdata为 顶级volumes下的一项。
  25. ports:
  26. - 9200:9200 # http端口,可以直接浏览器访问
  27. - 9300:9300 # es集群之间相互访问的端口,jar之间就是通过此端口进行tcp协议通信,遵循tcp协议。
  28. volumes:
  29. esdata:
  30. driver: local # 会生成一个对应的目录和文件,如何查看,下面有说明。
  • 另外两台服务器也照着这个配置进行配置,但 publish_host,以及 node.name 需要改一下即可。

  • 内存设置,三台服务器都需要进行设置

  1. 两种设置内存的方式:
  2. 1、设置简单,但机器重启后需再次设置
  3. sysctl -w vm.max_map_count=262144
  4. 2、直接修改配置文件, 进入sysctl.conf文件添加一行(解决容器内存权限过小问题)
  5. vi /etc/sysctl.conf
  6. sysctl vm.max_map_count=262144 # 添加此行
  7. 退出文件后,执行命令: sysctl -p 立即生效
  1. {
  2. "cluster_name" : "es-cluster",
  3. "status" : "green",
  4. "timed_out" : false,
  5. "number_of_nodes" : 3,
  6. "number_of_data_nodes" : 3,
  7. "active_primary_shards" : 0,
  8. "active_shards" : 0,
  9. "relocating_shards" : 0,
  10. "initializing_shards" : 0,
  11. "unassigned_shards" : 0,
  12. "delayed_unassigned_shards" : 0,
  13. "number_of_pending_tasks" : 0,
  14. "number_of_in_flight_fetch" : 0,
  15. "task_max_waiting_in_queue_millis" : 0,
  16. "active_shards_percent_as_number" : 100.0
  17. }
  • elasticsearch.yml 文件内容如下:
  1. network.host: 0.0.0.0
  2. http.cors.enabled: true # 是否支持跨域
  3. http.cors.allow-origin: "*" # 表示支持所有域名
  • 上面说到的顶级volumes, 如何查看挂载卷在宿主机的位置呢?
  1. # docker volume create elk_data // 创建一个自定义容器卷,本教程内不需要执行,我们的docker-compose.yml会帮我们自动执行改命令。
  2. # docker volume ls // 查看所有容器卷,
  3. # docker volume inspect elk_data // 查看指定容器卷详情信息, 包括真实目录
  4. 注意: 如果你要删除一个挂载卷,或者重新生成,请执行删除卷操作
  5. # docker volume rm elk_data // 直接执行这个命令,同时会删除文件,但是先删除文件的话,必须再次执行此命令,否则可能导致该节点无法加入集群。
  • 以上就是es集群的搭建,如果出现权限不足等简单问题,可以百度自行解决。

  • 接下来我们将在172.168.50.41服务器上搭建elk服务,用elk中的es替换掉50.41服务器上之前的es。

搭建ELK服务

  1. // 下载elasticsearch,logstash,kibana的镜像,建议提前下载好。 自es5开始,一般三个软件的版本都保持一致了。如果下载网络有问题,尝试重新配置一下docker的镜像源地址。
  2. docker pull docker.elastic.co/elasticsearch/elasticsearch:7.1.1 && docker pull docker.elastic.co/logstash/logstash:7.1.1 && docker pull docker.elastic.co/kibana/kibana:7.1.1

配置

  • 我们建立一个目录,用来存放yml文件(docker-compose启动一组编排过的容器时使用)
  1. mkdir -p /root/elk(位置和名称都随意) # 与刚才的elasticsearch目录进行区别
  2. cd /root/elk
  3. vim docker-compose.yml
  • docker-compose.yml文件内容如下
  1. version: '3'
  2. services: # 服务(s代表复数)
  3. elasticsearch: # 服务名称:elasticsearch
  4. image: docker.elastic.co/elasticsearch/elasticsearch:7.1.1 # 使用的镜像以及版本号
  5. container_name: elasticsearch7.1.1 # 容器名称
  6. environment: # 环境变量
  7. - node.name=node-41 # 节点名称
  8. - network.publish_host=172.168.50.41 # 用于集群内各机器间通信,对外使用,其他机器访问本机器的es服务,一般为本机宿主机IP
  9. - network.host=0.0.0.0 # 设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0,即本机
  10. - discovery.seed_hosts=172.168.50.40,172.168.50.240,172.168.50.41 # es7.0之后新增的写法,写入候选主节点的设备地址,在开启服务后,如果master挂了,哪些可以被投票选为主节点
  11. - cluster.initial_master_nodes=172.168.50.40,172.168.50.240,172.168.50.41 # es7.0之后新增的配置,初始化一个新的集群时需要此配置来选举master
  12. - cluster.name=es-cluster # 集群名称,相同名称为一个集群, 三个es节点须一致
  13. - bootstrap.memory_lock=true # 内存交换的选项,官网建议为true
  14. - "ES_JAVA_OPTS=-Xms512m -Xmx512m" # 设置内存,如内存不足,可以尝试调低点
  15. #- discovery.type=single-node # 单es节点模式,这里我们就不启用,启用的话,除了两个内存外其他的环境配置都不需要。
  16. volumes:
  17. - esdata:/usr/share/elasticsearch/data # 设置es数据存放的目录
  18. - /root/elk/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml # 映射es容器中的配置文件到宿主机
  19. hostname: elasticsearch # 服务hostname
  20. ulimits: # 栈内存的上限
  21. memlock:
  22. soft: -1 # 不限制
  23. hard: -1 # 不限制
  24. restart: always # 重启策略,失败时总是重启
  25. ports:
  26. - 9200:9200 # http端口,可以直接浏览器访问
  27. - 9300:9300 # es集群之间相互访问的端口,jar之间就是通过此端口进行tcp协议通信,遵循tcp协议。
  28. kibana: # 服务名称:kibana
  29. image: docker.elastic.co/kibana/kibana:7.1.1 # 使用的镜像及版本号
  30. container_name: kibana7.1.1 # 容器名称
  31. environment: # 环境配置
  32. - elasticsearch.hosts=http://elasticsearch:9200 # 设置连接的es节点,此处的elasticsearch即上面的elasticsearch服务中的hostname:elasticsearch
  33. # - TZ=Asia/Shanghai # 设置容器内时区
  34. hostname: kibana # 服务hostname
  35. depends_on:
  36. - elasticsearch # 依赖es服务,必须先启动es才会启动kibana
  37. restart: always
  38. ports:
  39. - 5601:5601 # 访问的端口号
  40. logstash: # 服务名称:logstash
  41. image: docker.elastic.co/logstash/logstash:7.1.1
  42. container_name: logstash7.1.1
  43. hostname: logstash
  44. restart: always
  45. # volumes: # 挂载卷,先注释,等ELK启动起来之后,从容器中复制出来一份,下面会说
  46. # - /root/elk/logstash/config/:/usr/share/logstash/config/ # logstash 配置文件目录
  47. # - /root/elk/logstash/pipeline/:/usr/share/logstash/pipeline/ # logstash 的采集与输入的配置文件目录
  48. depends_on:
  49. - elasticsearch
  50. # ports:
  51. # - 9600:9600 # 端口号,后来没用到
  52. # - 5044:5044 # filebeat直接传递数据给logstash时默认使用的端口号,测试了一下,没用
  53. volumes:
  54. esdata:
  55. driver: local
  • 上面用到了/root/elk/logstash/ 下面的config目录与pipeline目录,如何得到这两个目录呢?

    // 先停止之前该服务器上的es节点

    docker stop es节点ID

    docker rm es节点ID

    • 1、在/root/elk目录下,docker-compose up -d 启动elk

    • 2、mkdir logstash

    • 3、从容器中复制两个目录到logstash下,这样我们就有了初始配置文件

  1. docker cp 容器ID:/usr/share/logstash/config/ logstash // 容器ID为Logstash的ID
  2. docker cp 容器ID:/usr/share/logstash/pipeline/ logstash
  • 修改配置文件 config目录中的logstash.yml文件,内容如下
  1. http.host: "0.0.0.0"
  2. xpack.monitoring.enabled: true
  3. xpack.monitoring.elasticsearch.hosts: [ "172.168.50.41:9200","172.168.50.40:9200","172.168.50.240:9200" ]
  4. // elasticsearch.hosts 为你的es服务器列表以及端口号,用于将数据存储到es
  • 修改pipeline目录中的logstash.conf文件(此文件是通过config目录下的 pipelines.yml 来指定的),内容如下
  1. input{ # 输入组件
  2. kafka{ # 从kafka消费数据
  3. bootstrap_servers => ["172.168.50.41:9092,172.168.50.41:9097,172.168.50.41:9098"] # kafka节点的IP+端口号
  4. #topics => "%{[@metadata][topic]}" # 使用kafka传过来的topic
  5. topics_pattern => "elk-.*" # 使用正则匹配topic
  6. codec => "json" # 数据格式
  7. consumer_threads => 3 # 消费线程数量
  8. decorate_events => true # 可向事件添加Kafka元数据,比如主题、消息大小的选项,这将向logstash事件中添加一个名为kafka的字段,
  9. auto_offset_reset => "latest" # 自动重置偏移量到最新的偏移量
  10. group_id => "logstash-node-41" # 消费组ID,多个有相同group_id的logstash实例为一个消费组
  11. }
  12. }
  13. filter {
  14. # 当非业务字段时,无traceId则移除
  15. if ([message] =~ "traceId=null") { # 过滤组件,这里只是展示,无实际意义,根据自己的业务需求进行过滤
  16. drop {}
  17. }
  18. }
  19. output { # 输出组件
  20. elasticsearch {
  21. # Logstash输出到es
  22. hosts => ["172.168.50.41:9200", "172.168.50.40:9200", "172.168.50.240:9200"]
  23. # index => "%{[fields][source]}" #直接在日志中匹配,索引会去掉elk
  24. index => "%{[@metadata][topic]}-%{+YYYY-MM-dd}" # 以日期建索引
  25. #flush_size => 20000
  26. #idle_flush_time => 10
  27. #sniffing => true
  28. #template_overwrite => false
  29. }
  30. # stdout {
  31. # codec => rubydebug
  32. # }
  33. }
  34. # 可以写多个input,但是output中的index即索引要处理好,根据过滤组件或者kafka传过来的不同话题,应有不同的索引
  35. # 也可以写多个output,向其他程序(非es)传送数据
  • 有了这两个目录后,将docker-compose.yml文件中的三行注释打开
  1. volumes: # 挂载卷,先注释,等ELK启动起来之后,从容器中复制出来一份,下面会说
  2. - /root/elk/logstash/config/:/usr/share/logstash/config/ # logstash 配置文件目录
  3. - /root/elk/logstash/pipeline/:/usr/share/logstash/pipeline/ # logstash 的采集与输入的配置文件目录
  • 在/root/elk目录,重新编译和启动elk
  1. // 启动ELK
  2. docker-compose up -d --force --build
  • 出现done表示成功,docker-compose logs 查看日志(分别输出elk三个服务的日志)执行docker-compose ps 可以看到三个服务的运行状态

  • 在浏览器输入http://IP:5601/ 访问kibana。

  • 可以使用head监控es

  1. // 拉取镜像
  2. docker pull mobz/elasticsearch-head:5
  3. // 启动
  4. docker run -d --name es_admin -p 9100:9100 mobz/elasticsearch-head:5
  • 在浏览器输入http://IP:9100

  • 注意,IP地址要使用你es所在服务器的地址,然后点击连接,出现类似的显示说明,没问题,本教程是三个节点,当关掉一个es会变成两个节点。

  • 如果点击连接没有反应,F12查看network是403,或者200,但是console中提示跨域,那么应该是跨域未设置好,重新回去检查一遍,看看容器内配置文件是否加入了那两行跨域。

  • 至此,我们的Elasticsearch(集群)+ Logstash + Kibana 搭建完成, 你可以在kibana中的dev-tools菜单中操作es,甚至向es中添加数据,或者通过其他方式向es中添加数据进行测试。

  • Logstash可以采集数据, 过滤数据; Elasticsearch 可以存储和索引数据; Kibana提供可视化展示和操作

  • 这个时候就可以配置Logstash采集数据然后想es输入了,但是我们并不满足于此,我想在需要采集日志的应用服务器上安装 filebeat,然后经filebeat将数据转发给Logstash,Logstash只进行过滤即可(也可以filebeat直接将数据传给es,不要Logstash,看个人需求)。

  • 但我没有保留filebeat直接传给Logstash的配置文件,所以我们直接在此时将kafka也接入进来,不再演示filebeat与Logstash直接交互的情景。

  • 不用担心,我们尽量降低复杂度,比如,现在我们不考虑ELK,也不考虑filebeat,抛开这些东西,仅仅搭建一个kafka集群。

  • kafka依赖zookeeper,我们前面说过,本文使用独立的zookeeper集群,所以接下来介绍如何搭建zookeeper

zookeeper集群的搭建

  • 依然是三节点集群,但是为了减少复杂性,我们直接在172.168.50.41(内存最大的服务器)上通过docker容器搭建单机zookeeper集群。

  • 建立目录,并创建yml文件

  1. mkdir -p /root/zookeeper
  2. cd /root/zookeeper
  3. vim docker-compose.yml
  • docker-compose.yml文件内容如下:
  1. version: '2'
  2. services:
  3. zoo1:
  4. image: zookeeper:3.4.14 # 尽量使用3.4版本,3.4.14的镜像就可以。 3.5坑太多
  5. restart: always
  6. hostname: zoo1
  7. container_name: zoo1
  8. ports:
  9. - 2181:2181 # 端口号
  10. volumes:
  11. - /usr/local/docker-compose/zk/zk1/data:/data # 数据文件存放目录
  12. - /usr/local/docker-compose/zk/zk1/datalog:/datalog # 日志文件存放目录
  13. - /root/zookeeper/zoo.cfg:/conf/zoo.cfg # zookeeper的配置文件,下面会给出该文件内容
  14. environment:
  15. ZOO_MY_ID: 1 # 表示 ZK服务的 id, 它是1-255 之间的整数, 必须在集群中唯一
  16. ZOO_SERVERS: server.1=0.0.0.0:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=zoo3:2888:3888;2181 # ZK集群的主机列表即端口号
  17. # ZOOKEEPER_CLIENT_PORT: 2181
  18. networks:
  19. default:
  20. ipv4_address: 172.23.0.11 # 集群使用的网络
  21. zoo2:
  22. image: zookeeper:3.4.14
  23. restart: always
  24. hostname: zoo2
  25. container_name: zoo2
  26. ports:
  27. - 2180:2181
  28. volumes:
  29. - /usr/local/docker-compose/zk/zk2/data:/data
  30. - /usr/local/docker-compose/zk/zk2/datalog:/datalog
  31. - /root/zookeeper/zoo.cfg:/conf/zoo.cfg
  32. environment:
  33. ZOO_MY_ID: 2
  34. #ZOOKEEPER_CLIENT_PORT: 2181
  35. ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=0.0.0.0:2888:3888;2181 server.3=zoo3:2888:3888;2181
  36. networks:
  37. default:
  38. ipv4_address: 172.23.0.12
  39. zoo3:
  40. image: zookeeper:3.4.14
  41. restart: always
  42. hostname: zoo3
  43. container_name: zoo3
  44. ports:
  45. - 2179:2181
  46. volumes:
  47. - /usr/local/docker-compose/zk/zk3/data:/data
  48. - /usr/local/docker-compose/zk/zk3/datalog:/datalog
  49. - /root/zookeeper/zoo.cfg:/conf/zoo.cfg
  50. environment:
  51. ZOO_MY_ID: 3
  52. #ZOOKEEPER_CLIENT_PORT: 2181
  53. ZOO_SERVERS: server.1=zoo1:2888:3888;2181 server.2=zoo2:2888:3888;2181 server.3=0.0.0.0:2888:3888;2181
  54. networks:
  55. default:
  56. ipv4_address: 172.23.0.13
  57. networks:
  58. default:
  59. external:
  60. name: zookeeper_network # 网络名称,此网络需要进行创建
  • zoo.cfg文件内容如下:
  1. tickTime=2000 # 心跳2秒,服务器之间或客户端与服务器之间维持心跳的时间间隔
  2. initLimit=10 # 集群中的follower服务器(F)与leader服务器(L)之间 初始连接 时能容忍的最多心跳数(tickTime的数量)。
  3. syncLimit=5 # 集群中的follower服务器(F)与leader服务器(L)之间 请求和应答 之间能容忍的最多心跳数(tickTime的数量)。
  4. dataDir=/data # 数据目录
  5. dataLogDir=/datalog # 日志文件目录
  6. clientPort=2181 # 客户端连接端口
  7. autopurge.snapRetainCount=3 # 至少需要保留3个快照数据文件和对应的事务日志文件
  8. autopurge.purgeInterval=1 # 进行历史文件自动清理的频率,单位小时
  9. server.1= zoo1:2888:3888 # 定义个服务通信端口,以及投票端口
  10. server.2= zoo2:2888:3888
  11. server.3= zoo3:2888:3888
  • 启动前先创建网络
  1. docker network create --driver bridge --subnet 172.23.0.0/25 --gateway 172.23.0.1 zookeeper_network
  • 启动zk集群
  1. 当前目录下执行 docker-compose up -d
  • 连接zk,并打开客户端
  1. docker run -it --rm --link zoo1:zk1 --link zoo2:zk2 --link zoo3:zk3 --net zookeeper_network zookeeper:3.4.14 zkCli.sh -server zk1:2181,zk2:2181,zk3:2181
  2. // 执行完上面的命令后,会进去zk的客户端,我们可以进行一些操作,比如
  3. 执行 ls / 可以查看根节点信息,然后根据现实内容,查看下一级数据节点的信息
  4. 建议等下搭建完kafka集群并创建topic后通过 ls /brokers/topics 来查看topic列表(kafkazookeeper注册后,创建的话题会被zookeeper记录下来)
  5. zk常用命令
  6. create /test "test"
  7. get /test
  8. set /test "hello test"
  9. delete /test
  10. quit
  • 至此zookeeper集群搭建完毕,比较简单。

kafka集群的搭建

  • 老规矩先建立目录,用于存放yml文件以及kafka的配置文件
  1. mkdir -p /root/kafka
  2. cd /root/kafka
  3. vim docker-compose.yml
  • docker-compose.yml 文件内容如下:
  1. version: '2'
  2. services:
  3. kafka1:
  4. image: wurstmeister/kafka:2.12-2.3.0
  5. restart: always
  6. hostname: kafka1
  7. container_name: kafka1
  8. ports:
  9. - "9092:9092"
  10. environment:
  11. KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://172.168.50.41:9092 # 宿主机的IP地址而非容器的IP,及暴露出来的端口
  12. KAFKA_ADVERTISED_HOST_NAME: 172.168.50.41 # 外网访问地址
  13. KAFKA_ADVERTISED_PORT: 9092 # 端口
  14. KAFKA_ZOOKEEPER_CONNECT: zoo1:2181,zoo2:2181,zoo3:2181 # 连接的zookeeper服务及端口
  15. JMX_PORT: 9966 # kafka需要监控broker和topic的数据的时候,是需要开启jmx_port的
  16. volumes:
  17. - /usr/local/docker-compose/kafka/kafka1:/kafka # kafka数据文件存储目录
  18. - /root/kafka/kafka-run-class.sh:/opt/kafka_2.12-2.3.0/bin/kafka-run-class.sh # kafka启动时的配置文件,我们修改了一部分代码,用来解决java.rmi.server.ExportException: Port already in use这个问题。过程详见https://github.com/apache/kafka/pull/1983/commits/2c5d40e946bcc149b1a9b2c01eced4ae47a734c5。
  19. external_links: # 连接本compose文件以外的容器
  20. - zoo1
  21. - zoo2
  22. - zoo3
  23. networks:
  24. default:
  25. ipv4_address: 172.23.0.14 # 使用zookeeper创建的网络中一个IP
  26. kafka2:
  27. image: wurstmeister/kafka:2.12-2.3.0
  28. restart: always
  29. hostname: kafka2
  30. container_name: kafka2
  31. ports:
  32. - "9097:9092"
  33. environment:
  34. KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://172.168.50.41:9097
  35. KAFKA_ADVERTISED_HOST_NAME: 172.168.50.41
  36. KAFKA_ADVERTISED_PORT: 9097
  37. KAFKA_ZOOKEEPER_CONNECT: zoo1:2181,zoo2:2181,zoo3:2181
  38. JMX_PORT: 9988
  39. volumes:
  40. - /usr/local/docker-compose/kafka/kafka2:/kafka
  41. - /root/kafka/kafka-run-class.sh:/opt/kafka_2.12-2.3.0/bin/kafka-run-class.sh
  42. external_links: # 连接compose文件以外的container
  43. - zoo1
  44. - zoo2
  45. - zoo3
  46. networks:
  47. default:
  48. ipv4_address: 172.23.0.15
  49. kafka3:
  50. image: wurstmeister/kafka:2.12-2.3.0
  51. restart: always
  52. hostname: kafka3
  53. container_name: kafka3
  54. ports:
  55. - "9098:9092"
  56. environment:
  57. KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://172.168.50.41:9098
  58. KAFKA_ADVERTISED_HOST_NAME: 172.168.50.41
  59. KAFKA_ADVERTISED_PORT: 9098
  60. KAFKA_ZOOKEEPER_CONNECT: zoo1:2181,zoo2:2181,zoo3:2181
  61. JMX_PORT: 9977
  62. volumes:
  63. - /usr/local/docker-compose/kafka/kafka3
  64. - /root/kafka/kafka-run-class.sh:/opt/kafka_2.12-2.3.0/bin/kafka-run-class.sh
  65. external_links: # 连接compose文件以外的container
  66. - zoo1
  67. - zoo2
  68. - zoo3
  69. networks:
  70. default:
  71. ipv4_address: 172.23.0.16
  72. kafka-manager: # kafka管理和监控的一个工具
  73. image: sheepkiller/kafka-manager:latest # 此时我使用的最新版本为5.0
  74. restart: always
  75. container_name: kafa-manager
  76. hostname: kafka-manager
  77. ports:
  78. - "9099:9000" # 浏览器访问的端口
  79. links: # 连接本compose文件创建的container
  80. - kafka1
  81. - kafka2
  82. - kafka3
  83. external_links: # 连接compose文件以外的container
  84. - zoo1
  85. - zoo2
  86. - zoo3
  87. environment:
  88. ZK_HOSTS: zoo1:2181,zoo2:2181,zoo3:2181 # zk服务列表
  89. KAFKA_BROKERS: kafka1:9092,kafka2:9097,kafka3:9098 # kafka节点列表及端口号
  90. APPLICATION_SECRET: letmein # 应用秘钥,默认letmein
  91. KM_ARGS: -Djava.net.preferIPv4Stack=true # 在ipv4的机器上想获取到完整的机器名, 应该是IPV4网络相关的东西
  92. networks:
  93. default:
  94. ipv4_address: 172.23.0.10 # IP地址,zookeeper创建的网络中的一个IP
  95. networks:
  96. default:
  97. external:
  98. name: zookeeper_network # 使用zookeeper创建的网络
  1. #!/bin/bash
  2. # Licensed to the Apache Software Foundation (ASF) under one or more
  3. # contributor license agreements. See the NOTICE file distributed with
  4. # this work for additional information regarding copyright ownership.
  5. # The ASF licenses this file to You under the Apache License, Version 2.0
  6. # (the "License"); you may not use this file except in compliance with
  7. # the License. You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. if [ $# -lt 1 ];
  17. then
  18. echo "USAGE: $0 [-daemon] [-name servicename] [-loggc] classname [opts]"
  19. exit 1
  20. fi
  21. # CYGWIN == 1 if Cygwin is detected, else 0.
  22. if [[ $(uname -a) =~ "CYGWIN" ]]; then
  23. CYGWIN=1
  24. else
  25. CYGWIN=0
  26. fi
  27. if [ -z "$INCLUDE_TEST_JARS" ]; then
  28. INCLUDE_TEST_JARS=false
  29. fi
  30. # Exclude jars not necessary for running commands.
  31. regex="(-(test|test-sources|src|scaladoc|javadoc)\.jar|jar.asc)$"
  32. should_include_file() {
  33. if [ "$INCLUDE_TEST_JARS" = true ]; then
  34. return 0
  35. fi
  36. file=$1
  37. if [ -z "$(echo "$file" | egrep "$regex")" ] ; then
  38. return 0
  39. else
  40. return 1
  41. fi
  42. }
  43. ################ lizheng #################
  44. # need to check if called to start server or client
  45. # in order to correctly decide about JMX_PORT
  46. ISKAFKASERVER="false"
  47. if [[ "$*" =~ "kafka.Kafka" ]]; then
  48. ISKAFKASERVER="true"
  49. fi
  50. ################ lizheng #################
  51. base_dir=$(dirname $0)/..
  52. if [ -z "$SCALA_VERSION" ]; then
  53. SCALA_VERSION=2.12.8
  54. fi
  55. if [ -z "$SCALA_BINARY_VERSION" ]; then
  56. SCALA_BINARY_VERSION=$(echo $SCALA_VERSION | cut -f 1-2 -d '.')
  57. fi
  58. # run ./gradlew copyDependantLibs to get all dependant jars in a local dir
  59. shopt -s nullglob
  60. for dir in "$base_dir"/core/build/dependant-libs-${SCALA_VERSION}*;
  61. do
  62. CLASSPATH="$CLASSPATH:$dir/*"
  63. done
  64. for file in "$base_dir"/examples/build/libs/kafka-examples*.jar;
  65. do
  66. if should_include_file "$file"; then
  67. CLASSPATH="$CLASSPATH":"$file"
  68. fi
  69. done
  70. if [ -z "$UPGRADE_KAFKA_STREAMS_TEST_VERSION" ]; then
  71. clients_lib_dir=$(dirname $0)/../clients/build/libs
  72. streams_lib_dir=$(dirname $0)/../streams/build/libs
  73. rocksdb_lib_dir=$(dirname $0)/../streams/build/dependant-libs-${SCALA_VERSION}
  74. else
  75. clients_lib_dir=/opt/kafka-$UPGRADE_KAFKA_STREAMS_TEST_VERSION/libs
  76. streams_lib_dir=$clients_lib_dir
  77. rocksdb_lib_dir=$streams_lib_dir
  78. fi
  79. for file in "$clients_lib_dir"/kafka-clients*.jar;
  80. do
  81. if should_include_file "$file"; then
  82. CLASSPATH="$CLASSPATH":"$file"
  83. fi
  84. done
  85. for file in "$streams_lib_dir"/kafka-streams*.jar;
  86. do
  87. if should_include_file "$file"; then
  88. CLASSPATH="$CLASSPATH":"$file"
  89. fi
  90. done
  91. if [ -z "$UPGRADE_KAFKA_STREAMS_TEST_VERSION" ]; then
  92. for file in "$base_dir"/streams/examples/build/libs/kafka-streams-examples*.jar;
  93. do
  94. if should_include_file "$file"; then
  95. CLASSPATH="$CLASSPATH":"$file"
  96. fi
  97. done
  98. else
  99. VERSION_NO_DOTS=`echo $UPGRADE_KAFKA_STREAMS_TEST_VERSION | sed 's/\.//g'`
  100. SHORT_VERSION_NO_DOTS=${VERSION_NO_DOTS:0:((${#VERSION_NO_DOTS} - 1))} # remove last char, ie, bug-fix number
  101. for file in "$base_dir"/streams/upgrade-system-tests-$SHORT_VERSION_NO_DOTS/build/libs/kafka-streams-upgrade-system-tests*.jar;
  102. do
  103. if should_include_file "$file"; then
  104. CLASSPATH="$file":"$CLASSPATH"
  105. fi
  106. done
  107. fi
  108. for file in "$rocksdb_lib_dir"/rocksdb*.jar;
  109. do
  110. CLASSPATH="$CLASSPATH":"$file"
  111. done
  112. for file in "$base_dir"/tools/build/libs/kafka-tools*.jar;
  113. do
  114. if should_include_file "$file"; then
  115. CLASSPATH="$CLASSPATH":"$file"
  116. fi
  117. done
  118. for dir in "$base_dir"/tools/build/dependant-libs-${SCALA_VERSION}*;
  119. do
  120. CLASSPATH="$CLASSPATH:$dir/*"
  121. done
  122. for cc_pkg in "api" "transforms" "runtime" "file" "json" "tools" "basic-auth-extension"
  123. do
  124. for file in "$base_dir"/connect/${cc_pkg}/build/libs/connect-${cc_pkg}*.jar;
  125. do
  126. if should_include_file "$file"; then
  127. CLASSPATH="$CLASSPATH":"$file"
  128. fi
  129. done
  130. if [ -d "$base_dir/connect/${cc_pkg}/build/dependant-libs" ] ; then
  131. CLASSPATH="$CLASSPATH:$base_dir/connect/${cc_pkg}/build/dependant-libs/*"
  132. fi
  133. done
  134. # classpath addition for release
  135. for file in "$base_dir"/libs/*;
  136. do
  137. if should_include_file "$file"; then
  138. CLASSPATH="$CLASSPATH":"$file"
  139. fi
  140. done
  141. for file in "$base_dir"/core/build/libs/kafka_${SCALA_BINARY_VERSION}*.jar;
  142. do
  143. if should_include_file "$file"; then
  144. CLASSPATH="$CLASSPATH":"$file"
  145. fi
  146. done
  147. shopt -u nullglob
  148. if [ -z "$CLASSPATH" ] ; then
  149. echo "Classpath is empty. Please build the project first e.g. by running './gradlew jar -PscalaVersion=$SCALA_VERSION'"
  150. exit 1
  151. fi
  152. # JMX settings
  153. if [ -z "$KAFKA_JMX_OPTS" ]; then
  154. KAFKA_JMX_OPTS="-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false "
  155. fi
  156. # JMX port to use
  157. #if [ $JMX_PORT ]; then
  158. if [ $JMX_PORT ] && [ -z "$ISKAFKASERVER" ]; then
  159. KAFKA_JMX_OPTS="$KAFKA_JMX_OPTS -Dcom.sun.management.jmxremote.port=$JMX_PORT "
  160. fi
  161. # Log directory to use
  162. if [ "x$LOG_DIR" = "x" ]; then
  163. LOG_DIR="$base_dir/logs"
  164. fi
  165. # Log4j settings
  166. if [ -z "$KAFKA_LOG4J_OPTS" ]; then
  167. # Log to console. This is a tool.
  168. LOG4J_DIR="$base_dir/config/tools-log4j.properties"
  169. # If Cygwin is detected, LOG4J_DIR is converted to Windows format.
  170. (( CYGWIN )) && LOG4J_DIR=$(cygpath --path --mixed "${LOG4J_DIR}")
  171. KAFKA_LOG4J_OPTS="-Dlog4j.configuration=file:${LOG4J_DIR}"
  172. else
  173. # create logs directory
  174. if [ ! -d "$LOG_DIR" ]; then
  175. mkdir -p "$LOG_DIR"
  176. fi
  177. fi
  178. # If Cygwin is detected, LOG_DIR is converted to Windows format.
  179. (( CYGWIN )) && LOG_DIR=$(cygpath --path --mixed "${LOG_DIR}")
  180. KAFKA_LOG4J_OPTS="-Dkafka.logs.dir=$LOG_DIR $KAFKA_LOG4J_OPTS"
  181. # Generic jvm settings you want to add
  182. if [ -z "$KAFKA_OPTS" ]; then
  183. KAFKA_OPTS=""
  184. fi
  185. # Set Debug options if enabled
  186. if [ "x$KAFKA_DEBUG" != "x" ]; then
  187. # Use default ports
  188. DEFAULT_JAVA_DEBUG_PORT="5005"
  189. if [ -z "$JAVA_DEBUG_PORT" ]; then
  190. JAVA_DEBUG_PORT="$DEFAULT_JAVA_DEBUG_PORT"
  191. fi
  192. # Use the defaults if JAVA_DEBUG_OPTS was not set
  193. DEFAULT_JAVA_DEBUG_OPTS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=${DEBUG_SUSPEND_FLAG:-n},address=$JAVA_DEBUG_PORT"
  194. if [ -z "$JAVA_DEBUG_OPTS" ]; then
  195. JAVA_DEBUG_OPTS="$DEFAULT_JAVA_DEBUG_OPTS"
  196. fi
  197. echo "Enabling Java debug options: $JAVA_DEBUG_OPTS"
  198. KAFKA_OPTS="$JAVA_DEBUG_OPTS $KAFKA_OPTS"
  199. fi
  200. # Which java to use
  201. if [ -z "$JAVA_HOME" ]; then
  202. JAVA="java"
  203. else
  204. JAVA="$JAVA_HOME/bin/java"
  205. fi
  206. # Memory options
  207. if [ -z "$KAFKA_HEAP_OPTS" ]; then
  208. KAFKA_HEAP_OPTS="-Xmx256M"
  209. fi
  210. # JVM performance options
  211. if [ -z "$KAFKA_JVM_PERFORMANCE_OPTS" ]; then
  212. KAFKA_JVM_PERFORMANCE_OPTS="-server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -Djava.awt.headless=true"
  213. fi
  214. while [ $# -gt 0 ]; do
  215. COMMAND=$1
  216. case $COMMAND in
  217. -name)
  218. DAEMON_NAME=$2
  219. CONSOLE_OUTPUT_FILE=$LOG_DIR/$DAEMON_NAME.out
  220. shift 2
  221. ;;
  222. -loggc)
  223. if [ -z "$KAFKA_GC_LOG_OPTS" ]; then
  224. GC_LOG_ENABLED="true"
  225. fi
  226. shift
  227. ;;
  228. -daemon)
  229. DAEMON_MODE="true"
  230. shift
  231. ;;
  232. *)
  233. break
  234. ;;
  235. esac
  236. done
  237. # GC options
  238. GC_FILE_SUFFIX='-gc.log'
  239. GC_LOG_FILE_NAME=''
  240. if [ "x$GC_LOG_ENABLED" = "xtrue" ]; then
  241. GC_LOG_FILE_NAME=$DAEMON_NAME$GC_FILE_SUFFIX
  242. # The first segment of the version number, which is '1' for releases before Java 9
  243. # it then becomes '9', '10', ...
  244. # Some examples of the first line of `java --version`:
  245. # 8 -> java version "1.8.0_152"
  246. # 9.0.4 -> java version "9.0.4"
  247. # 10 -> java version "10" 2018-03-20
  248. # 10.0.1 -> java version "10.0.1" 2018-04-17
  249. # We need to match to the end of the line to prevent sed from printing the characters that do not match
  250. JAVA_MAJOR_VERSION=$($JAVA -version 2>&1 | sed -E -n 's/.* version "([0-9]*).*$/\1/p')
  251. if [[ "$JAVA_MAJOR_VERSION" -ge "9" ]] ; then
  252. KAFKA_GC_LOG_OPTS="-Xlog:gc*:file=$LOG_DIR/$GC_LOG_FILE_NAME:time,tags:filecount=10,filesize=102400"
  253. else
  254. KAFKA_GC_LOG_OPTS="-Xloggc:$LOG_DIR/$GC_LOG_FILE_NAME -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCTimeStamps -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=100M"
  255. fi
  256. fi
  257. # Remove a possible colon prefix from the classpath (happens at lines like `CLASSPATH="$CLASSPATH:$file"` when CLASSPATH is blank)
  258. # Syntax used on the right side is native Bash string manipulation; for more details see
  259. # http://tldp.org/LDP/abs/html/string-manipulation.html, specifically the section titled "Substring Removal"
  260. CLASSPATH=${CLASSPATH#:}
  261. # If Cygwin is detected, classpath is converted to Windows format.
  262. (( CYGWIN )) && CLASSPATH=$(cygpath --path --mixed "${CLASSPATH}")
  263. # Launch mode
  264. if [ "x$DAEMON_MODE" = "xtrue" ]; then
  265. nohup $JAVA $KAFKA_HEAP_OPTS $KAFKA_JVM_PERFORMANCE_OPTS $KAFKA_GC_LOG_OPTS $KAFKA_JMX_OPTS $KAFKA_LOG4J_OPTS -cp $CLASSPATH $KAFKA_OPTS "$@" > "$CONSOLE_OUTPUT_FILE" 2>&1 < /dev/null &
  266. else
  267. exec $JAVA $KAFKA_HEAP_OPTS $KAFKA_JVM_PERFORMANCE_OPTS $KAFKA_GC_LOG_OPTS $KAFKA_JMX_OPTS $KAFKA_LOG4J_OPTS -cp $CLASSPATH $KAFKA_OPTS "$@"
  268. fi
  • 启动kafka,在当前目录下
  1. docker-compose up -d
注意点:
  1. 1、单机搭建zk集群需要创建网络
  2. 2zk的版本要使用3.4的,3.5坑太多,另外需要挂载配置文件,并在配置文件中设置客户端端口
  3. 3、使kafkazk在同一网络下,
  4. 4、映射kafka-run-class.sh文件,主要修改配置解决JMX_PORT相关的报错
  • 通过 http://你的IP:9099 访问kafka-manager,然后点击 Cluster 按钮, 在下拉框中选择 Add Cluster, 添加你的kafka集群接口,其中kafka的版本不用管他

  • 然后查看该集群,能看到相关的zookeeper、topic等信息。

  • 然后我们可以创建话题并查看

  1. 1 通过docker exec -it 容器ID /bin/bash 进入容器
  2. 2 cd /opt/kafka_2.12-2.3.0/
  3. 3 bin/kafka-topics.sh --create --zookeeper zoo1:2181 --replication-factor 3 --partitions 3 --topic test (测试数据记得删除)
  4. 4 bin/kafka-topics.sh --list --zookeeper zoo1:2181 # 查看话题列表
  • 话题创建成功后,就可以退出容器了,我们在宿主机上运行一个生产者和一个消费者
  1. 运行一个消息生产者
  2. bin/kafka-console-producer.sh --broker-list localhost:9092 --topic test
  3. 运行一个消息消费者
  4. bin/kafka-console-consumer.sh --bootstrap-server localhost:9092 --topic test --from-beginning
  5. 此时我们在生产者中输入任何字符,都会及时的显示在消费者的页面中,并且kafkazookeeper注册后,创建的话题会被zookeeper记录下来。
  • 另外我们可以在zookeeper中查看话题是否创建成功
  1. 连接zk,并打开客户端
  2. docker run -it --rm --link zoo1:zk1 --link zoo2:zk2 --link zoo3:zk3 --net zookeeper_network zookeeper:3.4.14 zkCli.sh -server zk1:2181,zk2:2181,zk3:2181
  3. // 执行完上面的命令后,会进去zk的客户端,我们可以进行一些操作,比如
  4. 执行 ls / 可以查看根节点信息,然后根据现实内容,查看下一级数据节点的信息
  5. 建议等下搭建完kafka集群并创建topic后通过 ls /brokers/topics 来查看topic列表(kafkazookeeper注册后,创建的话题会被zookeeper记录下来)
  • 至此,kafka + zookeeper 集群搭建完毕,也进行了topic的创建以及监听,记得删除测试数据。

下面讲解filebeat的部署在应用服务器采集应用或系统日志,此处我们以Nginx日志为例

我们选择172.168.50.240 作为应用服务器,你可以将filebeat部署到任何可以与kafka集群通信的机器

  • 老规矩,建立文件夹,存放yml以及filebeat的配置文件
  1. mkdir -p /root/filebeat // 可以是任意目录
  2. cd /root/filebeat
  3. vim docker-compose.yml
  • docker-compose.yml的内容如下:
  1. version: '3'
  2. services:
  3. filebeat-240:
  4. image: docker.elastic.co/beats/filebeat:7.1.1 # 镜像依然选择与elk的版本一致
  5. container_name: filebeat-240
  6. restart: always
  7. volumes:
  8. - /home/wwwlogs:/home/wwwlogs # 此处是宿主机的Nginx日志目录(修改为你自己的目录)
  9. # - /root/dockerfiles/nginx/logs:/logs/nginx/logs # 宿主机部署了nginx+php的 docker环境,此处为容器中Nginx映射到宿主机的日志目录
  10. - /root/filebeat/filebeat.yml:/usr/share/filebeat/filebeat.yml # filebeat的配置文件
  • 上面提到的filebeat.yml 配置文件如下:
  1. filebeat.inputs: # inputs为复数,表名type可以有多个
  2. - type: log # 输入类型
  3. access:
  4. enabled: true # 启用这个type配置
  5. paths:
  6. - /logs/nginx/logs/access.log # 监控nginx1 的access日志,建议采集日志时先采集单一nginx的access日志。
  7. - /home/wwwlogs/access.log # 监控nginx2 的access日志(docker产生的日志)
  8. close_rename: true # 重命名后,文件将不会继续被采集信息
  9. tail_files: true # 配置为true时,filebeat将从新文件的最后位置开始读取,如果配合日志轮循使用,新文件的第一行将被跳过
  10. multiline.pattern: '^\[.+\]' # 这三行表示,如果是多行日志,合并为一行
  11. multiline.negate: true
  12. multiline.match: "after"
  13. fields: # 额外的字段
  14. source: nginx-access-240 # 自定义source字段,用于es建议索引(字段名小写,我记得大写好像不行)
  15. - type: log
  16. access:
  17. enabled: true
  18. paths:
  19. - /logs/nginx/logs/error.log # 监控nginx1 的error日志
  20. - /home/wwwlogs/error.log # 监控nginx2 的error日志(docker产生的日志)
  21. fields:
  22. source: nginx-error-240
  23. # 多行合并一行配置
  24. multiline.pattern: '^\[.+\]'
  25. multiline.negate: true
  26. multiline.match: "after"
  27. tail_files: true
  28. filebeat.config: # 这里是filebeat的各模块配置,我理解modules为inputs的一种新写法。
  29. modules:
  30. path: ${path.config}/modules.d/*.yml # 进入容器查看这里有很多模块配置文件,Nginx,redis,apache什么的
  31. reload.enabled: false # 设置为true来启用配置重载
  32. reload.period: 10s # 检查路径下的文件更改的期间(多久检查一次)
  33. # 在7.4版本中,自定义es的索引需要把ilm设置为false, 这里未验证,抄来的
  34. setup.ilm.enabled: false
  35. output.kafka: # 输出到kafka
  36. enabled: true # 该output配置是否启用
  37. hosts: ["172.168.50.41:9092", "172.168.50.41:9097", "172.168.50.41:9098"] # kafka节点列表
  38. topic: "elk-%{[fields.source]}" # kafka会创建该topic,然后logstash(可以过滤修改)会传给es作为索引名称
  39. partition.hash:
  40. reachable_only: true # 是否只发往可达分区
  41. compression: gzip # 压缩
  42. max_message_bytes: 1000000 # Event最大字节数。默认1000000。应小于等于kafka broker message.max.bytes值
  43. required_acks: 1 # kafka ack等级
  44. worker: 3 # kafka output的最大并发数
  45. # version: 0.10.1 # kafka版本
  46. bulk_max_size: 2048 # 单次发往kafka的最大事件数
  47. logging.to_files: true # 输出所有日志到file,默认true, 达到日志文件大小限制时,日志文件会自动限制替换,详细配置:https://www.cnblogs.com/qinwengang/p/10982424.html
  48. close_older: 30m # 如果一个文件在某个时间段内没有发生过更新,则关闭监控的文件handle。默认1h
  49. force_close_files: false # 这个选项关闭一个文件,当文件名称的变化。只在window建议为true
  50. #没有新日志采集后多长时间关闭文件句柄,默认5分钟,设置成1分钟,加快文件句柄关闭;
  51. #close_inactive: 1m
  52. #
  53. ##传输了3h后荏没有传输完成的话就强行关闭文件句柄,这个配置项是解决以上案例问题的key point;
  54. #close_timeout: 3h
  55. #
  56. ###这个配置项也应该配置上,默认值是0表示不清理,不清理的意思是采集过的文件描述在registry文件里永不清理,在运行一段时间后,registry会变大,可能会带来问题。
  57. #clean_inactive: 72h
  58. #
  59. ##设置了clean_inactive后就需要设置ignore_older,且要保证ignore_older < clean_inactive
  60. #ignore_older: 70h
  61. #
  62. ## 限制 CPU和内存资源
  63. #max_procs: 1
  64. #queue.mem.events: 256
  65. #queue.mem.flush.min_events: 128
  • 配置完成后,docker-compose up -d 启动filebeat服务

  • 访问你的nginx,看看access.log文件是否正常产生日志

  • 通过kafka-manage查看是否接受到消息 http://172.168.50.41:9099/ (部署kafka-manage服务的机器)

  • kafka正常收到消息后,通过elasticsearch-head查看是否正常建立索引 http://172.168.50.41:9201/ (部署elasticsearch-head服务的机器)

  • 如kafka未正常收到消息,检查file的配置,如es未正常建立索引,检查logstash配置并查看日志

  • 查看单个容器日志

  1. docker logs --since 30m 容器ID

以上就是日志采集与存储的过程,以Nginx的access.log日志(应用日志,接口日志也一样)为例,filebeat从服务器的日志文件采集到日志,发送给kafka,然后由logstash进行消费,再经由logstash过滤后输出到elasticsearch进行存储并建立索引。

  • 需要注意的一点就是容器内时区设置的问题

  • kibana的使用教程,不打算写了,我会找一篇优质的文章贴过来。

  • 转载请注明原文

完整的ELK+filebeat+kafka笔记的更多相关文章

  1. ELK+Filebeat+Kafka+ZooKeeper 构建海量日志分析平台(elk5.2+filebeat2.11)

    ELK+Filebeat+Kafka+ZooKeeper 构建海量日志分析平台 参考:http://www.tuicool.com/articles/R77fieA 我在做ELK日志平台开始之初选择为 ...

  2. ELK+Filebeat+Kafka+ZooKeeper 构建海量日志分析平台

    日志分析平台,架构图如下: 架构解读 : (整个架构从左到右,总共分为5层) 第一层.数据采集层 最左边的是业务服务器集群,上面安装了filebeat做日志采集,同时把采集的日志分别发送给两个logs ...

  3. Zookeeper、Kafka集群与Filebeat+Kafka+ELK架构

    Zookeeper.Kafka集群与Filebeat+Kafka+ELK架构 目录 Zookeeper.Kafka集群与Filebeat+Kafka+ELK架构 一.Zookeeper 1. Zook ...

  4. ELK+FileBeat+Log4Net搭建日志系统

    ELK+FileBeat+Log4Net搭建日志系统 来源:https://www.zybuluo.com/muyanfeixiang/note/608470 标签(空格分隔): ELK Log4Ne ...

  5. 「视频小课堂」ELK和Kafka是怎么就玩在一起成了日志采集解决方案文字版

    视频地址:ELK和Kafka是怎么就玩在一起成了日志采集解决方案 视频文字版 今天呢我就带来了一期视频,主要就是讲ELK和Kafka之间的通讯关系通过对一张通讯图,和一些操作命令,让我们能更深入的去理 ...

  6. ELK+FileBeat+Log4Net

    ELK+FileBeat+Log4Net搭建日志系统 output { elasticsearch { hosts => ["localhost:9200"] } stdou ...

  7. ELK + Filebeat 日志分析系统

    ELK + Filebeat 日志分析系统 架构图 环境 OS:CentOS 7.4 Filebeat: 6.3.2 Logstash: 6.3.2 Elasticsearch 6.3.2 Kiban ...

  8. 基于docker部署使用ELK+FileBeat日志管理平台

    Docker从狭义上来讲就是一个进程,从广义上来讲是一个虚拟容器,专业叫法为 Application Container(应用容器).Docker进程和普通的进程没有任何区别,它就是一个普通的应用进程 ...

  9. Docker 部署 elk + filebeat

    Docker 部署 elk + filebeat kibana 开源的分析与可视化平台logstash 日志收集工具 logstash-forwarder(原名lubmberjack)elastics ...

随机推荐

  1. mycat 实现读写分离

    mycat 实现读写分离 配置mysql实现主从复制 安装jdk 安装mycat实现读写分离 tar zxf Mycat-server-1.6-RELEASE-20161028204710-sangn ...

  2. ElasticSearch文档删除字段

    https://www.cnblogs.com/ljhdo/archive/2017/03/24/4885796.html

  3. html设置多个div并排显示

    我这里以4个div为例,html代码如下: <body> <div id="column1" style="background-color: blue ...

  4. DB2存储过程简单示例

    在这个示例中,我们将在DB2中创建一个名为DEMO1201的存储过程. 该存储过程的输入参数IN_NAME和IN_CREDITCARD,表示用户的姓名和身份证号. 该存储过程的作用是根据身份证号来新建 ...

  5. 【Leetcode_easy】594. Longest Harmonious Subsequence

    problem 594. Longest Harmonious Subsequence 最长和谐子序列 题意: 可以对数组进行排序,那么实际上只要找出来相差为1的两个数的总共出现个数就是一个和谐子序列 ...

  6. 【c# 学习笔记】类实例化

    类中可以定义的成员,包括字段.属性.构造函数.实例方法和析构函数等. 要访问这些实例成员,必须通过类的实例对象来完成.而要得到一个类的实例对象,就必须先声明一个该类类型的变量,然后使用new运算符后跟 ...

  7. 给.Net Core添加Swagger实现接口文档自动生成

    1.添加Nuget相关引用 Swashbuckle.AspNetCore

  8. C#使用KingAOP实现AOP面向切面编程一

    AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. 实现AOP主要由两种方式,一种是编译时静态植入,优点是 ...

  9. golang json解析到map中

    package main import ( "fmt" "encoding/json" ) type ItemMessage struct { ItemType ...

  10. python 修改文件内容3种方法

    原文链接:https://www.cnblogs.com/wc-chan/p/8085452.html def alter(file,old_str,new_str): ""&qu ...