在ARM平台上使用Logstash的SSL加密beats插件

缘起

ARM的软件硬件环境各种各样,相比X86平台要难搞得多,所以也难怪ELK官方不提供ARM平台的解决方案。但是因为我现在的几个服务都需要在家里跑,能耗是一个敏感指标,X86在这方面跟ARM完全没法比,所以还是需要自己折腾一下的。

虽然官方没有提供ELK的ARM平台解决方案,但因为ElasticSearch和Logstash是Java写的(Logstash中还有相当部是Ruby写的,基于JRuby运行),Kibana是Node.js,所以跨平台并无什么压力。安装好JRE和Node环境,全都顺利地跑了起来——当然,因为单机内存不足,我是在两台机器上跑这三个应用的。

但是当我把整个系统配置搞好以后,Logstash启动失败,日志显示:

ConfigurationError: Cipher 'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384' is not available

看上去跟加密相关,经过反复测试,确认了问题在配置中的SSL加密部分,关闭SSL加密就可以了,一但打开就出错。再打开debug日志查看,得到这个错误:

Unable to load the library 'netty_tcnative_linux_aarch_64', trying other loading mechanism.
java.lang.UnsatisfiedLinkError: no netty_tcnative_linux_aarch_64 in java.library.path
        at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1867) ~[?:1.8.0_181]
        at java.lang.Runtime.loadLibrary0(Runtime.java:870) ~[?:1.8.0_181]
        at java.lang.System.loadLibrary(System.java:1122) ~[?:1.8.0_181]
        ...

为了解决这个问题,花了我十几天时间,编译了几十遍的netty和netty-tcnative,直到这两天才终于成功。

分析

经过几番尝试和分析,得到这样一个大致思路:

input-beats是通过netty这个Java网络库来实现网络通讯的,虽然官方并未表示过对ARM的支持,但实践证明这个库本身在ARM平台运行是没问题的,应该是以纯Java实现为主,非Java的部分大概是我没用到,所以如果不使用SSL加密的话,还是可以用的。

但是用了SSL的话,netty就会用到netty-tcnative库,而这个库内置了一个二进制库:libnetty-tcnative,官方发布的版本这个库只有三个版本:

Linux-X86, Windows-X86, MacOSX-X86

没错,只有X86,而且这个库支持四种SSL实现方案:

openssl-dynamic, openssl-static, boringssl-static, libressl-static

相当麻烦。

为了解决这个问题,就得自己编译一个netty-tcnative。

准备

编译之前先要准备环境。

我用的软硬件环境如下:

  • 斐讯N1盒子:Amlogic S905D 4核A8 ARM64 CPU,2G RAM,8G NAND
  • 系统:Armbian 5.67 Ubuntu 18.04

需要安装的编译依赖有这些(可能不全,自行根据编译提示补装):

apt install -y openjdk-8-jdk maven libapr1 libapr1-dev autoconf automake libtool cmake ninja-build golang openssl1.0 libssl1.0-dev

从github下载netty-tcnative的源码:

git clone https://github.com/netty/netty-tcnative.git

因为我用的是Logstash 6.3.2,所以更新到对应使用的netty-tcnative版本:

git checkout netty-tcnative-parent-2.0.7.Final

为了省事起见,只编译一个版本,就是ARM版的openssl-dynamic:

编译,必须跳过测试,否则openssl-dynamic中有一个surefire测试不通过,跳过不会有实质性影响
mvn -x clean install -DskipTests=true -pl openssl-dynamic

之前编译整个项目,在openssl-static, libressl-static, boringssl-static里都碰到各种问题,解决起来花了很多时间,最后也并没有什么用。

部署

编译成功后,我们需要的只有一个文件:

openssl-dynamic/target/native-jar-work/META-INF/native/libnetty_tcnative.so

把它COPY到某个地方,比如logstash/lib,然后改名为libnetty_tcnative_linux_aarch_64.so,再配置一下环境变量:

export LD_LIBRARY_PATH=/path_to/logstash/lib

再启动logstash就可以使用SSL加密的input-beats插件了。

推送到[go4pro.org]