Elasticsearch
核心概念与版本
Elasticsearch 是基于 Lucene 的分布式搜索与分析引擎。Index 保存一类文档,Mapping 定义字段类型,Shard 是分布式存储与查询单元,Replica 提供副本及读取扩展。
- 文档写入成功不代表立即可被搜索,搜索可见性受 refresh 影响;实时 GET 与搜索的语义不同。
- 主分片数影响数据分布,创建后不能任意原地修改;副本数可动态调整,但需要足够节点与磁盘。
- 集群 health 为 green 表示分片已分配,不能代表查询性能、数据质量和备份均正常。
- Elasticsearch、Kibana、Logstash、客户端、ECK 和分析插件必须满足版本兼容矩阵。7.x、8.x、9.x 的安全与部署方式不同,不能只替换镜像标签。
Docker Compose 单节点实验
下面以 8.17.3 固定版本演示,启用账号认证并绑定宿主机回环,HTTP 层暂未配置 TLS。只用于本机实验;生产应选受支持的补丁版本、配置完整 TLS 并设计多节点拓扑。
创建 .env,替换密码并限制权限:
ELASTIC_PASSWORD=REPLACE_WITH_RANDOM_PASSWORD
chmod 600 .env
保存 compose.yaml:
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.17.3
environment:
discovery.type: single-node
xpack.security.enabled: "true"
xpack.security.http.ssl.enabled: "false"
ELASTIC_PASSWORD: ${ELASTIC_PASSWORD:?set ELASTIC_PASSWORD}
ES_JAVA_OPTS: -Xms1g -Xmx1g
ports:
- "127.0.0.1:9200:9200"
mem_limit: 2g
volumes:
- es-data:/usr/share/elasticsearch/data
volumes:
es-data:
按版本要求检查宿主机 vm.max_map_count、文件描述符和磁盘水位。Linux 上常见的 8.x 起点为 262144,目标版本若要求更高则使用该版本值;这是宿主机参数,在单独 init 容器里修改 ulimit 不会改变业务容器的进程限制。
docker compose config -q
docker compose up -d
docker compose logs --tail=100 elasticsearch
curl --user elastic http://127.0.0.1:9200/
curl --user elastic 'http://127.0.0.1:9200/_cluster/health?pretty'
curl --user elastic 会提示输入密码,避免明文密码进入命令历史。单节点设置副本为 0 才能分配全部分片;这只是实验取舍,不具备节点容错能力。
Mapping 与查询
以下为 Kibana Dev Tools 请求。应用使用独立最小权限账号,不使用 elastic 超级用户。
PUT /events-demo
{
"settings": {
"number_of_shards": 1,
"number_of_replicas": 0
},
"mappings": {
"dynamic": "strict",
"properties": {
"event_id": {"type": "keyword"},
"message": {"type": "text"},
"status": {"type": "keyword"},
"duration_ms": {"type": "long"},
"@timestamp": {"type": "date"}
}
}
}
PUT /events-demo/_doc/evt-001?refresh=wait_for
{
"event_id": "evt-001",
"message": "gateway request completed",
"status": "ok",
"duration_ms": 42,
"@timestamp": "2026-01-01T00:00:00Z"
}
GET /events-demo/_search
{
"query": {
"bool": {
"filter": [{"term": {"status": "ok"}}],
"must": [{"match": {"message": "gateway"}}]
}
}
}
text 用于分词检索,keyword 用于精确匹配、聚合与排序。动态映射可能造成字段爆炸,日志场景应使用模板、字段限制与受控结构。批量写入用 Bulk API,并逐项检查错误;HTTP 200 不代表批量中每条都成功。深分页优先使用 PIT 与 search_after,不要无限增大 from/size。
ECK 部署三节点
先安装与目标 Kubernetes、Elasticsearch 兼容的 ECK Operator,并核对官方发布清单和 RBAC。下面是应用 CR,不能在没有 CRD/Operator 的集群直接执行。
apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: logs
namespace: middleware
spec:
version: 8.17.3
nodeSets:
- name: default
count: 3
config:
node.roles: [master, data, ingest]
podTemplate:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
elasticsearch.k8s.elastic.co/cluster-name: logs
topologyKey: kubernetes.io/hostname
containers:
- name: elasticsearch
resources:
requests:
cpu: "1"
memory: 4Gi
limits:
memory: 4Gi
volumeClaimTemplates:
- metadata:
name: elasticsearch-data
spec:
accessModes: [ReadWriteOnce]
resources:
requests:
storage: 100Gi
---
apiVersion: kibana.k8s.elastic.co/v1
kind: Kibana
metadata:
name: logs
namespace: middleware
spec:
version: 8.17.3
count: 1
elasticsearchRef:
name: logs
要求至少 3 台满足反亲和性的节点、适当的 StorageClass 和容量。生产数据卷优先使用满足随机 I/O、延迟和持久性要求的块存储;不要未经压测直接使用共享 NFS 作为搜索数据盘。宿主机的内核参数由节点管理配置,不通过具有高权限的临时容器反复修改。
kubectl create namespace middleware
kubectl apply --dry-run=server -f elasticsearch.yaml
kubectl apply -f elasticsearch.yaml
kubectl -n middleware get elasticsearch,kibana,pods,pvc
kubectl -n middleware port-forward service/logs-es-http 9200:9200
ECK 默认创建 TLS 与凭据 Secret,不要关闭安全功能。导出 CA 和读取初始 elastic 密码时使用受控终端;密码不写入命令参数:
umask 077
kubectl -n middleware get secret logs-es-http-certs-public \
-o go-template='{{index .data "tls.crt" | base64decode}}' > es-ca.crt
kubectl -n middleware get secret logs-es-elastic-user \
-o go-template='{{.data.elastic | base64decode}}'
curl --cacert es-ca.crt --user elastic https://localhost:9200/
测试后妥善清理本地证书副本和终端记录。公网或正式域名使用受信证书与正确 SAN,不能用 curl -k 替代证书校验。Kibana 外部入口同样需认证、TLS 和来源控制。
Logstash 与 IK 插件
Logstash 输出配置片段,密码从受保护的环境或 Logstash keystore 提供,CA 使用部署时导出的可信证书:
output {
elasticsearch {
hosts => ["https://logs-es-http.middleware.svc:9200"]
user => "logstash_writer"
password => "${LOGSTASH_PASSWORD}"
ssl_enabled => true
ssl_certificate_authorities => ["/etc/logstash/certs/es-ca.crt"]
index => "application-%{+YYYY.MM.dd}"
}
}
插件选项以实际 Logstash output plugin 版本为准。启用持久队列和死信队列前评估吞吐、磁盘及失败重试,记录映射冲突和拒绝写入。高吞吐时优先按生命周期策略管理 data stream/rollover,避免每天大量小索引。
IK 为第三方分词插件,版本必须与 Elasticsearch 精确兼容。制作固定镜像并在所有需要的节点一致安装、核对来源,不使用来历不明的 7.x-ik 镜像。先用 _analyze 验证分词和词典,再创建依赖该 analyzer 的索引;已有文档不会因更换词典自动重新建立正确索引。
容量、监控与生命周期
- Heap 通常不超过可用内存约一半,保留文件系统缓存;容器环境以 limit 和版本自动计算行为为准,避免堆加原生内存超过 cgroup 限制。
- 主分片数量与大小依据实际数据量、查询、恢复时间和节点容量压测,避免过多小分片。
- 时间序列数据使用 ILM/数据生命周期与 rollover,明确热温冷层、保留期限、写入别名或 data stream。
- 监控未分配分片、磁盘水位、JVM/GC、写入和搜索延迟、rejected、熔断器、段合并、快照失败和集群主节点变化。
- Exporter 需要受保护的只读监控凭据,并根据版本核对指标;官方监控或 exporter 均不能只看 green 状态。
快照与恢复
使用 Snapshot API 将备份存入独立仓库,先完成目标仓库类型、凭据和插件配置。下面假定 backup-repo 已注册:
POST /_snapshot/backup-repo/_verify
PUT /_snapshot/backup-repo/snapshot-demo?wait_for_completion=true
{
"indices": "events-demo",
"include_global_state": false
}
GET /_snapshot/backup-repo/snapshot-demo
核对 snapshot 状态与每个 shard,配置自动快照和失败告警。快照不是跨所有分片同一瞬间的全局事务;需要业务一致性时另行设计停写或应用级检查点。
恢复前核对快照和索引版本兼容,优先在隔离集群恢复并验证文档量、查询、权限和业务。直接复制运行中的 data 目录不是受支持的数据备份。恢复系统索引和 feature states 涉及安全配置,应按目标版本专门流程操作。
故障排查
GET /_cluster/health
GET /_cat/nodes?v
GET /_cat/shards?v
GET /_cluster/allocation/explain
GET /_nodes/stats/jvm,fs,thread_pool
| 现象 | 检查方向 |
|---|---|
| yellow | 单节点副本、节点数量、分配规则与磁盘水位 |
| red | 未分配主分片、丢失磁盘、allocation explain 与恢复方案 |
| 写入被拒绝 | 磁盘 flood-stage、线程池、mapping、权限和写入压力 |
| 查询慢 | 查询 profile、分片数、慢日志、堆/GC、磁盘与聚合字段 |
| 插件启动失败 | Elasticsearch 与插件版本、全节点一致性、安装来源 |
| TLS 失败 | CA、SAN、有效期、客户端协议和认证配置 |
不要通过关闭证书校验、强制分配陈旧主分片或删除数据目录处理普通故障;这些动作可能丢数据,需明确恢复边界和业务批准。
评论