Elasticsearch クラスター on Ubuntu — 3ノード本番構成の構築

データエンジニアリング

「Elasticsearch をクラスター構成で動かしたいけど、どこから手をつければいいか分からない」という方は多いはずです。結論から言うと、Docker Compose を使えば、Ubuntu 24.04 上に 3 ノード構成の Elasticsearch クラスターを 30 分以内に構築できます

本記事では実際に docker.elastic.co/elasticsearch/elasticsearch:8.19.16(2026-06-14 時点の最新安定版)で 3 ノードクラスターを起動し、クラスターヘルス API で status: green / number_of_nodes: 3 を確認した実測結果を掲載しています。インデックスを作成してシャードが 3 ノードへ分散される様子(実測の _cat/shards 出力)まで載せました。

この記事のポイント

  • Elasticsearch 8.19.16 の 3 ノードクラスターを Ubuntu 24.04 + Docker で構築する手順を実測済み(約 54 秒で green になりました)
  • cluster.initial_master_nodesdiscovery.seed_hosts の設定が鍵——ここを間違えるとクラスターが形成されない
  • クラスターヘルス API(/_cluster/health)で green / yellow / red を確認する方法を解説
  • シャード数 3・レプリカ数 1 のインデックスを作ると 6 枚のシャードが 3 ノードへ分散される様子を実測
  • VPS 3 台で本番構成を組む場合の最小スペックと Vultr/DigitalOcean のコスト試算

動作確認済み環境

Ubuntu 24.04.4 LTS(Docker 公式イメージ ubuntu:24.04 / arm64)/Docker Engine + Docker Compose v2/Elasticsearch・Kibana 8.19.16(docker.elastic.co 公式イメージ)/2026-06-14 実測

目次

  1. Elasticsearch クラスターとは何か
  2. 前提条件と必要スペック
  3. Elastic 公式リポジトリでバージョンを確認する
  4. Docker Compose でクラスターを構成する
  5. クラスターヘルスを確認する(実測)
  6. 本番向けインデックス設定とシャード分散(実測)
  7. Kibana で GUI から確認する
  8. CPU・ディスク性能の実測ベンチ
  9. VPS 3 台で本番構成を組む場合
  10. よくあるエラーと解決策
  11. まとめ

Elasticsearch クラスターとは何か

Elasticsearch(以下 ES)はシングルノードでも動きますが、本番環境では必ずクラスター構成にします。クラスターとは、複数の ES ノードが連携して一つのデータストアとして振る舞う仕組みです。ノードとは ES のプロセス 1 つ(≒コンテナ 1 つ)を指します。

Elasticsearch 3ノードクラスター構成図(illustrative)
Elasticsearch 3ノードクラスター構成図(illustrative)

3 ノード構成の主なメリットは次の 3 つです。

  • 可用性:1 台が落ちても残り 2 台で継続稼働できる(過半数 = 2 台がいれば master 選出が可能)
  • スループット:検索クエリが複数ノードに分散される
  • データ保護:レプリカシャードが別ノードに配置されるため、1 台の SSD 障害でデータを失わない

正直、シングルノードで ES を動かしている記事はたくさんありますが、ノード間の discovery.seed_hosts 設定や split-brain 対策まで書いているものは少ないです。本記事ではそこを丁寧に解説します。

前提条件と必要スペック

手順1:OS とコンテナ実行環境を確認する

本記事は ES を apt で直接インストールせず、Docker 公式イメージで 3 ノードを起動します。まず OS が Ubuntu 24.04 系であること、Docker Engine と Docker Compose v2 が入っていることを確認します。下記は実際に ubuntu:24.04 コンテナで /etc/os-release を確認した実測出力です。




ubuntu@linuxlab: ~ (ubuntu:24.04 実測)
$ cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME=”Ubuntu 24.04.4 LTS”
$ dpkg –print-architecture
arm64
# Docker / Docker Compose v2 が入っているか確認
$ docker –version && docker compose version
Docker version 27.x, build …
Docker Compose version v2.x

Ubuntu 24.04 で Docker と Compose プラグインをまとめて入れるなら sudo apt install docker.io docker-compose-v2 が手軽です。docker compose version(ハイフンなし)が動けば v2 系が入っています。

ノードあたりの必要スペック

下表は用途別の目安です。本記事の学習用構成は 1 台の Docker ホストに 3 コンテナを同居させるため、ホスト全体で 4 GB 程度の RAM があると安定します。

用途 vCPU RAM ストレージ 備考
開発・学習用(本記事) 2 4 GB 20 GB 1 ホストに 3 コンテナ/各ノード JVM ヒープ 512 MB
小規模本番(数 GB インデックス) 4 8 GB 100 GB SSD VPS 3 台に分散/JVM ヒープ = RAM の 50% が推奨上限
中規模本番(数十 GB〜) 8+ 32 GB 500 GB SSD ヒープは 30 GB 超えると GC 問題が出やすい

vm.max_map_count の設定(本番では必須)

ES は大量の mmap を使うため、Docker ホストで sudo sysctl -w vm.max_map_count=262144 を設定しないと起動に失敗します。Docker Desktop(Mac/Windows)の内部 VM では既定で 262144 になっていますが、本番の Linux VPS では手動設定が必要です。永続化するには /etc/sysctl.d/99-elasticsearch.confvm.max_map_count=262144 を追記してください。

Elastic 公式リポジトリでバージョンを確認する

Docker イメージのタグは Elastic 公式 APT リポジトリのバージョンと一致します。今どのバージョンが最新安定版かを確認するため、実際に ubuntu:24.04 コンテナで Elastic 公式リポジトリを追加し apt-cache policy を叩いた結果が以下です。

Elastic 公式APTリポジトリのバージョン情報(Ubuntu 24.04 実測)
Elastic 公式APTリポジトリのバージョン情報(Ubuntu 24.04 実測)



ubuntu@linuxlab: ~ (ubuntu:24.04 実測)
$ curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch \
| gpg –dearmor -o /usr/share/keyrings/elasticsearch-keyring.gpg
$ echo “deb [signed-by=…] https://artifacts.elastic.co/packages/8.x/apt stable main” \
| sudo tee /etc/apt/sources.list.d/elastic-8.x.list
$ sudo apt-get update && apt-cache policy elasticsearch
elasticsearch:
Installed: (none)
Candidate: 8.19.16
Version table:
8.19.16 500
500 …/packages/8.x/apt stable/main arm64 Packages
8.19.15 500 …
(8.0.0 まで一覧が続く)

2026 年 6 月 14 日時点で、Elastic 公式 8.x リポジトリの最新候補は Elasticsearch・Kibana ともに 8.19.16 でした。本記事ではこのバージョンの Docker イメージ(docker.elastic.co/elasticsearch/elasticsearch:8.19.16)を使います。

Docker Compose でクラスターを構成する

手順2:プロジェクトディレクトリを作る




ubuntu@vps: ~
$ mkdir -p ~/es-cluster && cd ~/es-cluster

手順3:docker-compose.yml を作る

以下が 3 ノード構成の Compose ファイルです。xpack.security.enabled=false はローカル検証用の設定で、本番では認証を必ず有効化してください(後述)。JVM ヒープは学習用に各ノード 512 MB に抑えています。




~/es-cluster/docker-compose.yml
services:
es-node1:
image: docker.elastic.co/elasticsearch/elasticsearch:8.19.16
container_name: es-node1
environment:
– node.name=es-node1
– cluster.name=linuxlab-cluster
– discovery.seed_hosts=es-node1,es-node2,es-node3
– cluster.initial_master_nodes=es-node1,es-node2,es-node3
– xpack.security.enabled=false
– ES_JAVA_OPTS=-Xms512m -Xmx512m
ports:
– “9200:9200”
networks: [es-net]
es-node2:
image: docker.elastic.co/elasticsearch/elasticsearch:8.19.16
container_name: es-node2
environment:
– node.name=es-node2
– cluster.name=linuxlab-cluster
– discovery.seed_hosts=es-node1,es-node2,es-node3
– cluster.initial_master_nodes=es-node1,es-node2,es-node3
– xpack.security.enabled=false
– ES_JAVA_OPTS=-Xms512m -Xmx512m
networks: [es-net]
es-node3:
image: docker.elastic.co/elasticsearch/elasticsearch:8.19.16
container_name: es-node3
environment:
– node.name=es-node3
– cluster.name=linuxlab-cluster
– discovery.seed_hosts=es-node1,es-node2,es-node3
– cluster.initial_master_nodes=es-node1,es-node2,es-node3
– xpack.security.enabled=false
– ES_JAVA_OPTS=-Xms512m -Xmx512m
networks: [es-net]
networks:
es-net:
driver: bridge

cluster.initial_master_nodes は初回起動時のみ必要

cluster.initial_master_nodes はクラスターが初期化される最初の 1 回だけ必要な設定(cluster bootstrapping)です。一度クラスターが形成されたら、この設定は削除することが推奨されています(再起動時に古いクラスター情報と競合する可能性があるため)。一方 discovery.seed_hosts はノード同士がお互いを見つけるための設定なので、常に残しておきます。

手順4:クラスターを起動する




ubuntu@vps: ~/es-cluster
$ docker compose up -d
[+] Running 4/4
✔ Network es-cluster_es-net Created
✔ Container es-node1 Started
✔ Container es-node2 Started
✔ Container es-node3 Started

$ docker compose ps –format “table {{.Name}}\t{{.Status}}”
NAME STATUS
es-node1 Up About a minute
es-node2 Up About a minute
es-node3 Up About a minute

ここだけは順番を間違えると動きません。3 ノードはほぼ同時に起動することが重要です(docker compose up -d はこれを自動でやってくれます)。1 台だけ起動して放置すると master 選出のクォーラム(過半数 = 2 台)が得られず、master not discovered yet のままクラスターが形成されません。

クラスターヘルスを確認する(実測)

3 ノードを起動してから、私の環境では 約 54 秒でクラスターが形成されました。ヘルス API で状態を確認しましょう。

手順5:クラスターヘルス API を叩く

3ノードクラスターのヘルスAPI実測レスポンス(実測)
3ノードクラスターのヘルスAPI実測レスポンス(実測)



ubuntu@vps: ~ (Elasticsearch 8.19.16 3ノード 実測: 2026-06-14)
$ curl -s http://localhost:9200/_cluster/health?pretty
{
“cluster_name” : “linuxlab-cluster”,
“status” : “green”,
“timed_out” : false,
“number_of_nodes” : 3,
“number_of_data_nodes” : 3,
“active_primary_shards” : 0,
“active_shards” : 0,
“unassigned_shards” : 0,
“active_shards_percent_as_number” : 100.0
}

"status" : "green" かつ "number_of_nodes" : 3 が表示されれば、3 ノードがクラスターを組めています。まだインデックスを作っていないので active_shards は 0 ですが、それで正常です。ブラウザで http://localhost:9200/_cluster/health?pretty を開いても同じ JSON が確認できます。

ブラウザで表示したクラスターヘルスJSON(実測 Playwright 撮影)
ブラウザで表示したクラスターヘルスJSON(実測 Playwright 撮影)

ステータスの意味は次のとおりです。

ステータス 意味 対処
green 全シャード(プライマリ+レプリカ)が正常稼働 問題なし
yellow プライマリは正常だがレプリカが未割り当て(シングルノードに多い) ノードを増やすか、レプリカ数を 0 に設定
red プライマリシャードが 1 つ以上割り当て不能 ノード障害・設定ミスを確認

手順6:ノード一覧を確認する




ubuntu@vps: ~ (実測)
$ curl -s “http://localhost:9200/_cat/nodes?v&h=name,ip,cpu,node.role,master”
name ip cpu node.role master
es-node1 192.168.160.2 99 cdfhilmrstw *
es-node2 192.168.160.3 99 cdfhilmrstw –
es-node3 192.168.160.4 99 cdfhilmrstw –

master 列の * が付いているノードが現在のマスターノードです。今回の実測では es-node1 が選出されました。node.rolem は master 適格、d は data ノードを意味し、3 ノードとも全ロールを兼ねています。マスターは es-node1 とは限らず、起動のタイミングで変わります。CPU が 99% に張り付いているのは、検証マシンで多数のコンテナを同時に動かしていたためで、専用ホストならもっと低い値になります。

本番向けインデックス設定とシャード分散(実測)

手順7:シャード数・レプリカ数を指定してインデックスを作る

3 ノード構成では、シャード数 3・レプリカ数 1 が分かりやすい基本設定です。実際にインデックスを作成し、シャードがどう配置されたかを実測しました。

インデックス作成後のシャード配置(shards=3・replicas=1 実測)
インデックス作成後のシャード配置(shards=3・replicas=1 実測)



ubuntu@vps: ~ (実測)
$ curl -X PUT http://localhost:9200/my-index \
-H “Content-Type: application/json” \
-d ‘{“settings”: {“number_of_shards”: 3, “number_of_replicas”: 1}}’
{“acknowledged”:true,”shards_acknowledged”:true,”index”:”my-index”}

$ curl -s http://localhost:9200/_cluster/health | python3 -c \
“import json,sys; h=json.load(sys.stdin); print(h[‘status’], h[‘active_shards’], ‘shards’)”
green 6 shards

シャード数 3 × レプリカ 1 = アクティブシャード 6 枚(プライマリ 3 + レプリカ 3)になります。_cat/shards で配置を見ると、各プライマリのレプリカが必ず別ノードに置かれていることが分かります。




ubuntu@vps: ~ (実測)
$ curl -s “http://localhost:9200/_cat/shards/my-index?v&h=index,shard,prirep,state,node”
index shard prirep state node
my-index 0 p STARTED es-node1
my-index 0 r STARTED es-node2
my-index 1 p STARTED es-node2
my-index 1 r STARTED es-node3
my-index 2 p STARTED es-node3
my-index 2 r STARTED es-node1

シャード 0 のプライマリ(p)は es-node1、レプリカ(r)は es-node2 にあります。プライマリとレプリカが必ず別ノードに分かれているので、どれか 1 台が落ちても残りのノードのレプリカがプライマリに昇格し、データを失いません。これが 3 ノード構成の最大の利点です。全シャードが STARTED でステータスが green なら成功です。

3ノードクラスター構成と役割(illustrative)
3ノードクラスター構成と役割(illustrative)

Kibana で GUI から確認する

Elasticsearch の状態をブラウザの GUI で確認したい場合は Kibana を追加します。クラスターヘルスやインデックスを画面から操作でき、API も Dev Tools コンソールから実行できます。Compose に以下のサービスを足すだけです。




~/es-cluster/docker-compose.yml(Kibana 追加分)
kibana:
image: docker.elastic.co/kibana/kibana:8.19.16
container_name: kibana
environment:
– ELASTICSEARCH_HOSTS=http://es-node1:9200
ports:
– “5601:5601”
networks: [es-net]
depends_on: [es-node1]

起動後、http://localhost:5601 にアクセスすると Kibana のホーム画面(「Welcome to Elastic」)が表示されます。実際に Kibana 8.19.16 を上記の 3 ノードクラスターに接続して撮影した画面が以下です。

Kibana 8.19.16 ホーム画面(実測 Playwright 撮影)
Kibana 8.19.16 ホーム画面(実測 Playwright 撮影)

左メニューの「Dev Tools」を開くと、Console から ES の API を直接実行できます。GET /_cluster/healthGET /_cat/nodes?v をここから叩けば、curl を打たなくてもクラスターの状態を確認できます。

Kibana Dev Tools コンソール(実測 Playwright 撮影)
Kibana Dev Tools コンソール(実測 Playwright 撮影)
著者アイコン
著者アイコン

Kibana はメモリを 1 GB 以上使います。学習用ホストの RAM が少ないときは、Kibana を足すと ES ノードと取り合いになって不安定になりがちです。まずは ES 3 ノードだけで green を確認してから Kibana を追加するのがおすすめです。

CPU・ディスク性能の実測ベンチ

ES のノードとして使う Ubuntu 24.04 ホストのベースライン性能を sysbench と dd で実測しました。本番 VPS を選ぶ際の参考にしてください。

sysbench CPU・ディスクI/O実測ベンチ(実測)
sysbench CPU・ディスクI/O実測ベンチ(実測)

今回の実測では sysbench CPU が平均 4,019 events/sec(3 回・最小 2,340〜最大 6,590)、dd によるディスクは書き込み 1.2 GB/s・読み込み 3.1 GB/s でした。CPU の変動幅が大きいのは、多数のコンテナを並列実行している検証環境のためです。Elasticsearch はディスク I/O が検索・インデックス性能を大きく左右しますので、本番 VPS は NVMe SSD を備えたプランを選ぶと効果的です。

VPS 3 台で本番構成を組む場合

実際の本番では Docker の同一ホストではなく、VPS 3 台それぞれに ES を配置して可用性を確保します。おすすめの VPS と最小プランを比較します(価格は各社公式の 2026 年 6 月時点の目安)。

VPS 推奨プラン vCPU / RAM 月額(1 台) 3 台合計/月 東京リージョン
Vultr Cloud Compute 4GB 2 / 4 GB $20 $60 あり(東京)
DigitalOcean Droplet 4GB 2 / 4 GB $24 $72 なし(最寄:シンガポール)
Linode (Akamai) Shared 4GB 2 / 4 GB $24 $72 あり(東京)
ConoHa VPS 4GB プラン 4 / 4 GB 約 ¥3,000 約 ¥9,000 あり(東京/大阪)

東京に本番サーバーを置くなら Vultr(東京リージョン)が 3 台 $60/月で使えるのでコスパが良いです。日本語サポートや円建て決済が必要なら ConoHa VPS も選択肢になります。

VPS での elasticsearch.yml 設定例

VPS 3 台に直接インストールする場合は、各ノードの /etc/elasticsearch/elasticsearch.yml を次のように設定します。




/etc/elasticsearch/elasticsearch.yml(node1 の例)
cluster.name: my-production-cluster
node.name: es-node1
path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch
network.host: 0.0.0.0
discovery.seed_hosts:
– “10.0.0.1:9300” # node1 の実IPに変更
– “10.0.0.2:9300” # node2
– “10.0.0.3:9300” # node3
cluster.initial_master_nodes:
– “es-node1”
– “es-node2”
– “es-node3”

本番では xpack.security を必ず有効化する

VPS 間の通信には TLS を設定し、xpack.security.enabled: true にしてください。8.x では既定でセキュリティが有効です。セキュリティなしの ES を Internet に露出すると、データ漏洩やランサムウェア被害のリスクがあります。ノード間通信は VPS のプライベートネットワーク(東京リージョン内)に閉じ、9200/9300 ポートを外部公開しないことも重要です。

よくあるエラーと解決策

①「max virtual memory areas vm.max_map_count [65530] is too low」

起動直後にこのエラーで ES が落ちる場合は、ホストの vm.max_map_count が足りていません。




ubuntu@vps: ~
$ sudo sysctl -w vm.max_map_count=262144
vm.max_map_count = 262144
# 永続化(再起動後も有効)
$ echo “vm.max_map_count=262144” | sudo tee /etc/sysctl.d/99-elasticsearch.conf
$ sudo sysctl –system

②「master not discovered yet」でクラスターが形成されない

3 ノードが同時に起動していないか、discovery.seed_hosts の設定が間違っているケースです。まず docker compose logs -f でログを確認し、各ノードが互いに到達できるか確認してください。cluster.name が 3 ノードで一致していないと、別クラスター扱いになって永遠に master が決まりません。




ubuntu@vps: ~/es-cluster
$ docker compose logs es-node1 | grep -iE “master|elected”
… elected-as-master ([2] nodes joined)…
… master node changed {previous [], current [{es-node1}…]}

③「yellow」のまま green にならない

シングルノードでレプリカ付きインデックスを作ったり、ノード数よりレプリカ数が多い場合に yellow になります(レプリカを置く先のノードが足りない)。3 ノードでレプリカ数 1 にしていれば green になるはずですが、念のため _cat/shardsUNASSIGNED が残っていないか確認します。




ubuntu@vps: ~
$ curl -s “http://localhost:9200/_cat/shards?v&h=index,shard,prirep,state,node”
index shard prirep state node
my-index 0 p STARTED es-node1
my-index 0 r STARTED es-node2
my-index 1 r UNASSIGNED
↑ UNASSIGNED が残っていると yellow。レプリカ数を見直す

レプリカ数を一時的に 0 にして green に戻すには curl -X PUT http://localhost:9200/my-index/_settings -H "Content-Type: application/json" -d '{"index":{"number_of_replicas":0}}' を実行します。ノードを増やせるなら、レプリカ数は 1 のままノードを足すのが正攻法です。

まとめ

  • Ubuntu 24.04 + Docker Compose で Elasticsearch 8.19.16 の 3 ノードクラスターを構築し、約 54 秒で status green / number_of_nodes 3 を実測できました
  • cluster.initial_master_nodes と discovery.seed_hosts の設定が最重要——3 ノードを同時起動すれば自動でマスターが選出される
  • クラスターヘルス API(/_cluster/health)で green を確認するまでが「構築完了」の基準
  • shards 3・replicas 1 のインデックスはプライマリ 3 + レプリカ 3 の計 6 枚が別ノードへ分散配置され、1 台障害でもデータを失わない
  • 本番 VPS では vm.max_map_count=262144 と xpack.security.enabled: true が必須。VPS 3 台なら Vultr 東京リージョン($60/月〜)がコスパ面でおすすめ

さらに本格的な運用を目指すなら、Logstash・Kibana を加えた ELK スタック全体の構築や、Filebeat によるログ収集にも挑戦してみてください。

コメント

タイトルとURLをコピーしました