Skip to content

Elasticsearch Two-node Cluster

双节点集群 Two-node cluster

  • 实际是主从结构,集群自动同步保持数据一致性
    • 从节点宕机了,主依然可读写;health 会变为 yellow ;
    • 主节点宕机了,从只能读;部分集群相关 path 接口不可用,因为要查询 主,但主宕机了;
  • 每个分片数据冗余存储到另一个节点上;
    • 客户端需要通过 load balance 访问集群,或设置失败重试轮写另一个,避免写固定一个节点;
    • 不推荐在生产环境使用此结构;

从零开始搭建步骤

测试环境

  • ES 版本 8.18.2
  • 虚拟机系统

如果每个 ES 节点部署在不同主机上,注意:

  • 各个主机之间可互相访问 9200 (HTTP 默认 http.port )和 9300 (transport 默认 transport.port )端口
  • 各个 ES 节点数据目录为空,不能已初始化或加入过其他集群

下载二进制包

shell
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.18.2-darwin-x86_64.tar.gz
tar -xzf elasticsearch-8.18.2-darwin-x86_64.tar.gz
cd elasticsearch-8.18.2

配置 es01 节点

shell
mkdir es01
cp -a config es01/

修改 es01/config/elasticsearch.yml

yaml
bootstrap.memory_lock: true

xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false

path.data: es01/data
path.logs: es01/logs

http.port: 9201
transport.port: 9301

cluster.name: my-cluster
node.name: es01

network.host: 0.0.0.0
cluster.initial_master_nodes: ["es01"]

# 多个 ES 节点部署在不同主机上时需要设置
network.publish_host: "10.0.0.1"
discovery.seed_hosts: ["10.0.0.1", "10.0.0.2"]

启动 es01 节点 ES_PATH_CONF=es01/config bin/elasticsearch

INFO

默认通过 bin/elasticsearch 启动 ES 实例时,它会强制使用和 bin/ 目录同一层级的 config/ 目录作为配置目录。如果想使用同一个二进制包,启动多个 ES 实例,可通过指定环境 ES_PATH_CONF 值修改配置目录。

修改 es02/config/elasticsearch.yml

yaml
bootstrap.memory_lock: true

xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false

path.data: es02/data
path.logs: es02/logs

http.port: 9202
transport.port: 9302

cluster.name: my-cluster
node.name: es02

network.host: 0.0.0.0
cluster.initial_master_nodes: ["es01"]

# 多个 ES 节点部署在不同主机上时需要设置
network.publish_host: "10.0.0.2"
discovery.seed_hosts: ["10.0.0.1", "10.0.0.2"]

如果开发环境两个节点部署在同一个机器上(如 es01 10.0.0.1:9200/9300, es02 10.0.0.1:9202/9302 ),需修改以下选项:

yaml
# 指定 node 具体的 ip:port
cluster.initial_master_nodes: ["10.0.0.1:9200"]

network.publish_host: "10.0.0.1"

# 指定 node 具体的 ip:port
discovery.seed_hosts: ["10.0.0.1:9300", "10.0.0.1:9302"]

启动 es02 节点 ES_PATH_CONF=es02/config bin/elasticsearch

(可选)启动 kibana 实例

  • 在任意一个节点上重置 kibana_system 用户密码,如 ES_PATH_CONF=es02/config bin/elasticsearch-reset-password -u kibana_system -i
  • 修改 kibana 配置文件后启动 kibana 实例

kibana 配置文件参考:

yaml
elasticsearch.hosts: ["http://localhost:9200", "http://localhost:9201"]

# optional
elasticsearch.username: "kibana_system"
elasticsearch.password: "kibana_system"

实验 1: 集群(green)可用时,可同时读写主或从节点

写 es01 curl -XPOST -H 'Content-Type: application/json' 'localhost:9201/myidx/_doc/1?pretty' -d '{"id":"1","title":"hello"}'

分别读 es01 es02

  • curl -H 'Content-Type: application/json' 'localhost:9201/myidx/_search?pretty'
  • curl -H 'Content-Type: application/json' 'localhost:9202/myidx/_search?pretty'

输出结果一致

实验 2: 仅从节点宕机,主节点可读写

停止 es02, 写 es01 curl -XPOST -H 'Content-Type: application/json' 'localhost:9201/myidx/_doc/2?pretty' -d '{"id":"2","title":"world"}'

读 es01 curl -H 'Content-Type: application/json' 'localhost:9201/myidx/_search?pretty'

输出说明主节点可读写

启动 es02,读 es02

curl -H 'Content-Type: application/json' 'localhost:9202/myidx/_search?pretty'

输出说明从节点恢复后自动同步保持一致性。

实验 3: 仅主节点宕机,从节点只读

停止 es01, 写 es02 curl -XPOST -H 'Content-Type: application/json' 'localhost:9202/myidx/_doc/3?pretty' -d '{"id":"3","title":"foo"}'

es02 客户端堵塞直到超时报错。

读 es02 文档 curl -H 'Content-Type: application/json' 'localhost:9202/myidx/_search?pretty'

输出说明从节点仅可只读。

读 es02 集群相关 path curl 'localhost:9202/_cluster/stats?human&pretty'

输出说明从节点 集群相关接口 path 不可用。

启动 es01,写 es02 curl -XPOST -H 'Content-Type: application/json' 'localhost:9202/myidx/_doc/4?pretty' -d '{"id":"4","title":"bar"}'

分别读 es01 es02

  • curl -H 'Content-Type: application/json' 'localhost:9201/myidx/_search?pretty'
  • curl -H 'Content-Type: application/json' 'localhost:9202/myidx/_search?pretty'
  • curl 'localhost:9201/_cluster/stats?human&pretty'
  • curl 'localhost:9202/_cluster/stats?human&pretty'

输出说明集群可用后,又可同时读写主从。

将单个节点集群扩容为两个

原有节点 1 的数据保留,修改 ES 节点 1 配置后,重启节点实例:

  • 去掉 discovery.type: single-node 或新建容器实例去掉启动参数 discovery.type=single-node
  • 新增或修改以下集群相关参数,每个节点的 node.name network.hostnetwork.publish_host 选项值不一样,其他应该一样

参考配置:

yaml
cluster.name: my-cluster

node.name: es01

network.host: 0.0.0.0
cluster.initial_master_nodes: ["es01"]

# 多个 ES 节点部署在不同主机上时需要设置
network.publish_host: "10.0.0.1"
discovery.seed_hosts: ["10.0.0.1", "10.0.0.2"]

参考以上,新增数据目录为空、未加入过其他集群的新 ES 节点 2 的配置,并启动新实例。

访问集群

查看集群健康状态(人读表格格式) curl 'localhost:9200/_cat/health?v'

查看集群健康状态(JSON 格式) curl localhost:9200/_cluster/health

查看集群统计信息 curl "localhost:9200/_cluster/stats"

使用 ES SDK 或 第三方库访问 ES 时自定义 hosts 字符串数组参数,指定多个 node ["http://lcoalhsot:9201","http://lcoalhsot:9202"]; 默认库通过 round-robin 算法轮流读写每个 node ,避免只有一个节点过载。

Released under the CC-BY-NC-4.0