ELK日志环境入门-01之Elasticsearch官方源码部署
一、ELK日志环境概述
在排查线上异常的过程中,查询日志总是必不可缺的一部分。现今大多采用的微服务架构,日志被分散在不同的机器上,使得日志的查询变得异常困难。工欲善其事,必先利其器。如果此时有一个统一的实时日志分析平台,那可谓是雪中送碳,必定能够提高我们排查线上问题的效率。本文入门一下开源的实时日志分析平台 ELK 的Elasticsearch官方源码部署及使用。
二、Elasticsearch简介
Elasticsearch (ES)是一个分布式的 Restful 风格的搜索和数据分析引擎,它具有以下特点:
- 查询:允许执行和合并多种类型的搜索 — 结构化、非结构化、地理位置、度量指标 — 搜索方式随心而变。
- 分析:Elasticsearch 聚合让您能够从大处着眼,探索数据的趋势和模式。
- 速度:很快,可以做到亿万级的数据,毫秒级返回。
- 可扩展性:可以在笔记本电脑上运行,也可以在承载了 PB 级数据的成百上千台服务器上运行。
- 弹性:运行在一个分布式的环境中,从设计之初就考虑到了这一点。
- 灵活性:具备多个案例场景。支持数字、文本、地理位置、结构化、非结构化,所有的数据类型都欢迎。
三、ELK 实现方案
通常情况下我们的服务都部署在不同的服务器上,那么如何从多台服务器上收集日志信息就是一个关键点了。本篇文章中提供的解决方案如下图所示:
如上图所示,整个 ELK 的运行流程如下:
- 在微服务(产生日志的服务)上部署一个 Logstash,作为 Shipper 角色,主要负责对所在机器上的服务产生的日志文件进行数据采集,并将消息推送到 Redis 消息队列。
- 另用一台服务器部署一个 Indexer 角色的 Logstash,主要负责从 Redis 消息队列中读取数据,并在 Logstash 管道中经过 Filter 的解析和处理后输出到 Elasticsearch 集群中存储。
- Elasticsearch 主副节点之间数据同步。
- 单独一台服务器部署 Kibana 读取 Elasticsearch 中的日志数据并展示在 Web 页面。
通过这张图,相信您已经大致清楚了我们将要搭建的 ELK 平台的工作流程,以及所需组件。下面就让我们一起开始搭建起来吧。
四、ELK 平台搭建基于Elasticsearch官方源码部署
本节主要介绍搭建 ELK 日志平台,包括安装 Indexer 角色的 Logstash,Elasticsearch 以及 Kibana 三个组件。完成本小节,您需要做如下准备:
- 一台 Linux/CentOS 机器或虚拟机,作为入门教程,此处省略了 Elasticsearch 集群的搭建,将 Logstash(Indexer)、Elasticsearch 以及 Kibana 安装在不同机器上,即ELK分布式部署。
- 在 Linux/CentOS 上安装 JDK,注意 Logstash 要求 JDK 在 1.8 版本或以上。
- ELK官方组件下载,您可以在 ELK源码下载。
- 本文详细演示Elasticsearch官方源码部署
- Logstash官方源码部署,请移步《》
- Kibana官方源码部署,请移步《》
五、安装Elasticsearch
1、安装依赖环境
[root@es ~]# wget https://download.oracle.com/otn/java/jdk/8u301-b09/d3c52aa6bfa54d3ca74e617f18309292/jdk-8u301-linux-x64.rpm?AuthParam=1630374823_29c8a62eebc8754fe26188019ff8acfc
[root@es ~]# rpm -ivh jdk-8u301-linux-x64.rpm
正在升级/安装...
1:jdk1.8-2000:1.8.0_301-fcs ################################# [100%]
2、下载elastic官网最新版本 elasticsearch-7.14.0
-rw-r--r-- 1 root root 344030267 8月 31 09:48 elasticsearch-7.14.0-linux-x86_64.tar.gz
3、创建并解压至自定义目录
## 创建一个elasticsearch数据存储目录
[root@es ~]# mkdir -p /usr/local/elk/elasticsearch-7.14.0/data
## 解压缩至指定目录
[root@es ~]# tar xf /opt/elasticsearch-6.4.2.tar.gz -C /usr/local/elk/
4、创建一个普通用户es用来运行elasticsearch
[root@es ~]# groupadd es
[root@es ~]# useradd -g es es -m
[root@es ~]# chown -R es.es /usr/local/elk/elasticsearch-7.14.0/
[root@es ~]# ll /usr/local/elk/elasticsearch-7.14.0/
总用量 624
drwxr-xr-x 2 es es 4096 7月 30 04:52 bin
drwxr-xr-x 3 es es 169 8月 31 11:21 config
drwxr-xr-x 2 es es 6 8月 31 13:34 data
drwxr-xr-x 9 es es 107 7月 30 04:52 jdk
drwxr-xr-x 3 es es 4096 7月 30 04:52 lib
-rw-r--r-- 1 es es 3860 7月 30 04:47 LICENSE.txt
drwxr-xr-x 2 es es 6 7月 30 04:51 logs
drwxr-xr-x 59 es es 4096 7月 30 04:53 modules
-rw-r--r-- 1 es es 615722 7月 30 04:51 NOTICE.txt
drwxr-xr-x 2 es es 6 7月 30 04:51 plugins
-rw-r--r-- 1 es es 2710 7月 30 04:47 README.asciidoc
5、 修改 elasticsearch.yml 文件配置
[root@es ~]# cd /usr/local/elk/elasticsearch-7.14.0/config/
[root@es config]# cat elasticsearch.yml | grep ^[^#]
cluster.name: es-alione
node.name: es-1
path.data: /usr/local/elk/elasticsearch-7.14.0/data
path.logs: /usr/local/elk/elasticsearch-7.14.0/logs
network.host: 10.100.202.100
http.port: 9200
cluster.initial_master_nodes: ["es-1"]
6、修改相关内核参数
[root@es elasticsearch-7.14.0]# echo "vm.max_map_count=262144" >> /etc/sysctl.conf
[root@es elasticsearch-7.14.0]# sysctl -p
vm.max_map_count = 262144
[root@es elasticsearch-7.14.0]# vim /etc/security/limits.conf
* soft nproc 65536
* hard nproc 65536
* soft nofile 65536
* hard nofile 65536
7、切换普通用户运行es来运行elasticsearch
[root@es ~]# su - es
[es@es ~]$ nohup /usr/local/elk/elasticsearch-7.14.0/bin/elasticsearch -d
8、创建elasticsearch开机自启动脚本
创建es 的系统启动服务文件
[root@es init.d]# vim /etc/init.d/elasticsearch
## 脚本内容粘贴如下
#!/bin/bash
#chkconfig: 345 63 37
#description: elasticsearch
#processname: elasticsearch-7.0.0
# es根目录
export ES_HOME=/usr/local/elk/elasticsearch-7.14.0
case $1 in
start)
su es<<!
cd $ES_HOME
./bin/elasticsearch -d -p pid
exit
!
echo "elasticsearch is started"
;;
stop)
pid=`cat $ES_HOME/pid`
kill -9 $pid
echo "elasticsearch is stopped"
;;
restart)
pid=`cat $ES_HOME/pid`
kill -9 $pid
echo "elasticsearch is stopped"
sleep 1
su es<<!
cd $ES_HOME
./bin/elasticsearch -d -p pid
exit
!
echo "elasticsearch is started"
;;
*)
echo "start|stop|restart"
;;
esac
exit 0
## 修改文件权限
[root@es init.d]# chmod 777 elasticsearch
## 添加和删除服务并设置启动方式
chkconfig --add elasticsearch 【添加系统服务】
chkconfig --del elasticsearch 【删除系统服务】
## 关闭和启动服务
service elasticsearch start 【启动】
service elasticsearch stop 【停止】
service elasticsearch restart 【重启】
## 设置服务是否开机启动
chkconfig elasticsearch on 【开启】
chkconfig elasticsearch off 【关闭】
9、解决常见问题
启动时,提示 JAVA_HOME 版本问题:
warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME
Future versions of Elasticsearch will require Java 11; your Java version from [/usr/java/jdk1.8.0_301-amd64/jre] does not meet this requirement. Consider switching to a distribution of Elasticsearch with a bundled JDK. If you are already using a distribution with a bundled JDK, ensure the JAVA_HOME environment variable is not set.
warning: usage of JAVA_HOME is deprecated, use ES_JAVA_HOME
Future versions of Elasticsearch will require Java 11; your Java version from [/usr/java/jdk1.8.0_301-amd64/jre] does not meet this requirement. Consider switching to a distribution of Elasticsearch with a bundled JDK. If you are already using a distribution with a bundled JDK, ensure the JAVA_HOME environment variable is not set.
解决办法:将elasticserach启动文件中的默认JDK调用换成elasticserach自带的
[es@es bin]$ vim /usr/local/elk/elasticsearch-7.14.0/bin/elasticsearch
# 添加如下配置
export JAVA_HOME=/usr/local/elk/elasticsearch-7.14.0/jdk
export PATH=$JAVA_HOME/bin:$PATH
#添加jdk判断
if [ -x "$JAVA_HOME/bin/java" ]; then
JAVA="/usr/local/elk/elasticsearch-7.14.0/jdk/bin/java"
else
JAVA=`which java`
fi
四、Elasticsearch官方源码部署之X-pack-7.14.0插件许可破解
根据官方描述:目前,6.2及以下版本只能使用免费版,然而免费版的功能相当少。
1、X-pack 的破解基本思路是先安装正常版本,之后替换破解的 X-pack-<version>.jar包来实现,目前只能破解到[platinum]白金版,但已经够用了。更多版本功能介绍请查看官方版本订阅文档,步骤如下:
## 查找x-pack插件jar包,并下载至本地windows
[root@es ~]# ls /usr/local/elk/elasticsearch-7.14.0/modules/x-pack-core/
## 解压缩x-pack-core-7.14.0.jar,使用luyten编译软件提取org.elasticsearch.license.LicenseVerifier和org.elasticsearch.xpack.core.XPackBuild中配置信息。
2、新建LicenseVerifier.java,并修改为如下样式
package org.elasticsearch.license;
import java.io.InputStream;
import java.io.OutputStream;
import org.elasticsearch.core.internal.io.Streams;
import java.io.ByteArrayOutputStream;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.BytesRefIterator;
import java.util.Arrays;
import java.security.InvalidKeyException;
import java.security.SignatureException;
import java.security.NoSuchAlgorithmException;
import java.io.IOException;
import org.elasticsearch.common.bytes.BytesReference;
import java.security.Signature;
import java.util.Map;
import java.util.Collections;
import java.nio.ByteBuffer;
import java.util.Base64;
public class LicenseVerifier
{
public static boolean verifyLicense(final License license, final byte[] publicKeyData) {
/* byte[] signedContent = null;
byte[] publicKeyFingerprint = null;
try {
final byte[] signatureBytes = Base64.getDecoder().decode(license.signature());
final ByteBuffer byteBuffer = ByteBuffer.wrap(signatureBytes);
final int version = byteBuffer.getInt();
final int magicLen = byteBuffer.getInt();
final byte[] magic = new byte[magicLen];
byteBuffer.get(magic);
final int hashLen = byteBuffer.getInt();
publicKeyFingerprint = new byte[hashLen];
byteBuffer.get(publicKeyFingerprint);
final int signedContentLen = byteBuffer.getInt();
signedContent = new byte[signedContentLen];
byteBuffer.get(signedContent);
final XContentBuilder contentBuilder = XContentFactory.contentBuilder(XContentType.JSON);
license.toXContent(contentBuilder, (ToXContent.Params)new ToXContent.MapParams((Map)Collections.singletonMap("license_spec_view", "true")));
final Signature rsa = Signature.getInstance("SHA512withRSA");
rsa.initVerify(CryptUtils.readPublicKey(publicKeyData));
final BytesRefIterator iterator = BytesReference.bytes(contentBuilder).iterator();
BytesRef ref;
while ((ref = iterator.next()) != null) {
rsa.update(ref.bytes, ref.offset, ref.length);
}
return rsa.verify(signedContent);
}
catch (IOException ex) {}
catch (NoSuchAlgorithmException ex2) {}
catch (SignatureException ex3) {}
catch (InvalidKeyException e) {
throw new IllegalStateException(e);
}
finally {
if (signedContent != null) {
Arrays.fill(signedContent, (byte)0);
}
}
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.ToXContent;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
*/
return true;
}
public static boolean verifyLicense(final License license) {
/*
byte[] publicKeyBytes;
try {
final InputStream is = LicenseVerifier.class.getResourceAsStream("/public.key");
try {
final ByteArrayOutputStream out = new ByteArrayOutputStream();
Streams.copy(is, (OutputStream)out);
publicKeyBytes = out.toByteArray();
if (is != null) {
is.close();
}
}
catch (Throwable t) {
if (is != null) {
try {
is.close();
}
catch (Throwable t2) {
t.addSuppressed(t2);
}
}
throw t;
}
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
return verifyLicense(license, publicKeyBytes);
*/
return true;
}
}
3、新建XPackBuild.java,并修改为如下样式
package org.elasticsearch.xpack.core;
import java.util.jar.Manifest;
import java.io.IOException;
import java.util.jar.JarInputStream;
import java.nio.file.Files;
import java.nio.file.OpenOption;
import org.elasticsearch.core.SuppressForbidden;
import java.net.URL;
import java.net.URISyntaxException;
import org.elasticsearch.core.PathUtils;
import java.nio.file.Path;
public class XPackBuild
{
public static final XPackBuild CURRENT;
private String shortHash;
private String date;
@SuppressForbidden(reason = "looks up path of xpack.jar directly")
static Path getElasticsearchCodebase() {
final URL url = XPackBuild.class.getProtectionDomain().getCodeSource().getLocation();
try {
return PathUtils.get(url.toURI());
}
catch (URISyntaxException bogus) {
throw new RuntimeException(bogus);
}
}
XPackBuild(final String shortHash, final String date) {
this.shortHash = shortHash;
this.date = date;
}
public String shortHash() {
return this.shortHash;
}
public String date() {
return this.date;
}
static {
final Path path = getElasticsearchCodebase();
String shortHash = null;
String date = null;
Label_0109: {
/* if (path.toString().endsWith(".jar")) {
try {
final JarInputStream jar = new JarInputStream(Files.newInputStream(path, new OpenOption[0]));
try {
final Manifest manifest = jar.getManifest();
shortHash = manifest.getMainAttributes().getValue("Change");
date = manifest.getMainAttributes().getValue("Build-Date");
jar.close();
}
catch (Throwable t) {
try {
jar.close();
}
catch (Throwable t2) {
t.addSuppressed(t2);
}
throw t;
}
break Label_0109;
}
catch (IOException e) {
throw new RuntimeException(e);
}
}
*/
shortHash = "Unknown";
date = "Unknown";
}
CURRENT = new XPackBuild(shortHash, date);
}
}
4、分别编译生成 .class 文件
上述LicenseVerifier.java
和XPackBuild.java
两个文件在本地电脑windows修改完成后,我们需要将其复制到elasticsearch服务器上并编译成class文件,然后打包到x-pack-core-7.12.0.jar中。我们这里将这2个文件放到了/opt目录下。
## 编译LicenseVerifier.java
javac -cp "/usr/local/elk/elasticsearch-7.14.0/lib/elasticsearch-7.14.0.jar:/usr/local/elk/elasticsearch-7.14.0/lib/lucene-core-8.9.0.jar:/usr/local/elk/elasticsearch-7.14.0/modules/x-pack-core/x-pack-core-7.14.0.jar:/usr/local/elk/elasticsearch-7.14.0/modules/x-pack-core/netty-common-4.1.49.Final.jar:/usr/local/elk/elasticsearch-7.14.0/lib/elasticsearch-core-7.14.0.jar:" /opt/LicenseVerifier.java
## 编译XPackBuild.java
javac -cp "/usr/local/elk/elasticsearch-7.14.0/lib/elasticsearch-7.14.0.jar:/usr/local/elk/elasticsearch-7.14.0/lib/lucene-core-8.9.0.jar:/usr/local/elk/elasticsearch-7.14.0/modules/x-pack-core/x-pack-core-7.14.0.jar:/usr/local/elk/elasticsearch-7.14.0/modules/x-pack-core/netty-common-4.1.49.Final.jar:/usr/local/elk/elasticsearch-7.14.0/lib/elasticsearch-core-7.14.0.jar" /opt/XPackBuild.java
## 查看编译后的文件
ls /opt | grep .class
LicenseVerifier.class
XPackBuild.class
5、替换官方原 x-pack-core-7.14.0.jar 包
## 拷贝官方原文件jar包至/opt/下
cp /usr/local/elk/elasticsearch-7.14.0/modules/x-pack-core/x-pack-core-7.14.0.jar /opt/
## 解压x-pack-core-7.14.0.jar
jar -xvf x-pack-core-7.14.0.jar
# 替换.class文件
cp /opt/XPackBuild.class /opt/x-pack-core-7.14.0/org/elasticsearch/xpack/core/
cp /opt/LicenseVerifier.class /opt/x-pack-core-7.14.0/org/elasticsearch/license/
## 重新打包成x-pack-core-7.14.0.jar
cd x-pack-core-7.14.0/
jar cvf x-pack-core-7.0.1.jar . #“.”表示全选文件
## 上传覆盖官方原文件
cp /opt/x-pack-core-7.14.0/x-pack-core-7.14.0.jar /usr/local/elk/elasticsearch-7.14.0/modules/x-pack-core/
6、申请 elastic 官方许可证license.json,修改相关字段信息
## 申请License
完成以上步骤后,我们还需要去elastic官网申请一个license, [License申请地址](https://license.elastic.co/registration),申请完成后,下载下来的License格式为json格式。并将该License的`type`、`expiry_date_in_millis`、`max_nodes`分别修改成`platinum`、`2524579200999`、`1000`。如下:
{"license":{"uid":"89667e62-0747-4dcd-ba31-4e815d4f7ea9","type":"platinum","issue_date_in_millis":1558051200000,"expiry_date_in_millis":2524579200999,"max_nodes":1000,"issued_to":"es-alione","issuer":"elasticsearch","signature":"AAAAAwAAAA1ROmPFyse9lykP5SgkAAABmC9ZN0hjZDBGYnVyRXpCOW5Bb3FjZDAxOWpSbTVoMVZwUzRxVk1PSmkxaktJRVl5MUYvUWh3bHZVUTllbXNPbzBUemtnbWpBbmlWRmRZb25KNFlBR2x0TXc2K2p1Y1VtMG1UQU9TRGZVSGRwaEJGUjE3bXd3LzRqZ05iLzRteWFNekdxRGpIYlFwYkJiNUs0U1hTVlJKNVlXekMrSlVUdFIvV0FNeWdOYnlESDc3MWhlY3hSQmdKSjJ2ZTcvYlBFOHhPQlV3ZHdDQ0tHcG5uOElCaDJ4K1hob29xSG85N0kvTWV3THhlQk9NL01VMFRjNDZpZEVXeUtUMXIyMlIveFpJUkk2WUdveEZaME9XWitGUi9WNTZVQW1FMG1DenhZU0ZmeXlZakVEMjZFT2NvOWxpZGlqVmlHNC8rWVVUYzMwRGVySHpIdURzKzFiRDl4TmM1TUp2VTBOUlJZUlAyV0ZVL2kvVk10L0NsbXNFYVZwT3NSU082dFNNa2prQ0ZsclZ4NTltbU1CVE5lR09Bck93V2J1Y3c9PQAAAQB3iKwI0Si4vWz93EKvuajgjgqB98yCsntVU4akZBDCaVoLkaiQU+N6UmixgvCKCGJd4c3gOoBBnEfWxF8fVt54skFwrSAvjf1hK0Z30Jodt014yEuQhQJSa2n/C5xgqfodMZ/v4DpwR8kK68lnt1ttjEEzfehT9ugx1QObKkHkiGuuRMRjz7Ov9b9HtKy2ZMbSQBdtF8nwjy813iBemNnSnK3ZIVniXie8qvVZORIAaKM0kFxsbYp+HZjUq04C84zkCqADv697mwQNzY49SzyxRIFHOLitu1uU78sHqpJ5OL9SDFZ8jkJM10t/iqYeKMpTK32dZHgSEooos7Pyq6eS","start_date_in_millis":1630454400000}}
7、激活elasticserach-7.14.0
目前,实测新版ELK组件 elasticserach-7.14.0 激活方式为前端上传 license.json 许可文件来激活,其他已封堵。