ELK日志环境入门-01之Elasticsearch官方源码部署

一、ELK日志环境概述

在排查线上异常的过程中,查询日志总是必不可缺的一部分。现今大多采用的微服务架构,日志被分散在不同的机器上,使得日志的查询变得异常困难。工欲善其事,必先利其器。如果此时有一个统一的实时日志分析平台,那可谓是雪中送碳,必定能够提高我们排查线上问题的效率。本文入门一下开源的实时日志分析平台 ELK 的Elasticsearch官方源码部署及使用。

ELK日志环境入门系列
ELK日志环境入门系列工作流程图

二、Elasticsearch简介

Elasticsearch (ES)是一个分布式的 Restful 风格的搜索和数据分析引擎,它具有以下特点:

  • 查询:允许执行和合并多种类型的搜索 — 结构化、非结构化、地理位置、度量指标 — 搜索方式随心而变。
  • 分析:Elasticsearch 聚合让您能够从大处着眼,探索数据的趋势和模式。
  • 速度:很快,可以做到亿万级的数据,毫秒级返回。
  • 可扩展性:可以在笔记本电脑上运行,也可以在承载了 PB 级数据的成百上千台服务器上运行。
  • 弹性:运行在一个分布式的环境中,从设计之初就考虑到了这一点。
  • 灵活性:具备多个案例场景。支持数字、文本、地理位置、结构化、非结构化,所有的数据类型都欢迎。

三、ELK 实现方案

通常情况下我们的服务都部署在不同的服务器上,那么如何从多台服务器上收集日志信息就是一个关键点了。本篇文章中提供的解决方案如下图所示:

ELK日志环境入门系列实践逻辑图
ELK日志环境入门系列实践逻辑图

如上图所示,整个 ELK 的运行流程如下:

  1. 在微服务(产生日志的服务)上部署一个 Logstash,作为 Shipper 角色,主要负责对所在机器上的服务产生的日志文件进行数据采集,并将消息推送到 Redis 消息队列。
  2. 另用一台服务器部署一个 Indexer 角色的 Logstash,主要负责从 Redis 消息队列中读取数据,并在 Logstash 管道中经过 Filter 的解析和处理后输出到 Elasticsearch 集群中存储。
  3. Elasticsearch 主副节点之间数据同步。
  4. 单独一台服务器部署 Kibana 读取 Elasticsearch 中的日志数据并展示在 Web 页面。

通过这张图,相信您已经大致清楚了我们将要搭建的 ELK 平台的工作流程,以及所需组件。下面就让我们一起开始搭建起来吧。

四、ELK 平台搭建基于Elasticsearch官方源码部署

本节主要介绍搭建 ELK 日志平台,包括安装 Indexer 角色的 Logstash,Elasticsearch 以及 Kibana 三个组件。完成本小节,您需要做如下准备:

  1. 一台 Linux/CentOS 机器或虚拟机,作为入门教程,此处省略了 Elasticsearch 集群的搭建,将 Logstash(Indexer)、Elasticsearch 以及 Kibana 安装在不同机器上,即ELK分布式部署。
  2. 在 Linux/CentOS 上安装 JDK,注意 Logstash 要求 JDK 在 1.8 版本或以上。
  3. ELK官方组件下载,您可以在 ELK源码下载
  4. 本文详细演示Elasticsearch官方源码部署
  5. Logstash官方源码部署,请移步《》
  6. 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
Elasticsearch官方源码部署

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.javaXPackBuild.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 许可文件来激活,其他已封堵。

X-pack-7.14.0插件许可破解步骤图
X-pack-7.14.0插件许可破解结果

Docker部署Elasticsearch+Kibana+Logstash+Filebeat v7.14


ELK日志环境入门-01之Elasticsearch官方源码部署
https://cn.10691.cn//archives/10072
作者
Ley
发布于
2021年08月31日
许可协议