跳到主要内容

Filebeat 日志采集环境中如何获取主机 IP

· 阅读需 4 分钟
Dylan Li

在使用 Elastic Stack v7.4 实现统一的日志系统时,我们希望在 Filebeat 增加像 hostip 这样的参数来将宿主机的 IP 带到日志采集流中。比如这样配置:

- type: log
enabled: true
paths:
- /path/to/your/logs/your-serviceid.log
name: "your-serviceid-log"
multiline.pattern: '^[[:space:]]|^Caused by:|^<|^{|^}'
multiline.negate: false
multiline.match: after
ignore_older: 24h
fields_under_root: true
fields:
serviceid: your-serviceid
hostip: your-hostip

your-hostip 替换为当前宿主机的 IP,然后启动 filebeat 服务即可实现最初的目的。但是这样静态配置的方式还不够优雅,如果每台宿主机的配置文件中存在多组上述配置,在每一组配置中都去手动指定 IP 将会成一个繁琐而无味的工作。

换种思路,如果我们在 /etc/profile 文件中添加 HOST_IP 环境变量,并将值设置为宿主机的 IP,然后尝试重启获取一下,效果如何,我们将配置变更一下:

- type: log
enabled: true
paths:
- /path/to/your/logs/your-serviceid.log
name: "your-serviceid-log"
multiline.pattern: '^[[:space:]]|^Caused by:|^<|^{|^}'
multiline.negate: false
multiline.match: after
ignore_older: 24h
fields_under_root: true
fields:
serviceid: your-serviceid
hostip: "${HOST_IP}"

令人失落的是,我们发现使用这种方案会导致 filebeat 进程无法重启,原因出在它是通过 systemd 启动的,默认情况下系统的环境变量只有通过 pam 方式登录的用户才能读取到,但是 systemd 是不会进行登录的,所以就不能直接读取到系统的环境变量。该如何解决呢?

再换种思路,是否可以使用某种方法向 systemd 注入环境变量呢?答案是可以的,我们可以创建一个前置服务并在该服务中执行动态获取宿主机 IP 的脚本命令 ipecho,脚本的返回值就是宿主机的 IP 地址,像这种:

tee /usr/local/bin/ipecho <<-'EOF'
#!/bin/bash

ip -o -4 address show | awk ' NR==2 { gsub(/\/.*/, "", $4); print $4 } '
EOF

之后为此命令设置可执行权限:chmod u+x /usr/local/bin/ipecho,然后使用 systemctlset-environment 指令直接执行 ipecho 并将返回值赋值给 HOST_IP 变量再注入到 systemd 运行时环境中,最后向 systemd 提交一个名为 systemd-setenv.service 的新服务:

tee /usr/lib/systemd/system/systemd-setenv.service <<-'EOF'
[Unit]
Description=Transfers /etc/environment to systemd
Requires=network-online.target
After=network-online.target

[Service]
ExecStart=/usr/bin/bash -c "/usr/bin/systemctl set-environment HOST_IP=`ipecho`"

[Install]
WantedBy=multi-user.target
EOF

初次创建后需要设置开机自启并启动它。

systemctl enable systemd-setenv.service
systemctl start systemd-setenv.service

我们将该前置服务设置给 filebeat 服务。通过 vim /usr/lib/systemd/system/filebeat.service 来进行设置,重点是 After=systemd-setenv.service 这一行:

[Unit]
Description=Filebeat sends log files to Logstash or directly to Elasticsearch.
Documentation=https://www.elastic.co/products/beats/filebeat
Wants=network-online.target
After=network-online.target
After=systemd-setenv.service

[Service]

Environment="BEAT_LOG_OPTS=-e"
Environment="BEAT_CONFIG_OPTS=-c /etc/filebeat/filebeat.yml"
Environment="BEAT_PATH_OPTS=-path.home /usr/share/filebeat -path.config /etc/filebeat -path.data /var/lib/filebeat -path.logs /var/log/filebeat"
ExecStart=/usr/share/filebeat/bin/filebeat $BEAT_LOG_OPTS $BEAT_CONFIG_OPTS $BEAT_PATH_OPTS
Restart=always

[Install]
WantedBy=multi-user.target

运行 systemctl daemon-reloadsystemctl restart filebeat 命令重载和重启 filebeat 服务即可实现我们的目的,相比最原始的方式要优雅和便捷的多~