---
# System prepended metadata

title: Elasticsearch (七) - 多節點 Cluster 建立搭配 Kibana
tags: [NoSQL, Elasticsearch]

---

# Elasticsearch (七) - 多節點 Cluster 建立搭配 Kibana

在 [Elasticsearch (二) - 快速搭建與 Document 的建立、更新和刪除](https://tienyulin.github.io/elasticsearch-kibana-command-dsl-docker-compose/) 中，我們用 Docker Compose 建立了單節點的 Elasticsearch server 和 Kibana，本篇要來介紹如何用 Docker Compose 建立多節點的 Elasticsearch server 和 Kibana。

在建立前要先提醒一下，官方所提供的文件有許多坑是要注意的，如果對於 Docker Compose 不夠熟就很容易掉進坑裡。尤其是要搭配 Kibana 的地方要多加注意。本篇會以 Elasticsearch 7.8 和 Kibana 7.8 來做範例。

<!-- more -->

## Elasticsearch Cluster
建立多節點的 Elasticsearch cluster 在 [Elasticsearch 官網](https://www.elastic.co/guide/en/elasticsearch/reference/7.8/docker.html#docker-compose-file) 就有提供 docker-compose.yml 的內容，可以直接複製下來使用。如下 : 
```yaml=
version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.8.1
    container_name: es01
    environment:
      - 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
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.8.1
    container_name: es02
    environment:
      - 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
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.8.1
    container_name: es03
    environment:
      - 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
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic

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

networks:
  elastic:
    driver: bridge
```

啟動完成後就可以在瀏覽器輸入 http://localhost:9200 來連接 Elasticsearch。如果 Elasticsearch 正常運作的話，會回傳一個 Json 作為 Response。如下 : 
```json=
{
  "name" : "es01",
  "cluster_name" : "es-docker-cluster",
  "cluster_uuid" : "kVJqK-SgTa2Scab82iL0Og",
  "version" : {
    "number" : "7.8.1",
    "build_flavor" : "default",
    "build_type" : "docker",
    "build_hash" : "b5ca9c58fb664ca8bf9e4057fc229b3396bf3a89",
    "build_date" : "2020-07-21T16:40:44.668009Z",
    "build_snapshot" : false,
    "lucene_version" : "8.5.1",
    "minimum_wire_compatibility_version" : "6.8.0",
    "minimum_index_compatibility_version" : "6.0.0-beta1"
  },
  "tagline" : "You Know, for Search"
}
```

### vm.max_map_count [65530] is too low
啟動過程中如果失敗並且 log 顯示 `max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144]`，這時需要去修改 systcl.conf。作法如下 : 

1. Vim 開啟 sysctl.conf
```bash=
vim /etc/sysctl.conf
```

2. 在最後一行加上
```bash=
vm.max_map_count=262144
```

3. 執行 `sysctl -p` 來重新載入 systcl.conf 的設定，這樣就不需要重新開機。
```bash=
sysctl -p
```

4. 重新啟動 Container

## Elasticsearch Cluster + Kibana
要搭配 Kibana 首先要先知道 Kibana 啟動時會從 `kibana.yml` 中讀取設定的參數，而在 `kibana.yml` 中預設 `elasticsearch.hosts` 是 `http://elasticsearch:9200`。預設值可以參考 [Elasticsearch 官網](https://www.elastic.co/guide/en/kibana/current/docker.html#docker-defaults)。

這個 `http://elasticsearch:9200` 的 `elasticsearch` 是在 docker-compose.yml 中所定義的 Service 名稱，也就是下方範例的第三行這個 Service 所啟動的 Container。kibana 可以直接這樣連線到 elasticsearch 是因為他們在同一個網路環境下，而 Docker-Compose 允許在同一個網路環境下的 Container 可以直接以其他 Container 的 Service 名稱作為 Domain 來進行連線，這樣就不需要自己設定 Domain。

所以 Elasticsearch 官方提供的建立 Elasticsearch cluster 和 Kibana 的兩個 docker-compose.yml 不能直接合併，要稍做修改才能使用。如果直接合併使用不修改你就會發現 Kibana 一直連不到 `http://elasticsearch:9200`。修改後的 docker-compose.yml 如下 : 
```yaml=
version: '3'
services:
  elasticsearch:
    image: elasticsearch:7.8.1
    container_name: es01
    environment:
      - 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
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  elasticsearch2:
    image: elasticsearch:7.8.1
    container_name: es02
    environment:
      - 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
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
    depends_on: 
     - elasticsearch
  elasticsearch3:
    image: elasticsearch:7.8.1
    container_name: es03
    environment:
      - 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
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic
    depends_on: 
      - elasticsearch
  kibana:
    image: kibana:7.8.1
    container_name: kibana
    ports:  
      - 5601:5601
    networks: 
      - elastic
    depends_on: 
      - elasticsearch

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

networks:
  elastic:
    driver: bridge
```

我們總不可能為了 Kibana 預設連線到 `http://elasticsearch:9200` 就一定要命名一個叫做 elasticsearch 的 Service，所以這裡就要來介紹如何修改預設的連線。

下面的範例將 Elasticsearch 的 docker-compose.yml 做了一下調整，針對三個 es 的 Service 名稱改成 es001、es002、es003。

接著看到 Kibana 的地方，這裡新增了一個環境變數 `ELASTICSEARCH_HOSTS` 並且設定為 `http://es001:9200`。`ELASTICSEARCH_HOSTS` 就是上方提到的 `kibana.yml` 中的參數， `elasticsearch.hosts`，透過環境變數可以直接修改他的值。而這裡將預設的 `http://elasticsearch:9200` 改設定成 `http://es001:9200` 應該就可以理解原因了吧。

這裡特別註明一下，在 Elasticsearch 6 (含) 以前 `elasticsearch.hosts` 是 `elasticsearch.url`，所以要注意一下版本上的問題。
```yaml=
version: '3'
services:
  es001:
    image: elasticsearch:7.8.1
    container_name: es01
    environment:
      - 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
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  es002:
    image: elasticsearch:7.8.1
    container_name: es02
    environment:
      - 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
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
    depends_on: 
     - es001
  es003:
    image: elasticsearch:7.8.1
    container_name: es03
    environment:
      - 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
    volumes:
      - data03:/usr/share/elasticsearch/data
    networks:
      - elastic
    depends_on: 
      - es001
  kibana:
    image: kibana:7.8.1
    container_name: kibana
    ports:  
      - 5601:5601
    networks: 
      - elastic
    environment: 
      - ELASTICSEARCH_HOSTS=http://es001:9200
    depends_on: 
      - es001

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

networks:
  elastic:
    driver: bridge
```

除了上方介紹的改環境變數以外，也可以透過更改 kibana.yml 來達到一樣的目的。詳細 kibana.yml 可以設定哪些參數請參考 [Elasticsearch 官方](https://www.elastic.co/guide/en/kibana/7.8/settings.html)。

## Summary
本篇是因為在嘗試自己建立 Elasticsearch Cluster + Kibana 時發現了很多問題再加上自己對於 Docker Compose 不夠熟練，所以也踩了很多坑。

## 參考
[1] [Install Elasticsearch with Docker](https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html)
[2] [docker運行elasticse容器max virtual memory areas vm.max_map_count [65530] is too low](https://blog.csdn.net/JineD/article/details/107759975?utm_medium=distribute.pc_relevant.none-task-blog-baidulandingword-3&spm=1001.2101.3001.4242)
[3] [如何在docker中部署Elasticsearch叢集和kibana](https://www.itread01.com/content/1545894579.html)
[4] [Day21 - Elasticsearch Cluster](https://ithelp.ithome.com.tw/articles/10188506)
[5] [Docker-Compose 建立 Elasticsearch 與 Kibana 服務](https://kevintsengtw.blogspot.com/2018/07/docker-compose-elasticsearch-kibana.html)
[6] [elasticsearch.hosts or elasticsearch.url are not picked up at all in version 6.7.0](https://github.com/elastic/kibana-docker/issues/140)
[7] [ElasticSearch on Docker](http://john-cd.com/johnscloud/docker/elasticsearch_docker/)
[8] [Kibana Error Connecting to ES on Docker - Cannot Revive Connection](https://discuss.elastic.co/t/kibana-error-connecting-to-es-on-docker-cannot-revive-connection/133335)
[9] [Configure Kibana | Elasticsearch](https://www.elastic.co/guide/en/kibana/7.8/settings.html)
[10] [Install Elasticsearch with docker | Elasticsearch](https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker)
[11] [Kibana is unable to connect to ES](https://discuss.opendistrocommunity.dev/t/kibana-is-unable-to-connect-to-es/185/5)
[12] [Kibana Error Connecting to ElasticSearch using Docker - Cannot Revive Connection](https://stackoverflow.com/questions/50532208/kibana-error-connecting-to-elasticsearch-using-docker-cannot-revive-connection)
[13] [配置 Kibana](https://www.elastic.co/guide/cn/kibana/current/settings.html)
[14] [ElasticSearch詳解（一）](https://blog.51cto.com/hmtk520/2367766)
[15] [[ELK] Elasticsearch 安裝](https://ithelp.ithome.com.tw/articles/10189791)
[16] [Docker上的Kibana無法連接到Elasticsearch](https://www.thinbug.com/q/40341346)
[17] [How to setup ElasticSearch and Kibana using Docker](https://gunith.github.io/docker-kibana-elasticsearch/)

###### tags: `Elasticsearch` `NoSQL`