全面的日志管理和分析策略对任务至关重要,这使组织能够了解运营,安全性和变更管理事件之间的关系,并保持对其基础架构的全面理解。 来自 Web 服务器,应用程序和操作系统的日志文件也提供了有价值的数据,尽管格式不同,并且以随机和分布式方式提供。
为什么 Apache Web Server 如此受欢迎? 它是免费和开放源代码,为全球约40%的网站提供支持。并且开放源代码正比专有软件更加流行。 由 Apache Software Foundation 维护和开发,提供安全性,非常适合小型和大型网站,可以在所有主要操作系统上轻松设置,并且功能极其强大且非常灵活。
在本文中,我们将引导您完成初始步骤,并向您展示启动和配置集群的过程非常简单。 然后,我们安装并配置 Logstash,以将我们的 apache 日志发送到 Elasticsearch。 然后可以通过 Kibana 仪表板可视化并分析运送到 elasticsearch 的 Apache 日志。
我们的目标
本教程的目标是将使用 Elastic Stack 用作 Apache 日志的集中式日志记录和监视解决方案。 我们将在单独的节点中设置 Logstash,以从单个或多个服务器收集 Apache 日志,并使用预配置的 Kibana 可视化所收集的日志。
我们的 Elastic Stack 设置包含三个主要组件:
- Elasticsearch:用于存储所有应用程序和监视日志
- Logstash:服务器组件,用于处理传入的日志并馈送给 Elastic Stack
- Kibana:用于搜索和可视化日志的 Web 界面
配置
在上面的配置中,我们有两个操作系统:MacOS 及 Ubuntu OS。在它们的上面我们分别安装如上所示的 Elastic Stack 部分。针对你的安装,可能有不同的 IP 地址。需要在一下的安装中进行相应的修改。
我们将使用如下的方式来进行数据的采集:
我们把数据直接传入到 Logstash 中。我们使用 Logstash 对数据进行分析,丰富,然后再传入到 Elasticsearch 中。最后,我们使用 Kibana 来对数据进行分析及展示。
安装
Elasticsearch
我按照文档 “如何在Linux,MacOS 及 Windows 上进行安装 Elasticsearch” 安装 Elasticsearch。但是为了能够让我的 Elasticsearch 能被其它的虚拟机中被访问,我对 Elasticsearch 的配置文件 config/elasticsearch.yml 做了如下的配置:
cluster.name: elasticsearch
node.name: node1
network.host: _site_
cluster.initial_master_nodes: ["node1"]
在上面,我们命名 cluster.name 为 elasticsearch,并给予这个 node 的名字为 node1。如果大家对上面的 network.host 被定义为 _site_ 不太理解的话,可以参阅文档。它的意思就是把 elasticsearch 的 9200 绑定于该电脑是的私有 IP 地址上。修改完上面的 elasticsearch.yml 文件后,我们重新启动 Elasticsearch,我们可以看到:
上面显示9200端口已经成功地绑定于目前所有的网络的地址上了。我们可以通过如下的命令来查看我们的网路接口:
ifconfig
我们可以通过如下的命令来检查IP地址:
ifconfig eth0 | grep inet | awk '{ print $2 }'
在上面的命令中,我们需要根据自己的网络的接口来替换上面的 eth0。
我们可以分别在我们的浏览器中输入上面的9200端口的地址。如果你能看到输出,则表明我们的安装时正确的。
Kibana
我们根据文章 “如何在 Linux,MacOS 及 Windows 上安装 Elastic 栈中的 Kibana” 来安装 Kibana。为了能够访问我们上面安装的 Elasticsearch,我们需要在默认的 Kibana 中做相应的调整。我们来修改 config/kibana.yml 文件:
server.host: "192.168.43.220"
elasticsearch.hosts: ["http://192.168.43.220:9200"]
请用自己环境里的 host 的名字来做替换,同时也需要根据自己的 Elasticsearch 的 IP 地址来进行相应的修改。等我们修改完后,我们来重新启动我们的 Kibana。在我们的浏览器中,我们输入相应的 IP:5601 来查看安装是否正确:
如果能看到上面的输出,则表明我们的 Kibana 安装已经正确。
Apache
在今天的 Web server 设计中,我们将使用 Nodejs + Apache 的组合。你可以根据自己喜欢的方式选用自己喜欢的语言来设计自己的 Web:
我们来安装 nodejs 及 Apache。
sudo apt-get update
sudo apt-get install apache2 nodejs
接下来,我们需要将通过 node.js 应用程序的 URL 在端口80上传入的所有请求代理到正在运行的本地 node.js 进程。 为此,我们需要在 Apache 服务器上安装/启用 mod_proxy 和 mod_proxy_http 模块:
a2enmod proxy
a2enmod proxy_http
因此,现在令人兴奋的部分开始了。 我们需要配置 Apache 服务器以代理对 node.js 应用程序的请求。 然后,我们将为此配置一个 VirtualHost。我们首先进入目录 /etc/apache2/sites-available
$ pwd
/etc/apache2/sites-available
liuxg@liuxg:/etc/apache2/sites-available$ ls
000-default.conf default-ssl.conf
我首先来创建一个属于我们自己的 conf 文件。针对我的情况,我创建一个叫做 liuxg.conf 为文件,它的内容如下:
liuxg.conf
<VirtualHost *:80>
# The ServerName directive sets the request scheme, hostname and port that
# the server uses to identify itself. This is used when creating
# redirection URLs. In the context of virtual hosts, the ServerName
# specifies what hostname must appear in the request's Host: header to
# match this virtual host. For the default virtual host (this file) this
# value is not decisive as it is used as a last resort host regardless.
# However, you must set it for any further virtual host explicitly.
ServerName www.liuxg.com
ServerAlias www.liuxg.com
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
# Available loglevels: trace8, ..., trace1, debug, info, notice, warn,
# error, crit, alert, emerg.
# It is also possible to configure the loglevel for particular
# modules, e.g.
#LogLevel info ssl:warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
# For most configuration files from conf-available/, which are
# enabled or disabled at a global level, it is possible to
# include a line for only one particular virtual host. For example the
# following line enables the CGI configuration for this host only
# after it has been globally disabled with "a2disconf".
#Include conf-available/serve-cgi-bin.conf
</VirtualHost>
# vim: syntax=apache ts=4 sw=4 sts=4 sr noet
在上面,我们配置了如下的设置:
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
请注意我们在 VirtualHost 里定义的80口。通过上面的配置,我们可以把来自 127.0.0.1:80 的请求都映射到 127.0.0.1:3000。我在上面定义了 ServerName 定义为 www.liuxg.com。如果我们还没有自己的域名,我们可以在 /etc/hosts 里定义这个域名的解析:
liuxg@liuxg:/etc$ pwd
/etc
liuxg@liuxg:/etc$ cat hosts
127.0.0.1 localhost
127.0.1.1 liuxg
192.168.43.192 test.com
127.0.0.1 liuxg.com
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
接下来,我们必须启用此新站点配置,并禁用默认站点配置。
sudo a2ensite liuxg.conf
sudo a2dissite 000-default.conf
在修改完我们上面配置后,我们需要重新启动 Apache 的服务:
sudo service apache2 restart
我们可以通过如下命令来检查 apache 是否已经正常运行:
systemctl status apache2
$ systemctl status apache2
● apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Drop-In: /lib/systemd/system/apache2.service.d
└─apache2-systemd.conf
Active: active (running) since Sun 2020-03-22 10:17:05 CST; 7s ago
Process: 5683 ExecStart=/usr/sbin/apachectl start (code=exited, status=0/SUCCESS)
Main PID: 5687 (apache2)
Tasks: 55 (limit: 4915)
CGroup: /system.slice/apache2.service
├─5687 /usr/sbin/apache2 -k start
├─5688 /usr/sbin/apache2 -k start
└─5689 /usr/sbin/apache2 -k start
如果你看到上面的状态为 active,则表明 Apache 服务正在运行。我们也可以在浏览器地址栏中输入 localhost:80 来检查一下 apache 是否正常工作。
接下来,我们来用一个 nodejs 的项目做测试。首先我们下载如下的项目:
git clone https://github.com/contentful/the-example-app.nodejs
等下载上面的项目过后,我们进行到项目的根目录中:
$ pwd
/home/liuxg/nodejs/the-example-app.nodejs
liuxg@liuxg:~/nodejs/the-example-app.nodejs$ ls
app.js cypress.json helpers.js LICENSE package.json README.md test
app.json Dockerfile i18n node_modules package-lock.json routes variables.env
bin handlers lib npm-debug.log public services views
打入如下的命令:
npm install
等安装完后,接着打入如下的命令来进行运行:
npm run start:dev
这样在我们的 Ubuntu OS 里的浏览器中,我们可以检测 Web 服务器是否正常运行:
上面显示3000口地址已经运行正常。我们检查一下80口地址:
在上面,我们可以看到 localhost 在默认的情况下使用的是80口地址,它表明我们的 Apache 已经成功被运动成功。如果你已经在 /etc/hosts 已经进行过域名的设置后,那么:
我们可以在如下的地址找到 Apache 的 log 文件:
$ pwd
/var/log/apache2
liuxg@liuxg:/var/log/apache2$ ls
access.log access.log.1 error.log error.log.1 other_vhosts_access.log
在上面我们可以看到 access.log,error.log 等文件。access.log 的内容如下:
安装 Logstash
我们在 Ubuntu OS 上安装 Logstash。
Logstash 是一个开源工具,可以收集,解析和存储日志以备将来使用,并可以进行快速日志分析。 Logstash 可用于聚合来自多个来源(如 Docker 实例集群)的日志,并将其从文本行解析为 JSON 之类的结构化格式。 在 Elastic Stack 中,Logstash 使 Elasticsearch 来存储和索引日志。
Logstash 需要安装 Java 8 或 Java 11:
sudo apt-get install default-jre
验证是否已安装 Java:
java -version
如果上一个命令的输出与下面的相似,那么您将知道自己朝着正确的方向前进:
openjdk version "11.0.6" 2020-01-14
OpenJDK Runtime Environment (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1)
OpenJDK 64-Bit Server VM (build 11.0.6+10-post-Ubuntu-1ubuntu118.04.1, mixed mode, sharing)
使用以下命令安装 Logstash:
curl -L -O https://artifacts.elastic.co/downloads/logstash/logstash-7.6.1.deb
sudo dpkg -i logstash-7.6.1.deb
上面我们安装的是和我们的 Elasticsearch 相匹配的7.6.1版本。你可以根据自己的版本修改上面的版本来进行下载。
至此我们的安装已经全部完成。
配置 Logstash
Logstash 配置文件采用 JSON 格式,位于 /etc/logstash/conf.d 中。 该配置包括三个部分:输入,过滤器和输出。
让我们创建一个名为 02-apache-input.conf 的配置文件,并设置我们的 Apache 输入:
sudo vi /etc/logstash/conf.d/02-apache-input.conf
插入以下输入配置:
input {
file {
path => ["/var/log/apache2/access.log"]
start_position => "beginning"
sincedb_path => "/dev/null"
type => "apache_access"
}
file {
path => ["/var/log/apache2/error.log"]
start_position => "beginning"
sincedb_path => "/dev/null"
type => "apache_error"
}
}
注意:Apache 日志文件路径可能会根据您的环境和基础操作系统而有所不同。
保存并退出。 这指定了一个将在 TCP 端口5044上侦听的 Apache 输入。现在,我们创建一个名为 10-apache-filter.conf 的配置文件,在其中我们将为 Apache 消息添加一个过滤器:
sudo vi /etc/logstash/conf.d/10-apache-filter.conf
插入以下 Apache 过滤器配置:
filter {
if [type] in [ "apache" , "apache_access" , "apache-access" ] {
grok {
match => [
"message" , "%{COMBINEDAPACHELOG}+%{GREEDYDATA:extra_fields}",
"message" , "%{COMMONAPACHELOG}+%{GREEDYDATA:extra_fields}"
]
overwrite => [ "message" ]
}
mutate {
convert => ["response", "integer"]
convert => ["bytes", "integer"]
convert => ["responsetime", "float"]
}
geoip {
source => "clientip"
target => "geoip"
add_tag => [ "apache-geoip" ]
}
date {
match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ]
remove_field => [ "timestamp" ]
}
useragent {
source => "agent"
}
}
if [type] in ["apache_error","apache-error"] {
grok {
match => ["message", "\[%{WORD:dayname} %{WORD:month} %{DATA:day} %{DATA:hour}:%{DATA:minute}:%{DATA:second} %{YEAR:year}\] \[%{NOTSPACE:loglevel}\] (?:\[client %{IPORHOST:clientip}\] ){0,1}%{GREEDYDATA:message}"]
overwrite => [ "message" ]
}
mutate
{
add_field =>
{
"time_stamp" => "%{day}/%{month}/%{year}:%{hour}:%{minute}:%{second}"
}
}
date {
match => ["time_stamp", "dd/MMM/YYYY:HH:mm:ss"]
remove_field => [ "time_stamp","day","dayname","month","hour","minute","second","year"]
}
}
}
保存并退出。 该过滤器查找标记为 “apache” 类型的日志,它将尝试使用 grok 解析传入的 apache 日志以使其结构化和可查询。
最后,我们将创建一个名为 30-elasticsearch-output.conf 的配置文件:
sudo vi /etc/logstash/conf.d/30-elasticsearch-output.conf
插入以下输出配置:
output {
elasticsearch {
hosts => ["http://192.168.43.220:9200"]
user => "YourUserName"
password => "YourPassword"
index => "apache-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
如果你在 Elasticseearch 中已经配置了安全,那么请在上面填入自己的 user 及 password。否则的话,可以不用管。
保存并退出。 此输出基本上将 Logstash 配置为将日志数据存储在 http://192.168.43.220:9200 运行的 Elasticsearch 中。它的索引的名字为 apache_logs。
等我们配资完后,我们可以使用如下的命令来检查我们的配置是否成功:
/usr/share/logstash/bin/logstash --configtest -f /etc/logstash/conf.d/
我们也可以仿照我的另外一篇文章 “如何安装 Elastic 栈中的 Logstash” 来安装 Logstash。通过解压 Logstash 安装包来进行安装,并把所有的 inputs, filters 及 outputs 只要同一个配置文件中,比如 logstash.conf:
logstash.conf
input {
file {
path => ["/var/log/apache2/access.log"]
start_position => "beginning"
sincedb_path => "/dev/null"
type => "apache_access"
}
file {
path => ["/var/log/apache2/error.log"]
start_position => "beginning"
sincedb_path => "/dev/null"
type => "apache_error"
}
}
filter {
if [type] in [ "apache" , "apache_access" , "apache-access" ] {
grok {
match => [
"message" , "%{COMBINEDAPACHELOG}+%{GREEDYDATA:extra_fields}",
"message" , "%{COMMONAPACHELOG}+%{GREEDYDATA:extra_fields}"
]
overwrite => [ "message" ]
}
mutate {
convert => ["response", "integer"]
convert => ["bytes", "integer"]
convert => ["responsetime", "float"]
}
geoip {
source => "clientip"
target => "geoip"
add_tag => [ "apache-geoip" ]
}
date {
match => [ "timestamp" , "dd/MMM/YYYY:HH:mm:ss Z" ]
remove_field => [ "timestamp" ]
}
useragent {
source => "agent"
}
}
if [type] in ["apache_error","apache-error"] {
grok {
match => ["message", "\[%{WORD:dayname} %{WORD:month} %{DATA:day} %{DATA:hour}:%{DATA:minute}:%{DATA:second} %{YEAR:year}\] \[%{NOTSPACE:loglevel}\] (?:\[client %{IPORHOST:clientip}\] ){0,1}%{GREEDYDATA:message}"]
overwrite => [ "message" ]
}
mutate
{
add_field =>
{
"time_stamp" => "%{day}/%{month}/%{year}:%{hour}:%{minute}:%{second}"
}
}
date {
match => ["time_stamp", "dd/MMM/YYYY:HH:mm:ss"]
remove_field => [ "time_stamp","day","dayname","month","hour","minute","second","year"]
}
}
}
output {
elasticsearch {
hosts => ["http://192.168.43.220:9200"]
user => "YourUserName"
password => "YourPassword"
index => "apache-%{+YYYY.MM.dd}"
}
stdout { codec => rubydebug }
}
启动 Logstash
我们可以直接使用上面的 logstash.conf 来运行:
sudo /usr/share/logstash/bin/logstash -f logstash.conf
我们在 logstash.conf 所在目录里运行上面的命令。在 terminal 中,我们可以看到如下的输出:
打开 Kibana,并输入如下的命令:
GET _cat/indices
我们可以查看apache事件的数量:
在我们的 nodejs 的 Web 服务器中,点击几个链接,然后再查看一下事件的数量:
我们发现事件的数量在增加。我们也可以通过Kibana的Discover来发现apache的事件:
好了,今天的文章就先写到这里。希望对你有所帮助。
参考:
【2】Setup Node.js with Apache Proxy on Ubuntu 18.04 for Production
【3】How To Install the Apache Web Server on Ubuntu 18.04 | DigitalOcean