OpenSearch集群部署 OpenSearch 项目是ElasticSearch 7.10.2版本的一个分支而发展来的,包括企业安全、告警、机器学习、SQL、索引状态管理等功能。OpenSearch 项目中的所有软件均采用了 Apache License 2.0 开源许可协议。
ElasticSearch中的身份验证、授权、索引管理、告警等功能是付费订阅中的功能。尽管后续开放并免费提供基本的安全认证功能,但如果需要保障更多的安全性和管理易用性,免费版本仍然不足以支撑,因此本项目选用了OpenSearch。
1.概述 本次目标是部署一个跨主机的高可用OpenSearch小集群,根据官方提供的文档,最终采用了3个OpenSearch节点,2台服务器进行部署。以下内容均根据该目标进行设计,环境信息如下:
主机IP
配置
OS
用途
192.168.1.2
8核心16G内存
Ubuntu22.04 LTS jammy
用于部署1个OpenSearch节点和1个OpenSearch面板(类Kibana)
192.168.1.3
8核心16G内存
Ubuntu22.04 LTS jammy
用于部署2个OpenSearch节点
因为涉及跨主机网络通信,根据自身技术栈选择了Docker Swarm作为了集群管理和编排工具。
3节点集群建设时,根据官方文档提供的建议主要包括以下几点:
建议3节点都为数据节点
建议每个索引均不是 可搜索快照(searchable snapshot index)索引
建议将3节点都配置允许成为Master节点(Master-eligible node)
注:文章中可能同时出现了OpenSearch、ElasticSearch,你没有看错,这不是笔误,而是两边的文档需要同时参考,互为补充..
本文实际搭建时采用OpenSearch2.6版本。
主要参考如下版本的文档:
https://opensearch.org/docs/2.6/
https://www.elastic.co/guide/en/elasticsearch/reference/7.10/index.html
1.1 .本章概念解释及参考引用 1.1.1 Master Node/Master-eligible node概念及区别 节点具有一个或多个角色(Role),角色包括以下几种
master
data
data_content
data_hot
data_warm
data_cold
data_frozen
ingest
ml
remote_cluster_client
transform
当一个节点(Node)被赋予master角色时,并不代表其一定是Master主节点,而是赋予了其被选举权 ,也就是Master-eligible node。
如果集群只有1个节点 Role为master,那么其一定是master节点。
如果集群中有2个节点,全部设置为master,当任意节点不可用时,选举将失败,如果两个节点能够进行独立选举,失去连接会导致脑裂问题,导致数据丢失。Elasticsearch避免了这种情况来保护数据,它不选择任何一个节点作为主节点,直到该节点能够确定它拥有最新的集群状态,并且集群中没有其他主节点。这可能会导致集群没有master,直到连接恢复。
如果集群中有3个节点,全部设置为master,则集群允许单个节点丢失。
1.1.2 引用
ElasticNode概念及说明: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/modules-node.html
3节点高可用集群设计: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/high-availability-cluster-small-clusters.html#high-availability-cluster-design-three-nodes
脑裂问题: https://en.wikipedia.org/wiki/Split-brain_(computing)
2.安装部署 部署前解释下为什么要采用Docker Swarm,在部署OpenSearch集群时,有多个配置需要指定集群中节点的IP,以快速服务发现来实现节点通信。
但问题在于如果节点IP使用非标准端口,那么就需要在修改对应配置,特别是transport.port
他的默认端口是9300-9400
的范围IP。在配置环境变量时,如果对于这些端口不熟悉,很容易错误使用,特别是在第一次完成Docker部署OpenSearch后出现了9200、9300、9301、9600
等端口。
为了解决以上问题,通过Docker Swarm构建一个跨主机的虚拟网络,对于每个容器便拥有了虚拟网络中的独立IP,不会出现标准端口占用问题,在配置环境变量或者OpenSearch配置时,可直接使用容器的ServiceName
作为Hostname
直接进行通信,而无需配置额外的端口。
2.1 Docker Swarm跨主机部署 2.1.1 修改主机名 修改主机名以用于区分不同主机
该步骤为前期部署k8s的必要操作,Docker swarm集群暂未去了解是否必须该步骤,建议修改,便于在集群管理器中方便的识别对应主机。
将主机192.168.1.2
设置为db-1
,主机192.168.1.3
设置为db-2
,在不同主机编辑/etc/hostname
,重启服务器即可。
1 2 sudo vim /etc/hostname reboot
2.1.2 创建Swarm集群 1.在主机192.168.1.2
创建swarm管理节点 1 docker swarm init --advertise-addr=192.168.1.2
得到如下提示
1 2 3 4 5 6 7 8 9 Swarm initialized: current node (bvz81updecsj6wjz393c09vti) is now a manager. To add a worker to this swarm, run the following command: docker swarm join \ --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx \ 192.168.1.2:2377 To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
提示中出现了两个命令,docker swarm join ...
和docker swarm join-token manager
,区分见概念解释,默认显示的是以worker角色加入集群的命令。
1 2 3 docker swarm join \ --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx \ 192.168.1.2:2377
2.在主机192.168.1.3
中执行docker swarm join 加入swarm集群。 1 2 3 docker swarm join \ --token SWMTKN-1-3pu6hszjas19xyp7ghgosyx9k8atbfcr8p2is99znpy26u2lkl-1awxwuwd3z9j1z3puu7rcgdbx \ 192.168.1.2:2377
3.为节点增加标签 在编写部署文件时,可以通过标签来让服务(Service)部署在指定的节点(Docker Node)中。
1 docker node update --label-add db-node=2 un5y8qe03ehgy1i5b7ao6kk8y
1 docker node update --label-add db-node=1 fp6zni42p2iz319qihx0oek57
这样192.168.1.2
的swarm node节点就有了标签db-node,值为1
192.168.1.3
的swarm node节点就有了标签db-node,值为2
可通过docker inspect un5y8qe03ehgy1i5b7ao6kk8y -f "{{json .Spec.Labels}}"
查看节点的标签
4.创建Swarm Overlay网络 1 docker network create --driver overlay --attachable db-cluster
查看网络信息
1 docker network inspect db-cluster
5.编写部署compose文件 该compose文件配置了3个opensearch数据节点,自动选举主节点。将下面的完整compose文件内容保存为docker-compose-cluster.yml
即可。
注⚠️:本文件禁用了安全插件和默认的参数配置,安全方面主要体现在各个节点没有密码,没有通过SSL进行通讯,并且暴露了每个节点的端口,存在安全风险,请勿在生产环境中使用!!! 安全配置将在后续章节中写明!
Service下的deploy用于设置部署选项,通过标签来指定服务部署的节点。
1 2 3 deploy: placement: constraints: [ node.labels.db-node == 1 ]
其他字段可参考文件内的注释。
注:这里有个我认为设计不合理的地方,在部署时通过deploy的placement指定了Service部署的节点,但映射出来的端口重复判断依旧是在单机单节点来识别的,导致无法在不同的主机节点同时暴露9200端口。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 version: '3.8' services: opensearch-data-node1: image: opensearchproject/opensearch:2.6.0 environment: - cluster.name=opensearch-db - node.name=opensearch-data-node1 - node.roles=data,ingest,master - discovery.seed_hosts=opensearch-data-node1,opensearch-data-node2,opensearch-data-node3 - cluster.initial_master_nodes=opensearch-data-node1,opensearch-data-node2,opensearch-data-node3 - bootstrap.memory_lock=true - http.cors.enabled=true - http.cors.allow-origin=* - plugins.security.ssl.http.enabled=false - DISABLE_INSTALL_DEMO_CONFIG=true - DISABLE_SECURITY_PLUGIN=true - "OPENSEARCH_JAVA_OPTS=-Xms4g -Xmx4g" deploy: placement: constraints: [ node.labels.db-node == 1 ] ulimits: memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 volumes: - opensearch-node1-data:/usr/share/opensearch/data - /data/opensearch_cluster/node1.yml:/usr/share/opensearch/config/opensearch.yml ports: - 9200 :9200 - 9300 :9300 - 9600 :9600 networks: - db-cluster opensearch-dashboards: image: opensearchproject/opensearch-dashboards:2.6.0 ports: - 5601 :5601 environment: OPENSEARCH_HOSTS: '["http://opensearch-data-node1:9200","http://opensearch-data-node2:9200","http://opensearch-data-node3:9200"]' opensearch.requestHeadersWhitelist: '["securitytenant","Authorization"]' deploy: placement: constraints: [ node.labels.db-node == 1 ] networks: - db-cluster opensearch-data-node2: image: opensearchproject/opensearch:2.6.0 environment: - cluster.name=opensearch-db - node.name=opensearch-data-node2 - node.roles=data,ingest,master - discovery.seed_hosts=opensearch-data-node1,opensearch-data-node2,opensearch-data-node3 - cluster.initial_cluster_manager_nodes=opensearch-data-node1,opensearch-data-node2,opensearch-data-node3 - bootstrap.memory_lock=true - http.cors.enabled=true - http.cors.allow-origin=* - plugins.security.ssl.http.enabled=false - DISABLE_INSTALL_DEMO_CONFIG=true - DISABLE_SECURITY_PLUGIN=true - "OPENSEARCH_JAVA_OPTS=-Xms4g -Xmx4g" deploy: placement: constraints: [ node.labels.db-node == 2 ] ulimits: memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 volumes: - opensearch-node2-data:/usr/share/opensearch/data - /data/opensearch_cluster/node2.yml:/usr/share/opensearch/config/opensearch.yml ports: - 10200 :9200 - 10300 :9300 - 10600 :9600 networks: - db-cluster opensearch-data-node3: image: opensearchproject/opensearch:2.6.0 environment: - cluster.name=opensearch-db - node.name=opensearch-data-node3 - node.roles=data,ingest,master - discovery.seed_hosts=opensearch-data-node1,opensearch-data-node2,opensearch-data-node3 - cluster.initial_cluster_manager_nodes=opensearch-data-node1,opensearch-data-node2,opensearch-data-node3 - bootstrap.memory_lock=true - http.cors.enabled=true - http.cors.allow-origin=* - plugins.security.ssl.http.enabled=false - DISABLE_INSTALL_DEMO_CONFIG=true - DISABLE_SECURITY_PLUGIN=true - "OPENSEARCH_JAVA_OPTS=-Xms4g -Xmx4g" deploy: placement: constraints: [ node.labels.db-node == 2 ] ports: - 9400 :9200 - 9500 :9300 - 9800 :9600 ulimits: memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 volumes: - opensearch-node3-data:/usr/share/opensearch/data - /data/opensearch_cluster/node3.yml:/usr/share/opensearch/config/opensearch.yml networks: - db-cluster volumes: opensearch-node1-data: opensearch-node2-data: opensearch-node3-data: networks: db-cluster: external: true
6.编写每个节点的配置文件 复制以下内容到node1.yml、node2.yml、node3.yml,
1 2 3 4 5 6 7 cluster.name: opensearch-db network.host: 0.0 .0 .0 network.publish_host: opensearch-data-node1 http.publish_host: opensearch-data-node1 transport.publish_host: opensearch-data-node1 compatibility.override_main_response_version: true
将node2.yml中所有的opensearch-data-node1
字符替换为opensearch-data-node2
将node3.yml中所有的opensearch-data-node1
字符替换为opensearch-data-node3
节点配置和服务名称(ServiceName)保持一致即可,这个步骤必不可少! 。
实测如果缺少三个publish_host
配置,OpenSearch会在选举时识别到错误的IP,导致选举失败,进而无法启动集群。
compatibility.override_main_response_version
配置为true表示版本号返回兼容模式,对于OpenSearch2.6将返回7.10版本
后续需要将node1.yml、node2.yml、node3.yml按照部署的对应关系分别放到192.168.1.2
和192.168.1.3
主机的/data/opensearch_cluster
目录。
7.集群启动、查看 完成以上步骤便可在compose文件所在目录,执行以下命令启动集群。
1 docker stack deploy -c docker-compose-cluster.yml db-cluster
执行完成,可看到输出信息为
1 2 3 4 Creating service db-cluster_opensearch-data-node3 Creating service db-cluster_opensearch-data-node1 Creating service db-cluster_opensearch-dashboards Creating service db-cluster_opensearch-data-node2
查看所有的任务(Task)
1 2 # docker stack ps <集群名称> docker stack ps db-cluster
输出信息
1 2 3 4 5 ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS j70p5arth4jl db-cluster_opensearch-dashboards.1 opensearchproject/opensearch-dashboards:2.6.0 db-1 Running Running 4 minutes ago p9yu6h5yokyu db-cluster_opensearch-data-node1.1 opensearchproject/opensearch:2.6.0 db-1 Running Running 4 minutes ago ad7o1clcr7wi db-cluster_opensearch-data-node2.1 opensearchproject/opensearch:2.6.0 db-2 Running Running 3 minutes ago dikndljx5x2t db-cluster_opensearch-data-node3.1 opensearchproject/opensearch:2.6.0 db-2 Running Running 4 minutes ago
查看所有Service信息
1 2 # docker stack services <集群名称> docker stack services db-cluster
输出信息
1 2 3 4 5 ID NAME MODE REPLICAS IMAGE PORTS p6gzkh96c24r db-cluster_opensearch-dashboards replicated 1/1 opensearchproject/opensearch-dashboards:2.6.0 *:5601->5601/tcp 05pzy1h9lm0l db-cluster_opensearch-data-node1 replicated 1/1 opensearchproject/opensearch:2.6.0 *:9200->9200/tcp, *:9300->9300/tcp, *:9600->9600/tcp i9l86hr5ccnm db-cluster_opensearch-data-node2 replicated 1/1 opensearchproject/opensearch:2.6.0 *:10200->9200/tcp, *:10300->9300/tcp, *:10600->9600/tcp ybh9x23mgz9v db-cluster_opensearch-data-node3 replicated 1/1 opensearchproject/opensearch:2.6.0 *:9400->9200/tcp, *:9500->9300/tcp, *:9800->9600/tcp
最后确认下OpenSearch集群状态和OpenSearch节点状态。
前面9200部署给了主机192.168.1.2
,因此访问http://192.168.1.2:9200/_cluster/health?pretty
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 { "cluster_name" : "db-cluster" , "status" : "green" , "timed_out" : false , "number_of_nodes" : 3 , "number_of_data_nodes" : 3 , "discovered_master" : true , "discovered_cluster_manager" : true , "active_primary_shards" : 2 , "active_shards" : 5 , "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 }
节点信息访问http://192.168.1.2:9200/_cat/nodes?v
1 2 3 4 ip heap.percent ram.percent cpu load_1m load_5m load_15m node.role node.roles cluster_manager name 10.0.4.10 6 95 4 1.71 1.26 0.69 dim data,ingest,master - opensearch-data-node2 10.0.4.2 7 95 4 1.71 1.26 0.69 dim data,ingest,master * opensearch-data-node3 10.0.4.5 3 76 4 0.06 0.09 0.09 dim data,ingest,master - opensearch-data-node1
可以看到集群状态为绿色,显示拥有3个节点,同时opensearch-data-node3
被选为了集群的Master节点
大功告成!
2.1.3 集群删除 集群删除时涉及Service、网络、数据卷(Volume)的删除。
Service 可执行如下命令来删除集群以及集群下的所有服务
1 docker stack rm db-cluster
因为网络是单独创建的,没有通过compose文件,因此需要手动删除,在192.168.1.2
和192.168.1.3
两台主机分别执行
1 docker network rm db-cluster
如果在compose里面创建网络,在删除Service时会同步删除该网络。
数据卷在192.168.1.2
和192.168.1.3
两台主机中,需要根据Service部署的情况,在对应主机删除对应的volume,执行命令为
1 2 3 docker volume rm db-cluster_opensearch-node1-data docker volume rm db-cluster_opensearch-node2-data docker volume rm db-cluster_opensearch-node3-data
2.2 本章概念解释 2.2.1 Swarm中的worker和manager角色 Manager节点 还执行维护集群所需状态所需的编排和集群管理功能。Manager节点会选择一个领导者Leader来执行编排任务。
Worker节点 接收并执行从Manager节点分派的任务。默认情况下,Manager节点也将服务作为Worker节点运行,但您可以将它们配置为专门运行Manager任务并成为仅Manager节点(manager-only nodes)。Agent在每个工作节点上运行并报告分配给它的任务。工作节点将其分配任务的当前状态通知Manager节点,以便Manager节点可以维护每个Worker节点的所需状态。
如果要查看manager角色token或者manager角色 token遗忘时,可执行
1 docker swarm join-token manager
如果忘记worker角色token可执行
1 docker swarm join-token worker
如果节点以worker角色加入,想提升worker角色为manager角色的话,可以在管理节点执行如下命令
1 2 # docker node promote <hostname> docker node promote db-2
如果节点以manager角色加入,移除该节点时必须将其降级为worker角色,可以在管理节点执行如下命令
1 2 # docker node demote <hostname> docker node demote db-2
2.2.2 常用命令 Docker 网络
1 2 3 4 5 6 # 查看docker网络列表 docker network ls # 删除docker网络 docker network rm db-cluster # 查看网络详情 docker inspect db-cluster
Docker Volume存储卷
1 2 3 4 # 查看volume列表 docker volume ls # 删除volume卷 docker volume rm db-cluster_opensearch-node2-data
2.2.3 引用
docker swarm 关键概念: https://docs.docker.com/engine/swarm/key-concepts/
docker swarm 初始化: https://docs.docker.com/engine/reference/commandline/swarm_init/
ElasticSearch 网络: https://www.elastic.co/guide/en/elasticsearch/reference/7.10/modules-network.html
3.致谢 特别感谢提供各类教程和文档的站点以及协助排查问题的朋友,尤其是 @x 7% 在关键坑publish_host提供了有效思路和相关文档链接。
OpenSearch 官方
Creating a cluster - OpenSearch documentation
https://opensearch.org/docs/2.6/
https://raw.githubusercontent.com/opensearch-project/documentation-website/2.6/assets/examples/docker-compose.yml
ElasticSearch 官方
https://www.elastic.co/guide/en/elasticsearch/reference/7.10/index.html
Elastic开源社区
https://blog.csdn.net/wlei0618/article/details/127371710
面圈网
架构原理-ELK Stack 中文指南-面试哥 (mianshigee.com)
OpenAI ChatGpt3.5 & 4
文章评论