满江红·怒发冲冠
怒发冲冠,凭阑处、潇潇雨歇。
抬望眼,仰天长啸,壮怀激烈。
三十功名尘与土,八千里路云和月。莫等闲,白了少年头,空悲切。
靖康耻,犹未雪;臣子恨,何时灭?
驾长车,踏破贺兰山缺。
壮志饥餐胡虏肉,笑谈渴饮匈奴血。
待从头,收拾旧山河,朝天阙。
复制代码
背景
最近项目需要,使用 docker 部署了 ELK,因为我们日志产生在客户端,考虑安全问题,在后端提供了两个接口,一个实时的日志信息推送,还有一个提供日志文件上传,以此作为 logstash 的输入
原本以为很简单的问题,由于本人是前端临时过来打工的,对 docker 、java、linux、ELK 各种不熟悉,折腾了好久,现记录下,文中有不对的地方,请不吝赐教
业务流程
客户端产生日志,有两种情况推送给后端服务器
- 在线状态,直接通过接口推送
- 离线状态,会将日志本地持久化,等待下次联网,通过上传文件的方式推送给后端
服务器端提供以下两个接口
- 实时日志推送接口:1. 身份认证;2. 数据处理;3. 推送给消息队列
- 上传日志文件接口:1. 接收文件;2. 保存文件
ELK 负责数据采集,数据来源
- RabbitMQ 队列中的数据
- 上传的日志文件
以上是大概的流程
ELK 安装
安装主要是参考这片文章 使用 Docker 搭建 ELK 环境 ,具体安装按照这个来,很方便。
配置问题
我大部分的时间都是在这里浪费的,尤其是 logstash 的 input 配置
这里说一下项目里的配置文件
docker-compose.yml 是 ELK 三件套的配置文件,后续因为我的后端也是容器化部署的,上传的日志文件需要能让 logstash 拿到,所以我添加了一个 volume
- type: bind
source: ./logstash/logs ### 这个是相对于该配置文件的相对地址,后续我会把这个目录和后端服务上传文件的文件夹对应起来
target: /usr/share/logstash/logs ### 这个是 logstash 容器里的地址
复制代码
然后是 logstash pipeline 的配置
### 文件的 input, path 对应的是 logstash 容器里的绝对路径,这里要将这个地址和宿主机做映射,也就是后端上传文件映射的那个地址
input {
file {
mode => "read"
start_position => "beginning"
path => ["/usr/share/logstash/logs/logs/**"]
codec => json
}
}
### rabbitmq 的 input
input {
rabbitmq {
host => "172.20.10.2"
port => 5672
user => "admin"
password => "admin"
queue => "log.handler"
exchange => "scheduler-logs-exchange"
exchange_type => "direct"
key => "log.handler"
heartbeat => 30
durable => true
codec => json
}
}
## Add your filters / logstash plugins configuration here
output {
elasticsearch {
hosts => ["elasticsearch:9200"]
user => "your name"
password => "your password"
index => "your index"
}
}
复制代码
说几个遇到的问题:
- rabbitmq 的生产者是后端 java 代码,Java 在推送信息给 rabbitmq 之前,我在代码里面初始化了 exchange 和 queue ,导致 logstash 运行报错,这里正确的做法是,java 代码不用在初始化了,交给 logstash ,它会自动来创建的。这过程中还因为我修改了 rabbitmq 的 exchange_type,导致类似的问题发生。
- 最早的时候 pipeline 我配置了两个文件,我的想法是一个给 rabbitmq 使用,一个给文件使用;配置也生效了,可是每次我向 rabbitmq 推送一条数据,logstash 都会产生两笔数据,最后找到原因是两个配置文件,有两个 output,它的机制应该是只要有 input 满足了,output 会执行两次,so 我将配置又整合在一起了;此外还遇到一个奇怪的问题,rabbitmq 和 file 的 input 的位置问题,我测试发现,file 必须在 rabbitmq 上面,不然 file 就会无效,不知道啥原因。
- 部署问题,我在本地搭建的环境执行没有问题,可是到服务器上,文件的读取总是报错,错误提示是 file 里面某个输入字段不合法;后来和本地比对,我发现,logstash 正确读取 日志文件之后,会将文件自动删除(因为我配置的 start_position => "beginning"),但是服务器上没有,后来我发现是 logstash 容器里面对操作文件的权限不对,没有删除权限。我只能去容器里面把权限给改了。
- 配置文件修改后,记得重启服务,重启服务,重启服务。。。
最后,虽然现在看上去能够正确运行了,但我感觉有几个问题,我的方式应该是不对的
- logstash 里面修改文件的权限的
- java 服务上传文件目录和 logstash 读取日志目录链接方式
希望大家给出一些帮助,谢谢