You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Elasticsearch集群Compose部署正常但Swarm stack部署报master_not_discovered_exception

问题原因
  • Swarm 服务发现模式不兼容:Docker Swarm 中 overlay 网络默认的 endpoint 模式为 vip(虚拟IP负载均衡),你配置的 discovery.seed_hosts=es02,es03 解析后得到的是服务的负载均衡 VIP,而非单个 ES 容器的实际地址,ES 节点间无法正确识别对等节点身份,无法完成主节点选举,因此抛出 master_not_discovered_exception 异常。
  • 网络配置冲突:你将 elastic 网络设置为 internal: true(仅允许集群内服务互访,禁止对外通信),但同时给 es01 配置了 9200 端口的宿主机映射,该配置会冲突导致端口映射失效,也会间接影响跨节点的容器互访。
  • 缺少必要的系统配置与资源限制:ES 要求宿主机内核参数 vm.max_map_count 不低于 262144,Swarm 集群所有工作节点都需要提前配置该参数,否则 ES 容器会启动失败,无法凑够选举主节点的法定人数。另外配置缺失 ulimit 限制,ES 运行需要足够的文件描述符权限,Swarm 部署时默认的 ulimit 阈值无法满足 ES 运行要求。
  • 无调度约束:默认情况下 Swarm 可能将多个 ES 实例调度到同一个物理节点,本地存储卷、资源不足等问题都会导致 ES 实例启动失败。
修复方案
  1. 前置操作:在 Swarm 集群的所有工作节点执行以下命令配置内核参数,永久生效需要写入 /etc/sysctl.conf:
sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
  1. 修改 Docker Compose 配置,核心调整点如下:
  • 所有 ES 服务新增 endpoint_mode: dnsrr,使用 DNS 轮询模式替代默认 VIP 模式,服务名解析直接返回所有后端容器 IP
  • 移除 elastic 网络的 internal: true 配置(如果需要严格隔离可额外新增一张非 internal 网络用于暴露端口)
  • 给 ES 服务新增 ulimit 配置,满足 ES 运行的文件描述符要求
  • 新增部署调度约束,保证每个 ES 实例调度到不同的 Swarm 节点

修改后的完整配置如下:

version: '3.4'

services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
    hostname: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65535
        hard: 65535
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
    deploy:
      mode: replicated
      replicas: 1
      endpoint_mode: dnsrr
      placement:
        constraints:
          - node.labels.es_node == true # 可提前给Swarm节点打标签,也可替换为其他约束规则

  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
    hostname: es02
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65535
        hard: 65535
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
    deploy:
      mode: replicated
      replicas: 1
      endpoint_mode: dnsrr
      placement:
        constraints:
          - node.labels.es_node == true

  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.15.2
    hostname: es03
    environment:
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
      nofile:
        soft: 65535
        hard: 65535
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic
    deploy:
      mode: replicated
      replicas: 1
      endpoint_mode: dnsrr
      placement:
        constraints:
          - node.labels.es_node == true

  kib01:
    image: docker.elastic.co/kibana/kibana:7.15.2
    hostname: kib01
    ports:
      - 5601:5601
    environment:
      ELASTICSEARCH_URL: http://es01:9200
      ELASTICSEARCH_HOSTS: '["http://es01:9200","http://es02:9200","http://es03:9200"]'
    networks:
      - elastic
    deploy:
      replicas: 1

volumes:
  data01:
    driver: local
  data02:
    driver: local
  data03:
    driver: local

networks:
  elastic:
    driver: overlay
  1. 集群首次启动正常后,后续更新或重启部署时,需要删除所有 ES 服务的 cluster.initial_master_nodes 环境变量,避免重复执行初始化逻辑导致集群脑裂。

内容的提问来源于stack exchange,提问作者Ravi Soni

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 20:54:07