Beats:创建你自己的 Beat

Beats 是构建轻量级开源数据采集器的平台,该采集器将各种数据发送到 Elasticsearch 供以后分析。 我们有 Packetbeat 来监视服务器之间交换的网络流量,还有 Filebeat 来从服务器获取日志,Metricbeat 定期从外部系统获取指标。 如果需要收集其他自定义数据,则可以基于libbeat框架轻松构建自己的 Beat。 社区已经有90多个社区Beats

Elastic 提供了 Beats 生成器软件包,可帮助你创建自己的节拍。 在此博客文章中,你将看到如何使用Beat生成器创建自己的Beat。 我们今天为练习而创建的节拍是 lsbeat。 lsbeat 索引文件和目录的信息,类似于 Unix 命令 ls。 本文基于 Unix,因此,如果你是 Windows 或其他 OS 用户,请按照适合你的 OS 的说明进行操作。

在今天的开发环境中,我们将使用 Ubuntu 18.04 来作为我们 beat 的开发环境。

 

在今天的开发中,我们将使用 vagrant 来部署我的 Ubuntu OS。如果你还不知道如何创建自己的 Ubuntu 虚机的话,请参考我之前的文章 “Vagrant 入门教程”。

 

配置开发环境

 

安装 go 环境

Beats 实际上是 go 程序。我们可以参照链接 “Go get started” 来安装自己的 golang 语言开发环境。

wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.14.2.linux-amd64.tar.gz

当我们解压上面的 go 安装包后,它将生成一个 /usr/local/go 的目录,里面含有 go 语言的所有的安装:

$ pwd
/usr/local
vagrant@ubuntu-bionic:/usr/local$ ls go
AUTHORS          LICENSE    SECURITY.md  bin          lib   robots.txt
CONTRIBUTING.md  PATENTS    VERSION      doc          misc  src
CONTRIBUTORS     README.md  api          favicon.ico  pkg   test

将 /usr/local/go/bin 添加到 PATH 环境变量中。 你可以通过将以下行添加到你的 /etc/profile(用于系统范围的安装)或 $HOME/.profile 中来完成此操作。针对我们的 Ubuntu OS 情况,我们可以填加到 .bashrc 文件中:

export PATH=$PATH:/usr/local/go/bin

添加完后,我们打入如下的命令使它起作用:

source .bashrc

等我们安装好我们的 go 后,我们可以在 terminal 中打入如下的命令:

$ which go
/usr/local/go/bin/go

为了我们接下来的开发,我们也同时加入如下的变量。我们把下面的内容都加入到 .bashrc 中。

export GOROOT=/usr/local/go
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH
export GOPATH=$HOME/go/beats

在这里,我也设置了以 GOPATH。你可以设置自己的路径。针对我的情况,我在我的 home 目录下创建了一个 go 目录,并在 go 目录下生产一个叫做 beats 的目录。在一下,我们会在这个目录里生成我们的定制的 beat。在修改完 .bashrc 文件后,千万要记得打入如下的命令让修改的内容起作用:

$ source .bashrc

下载 Elastic beats 源码

在这一步我们下载 Elastic beats 的源码。在 termnial 中打入如下的命令:

mkdir -p ${GOPATH}/src/github.com/elastic
git clone https://github.com/elastic/beats ${GOPATH}/src/github.com/elastic/beats

安装 Python

目前的 generator 只适合 Python2,所以我们只需要安装 Python2。我们打入如下的指令:

 sudo apt install python-minimal

我们可以通过如下的方式来检查 python 的版本:

$ python --version
Python 2.7.17

安装 virtualenv

我们必须安装 virtualenv 才能使得 generator 正常工作。在 Ubuntu 上, 我们打入如下的命令进行安装:

sudo apt install virtualenv

如果自己的电脑上同时已经安装了python3,那么我们需要同时设置如写变量:

export PYTHON_EXE='python2.7'
export VIRTUALENV_PARAMS='-p python2.7'
export VIRTUALENV_PYTHON='/usr/bin/python2.7'
 
export VIRTUALENV_PYTHON='/usr/local/bin/python' (for Mac)

请注意:这里的 python 是 2.x 版本的 python,而不是 python3。我们需要保证 VIRTUALENV_PYTHON 指向我们的 Python2 的执行文件。

安装 mage

我们需要在地址 https://github.com/magefile/mage 下载这个源码,并编译:

go get -u -d github.com/magefile/mage
cd $GOPATH/src/github.com/magefile/mage
go run bootstrap.go

等上面的命令执行完后,我们可以在如下的目录中找到编译好的执行文件 mage:

$ ls $GOPATH/bin
mage

让我们看看我们将用于 lsbeat 的代码。 这是一个简单的 Golang 程序,它接收目录作为命令行参数,并列出该目录下的所有文件和子目录。

lsbeat.go

package main
import (
    "fmt"
    "io/ioutil"
    "os"
)
func main() {
    //apply run path "." without argument.
    if len(os.Args) == 1 {
        listDir(".")
    } else {
        listDir(os.Args[1])
    }
}
func listDir(dirFile string) {
    files, _ := ioutil.ReadDir(dirFile)
    for _, f := range files {
        t := f.ModTime()
        fmt.Println(f.Name(), dirFile+"/"+f.Name(), f.IsDir(), t, f.Size())
        if f.IsDir() {
            listDir(dirFile + "/" + f.Name())
        }
    }
}

我们可以通过如下的方式来编译这个文件,并执行它:

go build lsbeat.go
./lsbeat

然后,lsbeat 应用将会显示在目前目录下的所有的文件。

创建lsbeat

首先创建一个目录在 $GOPATH下,并进入该目录。

mkdir ${GOPATH}/src/github.com/{user}
cd ${GOPATH}/src/github.com/{user}

注意这里的 user 指的是自己在 github 上的用户名。比如针对我的情况是 liu-xiao-guo。我打入如下写的命令:

mkdir ${GOPATH}/src/github.com/liu-xiao-guo
cd  $GOPATH/src/github.com/elastic/beats/

接下来,我们运行如下的命令:

mage GenerateCustomBeat

执行的结果是:

$ mage GenerateCustomBeat
2020/05/06 14:38:24 Found Elastic Beats dir at /home/vagrant/go/beats/src/github.com/elastic/beats
Enter the beat name [examplebeat]: lsbeat
Enter your github name [your-github-name]: liu-xiao-guo
Enter the beat path [github.com/liu-xiao-guo/lsbeat]: 
Enter your full name [Firstname Lastname]: Xiaoguo Liu
Enter the beat type [beat]: 
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
DEPRECATION: Python 2.7 reached the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 is no longer maintained. pip 21.0 will drop support for Python 2.7 in January 2021. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
2020/05/06 14:43:13 Found Elastic Beats dir at /home/vagrant/go/beats/src/github.com/liu-xiao-guo/lsbeat/vendor/github.com/elastic/beats
Generated fields.yml for lsbeat to /home/vagrant/go/beats/src/github.com/liu-xiao-guo/lsbeat/fields.yml
2020/05/06 14:43:14 Found Elastic Beats dir at /home/vagrant/go/beats/src/github.com/liu-xiao-guo/lsbeat/vendor/github.com/elastic/beats

*** Please tell me who you are.

Run

  git config --global user.email "you@example.com"
  git config --global user.name "Your Name"

to set your account's default identity.
Omit --global to set the identity only in this repository.

fatal: unable to auto-detect email address (got 'vagrant@ubuntu-bionic.(none)')
Error: running "git commit -q -m Initial commit, Add generated files" failed with exit code 128

这样,我们基本上就生产了一个最基本的 beat 的框架。

接下来,我们进入到我们的 beat 目录里,并进行编译:

cd ${GOPATH}/src/github.com/{user}/lsbeat

针对我的情况:

cd ${GOPATH}/src/github.com/liu-xiao-guo/lsbeat
$ pwd
/home/vagrant/go/beats/src/github.com/liu-xiao-guo/lsbeat
vagrant@ubuntu-bionic:~/go/beats/src/github.com/liu-xiao-guo/lsbeat$ ls
CONTRIBUTING.md  _meta   docs                  lsbeat.yml    tests
LICENSE.txt      beater  fields.yml            magefile.go   vendor
Makefile         build   include               main.go
NOTICE.txt       cmd     lsbeat.docker.yml     main_test.go
README.md        config  lsbeat.reference.yml  make.bat

这里有最基本的框架文件。里面含有一个叫做 lsbeat.yml 的配置文件及一些标准的模板文件。我们在命令行中直接打入如下的指令

make

经过上面的编译,我们可以发现在当前的目录下,有一个已经编译好的 lsbeat 可执行文件:

在之前我们的 Elasticsearch 的IP地址是 192.168.0.100,所以,我们需要修改 lsbeat.yml 这个配置文件:

我们在当前的目录下直接运行这个可执行的文件:

./lsbeat -e -d "*"

我们可以在 terminal 中看到:

我们打开 Kibana,并查看 lsbeat 的索引信息:

 

从上面我们可以看出来,lsbeat 的 log 信息已经导入到 Elasticsearch中了,但是它里面的信息并不是我们所希望看到的文件目录的信息。我们需要在下面对它进行改造。

        "_source" : {
          "@timestamp" : "2020-05-06T14:57:01.751Z",
          "type" : "ubuntu-bionic",
          "counter" : 1,
          "ecs" : {
            "version" : "1.2.0"
          },
          "host" : {
            "id" : "feb6a76832e547e7909c1be08e939cf6",
            "containerized" : false,
            "name" : "ubuntu-bionic",
            "hostname" : "ubuntu-bionic",
            "architecture" : "x86_64",
            "os" : {
              "kernel" : "4.15.0-96-generic",
              "codename" : "bionic",
              "platform" : "ubuntu",
              "version" : "18.04.4 LTS (Bionic Beaver)",
              "family" : "debian",
              "name" : "Ubuntu"
            }
          },
          "agent" : {
            "id" : "7f65adcf-407a-4188-a5bf-0726693a8196",
            "version" : "8.0.0",
            "type" : "lsbeat",
            "ephemeral_id" : "83506f48-072f-4f8a-8a76-cf52ce0d3dd0",
            "hostname" : "ubuntu-bionic"
          }
        }
      },

它里面含有一个 counter 的整数值。时间上默认的 lsbeat 模板就是一个计数的 beat。

所有关于 beat 的设计上的代码可以在目录 ${GOPATH}/src/github.com/liu-xiao-guo/lsbeat 下的 /beater/CountBeat.go 文件里实现的。设计比较直接。大家可以看一下代码应该可以明白。

配置

我们首先来配置 lsbeat.yml 文件。

lsbeat.yml

lsbeat:
  # Defines how often an event is sent to the output
  period: 1s

period 是发生器在所有 beat 中包括的参数。 它表示 lsbeat 每1秒迭代一次该过程。 让我们将该时间段从1秒更改为10秒,并添加新的 path 参数,该参数代表顶级目录程序将扫描的路径。 我们可以将这些参数添加到 _meta 目录下的 beat.yml 中。

beat.yml

lsbeat:
  # Defines how often an event is sent to the output
  period: 10s
  path: "."

添加新参数后,我们运行 make update 命令将更改应用于 lsbeat.yml 配置文件。 我们可以看到在 lsbeat.yml 中现在可以使用在 _meta/beat.yml 中设置的新参数。

$ make update
$ cat lsbeat.yml
$ cat lsbeat.yml 
################### {Beat} Configuration Example #########################

############################# {Beat} ######################################

lsbeat:
  # Defines how often an event is sent to the output
  period: 10s
  path: "."
 
...

在更新完后,千万要记得在 lsbeat.yml 中修改我们的 Elasticsearch 的地址:

更新配置文件后,应编辑 config/config.go,以便可以添加 path 参数。

package config
import "time"
type Config struct {
    Period time.Duration `config:"period"`
    Path   string        `config:"path"`
}
var DefaultConfig = Config {
    Period: 10 * time.Second,
    Path:   ".",
}

让我们使用默认配置选项将时间段设置为10秒,将默认目录使用当前目录(.)。

添加代码

每个 Beat 都需要通过定义 Run() 和 Stop() 函数来实现 Beater 接口。 此处提供了有关 Beater 界面的更详细指南。

为此,你只需要定义一个名为 lsbeat 的结构即可定义应该实现 Beater 接口的 lsbeat 对象。 让我们添加 lastIndexTime,它将用于保存上一个时间戳数据。我们打开如下的文件:

beater/lsbeat.go

// lsbeat configuration.
type lsbeat struct {
        done   chan struct{}
        config config.Config
        client beat.Client
        lastIndexTime time.Time
}

此外,每个 Beat 都需要实现 New() 函数,该函数接收 Beat 的配置并返回类型为 lsbeat 的 Beat 对象。

// New creates an instance of lsbeat.
func New(b *beat.Beat, cfg *common.Config) (beat.Beater, error) {
        c := config.DefaultConfig
        if err := cfg.Unpack(&c); err != nil {
                return nil, fmt.Errorf("Error reading config file: %v", err)
        }

        bt := &lsbeat{
                done:   make(chan struct{}),
                config: c,
        }
        return bt, nil
}

对于 lsbeat,我们想扩展默认的 Run() 函数以导出有关目录中可用文件和子目录的信息。

在修改 Run() 函数之前,让我们首先在 lsbeat.go 文件底部添加 listDir() 函数,该函数收集文件和目录信息。 它生成的事件包括:

  • "@timestamp": common.Time(time.Now())
  • "type": beatname
  • "modtime": common.Time(t)
  • "filename": f.Name()
  • "path": dirFile + "/" + f.Name()
  • "directory": f.IsDir()
  • "filesize": f.Size()

它将第一次为所有文件和目录建立索引,但是在执行第一个例程后,它将检查在第一个例程之后是否创建或修改了文件或目录,以索引较新的文件和目录。 最后一个例程的时间戳将保存在 lasIndexTime 变量中。

func (bt *lsbeat) listDir(dirFile string, beatname string) {
    files, _ := ioutil.ReadDir(dirFile)
    for _, f := range files {
        t := f.ModTime()
        path := filepath.Join(dirFile, f.Name())
        if t.After(bt.lastIndexTime) {

            event := beat.Event{
                Timestamp: time.Now(),
                Fields: common.MapStr {
                        "type":       beatname,
                        "modtime":    common.Time(t),
                        "filename":   f.Name(),
                        "path":       path,
                        "directory":  f.IsDir(),
                        "filesize":   f.Size(),
                },
            }

            bt.client.Publish(event)
        }
        if f.IsDir() {
            bt.listDir(path, beatname)
        }
    }
}

并且不要忘记在导入库中添加 io/ioutil 及 path/filepath 包。

import (
        "fmt"
        "io/ioutil"
        "path/filepath"
        "time"

        "github.com/elastic/beats/libbeat/beat"
        "github.com/elastic/beats/libbeat/common"
        "github.com/elastic/beats/libbeat/logp"

        "github.com/liu-xiao-guo/lsbeat/config"
)

现在,让我们看一下 Run() 函数,该函数调用 listDir() 函数并将时间戳保存在 lasIndexTime 变量中。

func (bt *lsbeat) Run(b *beat.Beat) error {
    logp.Info("lsbeat is running! Hit CTRL-C to stop it.")

    var err error
    bt.client, err = b.Publisher.Connect()
    if err != nil {
        return err
    }

    // fmt.Printf("%+v\n", b)

    ticker := time.NewTicker(bt.config.Period)
    for {
        now := time.Now()
        bt.listDir(bt.config.Path, b.Info.Beat) // call listDir
        bt.lastIndexTime = now                  // mark Timestamp
        logp.Info("Event sent")
        select {
        case <-bt.done:
            return nil
        case <-ticker.C:
        }
    }
    return nil
}

Stop() 函数应该中断运行循环,并且与生成的函数相同:

func (bt *lsbeat) Stop() {
    bt.client.Close()
    close(bt.done)
}

我们几乎完成了编码。 我们必须在映射上添加新字段。 在  _meta/fields.yml 文件中添加字段信息。

_meta/fields.yml

- key: lsbeat
  title: lsbeat
  description:
  fields:
    - name: lsbeat
      type: long
      required: true
      description: >
        PLEASE UPDATE DOCUMENTATION

    #new fiels added lsbeat
    - name: modtime
      type: date
    - name: filename
      type: text
    - name: path
    - name: directory
      type: boolean
    - name: filesize
      type: long

我们在上面的除了添加新的字段以外,同时也把 name 字段修改为 lsbeat。

并应用新的更新:

$ make update

编译并运行

现在我们可以构建并运行。 只需运行 make 命令,它将编译代码并构建 lsbeat(在Windows上为lsbeat.exe)可运行的二进制文件。

make

我们可以看到新生产的 lsbeat 运行文件:

我们运行我们刚才生产的 lsbeat:

我们到 Kibana 中去查看:

我们来查看所有的文件:

最后整个 beat 的源码可以在地址下载:

https://github.com/liu-xiao-guo/beats-lsbeat

 

更多阅读

你可参阅另外一篇文章 “Beats:如何创建一个定制的 Elastic Beat”。

参考:

【1】https://www.elastic.co/guide/en/beats/devguide/7.6/newbeat-generate.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值