Elasticsearch 部署和管理
Elasticsearch 部署和管理

Elasticsearch 部署和管理

Elasticsearch 是一个分布式的免费开源搜索和分析引擎,适用于包括文本、数字、地理空间、结构化和非结构化数据等在内的所有类型的数据
Elasticsearch 基于 Java 语言实现

Elasticsearch 安装说明

官方文档

https://www.elastic.co/guide/en/elastic-stack/index.html
https://www.elastic.co/guide/en/elasticsearch/reference/master/install-elasticsearch.html

部署方式
包安装
二进制安装
Docker 部署
Ansible 批量部署

ES支持操作系统版本和 Java 版本官方说明:https://www.elastic.co/cn/support/matrix

安装前准备

CPU 2C 内存4G或更多
操作系统: Ubuntu20.04,Ubuntu18.04,Rocky8.X,Centos 7.X
操作系统盘50G
主机名设置规则为nodeX.shu.org
生产环境建议准备单独的数据磁盘
关闭防火墙和SELinux
各服务器配置本地域名解析

优化资源限制配置
内核参数 vm.max_map_count 用于限制一个进程可以拥有的VMA(虚拟内存区域)的数量使用默认系统配置,二进制安装时会提示错误,包安装会自动修改此配置

#查看默认值
[root@es-node1 ~]#sysctl -a |grep vm.max_map_count
vm.max_map_count = 65530
#修改配置
[root@es-node1 ~]#echo "vm.max_map_count = 262144" >> /etc/sysctl.conf
[root@es-node1 ~]#echo "fs.file-max = 1000000" >> /etc/sysctl.conf
[root@es-node1 ~]#sysctl -p
vm.max_map_count = 262144

修改资源限制配置

[root@es-node1 ~]#vi /etc/security/limits.conf
* soft core unlimited
* hard core unlimited
* soft nproc 1000000
* hard nproc 1000000
* soft nofile 1000000
* hard nofile 1000000
* soft memlock 32000
* hard memlock 32000
* soft msgqueue 8192000
* hard msgqueue 8192000

安装 Java 环境 (可选)

Elasticsearch 是基于java的应用,所以依赖JDK环境
注意: 安装7.X以后版本官方建议要安装集成JDK的包,所以无需再专门安装 JDK
关于JDK环境说明
1.x 2.x 5.x 6.x都没有集成JDK的安装包,也就是需要自己安装java环境7.x的安装包分为带JDK和不带JDK两种包,带JDK的包在安装时不需要再安装java,如果不带JDK的包仍然需要自己去安装java
如果安装no-jdk的包,才需要安装java环境

Elasticsearch 安装

有两种包: 包含jdk和no-jdk的包
注意: 官方提示no-jdk的包将被淘汰,建议使用包含JDK的包
下载地址:
#包含JDK的版本下载
https://www.elastic.co/downloads/elasticsearch
https://mirrors.tuna.tsinghua.edu.cn/elasticstack/
#不包含JDK的版本下载
https://www.elastic.co/cn/downloads/elasticsearch-no-jdk

[root@ES-Node1 ~]#hostnamectl set-hostname ES-Node1.com

[root@ES-Node1 ~]#vim /etc/hosts
127.0.0.1 localhost
127.0.1.1 ubuntu2004

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

10.0.0.208 ES-Node1
10.0.0.209 ES-Node2
10.0.0.210 ES-Node3
#其他节点同上

单节点安装脚本

#!/bin/bash
# 
#********************************************************************
#Author:            shuhong
#QQ:                985347841
#Date:              2022-12-12
#FileName:          install_elasticsearch_single_node.sh
#URL:               hhhhh
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************

ES_VERSION=7.17.5
#ES_VERSION=7.9.3
#ES_VERSION=7.6.2
UBUNTU_URL="https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/e/elasticsearch/elasticsearch-${ES_VERSION}-amd64.deb"
RHEL_URL="https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/yum/${ES_VERSION}/elasticsearch-${ES_VERSION}-x86_64.rpm"

LOCAL_IP=hostname -I|awk '{print $1}'

. /etc/os-release

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}

check_mem () {
    MEM_TOTAL=head -n1 /proc/meminfo |awk '{print $2}'
    if [ ${MEM_TOTAL} -lt 1997072 ];then
        color '内存低于2G,安装失败!' 1
        exit
    elif [ ${MEM_TOTAL} -le 2997072 ];then
        color '内存不足3G,建议调整内存大小!' 2
    else
        return
    fi
}

install_es() {
    if [ $ID = "centos" -o $ID = "rocky" ];then
        wget -P /usr/local/src/ $RHEL_URL || { color  "下载失败!" 1 ;exit ; } 
        yum -y install /usr/local/src/${RHEL_URL##*/}
    elif [ $ID = "ubuntu" ];then
        wget -P /usr/local/src/ $UBUNTU_URL || { color  "下载失败!" 1 ;exit ; }
        dpkg -i /usr/local/src/${UBUNTU_URL##*/}
    else
        color "不支持此操作系统!" 1
        exit
    fi
    [ $? -eq 0 ] ||  { color '安装软件包失败,退出!' 1; exit; }
}

config_es () {
    cp /etc/elasticsearch/elasticsearch.yml{,.bak}
    cat >> /etc/elasticsearch/elasticsearch.yml  <<EOF
node.name: node-1
network.host: 0.0.0.0
discovery.seed_hosts: ["$LOCAL_IP"]
cluster.initial_master_nodes: ["node-1"]
EOF

    mkdir -p /etc/systemd/system/elasticsearch.service.d/
    cat > /etc/systemd/system/elasticsearch.service.d/override.conf <<EOF
[Service]
LimitMEMLOCK=infinity
EOF
    systemctl daemon-reload
    systemctl enable  elasticsearch.service
}

prepare_es() {
    echo "vm.max_map_count = 262144" >> /etc/sysctl.conf
    sysctl  -p
}

start_es(){
    systemctl start elasticsearch || { color "启动失败!" 1;exit 1; }
    sleep 3
    curl http://127.0.0.1:9200 && color "安装成功" 0   || { color "安装失败!" 1; exit 1; } 
    echo -e "请访问链接: \E[32;1mhttp://hostname -I|awk '{print $1}':9200/\E[0m"
}

check_mem
install_es
config_es
prepare_es
start_es

集群安装脚本

[root@ES-Node1 ~]#cat install_elasticsearch_cluster.sh 
#!/bin/bash
# 
#********************************************************************
#Author:            shuhong
#QQ:                985347841
#Date:              2022-12-12
#FileName:          install_elasticsearch_cluster.sh
#URL:               hhhhh
#Description:       The test script
#Copyright (C):     2022 All rights reserved
#********************************************************************

ES_VERSION=7.17.5
#ES_VERSION=7.9.3
#ES_VERSION=7.6.2
UBUNTU_URL="https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/e/elasticsearch/elasticsearch-${ES_VERSION}-amd64.deb"
RHEL_URL="https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/yum/${ES_VERSION}/elasticsearch-${ES_VERSION}-x86_64.rpm"

CLUSTER_NAME=es-cluster
NODE_LIST='["10.0.0.208","10.0.0.209","10.0.0.210"]'
ES_DATA=/data/es-data
ES_LOGS=/data/es-logs

. /etc/os-release

color () {
    RES_COL=60
    MOVE_TO_COL="echo -en \\033[${RES_COL}G"
    SETCOLOR_SUCCESS="echo -en \\033[1;32m"
    SETCOLOR_FAILURE="echo -en \\033[1;31m"
    SETCOLOR_WARNING="echo -en \\033[1;33m"
    SETCOLOR_NORMAL="echo -en \E[0m"
    echo -n "$1" && $MOVE_TO_COL
    echo -n "["
    if [ $2 = "success" -o $2 = "0" ] ;then
        ${SETCOLOR_SUCCESS}
        echo -n $"  OK  "    
    elif [ $2 = "failure" -o $2 = "1"  ] ;then 
        ${SETCOLOR_FAILURE}
        echo -n $"FAILED"
    else
        ${SETCOLOR_WARNING}
        echo -n $"WARNING"
    fi
    ${SETCOLOR_NORMAL}
    echo -n "]"
    echo 
}

check_mem () {
    MEM_TOTAL=head -n1 /proc/meminfo |awk '{print $2}'
    if [ ${MEM_TOTAL} -lt 1997072 ];then
        color '内存低于2G,安装失败!' 1
        exit
    elif [ ${MEM_TOTAL} -le 2997072 ];then
        color '内存不足3G,建议调整内存大小!' 2
    else
        return
    fi
}

set_node_id () {
    read -p "请输入node编号(默认为 1): " NODE_ID

    if [ -z "$NODE_ID" ] ;then
        NODE_ID=1
    elif [[ ! "$NODE_ID" =~ ^[0-9]+$ ]];then
        color  "请输入正确的node编号!" 1
        exit
    else
        true
    fi
    NODE_NAME=node-$NODE_ID
}

install_es() {
    if [ $ID = "centos" -o $ID = "rocky" ];then
        wget -P /usr/local/src/ $RHEL_URL || { color  "下载失败!" 1 ;exit ; } 
        yum -y install /usr/local/src/${RHEL_URL##*/}
    elif [ $ID = "ubuntu" ];then
        wget -P /usr/local/src/ $UBUNTU_URL || { color  "下载失败!" 1 ;exit ; }
        dpkg -i /usr/local/src/${UBUNTU_URL##*/}
    else
        color "不支持此操作系统!" 1
        exit
    fi
    [ $? -eq 0 ] ||  { color '安装软件包失败,退出!' 1; exit; }
}

config_es () {
    cp /etc/elasticsearch/elasticsearch.yml{,.bak}
    cat > /etc/elasticsearch/elasticsearch.yml  <<EOF
cluster.name: $CLUSTER_NAME
node.name: $NODE_NAME
path.data: $ES_DATA
path.logs: $ES_LOGS
bootstrap.memory_lock: true
network.host: 0.0.0.0
discovery.seed_hosts: $NODE_LIST
cluster.initial_master_nodes: $NODE_LIST
gateway.recover_after_nodes: 2
action.destructive_requires_name: true
EOF

    mkdir -p /etc/systemd/system/elasticsearch.service.d/
    cat > /etc/systemd/system/elasticsearch.service.d/override.conf <<EOF
[Service]
LimitMEMLOCK=infinity
EOF
    systemctl daemon-reload
    systemctl enable  elasticsearch.service
}

prepare_es() {
    echo "vm.max_map_count = 262144" >> /etc/sysctl.conf
    sysctl  -p
    mkdir -p $ES_DATA $ES_LOGS
    chown  -R elasticsearch.elasticsearch $ES_DATA $ES_LOGS
}

start_es(){
    systemctl start elasticsearch || { color "启动失败!" 1;exit 1; }
    sleep 3
    curl http://127.0.0.1:9200 && color "安装成功" 0   || { color "安装失败!" 1; exit 1; } 
    echo -e "请访问链接: \E[32;1mhttp://hostname -I|awk '{print $1}':9200/\E[0m"
}

check_mem
set_node_id
install_es
config_es
prepare_es
start_es

集群测试

[root@ES-Node1 ~]#bash install_elasticsearch_cluster.sh 
请输入node编号(默认为 1): 
--2022-12-12 20:05:51--  https://mirrors.tuna.tsinghua.edu.cn/elasticstack/7.x/apt/pool/main/e/elasticsearch/elasticsearch-7.17.5-amd64.deb
正在解析主机 mirrors.tuna.tsinghua.edu.cn (mirrors.tuna.tsinghua.edu.cn)... 101.6.15.130, 2402:f000:1:400::2
正在连接 mirrors.tuna.tsinghua.edu.cn (mirrors.tuna.tsinghua.edu.cn)|101.6.15.130|:443... 已连接。
已发出 HTTP 请求,正在等待回应... 200 OK
长度: 308222842 (294M) [application/octet-stream]
正在保存至: “/usr/local/src/elasticsearch-7.17.5-amd64.deb”

elasticsearch-7.17.5-amd64.deb                                 100%[====================================================================================================================================================>] 293.94M  3.05MB/s    用时 2m 7s 

2022-12-12 20:07:59 (2.31 MB/s) - 已保存 “/usr/local/src/elasticsearch-7.17.5-amd64.deb” [308222842/308222842])

正在选中未选择的软件包 elasticsearch。
(正在读取数据库 ... 系统当前共安装有 72072 个文件和目录。)
准备解压 .../elasticsearch-7.17.5-amd64.deb  ...
Creating elasticsearch group... OK
Creating elasticsearch user... OK
正在解压 elasticsearch (7.17.5) ...
正在设置 elasticsearch (7.17.5) ...
### NOT starting on installation, please execute the following statements to configure elasticsearch service to start automatically using systemd
 sudo systemctl daemon-reload
 sudo systemctl enable elasticsearch.service
### You can start elasticsearch service by executing
 sudo systemctl start elasticsearch.service
Created elasticsearch keystore in /etc/elasticsearch/elasticsearch.keystore
正在处理用于 systemd (245.4-4ubuntu3.15) 的触发器 ...
Synchronizing state of elasticsearch.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable elasticsearch
Created symlink /etc/systemd/system/multi-user.target.wants/elasticsearch.service → /lib/systemd/system/elasticsearch.service.
vm.max_map_count = 262144
{
  "name" : "node-1",
  "cluster_name" : "es-cluster",
  "cluster_uuid" : "YGVscZnmQn-rGDU2RDdWOg",
  "version" : {
    "number" : "7.17.5",
    "build_flavor" : "default",
    "build_type" : "deb",
    "build_hash" : "8d61b4f7ddf931f219e3745f295ed2bbc50c8e84",
    "build_date" : "2022-06-23T21:57:28.736740635Z",
    "build_snapshot" : false,
    "lucene_version" : "8.11.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
安装成功                                                   [  OK  ]
请访问链接: http://10.0.0.208:9200/
[root@ES-Node1 ~]#ss -ntlp
State                     Recv-Q                    Send-Q                                       Local Address:Port                                       Peer Address:Port                   Process                                                       
LISTEN                    0                         4096                                         127.0.0.53%lo:53                                              0.0.0.0:*                       users:(("systemd-resolve",pid=746,fd=13))                    
LISTEN                    0                         128                                                0.0.0.0:22                                              0.0.0.0:*                       users:(("sshd",pid=779,fd=3))                                
LISTEN                    0                         4096                                                     *:9200                                                  *:*                       users:(("java",pid=2044,fd=317))                             
LISTEN                    0                         4096                                                     *:9300                                                  *:*                       users:(("java",pid=2044,fd=289))                             
LISTEN                    0                         128                                                   [::]:22                                                 [::]:*                       users:(("sshd",pid=779,fd=4))                                

服务配置文件说明

https://www.ibm.com/support/knowledgecenter/zh/SSFPJS_8.5.6/com.ibm.wbpm.main.doc/topics/rfps_esearch_configoptions.html
https://www.elastic.co/guide/en/elasticsearch/reference/index.html
https://www.elastic.co/guide/en/elasticsearch/reference/master/settings.html
https://www.elastic.co/guide/en/elasticsearch/reference/master/important-settings.html

[root@es-node1 ~]# grep "^[a-Z]" /etc/elasticsearch/elasticsearch.yml
#ELK集群名称,同一个集群内每个节点的此项必须相同,新加集群的节点此项和其它节点相同即可加入集群,而
无需再验证
cluster.name: ELK-Cluster

#当前节点在集群内的节点名称,同一集群中每个节点要确保此名称唯一
node.name: es-node1

#ES 数据保存目录
path.data: /data/es-data

#ES 日志保存目录
path.logs: /data/es-logs

#服务启动的时候立即分配(锁定)足够的内存,防止数据写入swap,提高启动速度
bootstrap.memory_lock: true

#指定监听IP,如果绑定了错误的IP,可将此修改为指定IP
network.host: 0.0.0.0

#监听端口
http.port: 9200

#发现集群的node节点列表,可以添加部分或全部节点IP
#在新增节点到集群时,此处需指定至少一个已经在集群中的节点地址
discovery.seed_hosts: ["10.0.0.101","10.0.0.102","10.0.0.103"]

#集群初始化时指定希望哪些节点可以被选举为 master,只在初始化时使用,新加节点到已有集群时此项可不配置
cluster.initial_master_nodes: ["10.0.0.101","10.0.0.102","10.0.0.103"]

#一个集群中的 N 个节点启动后,才允许进行数据恢复处理,默认是1,一般设为为所有节点的一半以上,防止出现脑裂现象
#当集群无法启动时,可以将之修改为1,或者将下面行注释掉,实现快速恢复启动
gateway.recover_after_nodes: 2

#设置是否可以通过正则表达式或者_all匹配索引库进行删除或者关闭索引库,默认true表示必须需要明确指定索引库名称,不能使用正则表达式和_all,生产环境建议设置为 true,防止误删索引库。action.destructive_requires_name: true
#不参与主节点选举
node.master: false

#存储数据,此值为false则不存储数据而成为一个路由节点
#如果将true改为false,需要先执行/usr/share/elasticsearch/bin/elasticsearch-node
repurpose 清理数据
node.data: true

#7.x以后版本下面指令已废弃,在2.x 5.x 6.x 版本中用于配置节点发现列表
discovery.zen.ping.unicast.hosts: ["10.0.0.101", "10.0.0.102","10.0.0.103"]

开启 bootstrap.memory_lock: true 导致无法启动的错误解决方法
官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/setup-configuration-memory.html#bootstrap-memory_lock
https://www.elastic.co/guide/en/elasticsearch/reference/current/setting-system-settings.html#systemd

[root@node1 ~]#vim /etc/elasticsearch/elasticsearch.yml
#开启此功能导致无法启动
bootstrap.memory_lock: true

[root@node1 ~]#systemctl restart elasticsearch.service
Job for elasticsearch.service failed because the control process exited with error code.
See "systemctl status elasticsearch.service" and "journalctl -xe" for details.

[root@node1 ~]#tail /data/es-logs/es-cluster.log
[2021-08-15T22:21:13,600][INFO ][o.e.t.TransportService ] [node-1]
publish_address {10.0.0.101:9300}, bound_addresses {[::]:9300}
[2021-08-15T22:21:13,911][INFO ][o.e.b.BootstrapChecks ] [node-1] bound or
publishing to a non-loopback address, enforcing bootstrap checks
[2021-08-15T22:21:13,934][ERROR][o.e.b.Bootstrap ] [node-1] node
validation exception
[1] bootstrap checks failed. You must address the points described in the
following [1] lines before starting Elasticsearch.
bootstrap check failure [1] of [1]: memory locking requested for elasticsearch
process but memory is not locked
[2021-08-15T22:21:13,941][INFO ][o.e.n.Node ] [node-1] stopping
...
[2021-08-15T22:21:13,955][INFO ][o.e.n.Node ] [node-1] stopped
[2021-08-15T22:21:13,955][INFO ][o.e.n.Node ] [node-1] closing ...
[2021-08-15T22:21:13,970][INFO ][o.e.n.Node ] [node-1] closed
[2021-08-15T22:21:13,971][INFO ][o.e.x.m.p.NativeController] [node-1] Native
controller process has stopped - no new native processes can be started

[root@node1 ~]#systemctl edit elasticsearch
[Service]
LimitMEMLOCK=infinity

[root@node1 ~]#cat /etc/systemd/system/elasticsearch.service.d/override.conf
[Service]
LimitMEMLOCK=infinity

[root@node1 ~]#systemctl daemon-reload
[root@node1 ~]#systemctl restart elasticsearch.service
[root@node1 ~]#systemctl is-active elasticsearch.service
active

优化 ELK 资源配置

官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/important-settings.html#heap-size-settings

推荐使用宿主机物理内存的一半,ES的heap内存最大不超过30G,26G是比较安全的
官方文档:

https://www.elastic.co/guide/en/elasticsearch/reference/master/advanced-
configuration.html#set-jvm-heap-size
The heap size should be based on the available RAM:
Set Xms and Xmx to no more than 50% of your total memory. Elasticsearch requires
memory for purposes other than the JVM heap. For example, Elasticsearch uses off-
heap buffers for efficient network communication and relies on the operating
system’s filesystem cache for efficient access to files. The JVM itself also
requires some memory. It’s normal for Elasticsearch to use more memory than the
limit configured with the Xmx setting.
When running in a container, such as Docker, total memory is defined as the
amount of memory visible to the container, not the total system memory on the
host.
Set Xms and Xmx to no more than the threshold for compressed ordinary object
pointers (oops). The exact threshold varies but 26GB is safe on most systems and
can be as large as 30GB on some systems. To verify you are under the threshold,
check the Elasticsearch log for an entry like this:
堆大小应基于可用 RAM:
将 Xms 和 Xmx 设置为不超过总内存的 50%。 Elasticsearch 需要内存用于 JVM 堆以外的用途。 例
如,Elasticsearch 使用堆外缓冲区来实现高效的网络通信,并依靠操作系统的文件系统缓存来高效地访问
文件。 JVM 本身也需要一些内存。 Elasticsearch 使用比 Xmx 设置配置的限制更多的内存是正常的。
在容器(例如 Docker)中运行时,总内存定义为容器可见的内存量,而不是主机上的总系统内存。
将 Xms 和 Xmx 设置为不超过压缩普通对象指针 (oops) 的阈值。 确切的阈值会有所不同,但在大多数系
统上 26GB 是安全的,在某些系统上可能高达 30GB。 要验证您是否低于阈值,请检查 Elasticsearch
日志中的条目,如下所示:

关于OOPS的说明

Managed pointers in the Java heap point to objects which are aligned on 8-byte
address boundaries. Compressed oops represent managed pointers (in many but not
all places in the JVM software) as 32-bit object offsets from the 64-bit Java
heap base address.
Because they're object offsets rather than byte offsets, they can be used to
address up to four billion objects (not bytes), or a heap size of up to about 32
gigabytes.
To use them, they must be scaled by a factor of 8 and added to the Java heap base
address to find the object to which they refer. Object sizes using compressed
oops are comparable to those in ILP32 mode.
Java 堆中的托管指针指向在 8 字节地址边界上对齐的对象。 压缩 oop 将托管指针(在 JVM 软件中的许
多但不是所有地方)表示为相对于 64 位 Java 堆基地址的 32 位对象偏移量。
因为它们是对象偏移量而不是字节偏移量,所以它们可用于处理多达 40 亿个对象(不是字节),或高达约
32 GB 的堆大小。
要使用它们,必须将它们缩放 8 倍并添加到 Java 堆基地址以找到它们所引用的对象。 使用压缩 oop 的
对象大小与 ILP32 模式中的对象大小相当。

内存优化建议:
为了保证性能,每个ES节点的JVM内存设置具体要根据 node 要存储的数据量来估算,建议符合下面约定
在内存和数据量有一个建议的比例:对于一般日志类文件,1G 内存能存储48G~96GB数据
JVM 堆内存最大不要超过30GB
对于主分片的数量,单个分片控制在30-50GB

范例:

假设总数据量为1TB,3个node节点,1个副本;那么实际要存储的大小为2TB
每个节点需要存储的数据量为:2TB / 3 = 700GB,然后每个节点需要预留20%的空间,意味着每个node要
存储大约 875GB 的数据;按照内存与存储数据的比率计算:875GB/48GB=18,即需要JVM内存为18GB,小于30GB
因为要尽量控制主分片的大小为30GB;875GB/30GB=30个主分片,即最多30个主分片

范例:指定heap内存最小和最大内存限制:
#建议将heap内存设置为物理内存的一半且最小和最大设置一样大,但最大不能超过30G
[root@es-node1 ~]# vim /etc/elasticsearch/jvm.options
-Xms2g
-Xmx2g
#每天1TB左右的数据量的建议服务器配置
16C 64G 6T硬盘 共3台服务器

范例: 修改service文件,做优化配置
[root@es-node1 ~]# vim /usr/lib/systemd/system/elasticsearch.service #修改内存限制
LimitNOFILE=1000000 #修改最大打开的文件数,默认值为65535
LimitNPROC=65535 #修改打开最大的进程数,默认值为4096
LimitMEMLOCK=infinity #无限制使用内存,以前旧版需要修改,否则无法启动服务,当前版本无需修改

内存锁定的配置参数:
https://discuss.elastic.co/t/memory-lock-not-working/70576

基于 Docker 部署

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/7.5/docker.html

单节点部署

docker run --name es-single-node -d -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" docker.elastic.co/elasticsearch/elasticsearch:7.6.2

多节点集群部署

部署前准备
注意:此方式需要3G以上内存,否则会出现OOM下面的信息
修改内核参数,默认无法启动
echo vm.max_map_count=262144 >> /etc/sysctl.conf
sysctl -p
 创建docker-compose.yml文件
version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
    memlock:
      soft: -1
      hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    container_name: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
    memlock:
      soft: -1
      hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    container_name: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
    memlock:
      soft: -1
      hard: -1
   volumes:
     - data03:/usr/share/elasticsearch/data
   networks:
     - elastic
volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local
networks:
  elastic:
    driver: bridge

Elasticsearch 集群状态监控

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/master/rest-apis.html

Elasticsearch 支持各种语言使用 RESTful API 通过端口 9200 与之进行通信,可以用你习惯的 web 客户端访问 Elasticsearch可以用三种方式和 Elasticsearch进行交互
curl 命令和其它浏览器: 基于命令行,操作不方便
插件: 在node节点上安装head,Cerebro 等插件,实现图形操作,查看数据方便
Kibana: 需要java环境并配置,图形操作,显示格式丰富
监控下面两个条件都满足才是正常的状态
集群状态为 green
所有节点都启动

Shell 命令

# curl -sXGET http://elk服务器:9200/_cluster/health?pretty=true

[root@ES-Node1 ~]#curl -sXGET http://127.0.0.1:9200/_cluster/health?pretty=true
{
  "cluster_name" : "es-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 2,
  "active_shards" : 4,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}

获取到的是一个json格式的返回值,那就可以通过python对其中的信息进行分析,例如对status进行分析,如果等于green(绿色)就是运行在正常,等于yellow(黄色)表示副本分片丢失,red(红色)表示主分片丢失ES集群状态:
绿色状态:表示集群各节点运行正常,而且没有丢失任何数据,各主分片和副本分片都运行正常
黄色状态:表示由于某个节点宕机或者其他情况引起的,node节点无法连接、所有主分片都正常分配,有副本分片丢失,但是还没有丢失任何数据
红色状态:表示由于某个节点宕机或者其他情况引起的主分片丢失及数据丢失,但仍可读取数据和存储

#查看支持的指令
curl http://127.0.0.1:9200/_cat
[root@ES-Node1 ~]#curl http://127.0.0.1:9200/_cat
=^.^=
/_cat/allocation
/_cat/shards
/_cat/shards/{index}
/_cat/master
/_cat/nodes
/_cat/tasks
/_cat/indices
/_cat/indices/{index}
/_cat/segments
/_cat/segments/{index}
/_cat/count
/_cat/count/{index}
/_cat/recovery
/_cat/recovery/{index}
/_cat/health
/_cat/pending_tasks
/_cat/aliases
/_cat/aliases/{alias}
/_cat/thread_pool
/_cat/thread_pool/{thread_pools}
/_cat/plugins
/_cat/fielddata
/_cat/fielddata/{fields}
/_cat/nodeattrs
/_cat/repositories
/_cat/snapshots/{repository}
/_cat/templates
/_cat/ml/anomaly_detectors
/_cat/ml/anomaly_detectors/{job_id}
/_cat/ml/trained_models
/_cat/ml/trained_models/{model_id}
/_cat/ml/datafeeds
/_cat/ml/datafeeds/{datafeed_id}
/_cat/ml/data_frame/analytics
/_cat/ml/data_frame/analytics/{id}
/_cat/transforms
/_cat/transforms/{transform_id}
查看es集群状态
curl http://127.0.0.1:9200/_cat/health
curl 'http://127.0.0.1:9200/_cat/health?v'

[root@ES-Node1 ~]#curl http://127.0.0.1:9200/_cat/health
1670848378 12:32:58 es-cluster green 3 3 4 2 0 0 0 0 - 100.0%
[root@ES-Node1 ~]#curl 'http://127.0.0.1:9200/_cat/health?v'
epoch      timestamp cluster    status node.total node.data shards pri relo init unassign pending_tasks max_task_wait_time active_shards_percent
1670848392 12:33:12  es-cluster green           3         3      4   2    0    0        0             0                  -                100.0%
#查看所有的节点信息
curl 'http://127.0.0.1:9200/_cat/nodes?v'

[root@ES-Node1 ~]#curl 'http://127.0.0.1:9200/_cat/nodes?v'
ip         heap.percent ram.percent cpu load_1m load_5m load_15m node.role   master name
10.0.0.208            7          93   1    0.00    0.00     0.00 cdfhilmrstw -      node-1
10.0.0.209           13          93   0    0.00    0.00     0.00 cdfhilmrstw -      node-2
10.0.0.210           20          93   1    0.00    0.00     0.00 cdfhilmrstw *      node-3
列出所有的索引 以及每个索引的相关信息
curl 'http://127.0.0.1:9200/_cat/indices?v'

[root@ES-Node1 ~]#curl 'http://127.0.0.1:9200/_cat/indices?v'
health status index            uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .geoip_databases K4MQn59HRGq8x9fDiKHHSg   1   1         40            0     76.1mb           38mb
#查看集群分健康性
curl http://127.0.0.1:9200/_cluster/health?pretty=true

[root@ES-Node1 ~]#curl http://127.0.0.1:9200/_cluster/health?pretty=true
{
  "cluster_name" : "es-cluster",
  "status" : "green",
  "timed_out" : false,
  "number_of_nodes" : 3,
  "number_of_data_nodes" : 3,
  "active_primary_shards" : 2,
  "active_shards" : 4,
  "relocating_shards" : 0,
  "initializing_shards" : 0,
  "unassigned_shards" : 0,
  "delayed_unassigned_shards" : 0,
  "number_of_pending_tasks" : 0,
  "number_of_in_flight_fetch" : 0,
  "task_max_waiting_in_queue_millis" : 0,
  "active_shards_percent_as_number" : 100.0
}

范例: 创建索引

#elasticsearch 7.X 默认创建1个分片1个副本,之前版本默认5分片1副本
#https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html

#创建索引index1,简单输出
root@ES-Node1 ~]#curl -XPUT '10.0.0.208:9200/index1'

[root@ES-Node1 ~]#curl 'http://127.0.0.1:9200/_cat/indices?v'
health status index            uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .geoip_databases K4MQn59HRGq8x9fDiKHHSg   1   1         40            0     76.1mb           38mb
green  open   index1           ky7gZhe-Tq-A_BSUG5hJBw   1   1          0            0       452b           226b

#创建索引index2,格式化输出
[root@ES-Node1 ~]#curl -XPUT '10.0.0.209:9200/index2?pretty'
{
  "acknowledged" : true,
  "shards_acknowledged" : true,
  "index" : "index2"
}

[root@ES-Node1 ~]#curl '10.0.0.208:9200/index1?pretty'
{
  "index1" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "1",
        "provided_name" : "index1",
        "creation_date" : "1670848732915",
        "number_of_replicas" : "1",
        "uuid" : "ky7gZhe-Tq-A_BSUG5hJBw",
        "version" : {
          "created" : "7170599"
        }
      }
    }
  }
}

[root@ES-Node1 ~]#curl 'http://127.0.0.1:9200/_cat/indices?v'
health status index            uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .geoip_databases K4MQn59HRGq8x9fDiKHHSg   1   1         40            0     76.1mb           38mb
green  open   index1           ky7gZhe-Tq-A_BSUG5hJBw   1   1          0            0       452b           226b
green  open   index2           dVVaHSYZTOKcDbjTn_NhLg   1   1          0            0       452b           226b

#创建3个分片和2个副本的索引
[root@ES-Node1 ~]#curl -XPUT '10.0.0.208:9200/index3' -H 'Content-Type:application/json' -d '
{
  "settings": {
     "index": {
       "number_of_shards": 3,
       "number_of_replicas": 2
     }
  }
}'
{"acknowledged":true,"shards_acknowledged":true,"index":"index3"}
[root@ES-Node1 ~]#curl '10.0.0.208:9200/index3?pretty'
{
  "index3" : {
    "aliases" : { },
    "mappings" : { },
    "settings" : {
      "index" : {
        "routing" : {
          "allocation" : {
            "include" : {
              "_tier_preference" : "data_content"
            }
          }
        },
        "number_of_shards" : "3",
        "provided_name" : "index3",
        "creation_date" : "1670848957300",
        "number_of_replicas" : "2",
        "uuid" : "QuGymaMdQHaFOdh5b-IU8A",
        "version" : {
          "created" : "7170599"
        }
      }
    }
  }
}
[root@ES-Node1 ~]#curl 'http://127.0.0.1:9200/_cat/indices?v'
health status index            uuid                   pri rep docs.count docs.deleted store.size pri.store.size
green  open   .geoip_databases K4MQn59HRGq8x9fDiKHHSg   1   1         40            0     76.1mb           38mb
green  open   index1           ky7gZhe-Tq-A_BSUG5hJBw   1   1          0            0       452b           226b
green  open   index3           QuGymaMdQHaFOdh5b-IU8A   3   2          0            0      1.9kb           678b
green  open   index2           dVVaHSYZTOKcDbjTn_NhLg   1   1          0            0       452b           226b

#早期版本,如es1.X,2.X可以直在下面数据目录下直接看到index的名称,5.X版本后只会显示下面信息
[root@ES-Node1 ~]#ll /data/es-data/nodes/0/indices/
总用量 24
drwxr-xr-x 6 elasticsearch elasticsearch 4096 12月 12 20:42 ./
drwxr-xr-x 5 elasticsearch elasticsearch 4096 12月 12 20:44 ../
drwxr-xr-x 4 elasticsearch elasticsearch 4096 12月 12 20:35 Enqi5YdQRcWIDNHsaS3szg/
drwxr-xr-x 4 elasticsearch elasticsearch 4096 12月 12 20:36 K4MQn59HRGq8x9fDiKHHSg/
drwxr-xr-x 4 elasticsearch elasticsearch 4096 12月 12 20:38 ky7gZhe-Tq-A_BSUG5hJBw/
drwxr-xr-x 6 elasticsearch elasticsearch 4096 12月 12 20:42 QuGymaMdQHaFOdh5b-IU8A/

范例: 插入数据

#_id 自动生成
#index1是索引数据库,book是type
[root@ES-Node1 ~]#curl -XPOST http://10.0.0.208:9200/index1/book/ -H 'Content-Type:application/json' -d '{"name":"linux", "author": "wangxiaochun", "version":"1.0"}'
{"_index":"index1","_type":"book","_id":"ZuZfBoUBzH-wHn1psldP","_version":1,"result":"created","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":0,"_primary_term":1}

[root@ES-Node1 ~]#curl -XPOST 'http://10.0.0.209:9200/index1/book?pretty' -H 'Content-Type: application/json' -d '{"name":"python", "author": "xuwei","version": "1.0"}'
{
  "_index" : "index1",
  "_type" : "book",
  "_id" : "16hgBoUBxdHaFN9liQSp",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 1,
  "_primary_term" : 1
}

#_id 指定为3
#index1是索引数据库,book是type,3是document记录
[root@ES-Node1 ~]#curl -XPOST 'http://10.0.0.208:9200/index1/book/3?pretty' -H 'Content-Type: application/json' -d '{"name":"golang", "author": "zhang","version": "1.0"}'
{
  "_index" : "index1",
  "_type" : "book",
  "_id" : "3",
  "_version" : 1,
  "result" : "created",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 2,
  "_primary_term" : 1
}

#数据存放的磁盘位置
[root@ES-Node1 ~]#tree /data/es-data/ -d
/data/es-data/
└── nodes
    └── 0
        ├── indices
        │   ├── Enqi5YdQRcWIDNHsaS3szg
        │   │   ├── 0
        │   │   │   ├── index
        │   │   │   ├── _state
        │   │   │   └── translog
        │   │   └── _state
        │   ├── K4MQn59HRGq8x9fDiKHHSg
        │   │   ├── 0
        │   │   │   ├── index
        │   │   │   ├── _state
        │   │   │   └── translog
        │   │   └── _state
        │   ├── ky7gZhe-Tq-A_BSUG5hJBw
        │   │   ├── 0
        │   │   │   ├── index
        │   │   │   ├── _state
        │   │   │   └── translog
        │   │   └── _state
        │   └── QuGymaMdQHaFOdh5b-IU8A
        │       ├── 0
        │       │   ├── index
        │       │   ├── _state
        │       │   └── translog
        │       ├── 1
        │       │   ├── index
        │       │   ├── _state
        │       │   └── translog
        │       ├── 2
        │       │   ├── index
        │       │   ├── _state
        │       │   └── translog
        │       └── _state
        ├── snapshot_cache
        └── _state

37 directories

范例: 查询指定ID的索引

#指定ID查询
#curl -XGET ‘http://localhost:9200/{index}/{type}/{id}’
[root@ES-Node1 ~]#curl -XGET 'http://localhost:9200/index1/book/3?pretty'
{
  "_index" : "index1",
  "_type" : "book",
  "_id" : "3",
  "_version" : 1,
  "_seq_no" : 2,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "golang",
    "author" : "zhang",
    "version" : "1.0"
  }
}

[root@ES-Node1 ~]#curl -XGET 'http://localhost:9200/index1/book/ZuZfBoUBzH-wHn1psldP?pretty'
{
  "_index" : "index1",
  "_type" : "book",
  "_id" : "ZuZfBoUBzH-wHn1psldP",
  "_version" : 1,
  "_seq_no" : 0,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "name" : "linux",
    "author" : "wangxiaochun",
    "version" : "1.0"
  }
}

#查询所有
[root@ES-Node1 ~]#curl -XGET 'http://localhost:9200/index1/_search?pretty'
{
  "took" : 745,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 3,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "index1",
        "_type" : "book",
        "_id" : "ZuZfBoUBzH-wHn1psldP",
        "_score" : 1.0,
        "_source" : {
          "name" : "linux",
          "author" : "wangxiaochun",
          "version" : "1.0"
        }
      },
      {
        "_index" : "index1",
        "_type" : "book",
        "_id" : "16hgBoUBxdHaFN9liQSp",
        "_score" : 1.0,
        "_source" : {
          "name" : "python",
          "author" : "xuwei",
          "version" : "1.0"
        }
      },
      {
        "_index" : "index1",
        "_type" : "book",
        "_id" : "3",
        "_score" : 1.0,
        "_source" : {
          "name" : "golang",
          "author" : "zhang",
          "version" : "1.0"
        }
      }
    ]
  }
}


#按条件进行查询
[root@ES-Node1 ~]#curl 'http://localhost:9200/index1/book/_search?q=name:linux&pretty'
{
  "took" : 201,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.9808291,
    "hits" : [
      {
        "_index" : "index1",
        "_type" : "book",
        "_id" : "ZuZfBoUBzH-wHn1psldP",
        "_score" : 0.9808291,
        "_source" : {
          "name" : "linux",
          "author" : "wangxiaochun",
          "version" : "1.0"
        }
      }
    ]
  }
}

范例: 更新

[root@ES-Node1 ~]#curl -XPOST 'http://localhost:9200/index1/book/3' -H 'Content-Type: application/json' -d '{"version": "2.0","name":"golang","author": "zhang"}'
{"_index":"index1","_type":"book","_id":"3","_version":2,"result":"updated","_shards":{"total":2,"successful":2,"failed":0},"_seq_no":3,"_primary_term":1}

[root@ES-Node1 ~]#curl -XGET 'http://localhost:9200/index1/book/3?pretty'
{
  "_index" : "index1",
  "_type" : "book",
  "_id" : "3",
  "_version" : 2,
  "_seq_no" : 3,
  "_primary_term" : 1,
  "found" : true,
  "_source" : {
    "version" : "2.0",
    "name" : "golang",
    "author" : "zhang"
  }
}

范例: 删除

curl -XDELETE http://kibana服务器:9200/<索引名称>
[root@ES-Node1 ~]#curl -XDELETE 'http://localhost:9200/index1/book/3?pretty'
{
  "_index" : "index1",
  "_type" : "book",
  "_id" : "3",
  "_version" : 3,
  "result" : "deleted",
  "_shards" : {
    "total" : 2,
    "successful" : 2,
    "failed" : 0
  },
  "_seq_no" : 4,
  "_primary_term" : 1
}
[root@ES-Node1 ~]#curl -XGET 'http://localhost:9200/index1/book/3?pretty'
{
  "_index" : "index1",
  "_type" : "book",
  "_id" : "3",
  "found" : false
}

范例: 删除指定索引
[root@es-node1 ~]#curl -XDELETE http://10.0.0.101:9200/tomcat-accesslog-0.107-2021.02.02
{"acknowledged":true}

范例: 删除所有索引
[root@es-node1 ~]#for i in curl 'http://10.0.0.101:9200/_cat/indices?v'|awk
'{print $3}';do curl -XDELETE http://10.0.0.101:9200/$i;done

Python脚本

[root@ES-Node1 ~]#vim els-cluster-monitor.py
#!/usr/bin/python3
#coding:utf-8
import smtplib
from email.mime.text import MIMEText
from email.utils import formataddr
import subprocess
import json
body = ""
false="false"
#用另外一个进程运行curl返回结果从stdout中读取
obj = subprocess.Popen(("curl -sXGET http://10.0.0.208:9200/_cluster/health?pretty=true"),shell=True, stdout=subprocess.PIPE) #
data = obj.stdout.read()
#print(type(data)) # 应该是字符串类型或bytes类型
#print(data) # 看看是不是返回的json形式的
es_dict = json.loads(data) if data else {} # 把json字符串解析为字典
status = es_dict.get("status") # 通过字典查找status
if status == "green":
  print("OK")
else:
  print("Not OK")

[root@ES-Node1 ~]#chmod +x els-cluster-monitor.py 

[root@ES-Node1 ~]#./els-cluster-monitor.py 
OK

Elasticsearch 插件

Head 插件

通过使用插件可以实现对 ES 集群的状态监控, 数据访问, 管理配置等功能。

Head 是一个 ES 在生产较为常用的插件
git地址:https://github.com/mobz/elasticsearch-head

三种安装方法:
编译安装
Docker
浏览器插件

编译安装

安装 Head 插件前准备
注意: 如果使用浏览器插件,则无需此步
修改elasticsearch节点的服务配置文件,开启跨域访问支持,然后重启elasticsearch服务
官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/6.8/modules-http.html

范例:

[root@es-node1 ~]# vim /etc/elasticsearch/elasticsearch.yml
#在文件最后添加下面两行
http.cors.enabled: true #开启支持跨域访问
http.cors.allow-origin: "*" #指定允许访问范围
[root@es-node1 ~]# systemctl restart elasticsearch

服务方式启动
在elasticsearch 5.x版本以后不再支持直接安装head插件,而是通过服务启动
此安装方式通过 npm 工具实现
npm(Node Package Manager)是和NodeJS一起安装的包管理和分发工具,使用npm 可以很方便让JavaScript开发者下载、安装、上传以及管理已经安装的相关包。
范例: CentOS 7 安装 Head 插件

[root@es-node1 ~]# yum install -y npm git
#因为使用了nodejs,建议用下面方式加速
[root@es-node1 ~]#apt install npm
[root@es-node1 ~]#npm config get registry
https://registry.npmjs.org/
[root@es-node1 ~]#npm config set registry https://registry.npm.taobao.org
[root@es-node1 ~]#npm config get registry
https://registry.npm.taobao.org/
[root@es-node1 ~]# cd /usr/local/src/
[root@es-node1 src]#git clone git://github.com/mobz/elasticsearch-head.git
[root@es-node1 src]# cd elasticsearch-head/
[root@es-node1 elasticsearch-head]# npm install grunt -save
[root@es-node2 elasticsearch-head]# ll node_modules/grunt #确认生成文件
[root@es-node1 elasticsearch-head]# npm install #执行安装
[root@es-node1 elasticsearch-head]# npm run start & #后台启动服务

范例: Ubuntu 安装 Head 插件

[root@es-node1 ~]# apt -y install npm
#因为使用了nodejs,建议用下面方式加速
[root@es-node1 ~]#npm config get registry
https://registry.npmjs.org/
[root@es-node1 ~]#npm config set registry https://registry.npm.taobao.org
[root@es-node1 ~]#npm config get registry
https://registry.npm.taobao.org/
[root@es-node1 ~]# git clone git://github.com/mobz/elasticsearch-head.git
[root@es-node1 ~]# cd elasticsearch-head/
[root@es-node1 elasticsearch-head]# npm install #执行安装
[root@es-node1 elasticsearch-head]# npm run start & #后台启动服务

Docker 方式启动 Head 插件

[root@es-node1 ~]#docker run -d -p 9100:9100 --name head mobz/elasticsearch-head:5
#安装完毕后,访问:http://localhost:9100

浏览器安装插件

从谷歌应用商店下载安装插件,支持chrome和edge浏览器
注意: 需要科学上网

在线安装

https://chrome.google.com/webstore/detail/elasticsearch-head/ffmkiejjmecolpfloofpjologoblkegm/related

离线安装

先下载Head插件文件,再离线安装

Cerebro 插件

Cerebro 介绍

Cerebro 是开源的 elasticsearch 集群 Web 管理程序,需要 java1.8 或者更高版本,此工具应用也很广泛
Cerebro v0.9.4 需要 Java11
github链接: https://github.com/lmenezes/cerebro

包安装

[root@ES-Node3 ~]#apt -y install openjdk-11-jdk

[root@ES-Node3 ~]#wget https://github.com/lmenezes/cerebro/releases/download/v0.9.4/cerebro_0.9.4_all.deb

[root@ES-Node3 ~]#dpkg -i cerebro_0.9.4_all.deb

[root@ES-Node3 ~]#systemctl start cerebro.service

#默认无法启动,查看日志,可以看到以下提示,原因是默认cerebro.db文件所有目录没有权限导致
[root@ES-Node3 ~]#journalctl -u cerebro
12月 13 10:17:06 ES-Node3.com cerebro[11605]: Caused by: java.sql.SQLException: opening db: './cerebro.db': 权限不够

[root@ES-Node3 ~]#vim /etc/cerebro/application.conf 
...
data.path: "/var/lib/cerebro/cerebro.db"
#data.path = "./cerebro.db"
...

[root@ES-Node3 ~]#systemctl restart cerebro.service
[root@ES-Node3 ~]#systemctl status cerebro.service
● cerebro.service - Elasticsearch web admin tool
     Loaded: loaded (/lib/systemd/system/cerebro.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2022-12-13 10:20:07 CST; 2s ago
....

[root@ES-Node3 ~]#ss -nltp
State              Recv-Q             Send-Q                         Local Address:Port                         Peer Address:Port            Process                                               
LISTEN             0                  4096                           127.0.0.53%lo:53                                0.0.0.0:*                users:(("systemd-resolve",pid=749,fd=13))            
LISTEN             0                  128                                  0.0.0.0:22                                0.0.0.0:*                users:(("sshd",pid=783,fd=3))                        
LISTEN             0                  128                                     [::]:22                                   [::]:*                users:(("sshd",pid=783,fd=4))                        
LISTEN             0                  100                                        *:9000                                    *:*                users:(("java",pid=12119,fd=127))                    
LISTEN             0                  4096                                       *:9200                                    *:*                users:(("java",pid=2815,fd=343))                     
LISTEN             0                  4096                                       *:9300                                    *:*                users:(("java",pid=2815,fd=289))                     

二进制安装

注意:内存建议大于3G以上

#先安装jdk
[root@es-node1 ~]#apt -y install openjdk-8-jdk
#下载文件
[root@es-node1 ~]#wget
https://github.com/lmenezes/cerebro/releases/download/v0.9.3/cerebro-0.9.3.tgz
[root@es-node1 ~]#tar xvf cerebro-0.9.3.tgz -C /usr/local/
[root@es-node1 ~]#ln -s /usr/local/cerebro-0.9.3/ /usr/local/cerebro
#修改配置
[root@es-node1 ~]#vim /usr/local/cerebro/conf/application.conf
hosts = [
{
host = "http://10.0.0.101:9200" #修改此行,指向ES的地址
name = "es-cluster" #修改此行
# headers-whitelist = [ "x-proxy-user", "x-proxy-roles", "X-Forwarded-For" ]
#}
# Example of host with authentication
#{
# host = "http://some-authenticated-host:9200"
# name = "Secured Cluster"
# auth = {
# username = "username"
# password = "secret-password"
# }
}
]
#启动插件
[root@es-node1 ~]#/usr/local/cerebro/bin/cerebro &
[info] play.api.Play - Application started (Prod) (no global state)
[info] p.c.s.AkkaHttpServer - Listening for HTTP on /0:0:0:0:0:0:0:0:9000
......

Docker 运行

docker run -p 9000:9000 --env-file env-ldap lmenezes/cerebro

Elasticsearch 集群工作原理

官方说明

https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html

节点分类

单机节点 ES 存在单点问题,可以实现多机的集群,每个节点的角色有所不同
ES的节点有三种
·Master 节点
ES集群中只有一个 Master 节点,用于控制整个集群的操作
Master 节点负责增删索引,增删节点,shard分片的重新分配
Master 主要维护Cluster State,包括节点名称,节点连接地址,索引名称和配置认息等
Master 接受集群状态的变化并推送给所有节点,集群中各节点都有一份完整的集群状态信息,都由master node负责维护
Master 节点不需要涉及到文档级别的变更和搜索等操作
协调创建索引请求或查询请求,将请求分发到相关的node上。
当Cluster State有新数据产生后, Master 会将数据同步给其他 Node 节点
Master节点通过超过一半的节点投票选举产生的
可以设置node.master: true 指定为是否参与Master节点选举, 默认true
·Data 节点
存储数据的节点即为 data 节点
当创建索引后,索引创建的数据会存储至某个数据节点
Data 节点消耗内存和磁盘IO的性能比较大
配置node.data: true, 默认为 true,即默认节点都是 data类型
·Coordinating 节点(协调)
处理请求的节点即为 coordinating 节点,该节点为所有节点的默认角色,不能取消
coordinating 节点主要将请求路由到正确的节点处理。比如创建索引的请求会由 coordinating路由到 master 节点处理
当配置 node.master:false、node.data:false 则只充当 coordinating节点

集群选举

ES集群的选举是由master-eligble(有资格的master节点)发起,当该节点发现当前节点不是master,并且该节点通过ZenDiscovery模块ping其他节点,得到超过mininum_master_nodes个节点无法连接master时,就会发起选举
选举时,优先选举ClusterStateVersion最大的Node节点,如果ClusterStateVersion相同,则选举ID最小的Node
ClusterStateVersion是集群的状态版本号,每一次集群选举ClusterStateVersion都会更新,因此最大的ClusterStateVersion是与原有集群数据最接近或者是相同的,这样就尽可能的避免数据丢失。
Node的ID是在第一次服务启动时随机生成的,直接选用最小ID的Node,主要是为了选举的稳定性,尽量少的出现选举不出来的问题。
每个集群中只有一个Master节点
每个集群中损坏的节点不能超过集群一半以上,否则集群将无法提供服务

ES 集群分片和副本

分片 Shard

ES 中存储的数据可能会很大,有时会达到PB级别基于性能和容量等原因,可以将一个索引数据分割成多个小的分片,再将每个分片分布至不同的节点,从而
实现数据的分布存储,实现性能和容量的水平扩展

在读取时,可以实现多节点的并行读取,提升性能

除此之外,如果一个分片的主机宕机,也不影响其它节点分片的读取

横向扩展即增加服务器,当有新的Node节点加入到集群中时,集群会动态的重新进行分配和负载

例如原来有两个Node节点,每个节点上有3个分片,即共6个分片,如果再添加一个node节点到集群中,集群会动态的将此6个分片分配到这三个节点上,最终每个节点上有两个分片。

7,X 默认每个索引只有一个分片

副本 Replication

将一个索引分成多个分片,仍然存在数据的单点问题,可以对每一个分片进行复制生成副本,即备份,实现数据的高可用

ES的分片分为主分片(primary shard)和副本分片(复制replica shard),而且通常分布在不同节点主分片实现数据读写,副本分片只支持读

每个数据分片只有一个主分片,而副本分片可以有多个,比如;一个副本,即有一个备份

7,X 默认每个索引只有一个副本分片

ES集群故障转移

故障转移指的是,当集群中有节点发生故障时,ES集群会进行自动修复

2.6.4 ES集群故障转移

故障转移指的是,当集群中有节点发生故障时,ES集群会进行自动修复
假设由3个节点的ES集群组成,其中一个节点宕机
ES集群的故障转移流程如下
重新选举
node3 节点宕机,导致 node3 的原有的P0和R2分片丢失
node1 和 node2 发现 node1 无法响应
一段时间后会发起 master 选举,比如这里选择 node1 为 master 节点;此时集群状态变为 Red状态


主分片调整
新的Master节点 node1 发现在原来在node3上的主分片 P0 未分配,将 node2 上的 R0 提升为主分片
此时所有的主分片都正常分配,但0和2分片没有副本分片,集群状态变为 Yellow状态
副本分片调整
node1 将 P0 和 P2 主分片重新生成新的副本分片 R0、R1,此时集群状态变为 Green

修复好node3节点后,自动将各个分片均匀分配

ES 文档路由

ES 文档路由原理
ES文档是分布式存储,当一个文档存储至 ES集群时,如何决定存储的节点位置,以及读取时从哪里获取数据?
在ES 中,通过如下的公式计算文档对应的分片存储到哪个节点

shard = hash(routing) % number_of_primary_shards
# hash 算法保证将数据均匀分散在分片中
# routing 是一个可变参数,默认是文档id,也可以自定义。
# number_of_primary_shards 主分片数
#注意:该算法与主分片数相关,一但确定后便不能更改主分片

ES 文档创建流程

客户端向协调节点 Node1 发送新建索引文档或者删除索引文档请求。
Node1节点使用文档的 _id 确定文档属于分片 0 。
因为分片 0 的主分片目前被分配在 Node 3 上,请求会被转发到 Node 3
Node3 在主分片上面执行创建或删除请求
Node3 执行如果成功,它将请求并行转发到 Node1 和 Node2 的副本分片上。
一旦所有的副本分片都报告成功, Node3 将向协调节点Node1 报告成功
协调节点Node1 客户端报告成功。在客户端收到响应时,文档变更已经在主分片和所有副本分片执行完成

ES 文档读取流程

客户端向 Node1 发送读取请求。
节点使用文档的 _id 来确定文档属于分片 0 。分片 0 的副本分片存在于所有的三个节点上。
在处理读取请求时,协调结点在每次请求的时候都会通过轮询所有的副本分片来达到负载均衡。在这种情况下,它将请求转发到 Node2 。
Node2 将文档返回给 Node1 ,然后将文档返回给客户端。