我大概从2021年就开始折腾OpenSearch了,那时候刚爆出Elasticsearch变更许可证的消息,不少团队都在观望。后来OpenSearch社区版越做越稳,我这边就把内部日志检索和监控可视化平台整体迁了过去。这套组合拳打下来,用一句话总结就是:OpenSearch负责存储和检索数据,Dashboards负责把数据变成图表和仪表盘,两者配合起来,完全可以替代一套商业版的日志分析平台。
这篇内容我会按自己实际搭建的过程来写,从选型、装环境、部署单节点、扩展到三节点集群、开启安全认证,再把Dashboards接上、导入真实数据做可视化,最后说说生产环境的调优和那些年踩过的坑。整个过程偏实战,代码和配置都能直接抄,适合刚接触OpenSearch的运维、后端和测试同学。
1. OpenSearch是什么,我为什么从Elasticsearch迁过来:选型逻辑与实际兼容性
1.1 许可变更与分叉背景
先说背景。Elasticsearch从7.11版本开始把协议从Apache 2.0改成了Elastic License,简单理解就是你不能再拿它做商业化的托管服务了。这消息一出来,很多云厂商和依赖ES做二次产品的团队就很被动。于是2021年,AWS牵头把Elasticsearch 7.10.2的代码分叉出来,孵化了OpenSearch项目,采用Apache 2.0协议,完全开源,社区驱动。
这个分叉时间点卡得很妙,7.10.2算是ES 7.x里性能比较稳定的版本,后面OpenSearch团队又额外开发了很多新功能,比如内置机器学习框架、事件监控、k-NN向量检索等。对于咱们这种自建搜索/日志平台的用户来说,最直观的感受就是——功能没落后,成本还是零,谁不爱。
1.2 与Elasticsearch的兼容性差异
很多第一次接触OpenSearch的人会问:我之前写的ES API、DSL查询、索引配置,搬到OpenSearch能用吗?
从我自己迁移的经验来看,90%以上是兼容的。索引API、搜索API、聚合语法基本沿用,分片、副本、refresh、translog这些底层概念也一致。Kibana要改成OpenSearch Dashboards,但界面逻辑和配置方式几乎一模一样。
要注意的几个差异:
- OpenSearch 2.x版本以后,默认包含OpenSearch Security插件(相当于免费版的安全模块),ES这边可是商业功能。
- 文档id生成、字段类型映射这些完全一致。
- 推荐用OpenSearch提供的客户端SDK,不过原本用ES REST API去调的代码几乎不用改。
1.3 什么时候该选OpenSearch
我个人判断的标准是这样的:
- 公司没有采购过ES商业版,也不想花钱买License的,直接上OpenSearch。
- 对数据主权有要求,希望完全自托管搜索、日志系统的,OpenSearch更合适。
- 如果团队已经重度使用了ES最新商业特性(如某些机器学习功能),那就得先评估功能替代成本。
- 如果体量很小,日志量每天不到几个GB,直接Docker跑个单节点OpenSearch,省心还不花钱。
2. 环境准备:版本选择、系统参数与安装方式
2.1 版本和机器选型
我当前线上用的稳定版本是OpenSearch 2.11系列,因为当时2.x已经迭代到比较成熟的阶段,k-NN、Segment Replication这些特性都稳定了。建议你们在部署前先去GitHub官方Release页看看最新稳定版,2.x的安装包基本都能直接用。
机器最低配置:
| 角色 | CPU | 内存 | 磁盘 | 数量 |
|---|---|---|---|---|
| 单节点体验 | 2核 | 4GB | 50GB SSD | 1台 |
| 生产集群最小规模 | 4核 | 16GB | 500GB SSD | 3台 |
| 带数据接驳的完整环境 | 8核 | 32GB | 1TB SSD | 5台以上 |
磁盘一定选SSD,搜索类的随机读写场景对IOPS极其敏感,机械盘跑起来你会怀疑人生的。
2.2 系统参数调整
这部分属于那种"配置不对,装上了也白搭"的环节。OpenSearch底层用的Lucene,会创建大量内存映射文件,Linux默认的vm.max_map_count根本不够用。
# 查看当前值 sysctl vm.max_map_count # 永久调整 echo "vm.max_map_count=262144" >> /etc/sysctl.conf sysctl -p同时把进程最大文件描述符调大,不然后面并发一上来,too many open files会把你折磨死:
ulimit -n 65535如果是在systemd环境下启动,直接在/etc/security/limits.conf里加:
opensearch soft nofile 65535 opensearch hard nofile 65535另外建议关闭swap,至少也要把vm.swappiness调低,防止操作系统把JVM进程的内存换到磁盘,一旦发生GC基本就是几十秒起步,集群分片很容易掉。
echo "vm.swappiness=1" >> /etc/sysctl.conf sysctl -p2.3 安装包方式 vs Docker
有两条路可以走。
Docker方式最省事,官方镜像直接拉:
docker pull opensearchproject/opensearch:2.11.1 docker run -d --name opensearch \ -p 9200:9200 -p 9600:9600 \ -e "discovery.type=single-node" \ opensearchproject/opensearch:2.11.1但我个人还是建议生产环境用tar.gz或RPM包安装,原因有两个:一是方便直接调JVM参数和系统内核参数;二是不需要额外折腾容器存储卷权限问题,排查问题更直接。
我线上用的是tar.gz方式,下载地址一般在https://artifacts.opensearch.org/releases/bundle/opensearch/2.x/opensearch-2.x.x-linux-x64.tar.gz,用wget拉到服务器上,解压到/opt/opensearch即可。
3. 最小可用配置:单节点 OpenSearch 跑通
3.1 解压与目录结构
我习惯把OpenSearch放在/opt/opensearch目录下,解压后目录结构大概长这样:
/opt/opensearch ├── bin # 启动脚本与插件命令 ├── config # 所有配置文件 ├── data # 节点存储的数据 ├── jdk # 内置的JDK ├── lib # Java运行库 ├── logs # 日志 └── plugins # 插件目录不需要另外装JDK,发行包已经内置了Java,这一点比早期ES还省事。
3.2 修改配置文件
核心配置文件是config/opensearch.yml。单节点的最小配置:
# 集群名称,同一集群的节点必须一致 cluster.name: os-cluster # 节点名称,建议每台机器不同 node.name: node-1 # 数据和日志路径 path.data: /opt/opensearch/data path.logs: /opt/opensearch/logs # 绑定地址。生产环境建议绑定内网IP network.host: 0.0.0.0 # HTTP端口,给客户端和Dashboards用 http.port: 9200 # 传输端口,集群节点之间通信用 transport.port: 9300 # 允许单节点运行,不参与集群发现 discovery.type: single-node还要把JVM堆内存调一下,位置在config/jvm.options。
-Xms4g -Xmx4g经验是给机器物理内存的一半,但不要超过31GB,因为JVM的压缩指针在大于32GB堆时反而会失效,GC性能下跌。
3.3 启动验证
启动之前,因为我用的不是root用户,先创建专用账户:
useradd -m -s /bin/bash opensearch chown -R opensearch:opensearch /opt/opensearch su - opensearch cd /opt/opensearch bin/opensearch第一次建议前台跑,日志直接刷到屏幕上可以看启动进度。如果看到Node 'node-1' successfully started就算成功了。
验证接口:
curl -u admin:admin https://localhost:9200这里注意,默认发行版开启了安全插件,API是HTTPS协议的。
如果只想先做功能验证,不想纠结证书,可以临时关掉安全插件:
bin/opensearch -Eplugins.security.disabled=true或者直接把opensearch.yml里的安全配置注释掉。但仅限测试环境,生产你一定得把安全打开。
4. 从单点到三节点:集群配置核心细节
4.1 节点角色划分
单节点玩通了就开始扩张。集群里的节点建议规划好角色,OpenSearch支持以下角色:
| 角色 | 作用 | 典型配置 |
|---|---|---|
| cluster_manager | 管理集群状态、分配分片 | 3台奇数,压力不大但必须稳 |
| data | 存储和检索数据 | 按数据量水平扩展 |
| ingest | 负责写入前的数据处理管道 | 可和data合并 |
| coordinating | 接收请求,分发到数据节点 | 独立节点可提升并发能力 |
小集群不需要搞太复杂,一个节点同时承担manager和data即可。但3个节点里如果有2个同时挂掉,集群就会失去法定人数,所以生产至少3台起。
4.2 集群 discovery 配置
三台机器的opensearch.yml配置逻辑如下:
cluster.name: os-cluster node.name: node-1 # node-2, node-3 node.roles: [cluster_manager, data, ingest] network.host: 0.0.0.0 http.port: 9200 transport.port: 9300 # 种子节点,告诉节点怎么找到其他伙伴 discovery.seed_hosts: - 10.0.0.11:9300 - 10.0.0.12:9300 - 10.0.0.13:9300 # 初始集群中可参与选举的master候选 cluster.initial_master_nodes: - node-1 - node-2 - node-3 # 为了避免脑裂,最小法定人数一般是 (可用节点数 / 2) + 1 discovery.zen.minimum_master_nodes: 2把这三份配置分别改完后,依次启动node-1、node-2、node-3。等待几十秒,执行:
curl -u admin:admin https://10.0.0.11:9200/_cluster/health?pretty如果返回的"status":"green",说明集群健康;"number_of_nodes":3表示三个节点都已加入。
4.3 四类常见集群异常
搭建集群时最容易遇到四类问题,我当年逐个踩过:
第一,节点之间无法互相发现。这时候看日志,如果发现connect-timeout,优先检查传输端口9300的防火墙和网络安全组,再用telnet 10.0.0.12 9300验证连通性。
第二,脑裂。两个节点都认为自己是主节点,写请求会冲突。解决办法就是上面的discovery.zen.minimum_master_nodes,保证法定人数才能选出唯一主节点。
第三,分片无法分配,集群状态黄色。通常是副本分片找不到地方放,curl _cat/allocation看磁盘空间和分片情况。
第四,集群状态红色。某个主分片丢失,索引无法正常读写,解决办法要么把分片强制分配到其他节点,要么从快照恢复,这个后面细说。
5. 安全配置:密码、TLS与最小权限
5.1 安全插件开启
OpenSearch自带的安全插件是opensearch-security,在没有外部认证系统的情况下,它提供内置用户体系、TLS传输加密和字段级权限控制。
第一次启动前,需要先手动生成管理员密码,避免用默认的admin弱口令:
cd /opt/opensearch bash plugins/opensearch-security/tools/securityadmin.sh \ -cd config/opensearch-security/ \ -icl -nhnv \ -cacert config/root-ca.pem \ -cert config/kirk.pem \ -key config/kirk-key.pem生成好之后,启动OpenSearch,访问API需要带用户名密码:
curl -k -u admin:你的密码 https://localhost:9200此时节点之间的通信也启用了TLS,如果日志中出现SSLException,赶紧检查节点证书的时间戳和主机名。
5.2 Dashboard 安全接入
Dashboards这边也要配置对应的安全信息,否则连接会被拒绝。
在/etc/opensearch-dashboards/opensearch_dashboards.yml里写入:
server.host: 0.0.0.0 server.port: 5601 opensearch.hosts: ["https://10.0.0.11:9200", "https://10.0.0.12:9200", "https://10.0.0.13:9200"] opensearch.ssl.verificationMode: none opensearch.username: kibanaserver opensearch.password: 设置的密码启动Dashboards后,浏览器访问http://服务器IP:5601,用admin登录就可以进入管理界面。
5.3 内置用户和权限
安全插件内置了几个预设账号,用途不同:
| 用户 | 用途 |
|---|---|
| admin | 管理员,全权限,不能用于日常写入 |
| kibanaserver | Dashboards后台连接OpenSearch使用 |
| logstash | 数据采集端写入专用 |
| snapshotrestore | 快照备份恢复专用 |
我更推荐的做法是新建业务专用用户,只给需要的索引权限,权限粒度可以做到具体索引和具体操作动作。比如只读用户就可以通过Dashboards的Security页面配置,用OpenSearch Dashboards自带的管理界面比直接改YAML直观得多。
6. Dashboard可视化平台搭建:接入数据并产出图表
6.1 Dashboards版本对齐
这一步强烈建议用与OpenSearch相同版本的Dashboards,不然很可能出现字段解析异常或插件不兼容。安装Dashboards同样建议tar.gz方式:
wget https://artifacts.opensearch.org/releases/bundle/opensearch-dashboards/2.11.1/opensearch-dashboards-2.11.1-linux-x64.tar.gz tar -xzf opensearch-dashboards-2.11.1-linux-x64.tar.gz -C /opt cd /opt/opensearch-dashboards-2.11.1 bin/opensearch-dashboardsDashboards默认端口5601,登录后进入“Home”页面。第一次进入需要创建索引模式才能做可视化。
6.2 创建索引模式
假设我们已经往OpenSearch里写入了一批nginx访问日志,索引名是nginx-access-2025.01.10。
在Dashboards左侧菜单进入“Stack Management” -> “Index patterns”,点击创建索引模式:
索引模式名称:nginx-access-* 时间字段:@timestamp时间字段千万别选错,否则后面做时间范围筛选和趋势图都会失灵。如果日志里没有时间字段,就让数据写入端补充一个@timestamp字段,不然图表基本废了。
6.3 构建可视化与仪表板
创建完索引模式,就可以在Visualize Library里新建可视化。
以一个非常常见的场景为例:查看最近24小时Nginx请求量和状态码分布。
第一步,点击“Visualize” -> “Create visualization”,选择“Line”或者“Bar”,选索引模式nginx-access-*。
第二步,配置指标(Metrics):
| 参数 | 值 |
|---|---|
| 聚合方式 | Count |
| 自定义标签 | 请求量 |
第三步,配置桶(Buckets):
| 参数 | 值 |
|---|---|
| X轴聚合方式 | Date Histogram |
| 字段 | @timestamp |
| 时间间隔 | 1小时 |
第四步,点击右上角“Save”存为“Nginx请求趋势”,再点击“Dashboard” -> “Create dashboard”,把这个图加进去。
这时候你会发现图表里请求量波动和状态码分布一目了然,比自己写脚本统计省了不知道多少时间。
再进阶一点,你可以用“TSVB”可视化或者“Vega”语法做更精细的报表,比如查询延迟的P90、P99,或者按照省份Map展示IP归属。
7. 生产环境调优与备份恢复经验
7.1 JVM堆与线程池
堆内存上面说过,给一半物理内存,别超31GB。额外要注意的是不要给JVM堆之外留太少内存,因为Lucene要用堆外内存做文件缓存,留太少会导致搜索性能严重下降。
线程池方面,OpenSearch默认有一套search、write、bulk线程池配置,一般不用动。真正要关注的是批量写入的bulk请求大小。刚开始我图省事一次塞10000条,结果直接把CPU打满,后来改成一次2000~5000条,根据响应时间动态调整,写入稳定多了。
一个简单的写入压测脚本思路:
from opensearchpy import OpenSearch client = OpenSearch( hosts=["https://10.0.0.11:9200"], http_auth=("admin", "密码"), use_ssl=True, verify_certs=False ) actions = [ {"_index": "test-001", "_source": {"value": i}} for i in range(10000) ] client.bulk(actions)7.2 索引生命周期与分片规划
索引不是越多越好,分片也不是越大越好。我的经验是:
- 单个分片大小控制在30GB~50GB比较合适,太大会拖慢恢复速度,太小会导致分片数过多,管理开销大。
- 按天或按周建索引,配合索引生命周期管理(ISM)策略自动轮转和删除。
- 开启强制段合并,减少段数量,能提升查询性能。
ISM策略在Dashboards的“Index Management”里配置,或者通过_plugins/_ism/policiesAPI创建。
7.3 快照备份
要说哪件事最容易被忽略,肯定是备份。我见过不止一次因为磁盘故障导致整个索引丢失的案例,所以快照仓库一定要建。
首先在opensearch.yml里加:
path.repo: /mnt/backups/opensearch然后调用API注册:
curl -k -u admin:密码 -X PUT "https://localhost:9200/_snapshot/backup_repo" -H 'Content-Type: application/json' -d' { "type": "fs", "settings": { "location": "/mnt/backups/opensearch" } }'接着创建快照:
curl -k -u admin:密码 -X PUT "https://localhost:9200/_snapshot/backup_repo/snapshot_20250110?wait_for_completion=true"恢复的话一串API的事,但务必在测试环境先演练一遍,别真出故障了才发现权限不对。
8. 运维踩坑记录:磁盘水位、堆压力、掉节点
8.1 磁盘水位线导致索引只读
这是一个非常经典的坑。OpenSearch在磁盘使用率超过一定阈值时,会自动把索引变成只读状态,防止数据节点写满盘。一旦触发,你会发现写入请求疯狂报错:
{ "reason": "blocked by: [FORBIDDEN/12/index read-only / allow delete (api)]" }解决办法不是删索引,而是先清理磁盘空间,然后解除只读:
curl -k -u admin:密码 -X PUT "https://localhost:9200/*/_settings" -H 'Content-Type: application/json' -d' { "index.blocks.read_only_allow_delete": null }'最佳实践是在集群配置里调高水位线,并设置监控告警:
cluster.routing.allocation.disk.watermark.low: 85% cluster.routing.allocation.disk.watermark.high: 90% cluster.routing.allocation.disk.watermark.flood_stage: 95%8.2 堆内存压力飙升
集群跑一段时间,会发现JVM堆使用率长期在85%以上,伴随频繁的Full GC。
我当时排查的链路是:先看_cat/nodes?v&h=name,heapPercent,ramPercent,load_1m确认哪个节点最严重;再用_nodes/hot_threads看是否有线程卡在Compaction或搜索上;最后确认是否因为分片数量太多,数据节点上每个分片都要占用堆。
最终方案是设置索引分片分配规则,把不同业务的索引分布到不同节点组,并关闭大量不用的旧索引:
{ "index.routing.allocation.require.box_type": "hot" }8.3 节点掉出集群
三节点集群最容易出现的一个问题是某个节点因网络抖动或GC停顿被误判为不可达,然后被踢出集群,等它恢复回来又要重新同步分片,非常消耗带宽。
排查思路主要是看日志里的disconnected或failed to send,配合tcpdump抓一下节点间传输端口9300的流量,确认是不是网卡丢包。
如果是因为磁盘慢导致GC时间过长,优先换SSD,或者调低分片数,减少单节点负担。另外OpenSearch的cluster.fault_detection.leader_check.interval也可以适当调大,避免因为瞬时抖动误判。
最后分享一个小技巧。如果你在Dashboards里创建了很多图表,发现加载速度变慢,先别急着加节点。多半是因为页面打开时发了太多分页聚合请求,把每个可视化的“Rows per page”和“Time range”收缩一下,用起来会顺滑很多。生产环境最重要的是可预测性,我之前就是因为把“最近7天”的查询全部默认拉到仪表盘上,结果每次开页面都等于做一次全量聚合,后来改成默认加载近1小时,再按钮按需拉取,体验立竿见影。
OpenSearch这套东西,真的能扛住日常规模的数据检索需求。你从单节点起步,慢慢往里填数据、画图表、加报警,它会越来越像一个得心应手的内部数据中台。希望这篇内容能帮你少走一些弯路。