前言
目前,efk作为一个比较热门的日志收集系统,了解它的运行过程比较重要,方便以后在更复杂的环境中更好的使用。下面以老版本efk 7搭建一套docker 容器的日志收集系统。
版本说明:
- elasticsearch: 7.17.22
- filebeat: 7.17.22
- kibana: 7.17.22
- docker: docker-ce-26.1.4
操作系统说明
用的centos7.7 版本,内核版本3.10+
[root@kube-master ~]# uname -a
Linux kube-master 3.10.0-1062.18.1.el7.x86_64 #1 SMP Tue Mar 17 23:49:17 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[root@kube-master ~]# cat /etc/redhat-release
CentOS Linux release 7.7.1908 (Core)
安装过程
服务器主机需要能访问互联网,方便起见本文所有安装包均采用 yum 安装。
安装顺序如下:
1、系统初始化
2、 docker-ce
3、elasticsearch
4、 kibana
5 、filebeat
在阅读本文前,最好对dockerd日志管理有一定的了解。具体可以参考https://blog.csdn.net/margu_168/article/details/131075337
系统初始化
系统初始化分为以下几步:
1、修改主机名
2、关闭selinux 和 firewalld
3、配置国内yum源
4、校对时间
修改主机名
host名字没啥影响,大家可以随意改,我这复用了我之前的环境。
[root@kube-master ~]# hostnamectl set-hostname kube-master
[root@kube-master ~]# hostname kube-master
[root@kube-master ~]# echo "192.168.10.128 kube-master" >> /etc/hosts
#断开会话重新连接
[root@kube-master ~]# hostname
kube-master
关闭selinux 和 firewalld
关闭 selinux
[root@kube-master ~]# sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
[root@kube-master ~]# systemctl disable firewalld
[root@kube-master ~]# setenforce 0
配置国内yum源
[root@kube-master ~]# cd /etc/yum.repos.d/
#centos-7源
[root@kube-master yum.repos.d]# curl http://mirrors.aliyun.com/repo/Centos-7.repo -o Centos-7.repo
#docker-ce源
[root@kube-master yum.repos.d]# curl http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o docker-ce.repo
#epel-7源
[root@kube-master yum.repos.d]# curl http://mirrors.aliyun.com/repo/epel-7.repo -o epel-7.repo
#efk源
[root@kube-master yum.repos.d]# cat << EOF > elasticstack.repo
[elasticstack]
name = elasticstack
gpgcheck = 0
baseurl = https://mirrors.tuna.tsinghua.edu.cn/elasticstack/yum/elastic-7.x/
EOF
校对时间
[root@kube-master ~]# yum install -y ntpdate
#任君选
[root@kube-master ~]# ntpdate tiger.sina.com.cn
28 Jun 11:47:21 ntpdate[6027]: step time server 202.108.0.246 offset -4.277028 sec
[root@kube-master ~]# ntpdate ntp1.aliyun.com
28 Jun 11:48:20 ntpdate[6186]: adjust time server 120.25.115.20 offset -0.009092 se
Docker-ce
安装docker-ce
[root@kube-master ~]# yum install -y docker-ce
添加docker-ce 配置
[root@kube-master ~]# mkdir /etc/docker/
[root@kube-master ~]# cat << 'EOF' > /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://5sssm2l6.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com/",
"https://docker.mirrors.ustc.edu.cn/",
"https://registry.docker-cn.com"
],
"data-root": "/data/docker",
"storage-driver": "overlay2",
"log-driver": "json-file",
"log-opts": {
"max-size": "100m",
"max-file": "3"
}
}
修改系统参数并启动 docker
# 注意该下面参数是之前安装k8s的时候设置,应该也是可以使用的
[root@kube-master ~]# cat /etc/sysctl.d/k8s.conf
net.ipv6.conf.all.disable_ipv6 = 1
net.ipv6.conf.default.disable_ipv6 = 1
net.ipv6.conf.lo.disable_ipv6 = 1
net.ipv4.neigh.default.gc_stale_time = 120
net.ipv4.conf.all.rp_filter = 0
net.ipv4.conf.default.rp_filter = 0
net.ipv4.conf.default.arp_announce = 2
net.ipv4.conf.lo.arp_announce = 2
net.ipv4.conf.all.arp_announce = 2
net.ipv4.ip_forward = 1
net.ipv4.tcp_max_tw_buckets = 5000
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 1024
net.ipv4.tcp_synack_retries = 2
# 要求iptables不对bridge的数据进行处理
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-arptables = 1
net.netfilter.nf_conntrack_max = 2310720
fs.inotify.max_user_watches=89100
fs.may_detach_mounts = 1
fs.file-max = 52706963
fs.nr_open = 52706963
vm.overcommit_memory=1
vm.panic_on_oom=0
vm.swappiness = 0
# https://github.com/moby/moby/issues/31208
# ipvsadm -l --timout
# 修复ipvs模式下长连接timeout问题 小于900即可
net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 30
net.ipv4.tcp_keepalive_probes = 10
#下面命令可以查看当前系统设置的参数
[root@kube-master ~]# sysctl --system
#启动docker
[root@kube-master ~]# systemctl enable docker; systemctl start docker
#查看docker信息
[root@kube-master ~]# docker info
Elasticsearch
Elasticsearch是个开源分布式搜索引擎,提供搜集、分析、存储数据三大功能。安装过程如下:
安装elasticsearch
[root@kube-master ~]# yum install -y elasticsearch
修改默认配置文件
[root@kube-master ~]# cd /etc/elasticsearch/
#修改操作前,一定要做好源文件的备份
[root@kube-master ~]# cp -a elasticsearch.yml elasticsearch.yml.init
# 修改后的配置文件
[root@kube-master ~]# egrep -v "^#|^$" /etc/elasticsearch/elasticsearch.yml
path.data: /var/lib/elasticsearch //es数据存储目录
path.logs: /var/log/elasticsearch //es日志存储目录
network.host: 192.168.10.128 //es监听地址
http.port: 9200 //es端口
### 这两项需要配置,否则启动会报错 ###
discovery.seed_hosts: ["efk-node"] // 配置候选节点通信,可以写hostname,也可以写IP自动
cluster.initial_master_nodes: ["efk-node"] // 集群初始化提供master地址,可以写hostname,也可以写IP自动
### 解决跨越问题 ###
http.cors.enabled: true
http.cors.allow-origin: "*"
启动elasticsearch
启动完成后,elasticsearch会监听 9200 和 9300
[root@kube-master ~]# systemctl enable elasticsearch; systemctl start elasticsearch
[root@kube-master ~]# netstat -ntplu | egrep '9200|9300'
tcp 0 0 192.168.10.128:9200 0.0.0.0:* LISTEN 1116/java
tcp 0 0 192.168.10.128:9300 0.0.0.0:* LISTEN 1116/java
#测试,使用curl访问9200端口
[root@kube-master ~]# curl 192.168.10.128:9200
{
"name" : "kube-master",
"cluster_name" : "elasticsearch",
"cluster_uuid" : "WPal1s8USsSqVFv2eEg4bw",
"version" : {
"number" : "7.17.22",
"build_flavor" : "default",
"build_type" : "rpm",
"build_hash" : "38e9ca2e81304a821c50862dafab089ca863944b",
"build_date" : "2024-06-06T07:35:17.876121680Z",
"build_snapshot" : false,
"lucene_version" : "8.11.3",
"minimum_wire_compatibility_version" : "6.8.0",
"minimum_index_compatibility_version" : "6.0.0-beta1"
},
"tagline" : "You Know, for Search"
}
Kibana
Kibana 也是一个开源和免费的工具,Kibana可以为 Logstash 和 ElasticSearch 提供的日志分析友好的 Web 界面,可以帮助汇总、分析和搜索重要数据日志。
安装kibana
[root@kube-master ~]# yum install -y kibana
修改 kibana 配置文件
[root@kube-master ~]# cd /etc/kibana/
#修改前,备份源文件
[root@kube-master ~]# cp -a kibana.yml kibana.yml.init
#修改后的配置如下
[root@kube-master ~]# egrep -v "^#|^$" /etc/kibana/kibana.yml
server.host: "192.168.10.128" //监听地址
elasticsearch.hosts: ["http://192.168.10.128:9200"] //连接es地址,不修改kibana浏览器访问会无法打开
i18n.locale: "zh-CN" //汉化,看个人习惯
启动kibana
[root@kube-master ~]# systemctl enable kibana ; systemctl start kibana
#kibana监听地址默认为:5601
[root@kube-master ~]# netstat -ntplu | egrep 5601
[root@kube-master ~]# netstat -ntplu | egrep 5601
tcp 0 0 192.168.10.128:5601 0.0.0.0:* LISTEN 4636/node
通过浏览器访问kibana,我这是第二次访问了,界面不太一样。第一次选择“自己浏览”。
Filebeat
安装 filebeat
[root@kube-master ~]# yum install -y filebeat
到此,所有安装的软件包都已经安装就位,接下来就是配置的修改及调整。由于filebeat涉及到收集各种不同情况下的日志,所以配置不定。下面以收集 nginx 容器日志为例,进行调试配置。
配置调试过程
配置说明
在编写 filebeat 配置文件之前,先了解下 filebeat 配置文件结构,建议参考官方文档:
https://www.elastic.co/guide/en/beats/filebeat/7.17/directory-layout.html
通过configure目录可以看到配置有很多项,主要要添加的有inputs 和 output 两部分,我们先来看看 inputs,与我们此次测试相关的是docker(container),首先看docker input
可以看到docker input 在 7.2.0 版本中已经被弃用,所以这里建议使用 container input
可以直接使用官方提供的示例。
接下来,查看 output 部分。可以看到output的选择也有多种,elasticsearch、redis、kafka等都是常见的。
目前我们处于配置调试节点,可以将日志收集直接打印在控制台展示,如果数据没问题,再进行配置到 elasticsearch 中,所以这里直接通过 Console输出。
综上,下面我们开始修改配置文件:
调试
注意配置文件的正确目录(使用绝对路径和相对路径都可),否则无法使用调试模式启动。
[root@kube-master ~]# cd /etc/filebeat/
[root@kube-master ~]# cat > /etc/filebeat/docker-nginx.yml <<EOF
filebeat.inputs:
- type: container
paths:
- '/data/docker/containers/*/*.log' #注意与实际使用中的位置一致,后面不在说明
output.console:
pretty: true
EOF
通过 filebeat 调试模式启动。
[root@kube-master filebeat]# filebeat -e -c docker-nginx.yml
2024-06-28T16:02:28.383+0800 INFO [registrar] registrar/registrar.go:109 States Loaded from registrar: 23
2024-06-28T16:02:28.383+0800 INFO [crawler] beater/crawler.go:71 Loading Inputs: 1
2024-06-28T16:02:28.383+0800 INFO [crawler] beater/crawler.go:117 starting input, keys present on the config: [filebeat.inputs.0.paths.0 filebeat.inputs.0.type]
2024-06-28T16:02:28.383+0800 WARN [cfgwarn] log/input.go:89 DEPRECATED: Log input. Use Filestream input instead.
2024-06-28T16:02:28.384+0800 INFO [input] log/input.go:171 Configured paths: [/data/docker/containers/*/*.log] {"input_id": "8767ef10-291f-44c7-9475-ccbd3ec07e90"}
2024-06-28T16:02:28.384+0800 INFO [crawler] beater/crawler.go:148 Starting input (ID: 17511724858553739275)
2024-06-28T16:02:28.384+0800 INFO [crawler] beater/crawler.go:106 Loading and starting Inputs completed. Enabled inputs: 1
出现如上信息,并占用控制台则表示启动成功,等待着日志的打印。
下面我们一个启动 nginx 容器
#新开一个窗口
[root@kube-master ~]# docker run --name ngx -p 80:80 -d nginx:alpine
# 当容器启动成功后,filebeat 控制台就会打印如下信息日志:
{
"@timestamp": "2024-06-28T08:05:38.175Z",
"@metadata": {
"beat": "filebeat",
"type": "_doc",
"version": "7.17.22"
},
"host": {
"name": "kube-master"
},
"agent": {
"id": "142a9309-4240-4fc0-99b9-631405d51c57",
"name": "kube-master",
"type": "filebeat",
"version": "7.17.22",
"hostname": "kube-master",
"ephemeral_id": "dd286e16-66c2-470a-aa49-2f3af8dbfe78"
},
"log": {
"offset": 0,
"file": {
"path": "/data/docker/containers/d561bec1e55849d471413c1eba08e0a3c148957990eb3b89ff5bc67e4d737f00/d561bec1e55849d471413c1eba08e0a3c148957990eb3b89ff5bc67e4d737f00-json.log"
}
},
"stream": "stdout",
"message": "/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration",
"input": {
"type": "container"
},
"ecs": {
"version": "1.12.0"
}
}
{
"@timestamp": "2024-06-28T08:05:38.175Z",
"@metadata": {
"beat": "filebeat",
"type": "_doc",
"version": "7.17.22"
},
"log": {
"offset": 167,
"file": {
"path": "/data/docker/containers/d561bec1e55849d471413c1eba08e0a3c148957990eb3b89ff5bc67e4d737f00/d561bec1e55849d471413c1eba08e0a3c148957990eb3b89ff5bc67e4d737f00-json.log"
}
},
"stream": "stdout",
"message": "/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/",
"input": {
"type": "container"
},
"ecs": {
"version": "1.12.0"
},
"host": {
"name": "kube-master"
},
"agent": {
"version": "7.17.22",
"hostname": "kube-master",
"ephemeral_id": "dd286e16-66c2-470a-aa49-2f3af8dbfe78",
"id": "142a9309-4240-4fc0-99b9-631405d51c57",
"name": "kube-master",
"type": "filebeat"
}
}
出现这样的信息,说明filebeat 已经捕获到了 容器的日志信息
接下来就要对日志信息进行筛选,大段的日志信息有很多我们并不需要过多的去关注,因此需要剔除无用的信息,继续查看官方文档,文档中有个processors,这个 Processors 可以理解为 filter ,筛选器的意思
在 Processors 子类中,找到了 drop_fields 删除字段配置,打开查看。
通过官方示例查看,when 当…时候… 这里就是通过条件筛选进行字段的删除,目前我们这里没有条件筛选,尝试直接删除字段。
注意:通过官方文档查看 processors 是与 input 和 output 平级的,所以注意格式。
于是,配置文件又修改为如下:
[root@kube-master ~]# cat > /etc/filebeat/docker-nginx.yml <<EOF
filebeat.inputs:
- type: container
paths:
- '/data/docker/containers/*/*.log'
processors:
- drop_fields:
fields: ["log","agent","ecs"]
output.console:
pretty: true
EOF
在刚才的控制台 ctrl + c 结束,重新启动。并在另一个终端使用curl访问Nginx。
[root@kube-master filebeat]# filebeat -e -c docker-nginx.yml
#输出如下
57990eb3b89ff5bc67e4d737f00-json.log", "old_finished": true, "old_os_id": "524517-2051", "harvester_id": "27afa26b-13f1-4d72-a275-87de4118eb45"}
{
"@timestamp": "2024-06-28T08:14:05.508Z",
"@metadata": {
"beat": "filebeat",
"type": "_doc",
"version": "7.17.22"
},
"message": "172.17.0.1 - - [28/Jun/2024:08:14:05 +0000] \"GET / HTTP/1.1\" 200 615 \"-\" \"curl/7.29.0\" \"-\"",
"input": {
"type": "container"
},
"host": {
"name": "kube-master"
},
"stream": "stdout"
}
到目前为止,已经提取出来对我们有用的日志信息,接下来就可以存储到 elasticsearch 中,查看官方文档如何存储到 es 中。
很简单就存储到 es 中,注意:这里我们并没有开启 https ,只需写成 http即可。修改 filebeat 配置如下:
filebeat.inputs:
- type: container
paths:
- '/var/lib/docker/containers/*/*.log'
processors:
- drop_fields:
fields: ["log","agent","ecs"]
output.elasticsearch:
hosts: ["http://192.168.10.128:9200"]
重启控制台,测试
#ctrl+c后执行
[root@kube-master ~]# filebeat -e -c docker-nginx.yml
#重启一个终端
[root@kube-master elasticsearch]# curl http://192.168.10.128
#浏览器访问 nginx 容器生成日志,然后通过 curl 查看 es 中所有索引信息:
[root@kube-master elasticsearch]# curl http://192.168.10.128:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .geoip_databases xZCNQt1qSXmYVt_ZruchyQ 1 0 33 0 31.2mb 31.2mb
yellow open filebeat-7.17.22-2024.07.01-000001 yVVnQ8B-QgCKjbSw7CTh9g 1 1 1 0 5kb 5kb
可以看到最下面这一条就是我们通过 filebeat 存储进去的日志信息。从这个索引名完全看不出该日志的相关信息,因为存储的是nginx 容器的日志,所以做好将索引名修改为 nginx 相关的名字,这样就可以通过索引名确定存储的数据信息。
官网查看 output -> elasticsearch 相关文档信息
修改 配置文件如下:
[root@kube-master filebeat]# vim docker-nginx.yml
filebeat.inputs:
- type: container
paths:
- '/data/docker/containers/*/*.log'
processors:
- drop_fields:
fields: ["log","agent","ecs"]
output.elasticsearch:
hosts: ["http://192.168.10.128:9200"]
index: "docker-nginx-%{+yyyy.MM.dd}"
重启控制台,ctrl+c后执行:
[root@kube-master filebeat]# filebeat -e -c docker-nginx.yml
2024-07-01T10:32:01.039+0800 INFO instance/beat.go:698 Home path: [/usr/share/filebeat] Config path: [/etc/filebeat] Data path: [/var/lib/filebeat] Logs path: [/var/log/filebeat] Hostfs Path: [/]
2024-07-01T10:32:01.039+0800 INFO instance/beat.go:706 Beat ID: 142a9309-4240-4fc0-99b9-631405d51c57
2024-07-01T10:32:01.039+0800 ERROR instance/beat.go:1027 Exiting: setup.template.name and setup.template.pattern have to be set if index name is modified
Exiting: setup.template.name and setup.template.pattern have to be set if index name is modified
出现了报错,根据报错信息可以看到,如果索引名被修改,就必须配置 setup.template.name and setup.template.pattern;修改配置文件如下:
[root@kube-master filebeat]# vim docker-nginx.yml
filebeat.inputs:
- type: container
paths:
- '/data/docker/containers/*/*.log'
processors:
- drop_fields:
fields: ["log","agent","ecs"]
output.elasticsearch:
hosts: ["http://192.168.10.128:9200"]
index: "docker-nginx-%{+yyyy.MM.dd}"
setup.ilm.enabled: false
setup.template.name: "docker"
setup.template.pattern: "docker-*"
重启控制台
[root@kube-master filebeat]# filebeat -e -c docker-nginx.yml
#通过浏览器访问后,再次查看索引
[root@kube-master ~]# curl http://192.168.10.128
[root@kube-master ~]# curl http://192.168.10.128:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .geoip_databases xZCNQt1qSXmYVt_ZruchyQ 1 0 33 0 31.2mb 31.2mb
yellow open docker-nginx-2024.07.01 f5sBI4EMRvWg5-WdPdX7bA 1 1 0 0 227b 227b
yellow open filebeat-7.17.22-2024.07.01-000001 yVVnQ8B-QgCKjbSw7CTh9g 1 1 1 0 5.1kb 5.1kb
[root@kube-master ~]#
可以看到这里已经生成了 docker-nginx-* 的相关索引
接下来就可以通过 kibana 展示出来。访问地址为IP+5601端口。
这样就将 nginx 容器的日志信息收集展示出来了。
前面 filebeat 一直使用的是 调试模式 filebeat -e -c docker-nginx.yml 模式来做的,下面将 docker-nginx.yml 配置信息整合到 主配置文件 filebeat.yml 中。
[root@kube-master filebeat]# egrep -v '^$|#' filebeat.yml
filebeat.inputs:
- type: filestream
id: my-filestream-id
enabled: false
paths:
- /var/log/*.log
- type: container
paths:
- '/data/docker/containers/*/*.log'
filebeat.config.modules:
path: ${path.config}/modules.d/*.yml
reload.enabled: false
setup.template.settings:
index.number_of_shards: 1
setup.kibana:
output.elasticsearch:
hosts: ["http://192.168.10.128:9200"]
index: "docker-nginx-%{+yyyy.MM.dd}"
setup.ilm.enabled: false
setup.template.name: "docker"
setup.template.pattern: "docker-*"
processors:
- drop_fields:
fields: ["log","agent","ecs"]
#启动服务:
[root@kube-master filebeat]# systemctl start filebeat
进阶配置
现在的数据就简化了很多,只保留对我们有用的信息。接下来就要考虑几个问题:
- nginx 日志分为 access.log 和 error.log 如何区分存储?
- 如果多个容器如果区分不同的容器日志?
stdout 及 stderr 存入不同索引
对于 nginx来说,有时候我们可能只需要关注错误日志,如何区分存储呢?其实查看上面控制台输出的日志内容不难发现一个字段:stream
#kibana界面查看的
{
"_index": "docker-nginx-2024.07.01",
"_type": "_doc",
"_id": "kNwobJABs91VXTkpc6Ik",
"_version": 1,
"_score": 1,
"_source": {
"@timestamp": "2024-07-01T02:38:19.450Z",
"host": {
"name": "kube-master"
},
"stream": "stdout",
"message": "192.168.10.128 - - [01/Jul/2024:02:38:19 +0000] \"GET / HTTP/1.1\" 200 615 \"-\" \"curl/7.29.0\" \"-\"",
"input": {
"type": "container"
}
},
其实对于 nginx 这样的容器,遵循一个标准,标准输出到 stdout 标准错误输出到 stderr 可进入容器查看:
[root@kube-master filebeat]# docker exec -it d5 /bin/sh
~ # ls -l /var/log/nginx/
total 0
lrwxrwxrwx 1 root root 11 Jun 22 19:20 access.log -> /dev/stdout
lrwxrwxrwx 1 root root 11 Jun 22 19:20 error.log -> /dev/stderr
所以,对于 stream: stderr 就是需要关注的 错误日志,所以根据字段条件进行区分,修改 filebeat 调试配置文件如下:
[root@kube-master filebeat]# cat docker-nginx.yml
filebeat.inputs:
- type: container
paths:
- '/data/docker/containers/*/*.log'
processors:
- drop_fields:
fields: ["log","agent","ecs"]
output.elasticsearch:
hosts: ["http://192.168.10.128:9200"]
indices:
- index: "docker-nginx-access-%{+yyyy.MM.dd}"
when.contains:
stream: "stdout"
- index: "docker-nginx-error-%{+yyyy.MM.dd}"
when.contains:
stream: "stderr"
setup.ilm.enabled: false
setup.template.name: "docker"
setup.template.pattern: "docker-*"
开始调试,调试 filebeat 时,先关闭 filebeat服务
[root@kube-master filebeat]# systemctl stop filebeat
[root@kube-master filebeat]# filebeat -e -c docker-nginx.yml
通过curl命令访问nginx,一个正常能访问的uri和一个并不存在的 uri 让其生成错误日志,然后查看索引:
#另开终端
[root@kube-master filebeat]# curl http://192.168.10.128
[root@kube-master filebeat]# curl http://192.168.10.128/123
[root@kube-master filebeat]# !1124
curl http://192.168.10.128:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
green open .geoip_databases xZCNQt1qSXmYVt_ZruchyQ 1 0 33 0 31.2mb 31.2mb
yellow open docker-nginx-access-2024.07.01 IHOUT7PJR2i1prqtBHhUPA 1 1 2 0 5.3kb 5.3kb
green open .kibana_task_manager_7.17.22_001 DoS2iFZNTPeRYCduvqRrXA 1 0 17 3058 434.7kb 434.7kb
green open .apm-custom-link trobzSMtS6iAUbG7jwGSuQ 1 0 0 0 227b 227b
green open .kibana_7.17.22_001 sHUgOQ3cRzG-oie60O7fpQ 1 0 29 13 2.3mb 2.3mb
yellow open docker-nginx-2024.07.01 f5sBI4EMRvWg5-WdPdX7bA 1 1 3 0 10.3kb 10.3kb
green open .apm-agent-configuration IO4Qcc4tR0GnJnoOVeXimw 1 0 0 0 227b 227b
yellow open filebeat-7.17.22-2024.07.01-000001 yVVnQ8B-QgCKjbSw7CTh9g 1 1 1 0 5.1kb 5.1kb
green open .async-search r6ov63XgSD2DZJfb00ovUA 1 0 0 0 250b 250b
yellow open docker-nginx-error-2024.07.01 FITBpG-BSqukRs-mFTU_zw 1 1 1 0 5.2kb 5.2kb
[root@kube-master filebeat]#
可以看到已经生成 了docker-nginx-access和docker-nginx-error两个索引。然后再kibana中设置,将不同是索引展示出来。
docker-nginx-error-* 也如上添加展示。然后通过discovery查看,可以看到错误日志中就是刚刚访问的不存在的地址。
这样, 就可以通过不同的索引展示各种所需日志数据。
总结:该部分解决的问题是:单容器,正常日志和错误日志分类存放的问题。
不同业务容器存入不同索引
容器使用场景,肯定会存在不同的程序或者不同的业务都运行于容器当中。举个最简单的架构 lnmp ,如果将nginx 和 php 的日志如果存储在同一个索引里,日后查询排错还不如直接查看源日志文件,这就违背了搭建日志收集系统的初衷。
通过上面 filebeat 中 inputs 可以看到是 通过解析容器日志目录来获取日志信息的,而容器的名称和ID 都会随着生命周期而变动的,因此无法像物理或者虚拟主机一样通过IP联系起来。这个时候就需要为容器打标签,通过打标签的形式区分不同业务的容器集合。
注意:做这一部分示例前,请将运行中的容器关闭并删除。
[root@kube-master filebeat]# docker rm -f `docker ps -aq`
为容器打标签,以下方式二选一,推进还是使用docker-compose。下面启动两个不同的 web 服务, 一个开启80端口,一个开启 8081 端口,并需要将它们日志存储到不同的索引里。
docker 直接启动打标签
[root@kube-master filebeat]# docker run --name nginx -p 80:80 --label service=nginx --log-opt labels=service -d nginx:alpine
[root@kube-master filebeat]# docker run --name httpd -p 8090:80 --label service=httpd --log-opt labels=service -d httpd
通过docker-compose 打标签
[root@kube-master filebeat]# cat docker-compose.yml
### docker-compose.yml
version: "3"
services:
#web服务
nginx:
container_name: "nginx"
image: nginx:alpine
environment:
- "TZ=Asia/Shanghai"
labels:
service: nginx
logging:
options:
labels: "service"
ports:
- "80:80"
# 8081 web 服务
httpd:
container_name: "httpd"
image: httpd:latest
environment:
- "TZ=Asia/Shanghai"
labels:
service: httpd # 标记
logging:
options:
labels: "service"
ports:
- "8081:80"
[root@kube-master filebeat]# docker-compose up -d
[+] Running 2/2
⠿ Container nginx Started 0.7s
⠿ Container httpd Started
上面两种方式,任意执行一种。下面查看日志
[root@kube-master filebeat]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a054d5301da1 nginx:alpine "/docker-entrypoint.…" 54 seconds ago Up 53 seconds 0.0.0.0:80->80/tcp nginx
74475221753d httpd:latest "httpd-foreground" 54 seconds ago Up 53 seconds 0.0.0.0:8081->80/tcp httpd
[root@kube-master filebeat]# tail -1 /data/docker/containers/a054d5301da114965a8c16f83947dcfe0026411eb02daf8bc8bf26dd2de9e9bc/a054d5301da114965a8c16f83947dcfe0026411eb02daf8bc8bf26dd2de9e9bc-json.log
{"log":"2024/07/01 16:07:40 [notice] 1#1: start worker process 32\n","stream":"stderr","attrs":{"service":"nginx"},"time":"2024-07-01T08:07:40.271351912Z"}
[root@kube-master filebeat]#
通过nginx的日志可以看到,日志中多有 attrs 属性字段,就是打的标签,然后下面通过 filebeat output 中 when 条件来过滤。编写修改 filebeat 配置文件:
#文件目录: /etc/filebeat/docker-compose-web.yml
[root@kube-master filebeat]# cat docker-nginx.yml
filebeat.inputs:
- type: container
paths:
- '/data/docker/containers/*/*.log'
processors:
- drop_fields:
fields: ["log","agent","ecs"]
output.elasticsearch:
hosts: ["http://192.168.10.128:9200"]
indices:
- index: "web-nginx-access-%{+yyyy.MM.dd}"
when.contains:
# 日志中包括 docker.attrs.service==nginx 且 stream=stdout 存入web-nginx-access-%{+yyyy.MM.dd}
docker.attrs.service: "nginx"
stream: "stdout"
- index: "web-nginx-error-%{+yyyy.MM.dd}"
when.contains:
# 日志中包括 docker.attrs.service==nginx 且 stream=stderr 存入web-nginx-error-%{+yyyy.MM.dd}
docker.attrs.service: "nginx"
stream: "stderr"
- index: "web-httpd-access-%{+yyyy.MM.dd}"
when.contains:
# 日志中包括 docker.attrs.service==httpd 且 stream=stdout 存入web-httpd-access-%{+yyyy.MM.dd}
docker.attrs.service: "httpd"
stream: "stdout"
- index: "web-httpd-error-%{+yyyy.MM.dd}"
when.contains:
# 日志中包括 docker.attrs.service==httpd 且 stream=stderr 存入web-httpd-error-%{+yyyy.MM.dd}
docker.attrs.service: "httpd"
stream: "stderr"
setup.kibana:
host: "192.168.10.128:5601"
setup.ilm.enabled: false
setup.template.name: "docker"
setup.template.pattern: "docker-*"
启动:
[root@kube-master filebeat]# filebeat -e -c docker-nginx.yml
#另开终端,通过curl访问后,查看索引
[root@kube-master filebeat]# curl localhost
[root@kube-master filebeat]# curl localhost:8081
[root@kube-master filebeat]# curl localhost/123 #生成nginx的错误索引
[root@kube-master filebeat]# curl localhost:8081/abc
[root@kube-master filebeat]# curl http://192.168.10.128:9200/_cat/indices?v
health status index uuid pri rep docs.count docs.deleted store.size pri.store.size
yellow open docker-nginx-access-2024.07.01 IHOUT7PJR2i1prqtBHhUPA 1 1 65 0 46.4kb 46.4kb
green open .kibana_7.17.22_001 sHUgOQ3cRzG-oie60O7fpQ 1 0 31 2 2.3mb 2.3mb
green open .apm-agent-configuration IO4Qcc4tR0GnJnoOVeXimw 1 0 0 0 227b 227b
yellow open web-nginx-access-2024.07.01 UaLIE1sWQ2y_mCrz_jTwwQ 1 1 1 0 7.1kb 7.1kb
yellow open web-nginx-error-2024.07.01 q1WHX15qQV-QSL36rpurRA 1 1 1 0 7.8kb 7.8kb
green open .geoip_databases xZCNQt1qSXmYVt_ZruchyQ 1 0 33 0 31.2mb 31.2mb
green open .kibana_task_manager_7.17.22_001 DoS2iFZNTPeRYCduvqRrXA 1 0 17 17343 1.8mb 1.8mb
green open .apm-custom-link trobzSMtS6iAUbG7jwGSuQ 1 0 0 0 227b 227b
yellow open docker-nginx-2024.07.01 f5sBI4EMRvWg5-WdPdX7bA 1 1 3 0 10.3kb 10.3kb
yellow open filebeat-7.17.22-2024.07.01-000001 yVVnQ8B-QgCKjbSw7CTh9g 1 1 1 0 5.1kb 5.1kb
green open .async-search r6ov63XgSD2DZJfb00ovUA 1 0 0 0 250b 250b
yellow open web-httpd-access-2024.07.01 CCUdIy5YTdGQeqLhfZ_mow 1 1 1 0 7kb 7kb
yellow open docker-nginx-error-2024.07.01 FITBpG-BSqukRs-mFTU_zw 1 1 65 0 59.1kb 59.1kb
查看es中的索引可以发现生成了3个我们期望的索引。但是web-httpd-error的相关索引始终没有生成。下面我们来排查原因。
[root@kube-master filebeat]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a054d5301da1 nginx:alpine "/docker-entrypoint.…" 12 minutes ago Up 12 minutes 0.0.0.0:80->80/tcp nginx
74475221753d httpd:latest "httpd-foreground" 12 minutes ago Up 12 minutes 0.0.0.0:8081->80/tcp httpd
[root@kube-master filebeat]# tail -1 /data/docker/containers/74475221753d2289c03737b9607a3a5ab90ec3d6d5c57ba8cbe0b56e3670a8ed/74475221753d2289c03737b9607a3a5ab90ec3d6d5c57ba8cbe0b56e3670a8ed-json.log
{"log":"172.19.0.1 - - [01/Jul/2024:16:18:25 +0800] \"GET /abc HTTP/1.1\" 404 196\n","stream":"stdout","attrs":{"service":"httpd"},"time":"2024-07-01T08:18:25.15760286Z"}
[root@kube-master filebeat]#
可以看到,在httpd服务中,404的相关日志它也是通过stdout输出的,与nginx有一定成差别。下面模拟其他错误来输出到httpd服务的stdout中。
[root@kube-master filebeat]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a054d5301da1 nginx:alpine "/docker-entrypoint.…" 12 minutes ago Up 12 minutes 0.0.0.0:80->80/tcp nginx
74475221753d httpd:latest "httpd-foreground" 12 minutes ago Up 12 minutes 0.0.0.0:8081->80/tcp httpd
[root@kube-master filebeat]# docker exec -it 74 /bin/sh
# pwd
/usr/local/apache2
# touch htdocs/123.html
# chmod -r htdocs/123.html
#退出容器,再测试
[root@kube-master filebeat]# curl localhost:8081/123.html
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access this resource.</p>
</body></html>
[root@kube-master filebeat]# tail -1 /data/docker/containers/74475221753d2289c03737b9607a3a5ab90ec3d6d5c57ba8cbe0b56e3670a8ed/74475221753d2289c03737b9607a3a5ab90ec3d6d5c57ba8cbe0b56e3670a8ed-json.log
{"log":"[Mon Jul 01 16:25:14.666123 2024] [core:error] [pid 10:tid 140365327705856] (13)Permission denied: [client 172.19.0.1:47572] AH00132: file permissions deny server access: /usr/local/apache2/htdocs/123.html\n","stream":"stderr","attrs":{"service":"httpd"},"time":"2024-07-01T08:25:14.666716306Z"}
[root@kube-master filebeat]#
可以看到,没有权限的403错误是通过stderr输出。web-httpd-error也已经自动生成。
这里就通过不同的条件将不同业务不同类型的日志进行了分开存储,然后在 kibana 如上配置,就可以分类查看。如下:
从截图也可以看出我们创建的4种索引,并且web-httpd-error中也有我们无权限访问的日志。
更多关于EFK的知识分享,请前往博客主页。编写过程中,难免出现差错,敬请指出