# 部署
ES 常见的部署架构:
- 单实例
- 集群
- 由多个实例组成分布式集群,获得更大的容量、更高的性能,还可通过冗余节点提高可用性。
- 远程集群
- 远程集群与本地集群之间独立工作,但可以查询、拷贝其数据,实现横向扩容。
# 版本
- v1.0 :于 2010 年发布。最初由 Shay Banon 开发,后来由 Elastic 公司管理。
- v6.0 :于 2017 年发布。
- v7.0 :于 2019 年发布。
- v8.0 :于 2022 年发布。
# 单实例
# 部署
下载二进制版:
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.10.0-linux-x86_64.tar.gz
解压后运行 ES 服务器:
bin/elasticsearch # 在前台运行 -d # 以 daemon 方式运行
- 运行时需要 JDK 环境,不过二进制发行版自带了一个 JDK 。
- 安装插件时,只需将插件解压到 plugins 目录下。
或者用 Docker 部署:
docker run -d --name elasticsearch \ -p 9200:9200 \ elasticsearch:7.10.0
# 配置
ES 服务器的配置文件是 config/elasticsearch.yml
,内容示例:
cluster.name: cluster-1 # 该 ES 所属的集群名
discovery.type: single-node # 取消发现集群的其它节点,从而部署成单示例
node.name: node-1 # 该 ES 的节点名,默认为当前主机名
network.host: 0.0.0.0 # 该 ES 的 Socket 绑定的 IP
network.publish_host: 10.0.0.1 # 该 ES 公布给集群中其它 ES 的 IP ,供它们访问。默认等于 network.host
# transport.port: 9300 # TCP 通信监听的端口,供集群中其它 ES 节点访问
# 关于 HTTP API
# http.port: 9200 # HTTP 通信监听的端口,供用户访问
# http.max_initial_line_length: 4kb # 允许接收的 HTTP 请求的 URL 长度
# http.max_header_size: 8kb # 允许接收的 HTTP 请求的 header 体积
# http.max_content_length: 100mb # 允许接收的 HTTP 请求的 body 体积(解压之后)
# http.compression: true # 是否压缩 HTTP 响应的 body
# http.compression_level: 3 # 压缩级别,取值范围为 1~9 ,9 的压缩率最高
# http.cors.enabled: false # 是否允许 CORS 请求
path.data: /var/data/elasticsearch
path.logs: /var/log/elasticsearch
xpack.monitoring.enabled: false # 是否启用对 ELK 自身的监控,默认为 true ,监控数据保存到索引 .monitoring-*
- ES 存在多种断路器,用于在 ES 占用内存达到一定阈值时,拒绝新的读、写请求,返回 HTTP 503: circuit_breaking_exception 。
- 如果没有断路器,ES 可能占用内存过大而被 OOM 杀死。
- 相关配置:
indices.breaker.total.limit: 70% # parent 断路器,用于限制所有断路器的内存总量,默认为 JVM 堆内存的 70% indices.breaker.fielddata.limit: 70% # fielddata 断路器,用于限制 fielddata 缓存,默认为 JVM 堆内存的 40% indices.breaker.request.limit: 60% # request 断路器,用于限制所有请求的占用的内存,比如聚合运算
# 运行环境
ES 启动时会检查以下环境条件是否满足,如果不满足则会发出警告。如果此时还配置了
network.host
参数,则 ES 会按生产环境严格要求,将这些警告升级为异常。- 禁用 Swap 分区:
- 需要执行命令
swapoff -a
,并且将/etc/fstab
文件中的 swap 分区都注释。
- 需要执行命令
- 增加进程虚拟内存的上限:
- 需要执行命令
sysctl vm.max_map_count=262144
,并在/etc/sysctl.conf
文件中永久修改该参数。
- 需要执行命令
- 增加进程数量的上限:
- 需要执行命令
ulimit -u 4096
,并在/etc/security/limits.conf
文件中永久修改该参数。
- 需要执行命令
- 增加文件描述符数量的上限:
- 需要执行命令
ulimit -n 65535
,并在/etc/security/limits.conf
文件中永久修改该参数。
- 需要执行命令
- 禁用 Swap 分区:
可以在 config/jvm.options 文件中配置 ES 的 JVM :
-Xms4g -Xmx4g -XX:MaxDirectMemorySize=2g # 建议设置为 -Xmx 的一半
- JVM -Xmx 过低时,会频繁引发 GC ,增加 CPU 负载,增加 ES 读写耗时。
- JVM -Xmx 最多为 32G ,否则会大幅降低 Java 对象指针的效率,增加 CPU 负载。
- 主机应该留出一些空闲内存,相当于 JVM -Xmx 的 0.5~1 倍,用作 Page Cache ,提高 Lucene 读写磁盘的性能。
# 备份数据
ES 备份数据的几种方式:
- 通过 Snapshot API 创建快照文件。
- 适合离线备份,备份速度快。
- 通过 reindex API 将远程集群的数据拷贝到本地集群。
# 集群
# 部署
部署 ES 集群时,需要部署多个 ES 实例,然后在它们的配置文件中都加入如下配置:
# discovery.type: single-node # 不设置该参数,则默认会寻找集群的其它节点 discovery.seed_hosts: # 声明该集群的所有节点,默认值为 127.0.0.1、[::1] - 10.0.0.1:9300 - 10.0.0.2:9300 - 10.0.0.3:9300
- ES 服务器启动之后,会自动检查这些节点,如果存在其它 ES 服务器,并且拥有相同的集群名,则组成同一个集群。
部署一个新集群时,还需要声明初始的主资格节点:
cluster.initial_master_nodes: - node-1 # 这里使用节点名,不使用 IP - node-2 - node-3
# 节点
一个 ES 集群(cluster)中的每个 ES 实例称为一个节点(node)。
集群中有且仅有一个主节点,负责管理集群,比如增删索引、分配分片给节点。
一个 ES 节点可以担任多种角色:
master
- :主资格节点(master-eligible),有资格被选为主节点。
- 只有主资格节点可以参与主节点的选举投票。
data
- :数据节点,负责存储数据,支持增删查改、聚合等操作。
- master 和 data 节点都需要使用
path.data
目录。
ingest
- :摄取节点,负责将管道应用于文档,以便在建立索引之前加工文档。
ml
- :机器学习节点。集群至少拥有一个此类节点才能提供机器学习功能。
remote_cluster_client
- :远程集群节点,可以连接到远程集群,作为其客户端。
transform
- :转换节点。提供转换功能。
coordinating
- :协调节点。它是每个节点的隐式角色,不能取消。
- 每个节点都知道各个文档存储在哪个节点上,也默认可以处理用户的 HTTP 请求。
因此用户可以向任意节点发出查询请求,该节点会将请求转发给存储相应文档的数据节点(可能有多个),然后将查询结果返回给用户。
节点的默认角色配置如下:
node.master: true node.voting_only: false # 是否只参与主节点选举,而不担任主节点 node.data: true node.ingest: true node.ml: true cluster.remote.connect: true
在以下情况下,主资格节点会发起主节点的选举:
- 发现它自己不是主节点。
- 询问其它节点,发现大家都没有连接到主节点。
- 发现有至少
discovery.zen.minimum_master_nodes
个主资格节点没有连接到主节点。 该参数的默认值为:主资格节点总数/2 + 1
ES 集群的高可用方案:
- 部署至少 3 个主资格节点,其中至少 2 个节点为
node.voting_only: false
,从而可以通过选举更换主节点。 - 不能同时停止 50% 数量的主资格节点,否则集群会不能投票决策。但可以分多次停止。
- 让每个节点专注于一种角色,以减少不相关的工作负担。比如配置专用的主节点:
node.master: true node.voting_only: false node.data: false node.ingest: false node.ml: false cluster.remote.connect: false
- 部署至少 3 个主资格节点,其中至少 2 个节点为
# 管理
相关 API :
GET / # 查询集群的基本信息 GET /_cluster/stats # 查询集群的统计信息 GET /_cluster/health # 查询集群的健康状态 GET /_cluster/settings # 查询集群的配置 GET /_nodes # 查询所有节点的配置 GET /_nodes/stats # 查询所有节点的状态
例:查询所有节点
[[email protected] ~]# curl 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.1 11 85 1 0.06 0.09 0.18 dilm * node-1
例:查询集群的基本信息
[[email protected] ~]# curl 127.0.0.1:9200 { "name" : "node-1", "cluster_name" : "cluster-1", "cluster_uuid" : "cDXF4mIeRqK4Dlj_YmSSoA", "version" : { "number" : "7.10.0", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "7f634e9f44834fbc12724506cc1da681b0c3b1e3", "build_date" : "2020-02-06T00:09:00.449973Z", "build_snapshot" : false, "lucene_version" : "8.4.0", "minimum_wire_compatibility_version" : "6.8.0", "minimum_index_compatibility_version" : "6.0.0-beta1" }, "tagline" : "You Know, for Search" }
例:查询集群的健康状态
[[email protected] ~]# curl 127.0.0.1:9200/_cluster/health?pretty { "cluster_name" : "cluster-1", "status" : "yellow", # 集群的状态 "timed_out" : false, "number_of_nodes" : 1, # 节点的数量 "number_of_data_nodes" : 1, # 数据节点的数量 "active_shards" : 4, # 可用分片的数量,包括主分片、副分片,不包括未分配的分片 "active_primary_shards" : 4, # 可用主分片的数量 "relocating_shards" : 0, "initializing_shards" : 0, "unassigned_shards" : 4, # 未分配的分片的数量 "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" : 50.0 }
- status 的可能取值:
- green :所有主分片、副分片都可用。
- yellow :所有主分片都可用,但存在不可用的副分片。
- red :存在不可用的主分片。
- status 的可能取值:
例:查询所有索引的状态
[[email protected] ~]# curl 127.0.0.1:9200/_cat/indices?v health status index uuid pri rep docs.count docs.deleted store.size pri.store.size yellow open class aeUT1h6QS8-vSAzoEclR3Q 1 1 0 0 283b 283b yellow open student EaDptPz9TtqGk-CNL-yTMg 1 1 1 0 4.4kb 4.4kb
- health 表示分片的状态,status 表示索引是否被关闭。
- 这里索引的 health 为 yellow ,是因为只部署了单实例 ES ,而副分片不能被分配到主分片所在节点上,导致一直处于未分配状态。
# 配置
用户可以在配置文件 elasticsearch.yml 中添加 ES 的配置参数,但这只会作用于当前 ES 节点。
部分配置参数支持在 ES 运行时通过 API 修改,称为动态参数(Dynamic)。而其它配置参数称为静态参数(Static)。
- 动态参数又分为两种作用域:
- persistent :持久配置,即使集群重启也会生效。
- transient :暂时配置,在集群重启之后失效。
- 集群按以下优先级顺序采用配置参数:
- transient
- persistent
- 配置文件
- 默认配置
- 例:将一个参数的 transient 值设置为 null ,或者等集群重启,则会采用该参数的 persistent 值。
- 动态参数又分为两种作用域:
修改动态参数的示例:
PUT /_cluster/settings { "persistent": { "indices.recovery.max_bytes_per_sec" : "50mb" } "transient" : { "indices.recovery.max_bytes_per_sec" : "20mb" } }
# 远程集群
- ES 支持给本地集群添加多个远程集群(remote cluster)。
- 这些集群之间会独立工作,独立存储自己的数据。
- 这是单向连接,本地集群故障时不会影响远程集群,但远程集群故障时可能影响本地集群。
- 用户可以跨集群搜索,同时查询本地集群和远程集群,从而实现 ES 的横向扩容。
- 原理:
- 用户将跨集群的查询请求发送到本地集群。
- 本地集群验证用户的身份,如果有效,则将请求及用户的身份转发到远程集群。
- 远程集群验证用户的身份,如果有权访问指定的数据,则执行查询,然后将查询结果返回给本地集群。
- 本地集群将远程集群的查询结果返回给用户。
- 本地集群使用的 SSL 公钥必须受到远程集群的信任。
- 用户账号必须在本地集群、远程集群都存在。
- 原理:
# 配置
可以在 elasticsearch.yml 文件中配置远程集群,但这只会对当前节点生效。如下:
cluster: remote: cluster_1: # 添加一个远程集群,该名称不必与目标集群的实际名称一致 seeds: - 10.0.0.1:9300 # 远程集群中的节点列表 cluster_2: # 添加另一个远程集群 seeds: - 10.0.0.2:9300 # transport.initial_connect_timeout: 30s # 启动当前节点时,第一次连接到远程集群的超时时间 # transport.ping_schedule: 30s # 每隔多久检查与远程集群的连接是否正常正常,默认为 -1 ,即不检查 # transport.compress: true # 将请求压缩之后再发送到远程集群 # skip_unavailable: false # 跨集群搜索时是否跳过不可用集群
也可以通过 API 添加远程集群,上传其配置信息:
PUT /_cluster/settings { "persistent": { "cluster": { "remote": { "cluster_1": { "seeds": [ # 设置 "seeds": null 则会删除该远程集群 "127.0.0.1:9300" ] }, "cluster_2": { "seeds": [ "10.0.0.2:9300" ] } } } } }
相关 API :
GET /_cluster/settings # 查询集群的配置,包括远程集群 GET /_remote/info # 查询远程集群的状态
# 查询
使用
<cluster_name>:<index_name>
的格式,即可查询远程集群的索引:GET /student/_search # 不指定集群名,则默认查询本地集群 GET /cluster_1:student/_search # 可以指定一个集群进行查询 GET /student,cluster_1:student,cluster_2:student/_search # 可以指定多个集群进行查询
可创建指向远程集群的 index pattern :
cluster_1:student