zzxworld

使用 Filebeat 提交数据到 ElasticSearch

前两天我用 ElasticSearch 和 Kibana 折腾了一个 Nginx 日志分析系统,虽然可以用起来了,但每次都要手动下载并提交数据,这让系统的易用性大打折扣,所以我琢磨着怎么让这个过程更加便捷。经过一番尝试,我选择了 Filebeat 的方案。

关于我搭建 Nginx 日志分析系统的基础流程,可以参考前一篇文章:《使用 ElasticSearch + Kibana 搭建 Nginx 日志分析系统》。文章结尾其实也提到了使用 CURL 和 Filebeat 的日志自动提交方案,当时想的是简单一点,能用 CURL 就用 CURL,但经过尝试才发现,默认生成的 JSON 日志格式根本无法正常提交,总提示无法解析。迫不得已,只能用 Filebeat。

把 Filebeat 正常用起来也花了我不少时间,主要是目前最新版本 8.4 的 ElasticSearch 默认就开启了 SSL 访问,但用的又是自签名证书。相应的也要让 Filebeat 用证书方式访问 ElasticSearch。但这个证书要在 Filebeat 中使用需要做格式转换,我在转换以 .key 结尾的证书文件时碰到了密码问题,一时无法解决。反正是在本地使用,也无所谓安全不安全的,最终我选择了关闭 ElasticSearch 的安全功能。这需要自己提供一个配置文件,配置文件如下:

cluster.name: "docker-cluster"
network.host: 0.0.0.0
xpack.security.enabled: false

其中 xpack.security.enabled: false 就是禁用 SSL 证书访问以及密码登陆等功能的。在 ElasticSearch 的 Docker 启动命令中挂载这个配置文件到 /usr/share/elasticsearch/config/elasticsearch.yml 这个路径,等 ElasticSearch 启动就能以 *http://` 方式访问了。

然后来配置 Filebeat。首先创建一个目录 logs,用来存放下载的日志文件。Filebeat 会监控这个目录中的文件变动,一旦有新文件进来,就会自动提交到 ElasticSearch。

mkdir logs

然后创建一份 Filebeat 配置文件,内容如下:

filebeat.inputs:
  - type: log
    paths:
      - /data/access.*
    json.keys_under_root: true
    json.add_error_key: true
    json.overwrite_keys: true

processors:
  - decode_json_fields:
      fields: ["message"]

output.elasticsearch:
  hosts: ["http://host.containers.internal:9200"]
  indices:
    - index: "nginx"

以上配置主要啊分为三块:

  1. filebeat.inputs 定义日志的输入配置。path 指定了日志目录和文件选取规则。Nginx 的访问日志默认是以 access 命名开头的,所以就这么定义了。你会发现这个目录为什么是 /data 而不是上面创建的 logs,这是因为我会以 Docker 容器的方式来启动 Filebeat,我会把 logs 目录挂载到容器中的 /data 路径下,所以这里配置的是容器中的路径。后面几个以 json 开头的配置项很重要,它们决定了日志内容的展开方式。
  2. processors 定义日志的处理部分。Filebeat 默认会把从文件中获取的日志内容放到 message 字段,这里的定义就是告诉 Filebeat 在处理时用 JSON 解析日志内容。
  3. output.elasticsearch 定义了日志的输出。它主要告诉 Filebeat 数据提交地址,以及相关索引名称。不存在的索引会自动创建。http://host.containers.internal 是 Podman 容器引擎的一个特殊的地址,它指向运行容器的主机 IP。

然后用容器命令启动 Filebeat:

podman run --rm -it \
    --userns keep-id \
    --network analysis \
    -v $PWD/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro \
    -v $PWD/logs:/data \
    --name filebeat docker.elastic.co/beats/filebeat:8.4.0

这里使用的容器引擎是 Podman,如果你使用的是 Docker,大可不必担心,它们区别不大。把 podman 换成 docker,然后删掉 --userns keep-id 选项就可以了。

如果 logs 目录中有日志文件,或是现在就丢几个进去,数据立马就会被 Filebeat 提交到 ElasticSearch 中。打开 Kibana,看看 「Index Management」 索引管理页面,会发现数据已经有了。

Index Management

现在我每天要看最新数据时,只需要用 Shell 命令把日志下载到 logs 目录就可以了。这一步貌似也可以通过 Crontab 计划任务来省掉。