Elasticsearch 集群不适用于 Docker Swarm

Posted

技术标签:

【中文标题】Elasticsearch 集群不适用于 Docker Swarm【英文标题】:Elasticsearch cluster doesn't work on Docker Swarm 【发布时间】:2022-01-05 12:29:22 【问题描述】:

当与docker compose 命令一起使用时,下面的 docker-compose YAML 文件会启动一个 3 节点 Elasticsearch 集群。这对于调试来说没问题,但我想转向部署,所以我想部署在一个容器可以在不同系统上运行的集群上。

所以

docker compose up

有效,但是

docker stack deploy -c docker-compose.yml p3es

创建相同的容器(尽管在不同的系统上)和覆盖网络,但是 elasticsearch 实例无法通过端口 9300 相互通信。因此,master 永远不会被分配,尽管 elasticsearch 响应 HTTP 请求,但它们只是出错出去。

在日志中,每个容器上都会出现以下异常/堆栈跟踪:

p3es_es01.1.sv26uqp4i4s3@carbon    | "stacktrace": ["org.elasticsearch.transport.RemoteTransportException: [es03][10.0.12.9:9300][internal:cluster/coordination/join]",
p3es_es01.1.sv26uqp4i4s3@carbon    | "Caused by: org.elasticsearch.transport.ConnectTransportException: [es01][10.0.0.53:9300] connect_exception",
(etc)

异常的原因原来是:

p3es_es01.1.sv26uqp4i4s3@carbon    | "Caused by: java.io.IOException: connection timed out: 10.0.0.53/10.0.0.53:9300",

以下是我尝试过的一些方法:

    我在其中一个容器上调用了一个 shell。我可以 ping 其他每个容器。我还可以对每个容器执行curl -XGET 并从端口 9200 获得响应。 如果我在其中一个容器的端口 9300 上执行 curl -XGET,我会收到“不是 HTTP 端口”消息。但至少它能够解析地址。 Docker 堆栈喜欢为对象的名称添加前缀。因此,如果您将网络命名为 xyz,该网络实际上会被命名为 project_xyz。所以我改变了环境变量,告诉elasticsearch谁是集群的一部分,包括项目名称前缀。不走运。

我的想法已经用完了。有什么建议吗?

version: '3.9'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    environment:
      - HOSTNAME=es01
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    networks:
      - es9300
    volumes:
      - nfs-es01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    environment:
      - HOSTNAME=es02
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    networks:
      - es9300
    volumes:
      - nfs-es02:/usr/share/elasticsearch/data
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.5.2
    environment:
      - HOSTNAME=es03
      - node.name=es03
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    networks:
      - es9300
    volumes:
      - nfs-es03:/usr/share/elasticsearch/data

volumes:
  nfs-es01:
    driver_opts:
      type: nfs
      o: addr=10.2.0.1,rw,nfsvers=4,local_lock=all
      device: :/sbn/process3/elasticsearch01
  nfs-es02:
    driver_opts:
      type: nfs
      o: addr=10.2.0.1,rw,nfsvers=4,local_lock=all
      device: :/sbn/process3/elasticsearch02
  nfs-es03:
    driver_opts:
      type: nfs
      o: addr=10.2.0.1,rw,nfsvers=4,local_lock=all
      device: :/sbn/process3/elasticsearch03

networks:
  es9300:
    driver: overlay
    attachable: true

【问题讨论】:

【参考方案1】:

事实证明,当 Docker 为其提供多个覆盖网络时,Elasticsearch 会感到困惑。所以指令:

ports:
  - 9200:9200

使 Docker 在指定的覆盖网络之外提供一个覆盖网络(在本例中为 es9300)。由于某种原因,当 Elasticsearch 在容器中运行时,它在解析服务/DNS“es01”时获取了错误的 IP 地址。

我还没有确定为什么会这样,但是删除 ports 指令以发布端口 9200 可以解决问题。

希望这篇文章能帮助遇到同样问题的人。

【讨论】:

以上是关于Elasticsearch 集群不适用于 Docker Swarm的主要内容,如果未能解决你的问题,请参考以下文章

使用docker方式运行elasticsearch-head

Spring Data REST 似乎不适用于 elasticsearch

ElasticSearch 索引适用于 REST API,但不适用于 C# 代码

nginx 的 gitlab 容器代理传递不适用于推送请求

Spring Cloud Config Server 不适用于 Docker 构建

ElasticSearch ElasticSearch集群