Elasticsearch 集群安装:RPM 裸机生产部署 vs docker-compose 快速起集群
部署 Elasticsearch 集群有两种常见方式:RPM 包裸机安装适合生产环境长期运行,docker-compose 适合本地测试或快速验证。7.x 与 8.x 在安全默认值上存在显著差异——7.x 需手动开启 xpack 并生成证书,8.x 则默认启用 TLS 和密码且无法匿名启动。本文覆盖两种部署形态的全量配置、安全差异、验证步骤以及两个必须知道的性能坑。
版本说明
本文原写于 2022-03,2026-09 重写。
RPM 部署基于 Elasticsearch 7.17.9;docker-compose 基于 8.1.2。在 8.x 上的差异已单独成章说明。
# 1. 选型对比表
| 维度 | RPM 裸机生产部署 | docker-compose 快速起集群 |
|---|---|---|
| 部署形态 | systemd 托管的长期稳定集群 | 容器化的临时/开发环境 |
| 安全默认值 | 7.x 需手动开启 xpack.security | 8.x 默认开启 TLS + 密码,无法匿名 |
| 资源隔离 | 依赖 OS 级 cgroup/limits | 容器 mem_limit 可精确约束 |
| 升级方式 | 逐个节点 yum upgrade + 滚动重启 | 改 .env 版本号重新 up |
| 适用场景 | 生产长期运行、需要精细调优 | 本地测试、CI/CD、快速验证 |
# 2. 方案一:RPM 裸机生产部署
基于 Elasticsearch 7.17.9 的 RPM 包安装,适用于生产环境三节点集群。
# 2.1 RPM 安装
wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.9-x86_64.rpm
yum install elasticsearch-7.17.9-x86_64.rpm
2
# 2.2 JVM 配置 /etc/elasticsearch/jvm.options
-Xms30g
-Xmx30g
-XX:+UnlockDiagnosticVMOptions
-Xlog:gc+heap+coops
14-:-XX:+UseG1GC
14-:-XX:G1ReservePercent=25
14-:-XX:InitiatingHeapOccupancyPercent=30
14-:-XX:MaxGCPauseMillis=50
-Djava.io.tmpdir=${ES_TMPDIR}
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/data/es
-XX:ErrorFile=/data/es/hs_err_pid%p.log
8:-XX:+PrintGCDetails
8:-XX:+PrintGCDateStamps
8:-XX:+PrintTenuringDistribution
8:-XX:+PrintGCApplicationStoppedTime
8:-Xloggc:/data/es/gc.log
8:-XX:+UseGCLogFileRotation
8:-XX:NumberOfGCLogFiles=32
8:-XX:GCLogFileSize=64m
9-:-Xlog:gc*,gc+age=trace,safepoint:file=/data/es/gc.log:utctime,pid,tags:filecount=32,filesize=64m
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
JVM 堆与容器内存三元配置:
-Xms30g -Xmx30g仅约束 JVM 堆内存- 堆外内存:Lucene 段缓存、网络缓冲区、JNI 调用等不走 JVM 堆
- 容器场景下:容器内存限制(
mem_limit或systemd LimitAS)应 ≥ 1.5 ~ 2 × JVM 堆 - 若不设容器内存限制,30GB 堆 + 无上限堆外可能导致容器 OOM 被 Kill
为什么 -Xms30g -Xmx30g 卡在 30GB 而不是更大:
JVM 的压缩普通对象指针(compressed oops)在堆超过约 32GB 时会失效,指针从 4 字节变成 8 字节,导致可寻址对象数量反而变少、GC 压力上升。因此在单节点场景下,30-31GB 是经验上的堆内存上限。如果机器内存更大,应该通过增加节点数来水平扩容,而不是继续增大单个节点的堆。另外,-Xms 与 -Xmx 必须设置为相同值,避免运行时因扩堆而引发的 GC 停顿。
# 2.3 Elasticsearch 配置 /etc/elasticsearch/elasticsearch.yml
cluster.name: test-es-cluster
node.name: es-master01
node.master: true
node.data: true
node.ingest: true
node.attr.rack_id: rack_es-master01
cluster.routing.allocation.awareness.attributes: rack_id
cluster.routing.allocation.same_shard.host: true
path.data: /data/es/data
path.logs: /data/es/logs
bootstrap.memory_lock: true
indices.memory.index_buffer_size: 17%
indices.recovery.max_bytes_per_sec: 1g
network.host: 0.0.0.0
network.publish_host: 192.0.2.11
http.port: 9200
transport.tcp.port: 9300
discovery.seed_hosts: ['192.0.2.11:9300', '192.0.2.12:9300', '192.0.2.13:9300']
cluster.initial_master_nodes: ['192.0.2.11', '192.0.2.12', '192.0.2.13']
cluster.fault_detection.leader_check.interval: 20s
discovery.cluster_formation_warning_timeout: 30s
cluster.join.timeout: 120s
cluster.publish.timeout: 90s
action.destructive_requires_name: true
xpack.ml.enabled: false
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.keystore.type: PKCS12
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.type: PKCS12
xpack.security.audit.enabled: true
thread_pool:
write:
size: 17 # 建议设置为 CPU 核数;若机器 8 核却设 17,会造成线程浪费
indices.fielddata.cache.size: 17%
indices.breaker.fielddata.limit: 30%
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
为什么这些配置项这么设:
bootstrap.memory_lock: true 是为了防止 JVM 堆内存被操作系统交换到 swap。一旦堆被换出,GC 扫描时会触发磁盘 IO,延迟从毫秒级直接崩到秒级。开启它需要在 systemd unit 里配套设置 LimitMEMLOCK=infinity,两者是一对:前者是 ES 进程请求锁定内存,后者是 OS 允许它这么做。
cluster.initial_master_nodes 只在集群首次启动时用于引导形成集群,一旦集群形成后就不再生效。重启节点时不应依赖此配置。候选 master 节点取奇数(如 3 个)是为了让多数派投票可以达成明确结论,避免脑裂场景下出现多个 master。
node.attr.rack_id + cluster.routing.allocation.awareness.attributes 的组合用于强制让主分片与副本分片分布在不同机架。这样单机架掉电或网络中断时,不会同时失去主副本两份数据。cluster.routing.allocation.same_shard.host: true 是同一逻辑在单机层面的实现——确保同一分片的主副本不会落在同一台物理机上。
indices.memory.index_buffer_size: 17% 控制写入缓冲占 JVM 堆的比例,写入密集场景可适当调大,让更多数据在内存中缓冲后再刷盘。**indices.recovery.max_bytes_per_sec: 1g`** 则是分片恢复时的带宽限速,默认值在万兆网络下会让恢复变得过慢,但调太大又会挤占正常读写带宽——这是一个此消彼长的权衡点,不是越大越好。
# 2.4 生产模式与启动检查(bootstrap checks)
本文的 network.host: 0.0.0.0 配置是一个关键开关:ES 只要监听非回环地址,就认定自己处于生产模式,此时一组启动检查(bootstrap checks)从「警告」升级为「硬性拒绝启动」。开发模式(仅监听 127.0.0.1)下这些检查只打日志。这是很多人「本地跑得好好的,上生产起不来」的直接原因。
| 检查项 | 要求 | 配置方式 |
|---|---|---|
vm.max_map_count | ≥ 262144 | sysctl -w vm.max_map_count=262144,持久化写入 /etc/sysctl.conf |
| 文件描述符 nofile | ≥ 65535 | systemd unit 中的 LimitNOFILE=65535(本文 2.5 节的 unit 文件已包含) |
| 最大线程数 | ≥ 4096 | systemd unit 中的 LimitNPROC=65535(本文 unit 已包含) |
| 内存锁定 | 必须成功锁定 | bootstrap.memory_lock: true 要求 LimitMEMLOCK=infinity,两者缺一,节点要么起不来,要么锁不住内存 |
| 堆大小一致性 | Xms 必须等于 Xmx | 本文 jvm.options 中的 -Xms30g -Xmx30g 就是满足这条 |
| 发现配置 | 至少配置 discovery 或 initial_master 之一 | discovery.seed_hosts 与 cluster.initial_master_nodes 至少配置一个,否则生产模式拒绝启动 |
排障入口:启动失败时错误信息统一带 bootstrap check failure 前缀,日志会逐条列出未通过的检查。直接按提示修改即可,不要盲目关闭安全特性绕过。
# 2.5 Systemd 配置 /usr/lib/systemd/system/elasticsearch.service
[Unit]
Description=Elasticsearch
Documentation=https://www.elastic.co
Wants=network-online.target
After=network-online.target
[Service]
Type=notify
RuntimeDirectory=elasticsearch
PrivateTmp=true
Environment=ES_HOME=/usr/share/elasticsearch
Environment=ES_PATH_CONF=/etc/elasticsearch
Environment=PID_DIR=/var/run/elasticsearch
Environment=ES_SD_NOTIFY=true
EnvironmentFile=-/etc/sysconfig/elasticsearch
WorkingDirectory=/usr/share/elasticsearch
User=elasticsearch
Group=elasticsearch
ExecStart=/usr/share/elasticsearch/bin/systemd-entrypoint -p ${PID_DIR}/elasticsearch.pid --quiet
StandardOutput=journal
StandardError=inherit
LimitNOFILE=65535
LimitMEMLOCK=infinity
LimitNPROC=65535
LimitAS=infinity
LimitFSIZE=infinity
TimeoutStopSec=0
KillSignal=SIGTERM
KillMode=process
SendSIGKILL=no
SuccessExitStatus=143
TimeoutStartSec=575
[Install]
WantedBy=multi-user.target
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
# 2.6 生成证书与设置密码
export PATH=$PATH:/usr/share/elasticsearch/bin
elasticsearch-certutil ca
elasticsearch-certutil cert --ca elastic-stack-ca.p12
# 将生成的证书复制到各节点 config 目录
# 设置各内置用户密码
elasticsearch-setup-passwords interactive
2
3
4
5
6
7
# 3. 方案二:docker-compose 快速起集群
基于 Elasticsearch 8.x,适用于本地测试或快速验证三节点集群。
# 3.1 docker-compose.yml
version: "2.2"
services:
setup:
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
user: "0"
command: >
bash -c '
if [ x${ELASTIC_PASSWORD} == x ]; then
echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
exit 1;
elif [ x${KIBANA_PASSWORD} == x ]; then
echo "Set the KIBANA_PASSWORD environment variable in the .env file";
exit 1;
fi;
if [ ! -f certs/ca.zip ]; then
echo "Creating CA";
bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
unzip config/certs/ca.zip -d config/certs;
fi;
if [ ! -f certs/certs.zip ]; then
echo "Creating certs";
echo -ne \\
"instances:\\n"\\
" - name: es01\\n"\\
" dns:\\n"\\
" - es01\\n"\\
" - localhost\\n"\\
" ip:\\n"\\
" - 127.0.0.1\\n"\\
" - name: es02\\n"\\
" dns:\\n"\\
" - es02\\n"\\
" - localhost\\n"\\
" ip:\\n"\\
" - 127.0.0.1\\n"\\
" - name: es03\\n"\\
" dns:\\n"\\
" - es03\\n"\\
" - localhost\\n"\\
" ip:\\n"\\
" - 127.0.0.1\\n"\\
> config/certs/instances.yml;
bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
unzip config/certs/certs.zip -d config/certs;
fi;
echo "Setting file permissions";
chown -R root:root config/certs;
find . -type d -exec chmod 750 \\{} \\;;
find . -type f -exec chmod 640 \\{} \\;;
echo "Waiting for Elasticsearch availability";
until curl -s --cacert config/certs/ca/ca.crt https://es01:9200/_cluster/health | grep -q '"status":"\\(green\\|yellow\\)"'; do sleep 30; done;
echo "Setting kibana_system password";
until curl -s -X POST --cacert config/certs/ca/ca.crt -u elastic:${ELASTIC_PASSWORD} -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
echo "All done!";
'
healthcheck:
test: ["CMD-SHELL", "[ -f config/certs/es01/es01.crt ]"]
interval: 1s
timeout: 5s
retries: 120
es01:
depends_on:
setup:
condition: service_healthy
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata01:/usr/share/elasticsearch/data
ports:
- ${ES_PORT}:9200
environment:
- node.name=es01
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es02,es03
- ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es01/es01.key
- xpack.security.http.ssl.certificate=certs/es01/es01.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.http.ssl.verification_mode=certificate
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es01/es01.key
- xpack.security.transport.ssl.certificate=certs/es01/es01.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
es02:
depends_on:
- es01
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata02:/usr/share/elasticsearch/data
environment:
- node.name=es02
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es01,es03
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es02/es02.key
- xpack.security.http.ssl.certificate=certs/es02/es02.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.http.ssl.verification_mode=certificate
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es02/es02.key
- xpack.security.transport.ssl.certificate=certs/es02/es02.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
es03:
depends_on:
- es02
image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
volumes:
- certs:/usr/share/elasticsearch/config/certs
- esdata03:/usr/share/elasticsearch/data
environment:
- node.name=es03
- cluster.name=${CLUSTER_NAME}
- cluster.initial_master_nodes=es01,es02,es03
- discovery.seed_hosts=es01,es02
- bootstrap.memory_lock=true
- xpack.security.enabled=true
- xpack.security.http.ssl.enabled=true
- xpack.security.http.ssl.key=certs/es03/es03.key
- xpack.security.http.ssl.certificate=certs/es03/es03.crt
- xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.http.ssl.verification_mode=certificate
- xpack.security.transport.ssl.enabled=true
- xpack.security.transport.ssl.key=certs/es03/es03.key
- xpack.security.transport.ssl.certificate=certs/es03/es03.crt
- xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
- xpack.security.transport.ssl.verification_mode=certificate
- xpack.license.self_generated.type=${LICENSE}
mem_limit: ${MEM_LIMIT}
ulimits:
memlock:
soft: -1
hard: -1
healthcheck:
test:
[
"CMD-SHELL",
"curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
]
interval: 10s
timeout: 10s
retries: 120
kibana:
depends_on:
es01:
condition: service_healthy
es02:
condition: service_healthy
es03:
condition: service_healthy
image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
volumes:
- certs:/usr/share/kibana/config/certs
- kibanadata:/usr/share/kibana/data
ports:
- ${KIBANA_PORT}:5601
environment:
- SERVERNAME=kibana
- ELASTICSEARCH_HOSTS=https://es01:9200
- ELASTICSEARCH_USERNAME=kibana_system
- ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
- ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
mem_limit: ${MEM_LIMIT}
healthcheck:
test:
[
"CMD-SHELL",
"curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
]
interval: 10s
timeout: 10s
retries: 120
volumes:
certs:
driver: local
esdata01:
driver: local
esdata02:
driver: local
esdata03:
driver: local
kibanadata:
driver: local
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
# 3.2 .env 环境变量
# ⚠️ 以下密码请自行设置为强密码,不要用示例值
ELASTIC_PASSWORD=<设置一个强密码>
KIBANA_PASSWORD=<设置一个强密码>
STACK_VERSION=8.1.2
CLUSTER_NAME=escluster
ES_PORT=9200
KIBANA_PORT=5601
LICENSE=basic
MEM_LIMIT=1073741824
2
3
4
5
6
7
8
9
内存配比提醒:MEM_LIMIT=1073741824(1GB)仅适用于测试环境。生产环境建议容器内存 ≥ 2 × JVM 堆大小。
# 3.3 启动命令
# 启动
docker-compose up -d
# 若有 vm.max_map_count 报错则执行
sysctl -w vm.max_map_count=262144
# 然后重启
docker-compose restart
2
3
4
5
6
7
8
# 3.4 容器化部署的原理
为什么 setup 容器要单独存在:在 8.x 中,TLS 证书必须在节点启动前就位。setup 容器是一个一次性任务容器,负责生成 CA 和各节点的证书、写入共享 volume,然后通过 healthcheck 让 es01 的 depends_on 卡住,直到证书就绪。这是为了避免「节点起来了证书还没生成好」的竞态条件。
容器里 memlock 与堆的关系:容器场景下,JVM 堆之外还有 Lucene 段缓存、网络缓冲、JIT 元空间等堆外开销。容器内存限制 mem_limit 应该留到堆的 1.5~2 倍裕量,否则容器会被 OOM Kill,而 ES 日志里看不到任何信息。
# 4. 7.x 与 8.x 的安全默认值差异
| 安全特性 | 7.x(RPM 部署) | 8.x(docker-compose) |
|---|---|---|
| xpack.security.enabled | 默认 false,需手动设为 true | 默认 true,无法匿名启动 |
| TLS 证书 | 需手动生成(elasticsearch-certutil) | 首次启动自动生成,或挂载自定义证书 |
| 内置用户密码 | 初始无密码,需 elasticsearch-setup-passwords 设置 | 首次启动自动生成 elastic 密码,控制台输出 |
| 启动方式 | 可匿名启动,后手动开启安全 | 必须提供密码或证书,否则拒绝启动 |
关键差异说明:
- 7.x 的「先无密码、后手动开启」流程在 8.x 不再适用
- 8.x 首次启动时,若
ELASTIC_PASSWORD未设置,setup 容器会报错退出 - 8.x 的自动生成密码和证书仅适用于单节点或 compose 场景;生产集群仍需手动管理证书生命周期
# 5. 坑与边界
# 5.1 thread_pool.write.size 配置不当
elasticsearch.yml 中 thread_pool.write.size 应根据实际 CPU 核数设置。若机器 8 核却设 17,会造成线程浪费——多余的线程竞争 CPU 时间片,反而降低写入吞吐。
建议:设置为 CPU 核数或略低(留余量给 OS 和其他进程)。
# 5.2 fielddata 断路器风险
indices.breaker.fielddata.limit: 30% 与 indices.fielddata.cache.size: 17% 联动:
- 当某聚合查询加载的 fielddata 超过堆的 30%,查询直接失败(而非丢弃缓存)
- 异常信息:
CircuitBreakingException: [fielddata] Data too large - 修复:改用
keyword字段做聚合(不启用 fielddata),或增大断路器阈值(需留足堆余量)
# 6. 验证
# 6.1 RPM 部署验证
# 1. 确认集群节点列表
GET _cat/nodes?v
# 2. 确认集群健康(green/yellow 为正常,red 为故障)
GET _cluster/health
# 3. 确认 JVM 参数生效(heap 应与 jvm.options 一致)
GET _nodes/jvm?filter_path=nodes.*.jvm.mem.heap_max_in_bytes
# 4. 确认 thread_pool 配置生效
GET _nodes/settings?filter_path=nodes.*.thread_pool.write
# 5. 检查 fielddata 当前占用(接近 limit 时需警惕)
GET _nodes/stats/fielddata?filter_path=nodes.*.fielddata
2
3
4
5
6
7
8
9
10
11
12
13
14
# 6.2 docker-compose 验证
# 1. 检查容器状态
docker-compose ps
# 2. 验证 ES 集群健康(返回 green/yellow 为正常)
curl -s --cacert config/certs/ca/ca.crt -u elastic:<密码> https://localhost:9200/_cluster/health | jq .
# 3. 验证节点列表
curl -s --cacert config/certs/ca/ca.crt -u elastic:<密码> https://localhost:9200/_cat/nodes
# 4. 验证 Kibana 可访问(返回 302 重定向到登录页)
curl -s -I http://localhost:5601 | head -1
2
3
4
5
6
7
8
9
10
11
# 6.3 常见故障
| 现象 | 原因 | 处置 |
|---|---|---|
max virtual memory areas vm.max_map_count [65530] is too low | 内核参数不足 | 执行 sysctl -w vm.max_map_count=262144 |
| ES 容器反复重启 | 内存不足(1GB 无法支撑 8.x 全功能) | 调高 .env 中 MEM_LIMIT |
| Kibana 无法连接 ES | 证书未就绪或密码错误 | 检查 setup 容器日志:docker-compose logs setup |
| 认证失败 | 密码错误或证书不受信任 | 确认使用正确的 elastic 密码,或证书挂载路径正确 |
ES 集群部署快速参考
{
"_meta": {
"doc_version": "1.0",
"article_id": "es-cluster-install-rpm-docker",
"profile_context": "elasticsearch-deployment",
"last_updated": "2026-09"
},
"quick_start": {
"rpm": {
"install": "yum install elasticsearch-7.17.9-x86_64.rpm",
"jvm_config": "/etc/elasticsearch/jvm.options",
"es_config": "/etc/elasticsearch/elasticsearch.yml",
"systemd": "systemctl start elasticsearch",
"passwords": "elasticsearch-setup-passwords interactive"
},
"docker_compose": {
"env": ".env (ELASTIC_PASSWORD, KIBANA_PASSWORD, STACK_VERSION)",
"start": "docker-compose up -d",
"verify": "curl -s --cacert config/certs/ca/ca.crt -u elastic:<密码> https://localhost:9200/_cluster/health"
}
},
"safety_rules": [
{"risk": "thread_pool.write.size 与 CPU 核数不匹配", "action": "线程数设为 CPU 核数或略低,避免浪费", "scope": "rpm"},
{"risk": "fielddata 超过断路器阈值", "action": "查询直接失败 CircuitBreakingException,改用 keyword 聚合或调大阈值", "scope": "all"},
{"risk": "JVM 堆外内存 OOM", "action": "容器内存限制 ≥ 1.5 ~ 2 × JVM 堆", "scope": "all"},
{"risk": "8.x 忘记设置 ELASTIC_PASSWORD", "action": "setup 容器会报错退出,必须设置强密码", "scope": "docker"},
{"risk": "vm.max_map_count 不足", "action": "执行 sysctl -w vm.max_map_count=262144", "scope": "docker"}
],
"verification": {
"rpm": [
"GET _cat/nodes?v",
"GET _cluster/health",
"GET _nodes/jvm?filter_path=nodes.*.jvm.mem.heap_max_in_bytes",
"GET _nodes/settings?filter_path=nodes.*.thread_pool.write",
"GET _nodes/stats/fielddata?filter_path=nodes.*.fielddata"
],
"docker": [
"docker-compose ps",
"curl -s --cacert config/certs/ca/ca.crt -u elastic:<密码> https://localhost:9200/_cluster/health",
"curl -s -I http://localhost:5601"
]
},
"version_diff": {
"security_default_7x": "手动开启 xpack.security.enabled + 生成证书",
"security_default_8x": "默认开启 TLS + 密码,无法匿名启动"
}
}
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