Elastic:Fluentd 在 Elastic Stack 中的运用

Posted Elastic 中国社区官方博客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Elastic:Fluentd 在 Elastic Stack 中的运用相关的知识,希望对你有一定的参考价值。

在我之前的文章 “Elastic:使用 Fluentd 及 Elastic Stack 进行应用日志采集”,我详细地介绍了如何使用 Elastic Stack 及 Fluentd 来收集一个 nodejs 服务器的日志信息。在今天的文章中,我将详细地介绍如何使用 Docker 来部署 Elastic Stack 及 Fluentd。在我们的设计中,我们把 Fluentd 作为一个日志收集器,并最终把所有的日志写入到 Elasticsearch 中。我们的设计框图如下:

如上图所示,我们将使用 Docker 来部署 Elasticsearch, Kibana 及 Fluentd。它们所使用的端口地址如上所示。运用 Fluentd 的好处是可以让 Fluentd 运行于 cluster 模式下:

在上面的 Fluentd 将作为一个数据收集器,并把数据发送至 Elasticsearch 中。如果其中的一个由于某种原因不能正常工作,那么备份的那个将起作用。在所有的 Fluentd 服务器都不工作的情况下,TD-Agent 还可以帮我们缓存数据,并在 Fluentd 重新正常工作时把数据发送过来。在左边,我们可以使用一个 centos 来部署我们所需要的服务。在本示例中,我们将使用 RSyslog 把日志信息发送至 TD-Agent,进而发送至 Fluentd 服务器。关于如何使用 RSyslog 发送日志到 Logstash,并发送至 Elasticsearch,请阅读我之前的文章 “Beats:使用 Linux 系统上的 Rsyslog 收集日志并导入 Elasticsearch”。

安装

安装 docker containers

我能接下来安装 Elasticsearch,Kibana 及 Fluent。你可以参考我之前的文章 “Elasticsearch:如何在 Docker 容器中安装 Elastic Stack”。我们需要添加 Fluentd 的部分:

docker-compose.yml

version: '2.2'

services:

  fluentd:
    build: ./fluentd
    container_name: fluentd
    volumes:
      - ./fluentd/conf:/fluentd/etc
    ports:
      - "24224:24224"
      - "24224:24224/udp"

  # Elasticsearch requires your vm.max_map_count set to 262144
  # Default will be 65530
  # sysctl -w vm.max_map_count=262144
  # Add this to /etc/sysctl.conf for making it permanent
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
    container_name: elasticsearch
    environment:
      - node.name=elasticsearch
      - discovery.seed_hosts=elasticsearch
      - cluster.initial_master_nodes=elasticsearch
      - cluster.name=docker-cluster
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - esdata1:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
  kibana:
    image: docker.elastic.co/kibana/kibana:7.15.2
    container_name: kibana
    environment:
      ELASTICSEARCH_URL: "http://elasticsearch:9200"
    ports:
      - 5601:5601
    depends_on:
      - elasticsearch

volumes:
  esdata1:
    driver: local

在上面,我们使用最新的 Elastic Stack 7.15.2。针对 Elasticsearch 及 Kibana,我们使用最新的 docker image,而针对 Fluentd,我们使用一个 Dockerfile 来进行编译。我们在当前的目录下创建一个叫做 fluentd 的子目录,并同时创建如下的两个文件:

Dockerfile

FROM fluent/fluentd
RUN ["gem", "install", "fluent-plugin-elasticsearch", "--no-rdoc", "--no-ri"]

在上面的文件中,我们需要安装 fluent-plugin-elasticsearch 这个插件。这样它才可以和 Elasticsearch 进行交互。

接着在 fluentd 字母下,我们创建另外一个叫做 conf 的子目录。在这个子目录中,我们针对 fluentd 进行配置。在该目录下,我们创建如下的 fluentd.conf 配资文件:

fluent.conf

<source>
  @type forward
  port 24224
</source>

# Store Data in Elasticsearch
<match *.**>
  @type copy
  <store>
    @type elasticsearch
    host elasticsearch
    port 9200
    include_tag_key true
    tag_key @log_name
    logstash_format true
    flush_interval 10s
  </store>
</match>

在上面,我们定义 source 端口为 24224,也即所有发送至端口 24244 的数据都将直接发送到 elasticsearch 这个服务。请注意这里的 elasticsearh 服务名称是在上面的 docker-compose 中所定义的 Elasticsearch 服务名称。因为 fluentd 和 Elasticsearch 及 Kibana 都是在同一个 docker-compose.yml 里所定义的,它们直接直接可以通过服务名称互相访问,否则我们需要定义一个 network 来做连接所有的服务。

我们整个部署的文件结构如下:

$ pwd
/Users/liuxg/data/elk/docker-efk
$ tree -L 3
.
├── docker-compose.yml
├── fluentd
│   ├── Dockerfile
│   └── conf
│       └── fluent.conf
└── misc
    └── clients-td-agent.conf

我们在上面的 docker-compose.yml 所处的目录下打入如下的命令:

docker-compose up -d

请注意上面的 -d 选项。它指的是在 detach 模式下运行,也即在后台运行。上面的命令将会自动下载 Elasticsearch 及 Kibana 的镜像并按照。同时它也会编译 fluentd 的 image 来进行按照。等安装完毕后,我们可以通过如下的命令来进行检查:

docker ps
$ docker ps
CONTAINER ID   IMAGE                                                  COMMAND                  CREATED          STATUS          PORTS                                                          NAMES
2669d8ec6d71   docker.elastic.co/kibana/kibana:7.15.2                 "/bin/tini -- /usr/l…"   47 seconds ago   Up 46 seconds   0.0.0.0:5601->5601/tcp                                         kibana
eb6ce5db5083   docker.elastic.co/elasticsearch/elasticsearch:7.15.2   "/bin/tini -- /usr/l…"   47 seconds ago   Up 47 seconds   0.0.0.0:9200->9200/tcp, 9300/tcp                               elasticsearch
e66845d61f75   docker-efk_fluentd                                     "/bin/entrypoint.sh …"   47 seconds ago   Up 46 seconds   5140/tcp, 0.0.0.0:24224->24224/tcp, 0.0.0.0:24224->24224/udp   fluentd

我们可以通过如下的命令来查看各个服务的日志信息:

docker logs elasticsearch | less
docker logs kibana | less
docker logs fluentd | less

比如,我们可以看到 fluentd 的日志信息:

上面表明我们的配置是成功的。 

如果我们进行的顺利,我们可以在电脑上打开浏览器,并打开地址 http://localhost:5601

我们可以看到 Kibana 已经正常运行起来了。

在我的 macOS 机器上,我们可以使用如下的命令来检查所有的相关端口:

$ sudo lsof -iTCP -sTCP:LISTEN -n -P | grep docke
com.docke 16488  liuxg   87u  IPv6 0xe44890273fc84edf      0t0  TCP *:9200 (LISTEN)
com.docke 16488  liuxg   89u  IPv6 0xe44890273fc8553f      0t0  TCP *:24224 (LISTEN)
com.docke 16488  liuxg   91u  IPv6 0xe44890274f6c7edf      0t0  TCP *:5601 (LISTEN)

我们发现 9200,5601 及 24224 端口都被使用。

安装 centos

我们接下来使用 Vagrant 来创建一个 centos 的虚拟机。我们使用如下的 Vagrantfile 文件。关于如何创建 centos,请阅读我的另外一篇文章 “Elastic:在 CentOS 上一步一步安装 Elastic Stack”。 我们首先创建如下的一个 Vagrantfile:

Vagrantfile

# vi: set ft=ruby :

ENV['VAGRANT_NO_PARALLEL'] = 'yes'

Vagrant.configure(2) do |config|

    config.vm.define "client" do |client|
    client.vm.box = "centos/7"
    client.vm.hostname = "client.example.com"
    client.vm.network "private_network", ip: "172.42.42.20"
    client.vm.provider "virtualbox" do |vb|
      vb.customize ["modifyvm", :id, "--natdnshostresolver1", "on"]
      vb.customize ["modifyvm", :id, "--natdnsproxy1", "on"]      
      vb.name = "client"
      vb.memory = 1024
      vb.cpus = 1
    end
    config.vm.provision 'shell', inline: <<-SHELL
       echo 'root:admin' | sudo chpasswd
    SHELL

  end

end

我们的文件结构如下:

$ pwd
/Users/liuxg/data/elk/docker-efk
$ ls
Vagrantfile        docker-compose.yml fluentd            misc
$ tree -L 3
.
├── Vagrantfile
├── docker-compose.yml
├── fluentd
│   ├── Dockerfile
│   └── conf
│       └── fluent.conf
└── misc
    └── clients-td-agent.conf

3 directories, 5 files
$ vagrant up

我们使用 vagrant up 命令来创建一个 centos 7 的虚拟机。我们可以在 Virtualbox 里发现这个运行的虚拟机:

 我们接下来使用如下的命令来进行登录:

vagrant ssh
$ vagrant ssh
Last login: Mon Dec  6 06:10:07 2021 from 10.0.2.2
-bash: warning: setlocale: LC_CTYPE: cannot change locale (UTF-8): No such file or directory
[vagrant@localhost ~]$ 

我们接下来安装 TD-Agent。根据官方文档 Install by RPM Package (Red Hat Linux) - Fluentd。我们执行如下的步骤:

sudo  curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent4.sh | sh

 等我们安装完毕后。我们查看一下 td-agent 的状态:

$ systemctl status td-agent
● td-agent.service - td-agent: Fluentd based data collector for Treasure Data
   Loaded: loaded (/usr/lib/systemd/system/td-agent.service; enabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: https://docs.treasuredata.com/display/public/PD/About+Treasure+Data%27s+Server-Side+Agent

我们通过如下的命令来启动它:

$ systemctl enable td-agent
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-unit-files ===
Authentication is required to manage system service or unit files.
Authenticating as: root
Password: 
==== AUTHENTICATION COMPLETE ===
==== AUTHENTICATING FOR org.freedesktop.systemd1.reload-daemon ===
Authentication is required to reload the systemd state.
Authenticating as: root
Password: 
==== AUTHENTICATION COMPLETE ===

在上面,我们输入密码  admin 来完成安装。这个密码是在我们的 Vagrantfile 里定义的。

在正式开始采集数据之前,我们需要对 td-agent 进行配置。我们在 docker-compose.yml 文件所在的目录里创建一个叫做 misc 的子目录。在这个目录中,我们创建一个叫做 clients-td-agent.conf 的文件:

<source>
  @type syslog
  @id input_syslog
  port 42185
  tag client.system
</source>

<match *.**>
  @type forward
  @id forward_syslog
  <server>
    host <fluentd-ip-address>
  </server>
</match>
$ pwd
/Users/liuxg/data/elk/docker-efk
$ ls
Vagrantfile        docker-compose.yml fluentd            misc
$ tree -L 3
.
├── Vagrantfile
├── docker-compose.yml
├── fluentd
│   ├── Dockerfile
│   └── conf
│       └── fluent.conf
└── misc
    └── clients-td-agent.conf

在上面,我们定义了源及需要 forward 的 fluentd 的 IP 地址。针对源的配置,我们使用 UDP 协议。所有来自端口 42185 的日志信息都会自动转发到 fluentd 的收集器器中。

我们可以通过如下的命令来找到你当前的 host 的 IP 地址:

$ ifconfig | grep 192
	inet 192.168.0.3 netmask 0xffffff00 broadcast 192.168.0.255

针对我的局域网,它的私有地址是以 192 开头的。我们很容易发现它的私有地址是 192.168.0.3。针对我的情况,我可以进行如下的配置:

<source>
  @type syslog
  @id input_syslog
  port 42185
  tag client.system
</source>

<match *.**>
  @type forward
  @id forward_syslog
  <server>
    host 192.168.0.3
  </server>
</match>

我们可以找到 td-agent 的 repo:

[vagrant@localhost ~]$ ls /etc/yum.repos.d/
CentOS-Base.repo       CentOS-Media.repo    CentOS-fasttrack.repo
CentOS-CR.repo         CentOS-Sources.repo  CentOS-x86_64-kernel.repo
CentOS-Debuginfo.repo  CentOS-Vault.repo    td.repo

 我们接下来配置 td-agent。编辑如下的文件:

vi /etc/td-agent/td-agent.conf 

在默认的文件中,有一些示例展示如何进行配置。我们把上述文件里的所有内容进行删除,然后把之前 clients-td-agent.conf 里的内容进行粘贴,并保存。

[vagrant@localhost ~]$ sudo vi /etc/td-agent/td-agent.conf 
[vagrant@localhost ~]$ cat vi /etc/td-agent/td-agent.conf 
cat: vi: No such file or directory
<source>
  @type syslog
  @id input_syslog
  port 42185
  tag client.system
</source>

<match *.**>
  @type forward
  @id forward_syslog
  <server>
    host 192.168.0.3
  </server>
</match>

我们接下来启动 td-agent:

$ systemctl start td-agent
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to manage system services or units.
Authenticating as: root
Password: 
==== AUTHENTICATION COMPLETE ===

我们需要输入 admin 作为密码。我们使用如下的命令来检查服务是否已经成功运行:

[vagrant@localhost ~]$ systemctl status td-agent
● td-agent.service - td-agent: Fluentd based data collector for Treasure Data
   Loaded: loaded (/usr/lib/systemd/system/td-agent.service; enabled; vendor preset: disabled)
   Active: active (running) since Mon 2021-12-06 06:46:54 UTC; 56s ago
     Docs: https://docs.treasuredata.com/display/public/PD/About+Treasure+Data%27s+Server-Side+Agent
  Process: 3008 ExecStart=/opt/td-agent/bin/fluentd --log $TD_AGENT_LOG_FILE --daemon /var/run/td-agent/td-agent.pid $TD_AGENT_OPTIONS (code=exited, status=0/SUCCESS)
 Main PID: 3014 (fluentd)
   CGroup: /system.slice/td-agent.service
           ├─3014 /opt/td-agent/bin/ruby /opt/td-agent/bin/fluentd --log /var...
           └─3017 /opt/td-agent/bin/ruby -Eascii-8bit:ascii-8bit /opt/td-agen..

上面表明 td-agent 已经成功地运行。你可以在如下的地址找到 td-agent 的日志信息:

less /var/log/td-agent/td-agent.log

我们接下来配置 RSyslog,这把所有的日志信息通过 UDP 的形式发送至 td-agent。我们来编辑如下的文件:

sudo vi /etc/rsyslog.conf

我们在该文件的最后添加如下的一行:

*.* @127.0.0.1:42185

 保存该配置文件,并重新启动 Rsyslog 服务:

[vagrant@localhost ~]$ systemctl restart rsyslog.service
==== AUTHENTICATING FOR org.freedesktop.systemd1.manage-units ===
Authentication is required to manage system services or units.
Authenticating as: root
Password: 
==== AUTHENTICATION COMPLETE ===

我们通过如下的命令来安装 netstat 命令:

yum install -y net-tools

我们可以通过如下的命令来查看 UDP 协议的端口使用情况:

$ netstat -tlup 
(No info could be read for "-p": geteuid()=1000 but you should be root.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 localhost:smtp          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:sunrpc          0.0.0.0:*               LISTEN      -                   
tcp        0      0 0.0.0.0:ssh             0.0.0.0:*               LISTEN      -                   
tcp6       0      0 localhost:smtp          [::]:*                  LISTEN      -                   
tcp6       0      0 [::]:sunrpc             [::]:*                  LISTEN      -                   
tcp6       0      0 [::]:ssh                [::]:*                  LISTEN      -                   
udp        0      0 0.0.0.0:59457           0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:bootpc          0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:bootpc          0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:sunrpc          0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:42185           0.0.0.0:*                           -                   
udp        0      0 localhost:323           0.0.0.0:*                           -                   
udp        0      0 0.0.0.0:931             0.0.0.0:*                           -                   
udp6       0      0 [::]:sunrpc             [::]:*                              -                   
udp6       0      0 localhost:323           [::]:*                              -                   
udp6       0      0 [::]:931                [::]:* 

我们可以看到 42185 端口已经被使用。

到目前位置,我们已经安装好了我们所有需要的软件栈,并配置好了它们。我们接下来,使用 Kibana 来查看收到的数据。

使用 Kibana 查看日志

还记得我们在配置 Fluentd 时所使用的配置吗?

<source>
  @type forward
  port 24224
</source>

# Store Data in Elasticsearch
<match *.**>
  @type copy
  <store>
    @type elasticsearch
    host elasticsearch
    port 9200
    include_tag_key true
    tag_key @log_name
    logstash_format true
    flush_interval 10s
  </store>
</match>

如上所示,我们使用的是 logstash_format,也就是说我们的日志的名称是以 logstash 为开头的。

打开 Kibana:

 

 

我们可以看到一个以 logstash 为开头的索引。点击上面的 Create index pattern:

这样我们就创建了一个叫做 logstash* 的索引模式。

我们可以在 Discover 中查看这个索引的所有内容:

 

我们看见日志里含有我们之前设置的 tag: client.system。

我们接下来在 centos 里打入如下的命令:

[vagrant@localhost ~]$ logger -t LIUXG this is so coool

我们使用如下的命令来查看所生产的 syslog:

sudo tail -f /var/log/messages

我们稍等一会儿,然后在 Kibana 的 Discover 中进行查看:

我们看到有两条收集到的日志信息。这个就是我们刚才使用 logger 命令所生产的日志。

以上是关于Elastic:Fluentd 在 Elastic Stack 中的运用的主要内容,如果未能解决你的问题,请参考以下文章

Elastic:使用 Fluentd 及 Elastic Stack 进行应用日志采集

Elastic:使用 Fluentd 及 Elastic Stack 进行应用日志采集

如何在 Elastic Beanstalk 多容器 docker 上使用 fluentd 日志驱动程序

安装Filebeat+Elasticsearch+Kibana(单节点)

是否可以使用 fluentd 的 redis_store 输出插件来处理大量日志?

Filebeat 核心配置详解