ElasticSearch6集群搭建及踩坑

ElasticSearch6集群搭建及问题解决

  • 下载安装
    • 安装JDK
    • 安装ElasticSearch
  • 配置文件
  • 常见问题
      • 启动报错:java.lang.RuntimeException: can not run elasticsearch as root
      • 启动报错:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]
      • 启动报错:max number of threads [2048] for user [es] is too low, increase to at least [4096]
      • 启动报错:system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk
      • 启动报错:max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]
      • 线上故障:Error: bash: fork: retry: Resource temporarily unavailable
  • 维护与监控
      • 集群宕机后重启由于索引太多恢复太慢,暂时关闭索引
  • 分词等其他插件
    • 安装Ik分词器
    • 安装pinyin分词器
  • 感谢

公司使用了es2.2版本,最近准备升级到es6.2,领导安排我来调研工作。在此之前其实对es只闻其名,从来没有在实际中运用过。利用这次机会好好的深入研究一番,把自己安装过程,以及踩得坑记录下去,避免大家入坑。

下载安装

安装JDK

在/usr/java/目录下执行,下载jdk1.8,注意es6.2要基于jdk1.8.131+,为了避免莫名其妙的问题,请先检查jdk版本

wget https://download.oracle.com/otn-pub/java/jdk/8u201-b09/42970487e3af4f5aa5bca3f542482c60/jdk-8u201-linux-x64.tar.gz
// 解压jdk到当前文件夹下
tar -xvf jdk-8u201-linux-x64.tar.gz 
// 修改profile文件 配置java环境变量
vi /etc/profile 
在文件的末尾添加 把JAVA_HOME到处到PATH中
export JAVA_HOME=/usr/java/jdk1.8.0_201
export PATH=${JAVA_HOME}/bin:${PATH}    
// wq 保存退出
// 使配置的环境变量生效
source /etc/profile     
//    检测Java命令是否可用,出现以下内容可用
java -vesion
java version "1.8.0_201"
Java(TM) SE Runtime Environment (build 1.8.0_201-b09)
Java HotSpot(TM) 64-Bit Server VM (build 25.201-b09, mixed mode)

安装ElasticSearch

在/tol/htdocs/目录下执行 获得es安装文件
weget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-6.2.2.tar.gz
解压elasticsearch
tar -xvf elasticsearch-6.2.2.tar.gz

此时其实已经可以运行es了,不过启动起来是用默认配置运行的单节点,下面更改es的配置,使其运行在集群上

配置文件

config目录下有三个文件分别是:

elasticsearch.yml	es的配置
jvm.options				jvm参数控制
log4j2.properties		日志规则配置

一般情况下我们只需要修改elasticsearch.yml文件的配置,其他的基本不需要动做,一下就是对三台机器上面elasticsearch.yml的配置

# ---------------------------------- Cluster -----------------------------------
# 配置集群的名称,同一个集群配置的这个名称要一样,es会自动发现同样名称的集群,然后加入进来
cluster.name: es6-trunk
# ------------------------------------ Node ------------------------------------
# 本节点的名称,在集群中的身份识别
node.name: es6-trunk-node-3
# ----------------------------------- Paths ------------------------------------
# es的数据保存目录
path.data: /tol/data/es/data
# es运行时日志的保存路径
path.logs: /tol/data/es/logs
# ----------------------------------- Memory -----------------------------------
# 是否锁定运行时的内容,默认不需要,system_call_filter:false否则启动会报错
#bootstrap.memory_lock: true
bootstrap.system_call_filter: false
# ---------------------------------- Network -----------------------------------
# 这里配置本机的节点,用来访问及发现
network.host: 10.155.20.52
# es 访问的端口
http.port: 9200
# --------------------------------- Discovery ----------------------------------
# 配置es集群的地址,es启动时,会去这些地址里,互相发现然后选举一个master
discovery.zen.ping.unicast.hosts: ["10.155.20.50", "10.155.20.51","10.155.20.52"]
# es形成集群所需要的最小的节点数,默认3,奇数节点
discovery.zen.minimum_master_nodes: 3

其他两台机器上面的配置于此相同,只不过是把network.host的值换成本机的ip
启动elasticsearch

./elasticsearch	
./elasticsearch -d

es 默认会前台运行,第一次启动可以直接用命令运行,这样可以看到输出日志,能够比较及时的发现问题,能够正常运行后可以在命令后面加上 -d ,让es在 后台运行

常见问题

启动报错:java.lang.RuntimeException: can not run elasticsearch as root

   原因: elasticsearch 用root账户启动会报错,
   解决:创建一个es组用户,更改所有权限,用es账户启动
    groupadd es 添加用户
    useradd es -g es -p es  添加用户到组es,用户名为es,密码为es
    groups es 显示组 用户
    chown -R es:es /app/elasticsearch-6.2.2     切换目录所有权

用es用户启动后,注意配置文件中指定了data/log的输出目录,创建目录且赋权

启动报错:max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]

原因:新建es账户后,系统分配的内存太低
解决:切换到root用户   执行命令:
sysctl -w vm.max_map_count=262144
查看结果:
sysctl -a|grep vm.max_map_count
显示:
vm.max_map_count = 262144
上述方法修改之后,如果重启虚拟机将失效,所以:
在   /etc/sysctl.conf文件最后添加一行,即可永久修改     
vm.max_map_count=262144
 执行命令sysctl -p重启

启动报错:max number of threads [2048] for user [es] is too low, increase to at least [4096]

    切换到root用户,进入limits.d目录下修改配置文件。
    vi /etc/security/limits.d/90-nproc.conf
    修改如下内容:
    * soft nproc 1024
    修改为
    * soft nproc 4096

启动报错:system call filters failed to install; check the logs and fix your configuration or disable system call filters at your own risk

  原因:
  这是在因为Centos6不支持SecComp,而ES5.2.0默认bootstrap.system_call_filter为true进行检测,
  所以导致检测失败,失败后直接导致ES不能启动。
  解决:
  在elasticsearch.yml中配置bootstrap.system_call_filter为false,注意要在Memory下面:
  bootstrap.memory_lock: false
  bootstrap.system_call_filter: false
  可以查看issues
  https://github.com/elastic/elasticsearch/issues/22899

启动报错:max file descriptors [4096] for elasticsearch process is too low, increase to at least [65536]

   切换到root用户
   ulimit -Hn  查看硬限制
   vim /etc/security/limits.conf
   添加下面设置 es是用户
   es soft nofile 65536
   es hard nofile 65536
   退出用户重新登录,使配置生效
   重新 ulimit -Hn  查看硬限制 会发现数值有4096改成65535

线上故障:Error: bash: fork: retry: Resource temporarily unavailable

由于按天拆分了索引了,导致es在运行一段时间之后,突然宕机,再次启动报错
因为用户能够创建的线程数和可以打开文件的最大数超过了系统给用户允许的限制
一个索引几十个G占用几千万条数据对查询没有什么影响
应当避免拆索引分成多个索引造成索引个数太多文件分片太多,降低es查询性能且会超过文件打开最大数

ulimit -a,查看一下,主要看两个值:
open files和max user processes,基本上这两个值最容易超,(当前用户的进程数可以用ulimit -u,ulimit -n 当前用户打开的文件数)

设置文件的打开数 /etc/security/limits.conf
vi /etc/security/limits.conf
* soft nofile 65535
* hard nofile 65535
* soft nproc 20480
* hard nproc 20480
* soft stack 10240
* hard stack 32768

然后在/etc/security/limits.d/90-nproc.conf中修改进程数(centos6的版本需要)
* soft nproc 201400
* hard nproc 201400
root soft nproc unlimited
root hard nproc unlimited

参考链接:https://www.cnblogs.com/aishangyizhihu/p/6276846.html

维护与监控

集群宕机后重启由于索引太多恢复太慢,暂时关闭索引

关闭索引尤其是日志数据, 一般短期内的数据还会被用于数据统计分析, 历史数据再被翻阅的可能性比较小,
由于倒排词典的索引常驻内存,无法 GC,尤其随着日积月累索引越来越多, 内存捉襟见肘(主要是穷),
动辄 gc 几十秒, 告警个不停, 或者直接 gg 了, 索引我们做了定时关闭历史索引, 只保留近期一段时间的索引开启着,
如果需要查询历史数据再单独开启。

curl -XPOST http://example.com:9200/my_index/_close
curl -XPOST http://example.com:9200/my_index/_open

定时扫描es的索引,大于7天前的索引邮件通知
shell脚本如下

#!/bin/bash
Indexs=`curl -XGET -s http://localhost:9200/_cat/indices |grep open|awk '{print $3}'|grep -E '(20[0-9]{2}\.[0-9]{1,2}\.[0-9]{1,2})$'`
if [ -n "$Indexs" ]; then
    flag=`date -d "-7 day" +"%Y.%m.%d"`
    arr=()
    for ind in $Indexs ; do
        temp="${ind:0-10}"
        if [[ "$temp" < "$flag" ]]; then
            len="${#arr[*]}"
            arr[len]="$ind"
        fi
    done
fi
arrStr=${arr[*]}
echo "$arrStr"
`python mail.py "$arrStr"`

通过python发邮件通知

#!/usr/bin/python
# -*- coding: UTF-8 -*-

import sys
from exchangelib import DELEGATE, Account, Credentials, Message, Mailbox, HTMLBody

def Email(to, subject, body):
    creds = Credentials(
        username='username',
        password='password'
    )
    account = Account(
        primary_smtp_address='user account',
        credentials=creds,
        autodiscover=True,
        access_type=DELEGATE
    )
    m = Message(
        account=account,
        subject=subject,
        body=HTMLBody(body),
        to_recipients = [Mailbox(email_address=to)]
    )
    m.send()
message=sys.argv[1]
Email("user account", "email subject", message)

分词等其他插件

安装Ik分词器

elasticsearch-analysis-ik:https://github.com/medcl/elasticsearch-analysis-ik
安装IK有2种方式

  1. 下载安装包,到plugin目录下解压

    1. 从github上下载zip包,地址:https://github.com/medcl/elasticsearch-analysis-ik/releases
    2. 在es_home/plugins/ 下创建一个文件夹命名为
      mkdir ik
    3. 解压 elasticsearch-analysis-ik-6.2.4.zip
      unzip elasticsearch-analysis-ik-6.2.4.zip
    4. 如果没有unzip
      yum install -y unzip
  2. 在线安装

    1. 用es_home/bin下的elasticsearch-plugin 直接安装插件
      shell ./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-ik/releases/download/v6.2.2/elasticsearch-analysis-ik-6.2.2.zip
    2. 安装报错:Exception in thread “main” java.lang.IllegalArgumentException: plugin [analysis-ik] is incompatible with version [6.2.2]; was designed for version [6.2.4]
      原因:我的本地版本是 6.2.2 ,ik的版本是6.2.4,版本不兼容,因为我看了readme上面没有6.2.2就误以为可以用6.2.4实际上是有的。
      解决:修改连接中版本为6.2.2
  3. 检查是否安装成功
    执行命令 elasticsearch-plugin list 参看已经安装上的插件 ,显示出ik表示安装成功

    ./elasticsearch-plugin list
    analysis-ik
    
  4. 验证分词
    创建索引 mytest/doc

    PUT mytest
    {
        "mappings": {
                "doc": {
                    "properties": {
                    "content": {
                        "type": "text",
                        "analyzer": "ik_max_word"
                    }
                }
            }
        }
    }
    
    // 插入数据
    POST mytest/doc/1
    {"content":"美国留给伊拉克的是个烂摊子吗"}
    POST mytest/doc/2
    {"content":"公安部:各地校车将享最高路权"}
    POST mytest/doc/3
    {"content":"中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"}
    
    //查询数据
    POST mytest/doc/_search
    {
        "query" : { "match" : { "content" : "中国" }}
    }
    
    //返回查询结果
    {
    	"took": 32,
    	"timed_out": false,
    	"_shards": {
    		"total": 5,
    		"successful": 5,
    		"skipped": 0,
    		"failed": 0
    	},
    	"hits": {
    		"total": 1,
    		"max_score": 0.2876821,
    		"hits": [ {
    			"_index": "mytest",
    			"_type": "doc",
    			"_id": "3",
    			"_score": 0.2876821,
    			"_source": {
    				"content": "中韩渔警冲突调查:韩警平均每天扣1艘中国渔船"
    			}
    		} ]
    	}
    }
    

    用分词api测试,可以直观的看到分词后的结果,一句话被分成什么样子了,可以在构建索引之前,用这种方法来测试自己到底需要什么类型的分词器,以便在构建索引的时候正确的选择分词器

    POST _analyze
    {
      "analyzer": "ik_max_word",
      "text": "中华人民共和国国歌"
    }
    // 返回
    {
        "tokens":[
            {
                "token":"中华人民共和国",
                "start_offset":0,
                "end_offset":7,
                "type":"CN_WORD",
                "position":0
            }, {
                "token":"中华人民",
                "start_offset":0,
                "end_offset":4,
                "type":"CN_WORD",
                "position":1
            }, {
                "token":"中华",
                "start_offset":0,
                "end_offset":2,
                "type":"CN_WORD",
                "position":2
            }, {
                "token":"华人",
                "start_offset":1,
                "end_offset":3,
                "type":"CN_WORD",
                "position":3
            }, {
                "token":"人民共和国",
                "start_offset":2,
                "end_offset":7,
                "type":"CN_WORD",
                "position":4
            }, {
                "token":"人民",
                "start_offset":2,
                "end_offset":4,
                "type":"CN_WORD",
                "position":5
            }, {
                "token":"共和国",
                "start_offset":4,
                "end_offset":7,
                "type":"CN_WORD",
                "position":6
            }, {
                "token":"共和",
                "start_offset":4,
                "end_offset":6,
                "type":"CN_WORD",
                "position":7
            }, {
                "token":"国",
                "start_offset":6,
                "end_offset":7,
                "type":"CN_CHAR",
                "position":8
            }, {
                "token":"国歌",
                "start_offset":7,
                "end_offset":9,
                "type":"CN_WORD",
                "position":9
            }
        ]
    }
    
  5. ik_max_word 和 ik_smart 什么区别?
    ik_max_word: 会将文本做最细粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,中华人民,中华,华人,人民共和国,人民,人,民,共和国,共和,和,国国,国歌”,会穷尽各种可能的组合;
    ik_smart: 会做最粗粒度的拆分,比如会将“中华人民共和国国歌”拆分为“中华人民共和国,国歌”。

安装pinyin分词器

github地址: https://github.com/medcl/elasticsearch-analysis-pinyin

  1. 用elasticsearch-plugin 插件安装
    ./elasticsearch-plugin install https://github.com/medcl/elasticsearch-analysis-pinyin/releases/download/v6.2.2/elasticsearch-analysis-pinyin-6.2.2.zip
    
  2. 检查是否安装成功
    ./elasticsearch-plugin list
    analysis-ik
    analysis-pinyin
    
    显示出analysis-pinyin 插件表示安装成功
  3. 验证分词结果
    用分词查看api查看分词结果,每个字做了拼音,首字母联合做个拼音
    POST	mytest/_analyze
    {
      "analyzer": "pinyin",
      "text": "刘德华"
    }
    // 返回结果
    {
    	"tokens": [
    		{
    			"token": "liu",
    			"start_offset": 0,
    			"end_offset": 0,
    			"type": "word",
    			"position": 0
    		},{
    			"token": "ldh",
    			"start_offset": 0,
    			"end_offset": 0,
    			"type": "word",
    			"position": 0
    		},{
    			"token": "de",
    			"start_offset": 0,
    			"end_offset": 0,
    			"type": "word",
    			"position": 1
    		},{
    			"token": "hua",
    			"start_offset": 0,
    			"end_offset": 0,
    			"type": "word",
    			"position": 2
    		}
    	]
    }
    

感谢

再次感谢领导给我机会,让我边工作边学习研究es6,准备替换公司现行运行的es2,这是一个很好的实践与学习的机会。
后续本文会持续更新,深入挖掘elasticsearch强大功能。

你可能感兴趣的:(ELK)