Elasticsearch

Elasticsearch 核心概念与版本 Elasticsearch 是基于 Lucene 的分布式搜索与分析引擎。Index 保存一类文档,Mapping 定义字段类型,Shard 是分布式存储与查询单元,Replica 提供副本及读取扩展。 文档写入成功不代表立即可被搜索,搜索可见性受 ref

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、有效期、客户端协议和认证配置

不要通过关闭证书校验、强制分配陈旧主分片或删除数据目录处理普通故障;这些动作可能丢数据,需明确恢复边界和业务批准。

评论