尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

基于Docker Compose构建高可用Elasticsearch集群:从零到生产级部署指南

基于Docker Compose构建高可用Elasticsearch集群:从零到生产级部署指南 1. 引言随着微服务架构、云原生和可观测性理念的普及Elasticsearch 作为一款分布式搜索和分析引擎已经成为日志分析、全文检索、安全监控等场景的核心基础设施。然而在生产环境中手把手搭建一个高可用的 Elasticsearch 集群并非易事需要考虑网络配置、节点角色划分、安全认证、持久化存储、性能调优等诸多细节。Docker Compose 作为一种声明式的容器编排工具可以大幅简化多容器应用的部署流程。通过一份 YAML 文件我们就能将多个 Elasticsearch 节点、Kibana、Logstash 以及其他监控组件统一编排实现快速部署和横向扩展。本指南将深入剖析如何基于 Docker Compose 构建一个具备高可用特性的 Elasticsearch 集群从零开始逐步走向生产级部署覆盖架构设计、配置文件编写、安全加固、性能优化以及运维监控等全部环节力求以超过两万字的篇幅为读者提供一份真正可落地的实践手册。2. 背景与需求分析2.1 为什么选择 ElasticsearchElasticsearch 基于 Apache Lucene 构建提供了近乎实时的搜索和分析能力。其分布式架构天然支持水平扩展通过分片和副本机制保障了数据的高可用性和容错性。在日志分析、应用性能监控、商品搜索、安全事件管理等众多领域Elastic Stack 已经形成了完整的解决方案。选择 Elasticsearch 作为核心数据引擎意味着可以同时享受全文搜索、聚合分析、时序数据处理等多种能力。2.2 高可用集群的核心诉求一个生产级别的高可用 Elasticsearch 集群通常需要满足以下要求无单点故障剔除任意单个节点后集群仍能正常提供读写服务。这要求至少三个主节点资格节点master-eligible node并且数据节点需配置副本。节点角色隔离为了平衡资源利用率和稳定性生产集群往往会将节点分为主节点专用 master、数据节点data、协调节点coordinating、采集节点ingest以及机器学习节点ml等避免混用带来的性能争抢。安全通信节点间通信和客户端与集群的通信均启用 TLS 加密并配合 RBAC 用户认证体系防止未授权访问。数据持久化与备份使用主机卷或网络存储卷确保数据不因容器消亡而丢失并制定快照备份策略以应对灾难恢复。监控与告警集成 Metricbeat、Filebeat 等组件搭建集群性能指标和日志的采集、可视化与告警通道。2.3 Docker Compose 的优势与局限使用 Docker Compose 管理 Elasticsearch 集群的优势在于环境一致性YAML 文件定义的服务、网络、卷可确保开发、测试和生产环境的高度一致。快速部署一条docker-compose up -d即可启动整个集群无需手动配置每台机器。可重复性任何团队成员都能通过版本控制获取 compose 文件并快速复现集群。但 Compose 本身也有局限性它默认运行在单台 Docker 主机上无法直接编排跨主机的容器。如果要在多台物理机或虚拟机上实现真正的高可用还需要配合 Docker Swarm 或 Kubernetes或者使用 Docker Compose 同时定义多个主机上的服务但实际部署时需要人工干预。不过在单台高配服务器上通过 Compose 模拟多节点高可用集群依然极具学习和测试价值而且只要底层存储和网络妥善配置同样能够应对中小规模的生产负载。本指南将以单机模拟多节点为起点同时给出扩展至多主机的思路。3. 环境准备3.1 硬件与操作系统要求为了运行一个包含三个 Elasticsearch 节点、一个 Kibana 节点以及其他辅助组件的集群推荐以下最低配置CPU至少 4 核建议 8 核及以上。内存至少 16 GBElasticsearch 堆内存默认占系统内存的一半但容器环境中需要额外留出空间。存储建议 SSD数据目录至少 100 GB 可用空间。操作系统Linux 发行版Ubuntu 20.04/22.04、CentOS 7/8 等。本文以 Ubuntu 22.04 为例。3.2 软件依赖安装首先确保系统已安装 Docker 和 Docker Compose。推荐使用 Docker Engine 23 和 Docker Compose v2 版本。# 更新软件包索引 sudo apt update # 安装依赖 sudo apt install -y apt-transport-https ca-certificates curl software-properties-common # 添加 Docker 官方 GPG 密钥 curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg # 添加 Docker 仓库 echo deb [archamd64 signed-by/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable | sudo tee /etc/apt/sources.list.d/docker.list /dev/null sudo apt update # 安装 Docker sudo apt install -y docker-ce docker-ce-cli containerd.io # 安装 Docker Compose Plugin sudo apt install -y docker-compose-plugin # 验证 docker --version docker compose version确保当前用户已被加入docker组避免每次都需要sudosudo usermod -aG docker $USER # 重新登录使生效3.3 调整系统参数Elasticsearch 在生产环境中需要调整一些内核参数例如vm.max_map_count。这些参数可以通过/etc/sysctl.conf永久设置echo vm.max_map_count262144 | sudo tee -a /etc/sysctl.conf sudo sysctl -p此外为了提高文件描述符限制可以在/etc/security/limits.conf中添加* soft nofile 65536 * hard nofile 65536 * soft memlock unlimited * hard memlock unlimited4. Elasticsearch 集群核心概念4.1 节点角色在 Elasticsearch 中节点可以承担多种角色。通过配置文件中的node.roles可以精确控制。常见的角色包括master具备被选举为主节点的资格负责集群状态管理和索引元数据操作。生产环境建议专用不处理读写请求。data存储数据并执行数据相关操作CRUD、搜索、聚合。可细分为data_content、data_hot、data_warm、data_cold、data_frozen等层级。ingest在索引文档之前进行预处理例如解析 JSON、字段改写等。ml机器学习节点运行异常检测、数据帧分析等作业。remote_cluster_client允许该节点连接远程集群。transform执行转换任务。voting_only仅参与主节点选举投票不能被选为主节点适合降低集群压力。coordinating如果不设置任何角色节点就充当协调节点负责路由请求但不存储数据可分担搜索负载。在生产级部署中我们通常会这样划分节点名称角色说明es-master01, es-master02, es-master03master专用于集群管理不存储数据es-data01, es-data02, es-data03data_hot, data_content存储热数据和处理读写es-coordinating01无专用协调协调节点可对外提供服务并聚合结果这套划分能够有效隔离主节点的压力保障集群稳定性。4.2 集群发现与选举Elasticsearch 集群使用基于 zen discovery 的机制通过单播列表discovery.seed_hosts互相发现并组成集群。在初始化时具备 master 资格的节点之间会通过 Bully 改进算法选举出主节点。为了保证在网络分区情况下仍能正常工作需要设置cluster.initial_master_nodes或discovery.seed_hosts并满足法定数量discovery.zen.minimum_master_nodes在 7.x 后由集群内部自动处理但需要明确初始主节点列表。对于 Docker Compose 环境由于节点通常位于同一个自定义网络中可以通过服务名发现彼此。需要在每个节点的配置文件中填入其他节点的服务名或 IP。4.3 分片与副本索引被分割成多个分片shard每个分片可以有一个或多个副本replica。分片数量在建索引时指定后续无法直接修改可通过 reindex 调整。副本则可以在运行时动态调整。副本提供了数据冗余和高可用性同时也能提升查询吞吐量。在生产集群中建议至少设置一个副本这样即使单个节点宕机数据也不会丢失服务不受影响。5. Docker Compose 编排基础5.1 Compose 文件结构Docker Compose v2 的 YAML 文件通常包含version、services、networks、volumes等顶级元素。对于 Elasticsearch 集群我们需要定义多个服务并为每个服务挂载数据卷、暴露端口、设置环境变量或绑定配置文件。version: 3.8 services: es-master01: image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0 container_name: es-master01 environment: - node.namees-master01 - cluster.namees-docker-cluster - discovery.seed_hostses-master02,es-master03,es-data01,es-data02,es-data03 - cluster.initial_master_nodeses-master01,es-master02,es-master03 - bootstrap.memory_locktrue - ES_JAVA_OPTS-Xms512m -Xmx512m ulimits: memlock: soft: -1 hard: -1 volumes: - data01:/usr/share/elasticsearch/data - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro networks: - esnet ports: - 9200:9200 volumes: data01: networks: esnet: driver: bridge这是一个最简示例。后续章节我们将基于此模板逐步完善。5.2 自定义网络与 DNS通过定义自定义桥接网络esnet所有容器都可以通过服务名进行相互访问无需关心 IP 地址。这为节点发现带来了极大的便利。Elasticsearch 的discovery.seed_hosts可以直接使用服务名如“es-master01”、“es-data02”。5.3 卷与数据持久化Elasticsearch 的数据必须持久化到宿主机否则容器重建后数据将丢失。Compose 中的volumes可以声明为命名卷或绑定挂载。对于生产环境建议使用绑定挂载到物理磁盘的指定路径这样更有利于管理和备份。示例volumes: - /data/es/data01:/usr/share/elasticsearch/data同时要确保目录的权限允许 elasticsearch 用户写入容器内 uid:gid 为 1000:0。6. 单节点快速部署在深入高可用集群之前我们先通过一个单节点示例快速体验 Elasticsearch 的启动过程并验证环境正确性。同时这也能让我们熟悉 Compose 文件的编写和调试。6.1 准备配置文件创建项目目录es-cluster并新建docker-compose-single.ymlversion: 3.8 services: es-single: image: docker.elastic.co/elasticsearch/elasticsearch:8.11.0 container_name: es-single environment: - node.namees-single - cluster.namees-single-cluster - discovery.typesingle-node - bootstrap.memory_locktrue - ES_JAVA_OPTS-Xms512m -Xmx512m - xpack.security.enabledfalse ulimits: memlock: soft: -1 hard: -1 volumes: - esdata:/usr/share/elasticsearch/data ports: - 9200:9200 networks: - esnet volumes: esdata: networks: esnet: driver: bridge这里设置了discovery.typesingle-node表示单节点模式无需选主。为了简化暂时禁用安全特性xpack.security.enabledfalse。6.2 启动并验证cd es-cluster docker compose -f docker-compose-single.yml up -d # 查看日志 docker logs es-single # 等待健康后发送测试请求 curl http://localhost:9200/如果返回类似下面的 JSON说明单节点运行成功{ name : es-single, cluster_name : es-single-cluster, cluster_uuid : ..., version : { ... } }6.3 清理环境docker compose -f docker-compose-single.yml down -v7. 多节点高可用集群部署接下来是本指南的核心部分构建一个具备高可用特性的多节点 Elasticsearch 集群。我们将采用角色分离的设计部署三个主节点、三个数据热节点和一个协调节点并启用安全认证。7.1 架构设计集群拓扑如下服务名角色堆内存宿主机端口es-master01master512m不对外es-master02master512mes-master03master512mes-data01data_hot,data_content2g9201可选es-data02data_hot,data_content2g9202es-data03data_hot,data_content2g9203es-coordinating无1g9200对外入口所有节点共用一个esnet网络。协调节点作为外部客户端访问的统一入口负责分发查询和聚合结果。数据节点之间通过副本保持数据冗余。三个主节点形成仲裁保证在主节点宕机时能重新选举。7.2 目录结构规划es-cluster/ ├── docker-compose.yml ├── .env ├── config/ │ ├── elasticsearch.yml # 通用模板 │ ├── master01.yml │ ├── master02.yml │ ├── master03.yml │ ├── data01.yml │ ├── data02.yml │ ├── data03.yml │ └── coordinating.yml ├── data/ │ ├── master01/ │ ├── master02/ │ ├── master03/ │ ├── data01/ │ ├── data02/ │ ├── data03/ │ └── coordinating/ └── certs/ # 存放证书后续生成7.3 编写通用配置文件我们使用统一的config/elasticsearch.yml作为基础配置每个节点的个性化配置通过额外的配置文件覆盖放在config.d/目录或直接指定。Elasticsearch 会按字典序加载config.d/下的所有文件。基础配置如下文件config/elasticsearch.ymlcluster.name: es-docker-cluster network.host: 0.0.0.0 bootstrap.memory_lock: true discovery.seed_hosts: - es-master01 - es-master02 - es-master03 - es-data01 - es-data02 - es-data03 cluster.initial_master_nodes: - es-master01 - es-master02 - es-master03 xpack.security.enabled: true xpack.security.transport.ssl.enabled: true xpack.security.transport.ssl.verification_mode: certificate xpack.security.transport.ssl.keystore.path: certs/elastic-stack.p12 xpack.security.transport.ssl.truststore.path: certs/elastic-stack.p12 xpack.security.http.ssl.enabled: true xpack.security.http.ssl.keystore.path: certs/http.p12 xpack.security.http.ssl.truststore.path: certs/http.p12 # 开启审计日志可选 xpack.security.audit.enabled: true注意这些证书路径将在后面步骤中通过elasticsearch-certutil生成并挂载到容器。7.4 各节点角色配置文件在config/目录下为不同节点创建角色配置文件例如master01.ymlnode.name: es-master01 node.roles: [ master ] path.data: /usr/share/elasticsearch/data/master01 path.logs: /usr/share/elasticsearch/logsdata01.ymlnode.name: es-data01 node.roles: [ data_hot, data_content ] path.data: /usr/share/elasticsearch/data/data01 path.logs: /usr/share/elasticsearch/logs协调节点coordinating.yml可以省略node.roles即无角色默认为协调节点。为了让每个容器加载特定的文件我们可以在容器内创建/usr/share/elasticsearch/config/config.d/目录并将对应的.yml文件映射进去。或者直接在环境变量中指定但更推荐使用配置文件方式。7.5 编写 Docker Compose 文件我们将所有服务定义在docker-compose.yml中。为了简化可以利用 YAML 的锚点特性重用公共配置。下面给出完整示例version: 3.8 x-logging: logging driver: json-file options: max-size: 10m max-file: 3 x-ulimits: ulimits memlock: soft: -1 hard: -1 nofile: soft: 65536 hard: 65536 services: es-master01: image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} container_name: es-master01 hostname: es-master01 environment: - node.namees-master01 - ES_JAVA_OPTS-Xms512m -Xmx512m ulimits: *ulimits volumes: - ./data/master01:/usr/share/elasticsearch/data/master01 - ./logs/master01:/usr/share/elasticsearch/logs - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - ./config/master01.yml:/usr/share/elasticsearch/config/config.d/master01.yml:ro - ./certs:/usr/share/elasticsearch/config/certs:ro networks: - esnet logging: *logging restart: unless-stopped es-master02: image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} container_name: es-master02 hostname: es-master02 environment: - node.namees-master02 - ES_JAVA_OPTS-Xms512m -Xmx512m ulimits: *ulimits volumes: - ./data/master02:/usr/share/elasticsearch/data/master02 - ./logs/master02:/usr/share/elasticsearch/logs - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - ./config/master02.yml:/usr/share/elasticsearch/config/config.d/master02.yml:ro - ./certs:/usr/share/elasticsearch/config/certs:ro networks: - esnet logging: *logging restart: unless-stopped es-master03: image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} container_name: es-master03 hostname: es-master03 environment: - node.namees-master03 - ES_JAVA_OPTS-Xms512m -Xmx512m ulimits: *ulimits volumes: - ./data/master03:/usr/share/elasticsearch/data/master03 - ./logs/master03:/usr/share/elasticsearch/logs - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - ./config/master03.yml:/usr/share/elasticsearch/config/config.d/master03.yml:ro - ./certs:/usr/share/elasticsearch/config/certs:ro networks: - esnet logging: *logging restart: unless-stopped es-data01: image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} container_name: es-data01 hostname: es-data01 environment: - node.namees-data01 - ES_JAVA_OPTS-Xms2g -Xmx2g ulimits: *ulimits volumes: - ./data/data01:/usr/share/elasticsearch/data/data01 - ./logs/data01:/usr/share/elasticsearch/logs - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - ./config/data01.yml:/usr/share/elasticsearch/config/config.d/data01.yml:ro - ./certs:/usr/share/elasticsearch/config/certs:ro networks: - esnet logging: *logging restart: unless-stopped es-data02: image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} container_name: es-data02 hostname: es-data02 environment: - node.namees-data02 - ES_JAVA_OPTS-Xms2g -Xmx2g ulimits: *ulimits volumes: - ./data/data02:/usr/share/elasticsearch/data/data02 - ./logs/data02:/usr/share/elasticsearch/logs - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - ./config/data02.yml:/usr/share/elasticsearch/config/config.d/data02.yml:ro - ./certs:/usr/share/elasticsearch/config/certs:ro networks: - esnet logging: *logging restart: unless-stopped es-data03: image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} container_name: es-data03 hostname: es-data03 environment: - node.namees-data03 - ES_JAVA_OPTS-Xms2g -Xmx2g ulimits: *ulimits volumes: - ./data/data03:/usr/share/elasticsearch/data/data03 - ./logs/data03:/usr/share/elasticsearch/logs - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - ./config/data03.yml:/usr/share/elasticsearch/config/config.d/data03.yml:ro - ./certs:/usr/share/elasticsearch/config/certs:ro networks: - esnet logging: *logging restart: unless-stopped es-coordinating: image: docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} container_name: es-coordinating hostname: es-coordinating environment: - node.namees-coordinating - ES_JAVA_OPTS-Xms1g -Xmx1g ulimits: *ulimits volumes: - ./data/coordinating:/usr/share/elasticsearch/data/coordinating - ./logs/coordinating:/usr/share/elasticsearch/logs - ./config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml:ro - ./config/coordinating.yml:/usr/share/elasticsearch/config/config.d/coordinating.yml:ro - ./certs:/usr/share/elasticsearch/config/certs:ro networks: - esnet ports: - 9200:9200 logging: *logging restart: unless-stopped volumes: 不使用命名卷全部绑定挂载 networks: esnet: driver: bridge ipam: config: - subnet: 172.23.0.0/16在上述 compose 文件中我们使用了${ES_VERSION}环境变量通过同级目录下的.env文件设置例如ES_VERSION8.11.0这种方式方便统一升级 Elasticsearch 版本。7.6 生成 TLS 证书由于我们启用了 X-Pack Security 的传输层和 HTTP 层加密需要提前生成证书。可以使用 Elasticsearch 自带的elasticsearch-certutil工具在容器内生成然后将证书文件复制到宿主机的certs/目录。具体步骤# 启动一个临时容器用于生成证书 docker run --rm -it -v $(pwd)/certs:/certs docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} bash # 进入容器后执行 cd /usr/share/elasticsearch bin/elasticsearch-certutil cert --out /certs/elastic-stack.p12 --pass # 提示输入密码时直接回车生成无密码的 PKCS#12 文件。 bin/elasticsearch-certutil http # 这里会启动交互式向导我们按需回答最终生成 http.p12 并复制到 /certs。 # 由于交互较为繁琐下面提供手动一次性方法实际上对于开发环境我们可以使用更简单的方式只需一个elastic-stack.p12作为传输层证书且不设置密码。对于 HTTP 层也可以复用同一个证书但为了规范建议分开。我们提供一个完整脚本generate-certs.sh#!/bin/bash CERT_DIR./certs mkdir -p ${CERT_DIR} docker run --rm -v ${CERT_DIR}:/certs docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} \ bin/elasticsearch-certutil ca --out /certs/elastic-stack-ca.p12 --pass # 生成传输层证书节点间通信 docker run --rm -v ${CERT_DIR}:/certs docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} \ bin/elasticsearch-certutil cert --ca /certs/elastic-stack-ca.p12 --out /certs/elastic-stack.p12 --pass # 生成 HTTP 层证书面向客户端 docker run --rm -v ${CERT_DIR}:/certs docker.elastic.co/elasticsearch/elasticsearch:${ES_VERSION} \ bin/elasticsearch-certutil http --generate执行后会生成http.p12等相关文件。确保所有文件都位于./certs目录且容器内映射为/usr/share/elasticsearch/config/certs/。7.7 启动集群在项目根目录下执行docker compose up -d查看节点日志确认所有节点依次加入集群docker logs -f es-master01 # 观察是否出现 master not discovered yet 到 elected as master 的过程。 docker logs es-data01 | grep -i cluster若一切正常通过协调节点的 HTTPS 端点测试# 由于启用了 https 且自签名证书需要 -k 参数 curl -k -u elastic:changeme https://localhost:9200/注意首次启动后需使用elastic内置超级用户登录密码默认为changeme。可以通过bin/elasticsearch-setup-passwords工具修改密码稍后介绍。7.8 集群状态验证curl -k -u elastic:changeme https://localhost:9200/_cat/nodes?v curl -k -u elastic:changeme https://localhost:9200/_cluster/health?pretty健康状态显示为green表示所有主分片和副本都已分配完毕。如果出现yellow检查是否有副本未分配可通过增加数据节点或调整副本数解决。8. 安全配置深入8.1 内置用户与密码管理Elasticsearch 从 8.x 开始默认启用安全功能。除了elastic超级用户外还内置了kibana_system、logstash_system、beats_system等用于服务间通信的账户。可以通过以下方式设置这些用户的密码# 进入任意一个容器内 docker exec -it es-coordinating bash # 执行密码设置工具 bin/elasticsearch-reset-password -u elastic --interactive --url https://localhost:9200 # 按提示输入新密码 # 对于系统用户可以批量自动生成随机密码 bin/elasticsearch-reset-password -u kibana_system -i --url https://localhost:9200我们也可以用elasticsearch-setup-passwords工具但该命令在 8.x 中已被reset-password替代。8.2 创建自定义角色和用户生产环境中我们不应该只使用elastic超级用户。可以通过 API 创建限定的角色和用户。例如创建一个仅对nginx-logs-*索引具有读写权限的日志采集角色curl -k -X POST -u elastic:yourpassword https://localhost:9200/_security/role/logstash_writer \ -H Content-Type: application/json -d { cluster: [monitor, manage_ilm], indices: [ { names: [nginx-logs-*], privileges: [create_index, index, write, read, manage] } ] }然后创建用户并赋予该角色curl -k -X POST -u elastic:yourpassword https://localhost:9200/_security/user/logstash_user \ -H Content-Type: application/json -d { password: logstash_password, roles: [logstash_writer], full_name: Logstash User }8.3 启用 API Key 认证对于微服务之间的访问API Key 是一种比账户密码更灵活的方式。可以基于角色创建 API Key 并设置过期时间curl -k -X POST -u elastic:yourpassword https://localhost:9200/_security/api_key \ -H Content-Type: application/json -d { name: my-app-key, role_descriptors: { my-app-role: { cluster: [monitor], indices: [{ names: [app-logs-*], privileges: [read, write] }] } } }9. 性能调优与系统参数调整9.1 JVM 堆内存设置Elasticsearch 严重依赖 JVM 堆内存一般推荐设置为物理内存的 50%但不要超过 32 GB受压缩普通对象指针影响。对于数据节点堆内存更大有助于缓存但需要留意ES_JAVA_OPTS中的-Xms和-Xmx必须相等避免运行时调整。在 compose 文件中我们通过环境变量设置environment: - ES_JAVA_OPTS-Xms2g -Xmx2g9.2 禁用 swap为了保证性能应禁止 Elasticsearch 使用 swap 内存。容器内通过bootstrap.memory_locktrue锁定物理内存。同时需要在系统层面和 compose 文件中设置ulimits中的memlock: -1:-1并确保宿主机有足够的物理内存。9.3 线程池调优Elasticsearch 内部使用多种线程池处理不同类型的操作。默认情况下线程池大小与 CPU 核心数相关。在 CPU 密集或高并发场景下可以适当调整搜索、写入等线程池。例如在config/elasticsearch.yml中添加thread_pool.search.queue_size: 2000 thread_pool.write.queue_size: 1000注意调整前需评估负载避免过度排队。9.4 索引级性能优化在创建索引时可以指定分片数、副本数、刷新间隔等参数。对于日志类时序数据建议采用rollover和 ILM索引生命周期管理自动管理。创建索引模板示例curl -k -X PUT -u elastic:password https://localhost:9200/_index_template/logs_template \ -H Content-Type: application/json -d { index_patterns: [logs-*], template: { settings: { number_of_shards: 3, number_of_replicas: 1, refresh_interval: 5s } } }10. Kibana 集成部署Kibana 是 Elastic Stack 的可视化界面。我们将其作为另一个服务加入 Compose 中。10.1 添加 Kibana 服务在docker-compose.yml中添加services: kibana: image: docker.elastic.co/kibana/kibana:${ES_VERSION} container_name: kibana hostname: kibana environment: - SERVER_NAMEkibana.example.com - ELASTICSEARCH_HOSTS[https://es-coordinating:9200] - ELASTICSEARCH_USERNAMEkibana_system - ELASTICSEARCH_PASSWORD${KIBANA_PASSWORD} - XPACK_SECURITY_ENABLEDtrue - XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY${KIBANA_ENCRYPTION_KEY} volumes: - ./config/kibana.yml:/usr/share/kibana/config/kibana.yml:ro - ./certs:/usr/share/kibana/config/certs:ro ports: - 5601:5601 networks: - esnet logging: *logging restart: unless-stopped需要先在.env文件中设置 Kibana 的密码和加密密钥至少 32 个字符KIBANA_PASSWORDyour_kibana_system_password KIBANA_ENCRYPTION_KEY$(openssl rand -hex 32)Kibana 配置文件config/kibana.yml可以简化为空因为大部分通过环境变量设置。但为了安全我们可以手动指定elasticsearch.ssl.certificateAuthorities等。10.2 启动与访问docker compose up -d kibana # 观察日志 docker logs kibana访问http://your-ip:5601使用elastic用户登录即可查看 Dashboard、Discover 等界面。11. 日志收集与监控完备的生产环境离不开日志收集和集群监控。我们可以将 Filebeat、Metricbeat、Logstash 等也纳入 Compose 编排。11.1 Filebeat 收集 Docker 日志部署 Filebeat 读取宿主机 Docker 容器的 stdout/stderr 日志并发送到 Elasticsearchfilebeat: image: docker.elastic.co/beats/filebeat:${ES_VERSION} container_name: filebeat user: root volumes: - ./config/filebeat.yml:/usr/share/filebeat/filebeat.yml:ro - /var/lib/docker/containers:/var/lib/docker/containers:ro - /var/run/docker.sock:/var/run/docker.sock - ./certs:/usr/share/filebeat/certs:ro networks: - esnet logging: *logging restart: unless-stopped对应的filebeat.ymlfilebeat.inputs: - type: container paths: - /var/lib/docker/containers/*/*.log output.elasticsearch: hosts: [https://es-coordinating:9200] username: elastic password: ${ES_PASSWORD} ssl.certificate_authorities: [/usr/share/filebeat/certs/http_ca.crt] index: filebeat-%{[agent.version]}-%{yyyy.MM.dd}11.2 Metricbeat 监控集群指标Metricbeat 可以采集 Elasticsearch 集群的节点状态、索引性能等指标。部署方式类似metricbeat: image: docker.elastic.co/beats/metricbeat:${ES_VERSION} container_name: metricbeat user: root volumes: - ./config/metricbeat.yml:/usr/share/metricbeat/metricbeat.yml:ro - /var/run/docker.sock:/var/run/docker.sock - ./certs:/usr/share/metricbeat/certs:ro networks: - esnet logging: *logging restart: unless-stopped而在metricbeat.yml中启用 Elasticsearch 模块metricbeat.modules: - module: elasticsearch metricsets: [node, node_stats, cluster_stats, index] period: 10s hosts: [https://es-coordinating:9200] username: elastic password: ${ES_PASSWORD} ssl.certificate_authorities: [/usr/share/metricbeat/certs/http_ca.crt] output.elasticsearch: hosts: [https://es-coordinating:9200] username: elastic password: ${ES_PASSWORD} ssl.certificate_authorities: [/usr/share/metricbeat/certs/http_ca.crt]11.3 使用 Kibana 仪表板启动这些 Beats 后数据会自动写入 Elasticsearch。在 Kibana 中通过 Stack Monitoring 或导入预置的 Elasticsearch 仪表板Setup instructions即可实时观测集群各项指标如 GC 时间、索引速率、搜索延迟等。12. 集群日常运维12.1 索引生命周期管理对于不断增长的日志数据必须实施生命周期管理定期删除或归档旧数据。通过 ILM 策略和索引模板自动执行curl -k -X PUT -u elastic:password https://localhost:9200/_ilm/policy/logs_policy \ -H Content-Type: application/json -d { policy: { phases: { hot: { actions: { rollover: { max_size: 50GB, max_age: 1d } } }, delete: { min_age: 30d, actions: { delete: {} } } } } }并在模板中引用该策略。12.2 快照与备份Elasticsearch 支持将快照存储到共享文件系统或 S3 等。在 Docker 环境中可以挂载一个 NFS 或者本地目录作为快照仓库路径。首先在elasticsearch.yml中注册仓库路径path.repo: [/usr/share/elasticsearch/backups]并在 compose 中挂载备份目录volumes: - ./backups:/usr/share/elasticsearch/backups然后通过 API 创建仓库并执行快照curl -k -X PUT -u elastic:password https://localhost:9200/_snapshot/my_backup \ -H Content-Type: application/json -d { type: fs, settings: { location: my_backup } } # 执行快照 curl -k -X PUT -u elastic:password https://localhost:9200/_snapshot/my_backup/snapshot_1?wait_for_completiontrue12.3 滚动升级使用 Docker Compose 升级 Elasticsearch 版本时可以采用滚动升级策略即逐个停止旧版本容器、替换镜像后启动确保集群健康后再升级下一个。由于 Compose 不具备原生滚动升级功能我们可以手动操作暂停分片分配PUT _cluster/settings {transient:{cluster.routing.allocation.enable:none}}停止一个非主节点更新 compose 中的镜像版本重新启动。等待节点重新加入并恢复分片分配然后对下一个节点重复操作。最后升级主节点注意保持奇数个主节点投票。13. 故障排查与常见问题13.1 节点发现失败症状某个节点启动后一直输出master not discovered。排查步骤检查discovery.seed_hosts是否正确填写了其他节点的服务名且网络可达可通过ping或curl测试。确认cluster.initial_master_nodes包含所有预期主节点名称。检查防火墙或 Docker 网络子网是否正确。13.2 内存锁定失败错误信息memory locking requested for elasticsearch process but memory is not locked。解决方法确认 compose 中设置了ulimits.memlock并且宿主机的/etc/security/limits.conf已正确修改。13.3 证书错误如果出现SSLHandshakeException可能是证书路径不对或证书不被信任。检查挂载路径确保容器内配置文件中的路径与实际一致。在开发环境可暂时设置xpack.security.transport.ssl.verification_mode: none跳过验证但生产环境不推荐。13.4 磁盘空间不足当数据节点磁盘使用率达到 95% 后Elasticsearch 会禁止写入read_only_allow_delete。需要清理磁盘或扩容。可以执行curl -k -X PUT -u elastic:password https://localhost:9200/_cluster/settings \ -H Content-Type: application/json -d { transient: { cluster.routing.allocation.disk.watermark.flood_stage: 99% } }但根治方法是扩容磁盘。14. 生产环境最佳实践14.1 使用专用主机部署虽然本指南采用单机 Docker Compose 模拟多节点但在真正的生产环境中每类节点应部署在独立的物理机或虚拟机上并通过 Docker Swarm 或 Kubernetes 实现跨主机的编排与高可用。Compose 文件可作为 Kubernetes 部署 YAML 的原型。14.2 定期备份与灾难恢复演练制定备份计划并定期测试恢复流程。将快照存储到远程仓库如 S3 或 HDFS确保数据异地容灾。14.3 安全审计与日志监控开启审计日志并收集到专用审计索引便于追溯所有操作。结合 SIEM安全信息和事件管理工具分析异常行为。14.4 使用钉钉/邮件告警利用 Elasticsearch 的 Watcher 或 ElastAlert 来设置磁盘使用率、集群健康状态异常的告警。例如当集群健康为 red 时发送钉钉机器人通知。15. 总结本指南从零开始详细阐述了如何利用 Docker Compose 构建一个高可用、安全加固的 Elasticsearch 集群。从环境准备、节点角色划分、配置文件编写到 TLS 证书生成、安全认证、性能调优再到 Kibana、Filebeat、Metricbeat 的集成以及日常运维和故障排查覆盖了生产级部署的全链路。通过将这些服务声明在同一个 Compose 文件中团队成员可以快速拉起一个完整的 Elastic Stack 环境无论是用于开发测试还是中小规模的生产负载都能满足高可用要求。当然随着业务增长单主机可能无法承载大量数据或请求。此时需要将 Compose 模型扩展到 Docker Swarm 或 Kubernetes 上利用真正的多主机编排能力。但思想是相通的合理的节点角色划分、网络隔离、安全加密、监控告警等原则依然适用。希望本指南能为您的 Elasticsearch 之旅铺平道路让运维工作变得更加轻松有序。
返回列表