配置文件本身非常脆弱!所以修改配置文件自然会引入部署失败的风险。如果能够对配置文件进行自动化测试将会极大的降低这种风险。本文将介绍一个可以自动化测试 logstash 配置文件的工具,让大家可以像写单元测试用例一样为 logstash 配置文件创建测试 case,并以快速迭代的方式变更 logstash 配置文件。
噩梦
在很多真实环境中,变更 logstash 的配置文件几乎是个噩梦。日志不是结构化的格式(甚至是乱七八糟!),导致我们几乎必须一个一个地处理日志,并对解析什么和不解析什么做出逻辑判定。这会导致我们在 logstash 的配置文件中写出复杂的日志处理逻辑。更加悲催的是,我们编写的仅仅是一个配置文件,大多数时候你找不到像 VisualStudio 那样豪华的带有拼写检查和语法检查的编辑工具。所以我们迫切的需要一个可以对 logstash 的配置文件做单元测试的工具,让我们更好的控制变更、执行迭代。
logstash-test-runner
logstash-test-runner 就是这样一个可以让我们应用 DevOps 原则来解决这个问题的工具。它具有下面几个特点:
- 它是一个测试框架
- 非常容易写测试用例
- 不用学习一个新的 DSL(Domain-Specific-Language)
- 能够快速的获得反馈
logstash-test-runner 的作者应该是饱受 logstash 的配置文件蹂躏之后创建的这个工具,所以这是一个写给自己用的工具,在使用的时候你能够切身体会到它的便利!
前提条件
运行 logstash-test-runner 依赖于下面三个条件:
- Docker
- NodeJS > v8
- Bash > v4
其中 logstash 的测试用例是在 docker 容器中运行的,默认使用的镜像中 logstash 的版本为 5.5.1,我们可以通过第二个命令行参数指定其它的版本。
NodeJS 程序用来对比实际运行的输出结果与期望的输出结果。
logstash-test-runner 其实就是一个 Bash 脚本,把上面的工具组织起来完成任务。
在运行 logstash-test-runner 前请确保你的环境满足上述条件。然后从这里克隆 logstash-test-runner。如果你确定你要运行的 logstash 的版本,最好是提前先把对应的容器镜像拉下来,比如笔者最常用的是 logstash 6.2.4:
$ docker pull docker.elastic.co/logstash/logstash:6.2.4
运行下内置的 demo
准备就绪,让我们先运行下 logstash-test-runner 内置的 demo 体验一下。进入到 logstash-test-runner 目录下,执行下面的命令:
$ npm install $ ./test.sh __tests__
test.sh 脚本的第一个参数是保存测试用例的根目录,第二个参数是 logstash 的 docker 镜像。也可以不指定 logstash 镜像,默认使用的镜像中的 logstash 版本为 5.5.1。该命令执行的结果如下:
__tests__ 目录的结构如下:
每个子目录代表一个测试用例,demo 中有三个测试用例,分别是 clustering、crawlers 和 mongo。每个测试用例下有三个文件,分别是 input.log、logstash.conf 和 output.log,他们的名称是固定的。input.log 模拟日志文件,保存的是日志记录;logstash.conf 则是待测的 logstash 配置文件;output.log 中是需要我们写入的期望结果(这就是 logstash 版的单元测试呀!)。
添加自己的测试用例
下面我们添加自己的测试用例来测试 multiline 功能(把应用程序中的异常堆栈合并到一条日志记录中)。先创建目录 __nick__/mlines,然后在 __nick__/mlines 目录中创建文件 input.log、logstash.conf 和 output.log。input.log 文件的内容如下:
2019-1 hello world 2019-2 aa 2019-3 bb 2019-4
模拟的日志记录以日期开头,非数字开头的记录则是异常堆栈。
logstash.conf 文件的内容如下:
input { stdin { codec => multiline { pattern => "^\d" negate => "true" what => "previous" } } } filter { mutate { replace => { "host" => "testing_host" } } }
filter 中设置 host 主要目的是让测试用例忽略真正的 host 值(在容器中运行这个值是随机的字符串,无法执行比较操作,所以总是让他输出 testing_host)。
output.log 文件的内容如下:
{"tags":["multiline"],"host":"testing_host","message":"2019-1\nhello\nworld","@version":"1","@timestamp":"2019-03-05T09:30:26.820Z"} {"tags":["multiline"],"host":"testing_host","message":"2019-2\naa","@version":"1","@timestamp":"2019-03-05T09:30:26.823Z"} {"tags":["multiline"],"host":"testing_host","message":"2019-3\n bb","@version":"1","@timestamp":"2019-03-05T09:30:26.824Z"}
这是我们期望 logstash 输出的 JSON 格式的日志记录。当然,在默认情况下 logstash-test-runner 会忽略 @timestamp。
接下来执行下面的命令运行测试:
$ ./test.sh __nick__ docker.elastic.co/logstash/logstash:6.2.4
该命令中笔者指定了 logstash 镜像,所以测试用例都是由 logstash 6.2.4 执行的,结果如下:
上图显示测试用例都通过了。如果有测试用例失败,就会输出详细的失败信息,非常有助于排除问题。
难点在于写 output.log
logstash-test-runner 非常简单易用,其实在整个使用过程中,笔者觉得写 output.log 是最困难的。因为你很难根据日志记录和 logstash 的配置文件直接推导出 logstash 输出的记录应该是什么样子的。logstash-test-runner 直接把 logstash 输出的日志记录输出到了 console 中:
这样我们就可以轻松的根据 console 中的输出来调整 output.log 文件了!
总结
使用者为自己编写的工具往往是直击痛点,logstash-test-runner 就是这样的工具。它让我们可以快速迭代 logstash 的配置变更。我们还可以自动化的执行 logstash-test-runner,作为 CI/CD 的一部分,从而确保每个配置变更都通过了测试。
对 logstash 之类的基础设施工具进行测试符合 DevOps(构建→测试→发布→运行)的实践。我想测试基础设施配置的实践会越来越普遍,并且在提高基础设施可靠性和交付方面体现出巨大的价值。
参考:
Dealing with Tight-Coupling
agolo/logstash-test-runner
原文地址:https://www.cnblogs.com/sparkdev/p/10564287.html