Настройка Elasticsearch кластера для веб-приложения

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.
Разработка и обслуживание любых видов сайтов:
Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Предлагаемые услуги
Показано 1 из 1 услугВсе 2065 услуг
Настройка Elasticsearch кластера для веб-приложения
Сложная
~3-5 рабочих дней
Часто задаваемые вопросы
Наши компетенции:
Этапы разработки
Последние работы
  • image_website-b2b-advance_0.png
    Разработка сайта компании B2B ADVANCE
    1214
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    852
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1041
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    823
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Разработка веб-сайта для компании ФИКСПЕР
    815

Настройка Elasticsearch кластера для веб-приложения

Elasticsearch — распределённая поисковая система на базе Apache Lucene. Одиночный узел подходит для разработки, но в продакшене нужен кластер: для отказоустойчивости, горизонтального масштабирования и изоляции нагрузок. Настройка кластера — это не просто запуск нескольких инстансов, а понимание ролей узлов, стратегии шардирования и процедуры обновления без простоя.

Роли узлов кластера

В Elasticsearch 8.x каждый узел может выполнять несколько ролей. Для небольшого кластера (3–5 узлов) все узлы обычно выполняют все роли. Для кластера от 10 узлов — разделение обязательно.

Master-eligible node — участвует в выборах мастера, управляет состоянием кластера (cluster state): список индексов, маппинги, настройки шардов. Мастер не обрабатывает поисковые запросы. Минимум 3 master-eligible узла для кворума.

Data node — хранит шарды, выполняет поиск и агрегации. Самые ресурсоёмкие: нужны быстрые диски (NVMe) и много RAM для JVM heap и файлового кэша OS.

Coordinating node (client node) — принимает запросы от клиентов, распределяет по data-узлам, собирает результаты. Снимает нагрузку с data-узлов на фазе scatter-gather.

Ingest node — обрабатывает документы перед индексацией через ingest pipelines (парсинг, обогащение, трансформация).

Конфигурация ролей в elasticsearch.yml:

# Master-only node
node.roles: [ master ]

# Data node
node.roles: [ data, data_content, data_hot, data_warm, data_cold ]

# Coordinating only
node.roles: []

Минимальная продакшен конфигурация: 3 узла

Все три узла — master-eligible + data. Это даёт кворум (2 из 3) и хранение данных.

elasticsearch.yml для узла 1:

cluster.name: myapp-prod
node.name: es-node-01
node.roles: [master, data, ingest]

network.host: 0.0.0.0
http.port: 9200
transport.port: 9300

discovery.seed_hosts:
  - es-node-01:9300
  - es-node-02:9300
  - es-node-03:9300

cluster.initial_master_nodes:
  - es-node-01
  - es-node-02
  - es-node-03

path.data: /var/lib/elasticsearch
path.logs: /var/log/elasticsearch

xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12

На узлах 2 и 3 меняется только node.name.

cluster.initial_master_nodes указывается только при первом запуске кластера. После формирования кластера эту строку нужно убрать или закомментировать — иначе при перезапуске узла возможно split-brain.

JVM и память

Elasticsearch по умолчанию берёт 1 GB heap — для продакшена критически мало. Правило: heap = половина доступной RAM, но не более 31 GB (выше 32 GB JVM теряет compressed oops).

В /etc/elasticsearch/jvm.options.d/heap.options:

-Xms16g
-Xmx16g

Оставшаяся память уходит на файловый кэш OS — Elasticsearch активно использует mmap для чтения сегментов Lucene. На сервере с 64 GB RAM: 31 GB heap + 30+ GB под OS cache = хорошо.

Настройка системы:

# /etc/sysctl.conf
vm.max_map_count=262144
vm.swappiness=1

# /etc/security/limits.conf
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited
elasticsearch soft nofile 65536
elasticsearch hard nofile 65536

Генерация TLS сертификатов и настройка безопасности

# Генерация CA и сертификатов для кластера
/usr/share/elasticsearch/bin/elasticsearch-certutil ca --out /etc/elasticsearch/elastic-ca.p12
/usr/share/elasticsearch/bin/elasticsearch-certutil cert \
  --ca /etc/elasticsearch/elastic-ca.p12 \
  --out /etc/elasticsearch/elastic-certificates.p12

# Установка пароля elastic пользователя
/usr/share/elasticsearch/bin/elasticsearch-setup-passwords auto

HTTP TLS (для клиентских подключений) — отдельный сертификат:

xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12

Docker Compose для разработки

version: '3.8'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
    environment:
      - node.name=es01
      - cluster.name=dev-cluster
      - discovery.seed_hosts=es02,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - ELASTIC_PASSWORD=changeme
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=false
      - xpack.security.transport.ssl.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - es01_data:/usr/share/elasticsearch/data
    ports:
      - "9200:9200"

  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
    environment:
      - node.name=es02
      - cluster.name=dev-cluster
      - discovery.seed_hosts=es01,es03
      - cluster.initial_master_nodes=es01,es02,es03
      - ELASTIC_PASSWORD=changeme
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=false
      - xpack.security.transport.ssl.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - es02_data:/usr/share/elasticsearch/data

  es03:
    image: docker.elastic.co/elasticsearch/elasticsearch:8.13.0
    environment:
      - node.name=es03
      - cluster.name=dev-cluster
      - discovery.seed_hosts=es01,es02
      - cluster.initial_master_nodes=es01,es02,es03
      - ELASTIC_PASSWORD=changeme
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=false
      - xpack.security.transport.ssl.enabled=false
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    volumes:
      - es03_data:/usr/share/elasticsearch/data

  kibana:
    image: docker.elastic.co/kibana/kibana:8.13.0
    environment:
      - ELASTICSEARCH_HOSTS=http://es01:9200
      - ELASTICSEARCH_USERNAME=kibana_system
      - ELASTICSEARCH_PASSWORD=changeme
    ports:
      - "5601:5601"

volumes:
  es01_data:
  es02_data:
  es03_data:

Проверка состояния кластера

# Статус кластера (green/yellow/red)
curl -u elastic:changeme http://localhost:9200/_cluster/health?pretty

# Список узлов
curl -u elastic:changeme http://localhost:9200/_cat/nodes?v

# Распределение шардов
curl -u elastic:changeme http://localhost:9200/_cat/shards?v&h=index,shard,prirep,state,node

# Неназначенные шарды и причины
curl -u elastic:changeme "http://localhost:9200/_cluster/allocation/explain?pretty"

Статус yellow означает, что все первичные шарды назначены, но часть реплик — нет. На кластере из 1 узла это нормально. На 3-узловом кластере yellow — сигнал проблемы.

ILM (Index Lifecycle Management)

Для логов и данных с временным горизонтом — обязательно настроить ILM. Без него индексы растут бесконечно.

PUT _ilm/policy/logs-policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_age": "7d",
            "max_size": "50gb"
          },
          "set_priority": { "priority": 100 }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "shrink": { "number_of_shards": 1 },
          "forcemerge": { "max_num_segments": 1 },
          "set_priority": { "priority": 50 }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "freeze": {},
          "set_priority": { "priority": 0 }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

Подключение из приложения

PHP (laravel-elasticsearch / elastic/elasticsearch-php):

use Elastic\Elasticsearch\ClientBuilder;

$client = ClientBuilder::create()
    ->setHosts(['https://es-node-01:9200', 'https://es-node-02:9200', 'https://es-node-03:9200'])
    ->setBasicAuthentication('elastic', 'changeme')
    ->setCABundle('/path/to/ca.crt')
    ->build();

Клиент автоматически выполняет sniffing — обнаруживает все узлы кластера и балансирует запросы. При падении узла переключается на оставшиеся.

Python (elasticsearch-py):

from elasticsearch import Elasticsearch

es = Elasticsearch(
    ['https://es-node-01:9200', 'https://es-node-02:9200'],
    basic_auth=('elastic', 'changeme'),
    ca_certs='/path/to/ca.crt',
    retry_on_timeout=True,
    max_retries=3,
)

Сроки

Развёртывание 3-узлового кластера в облаке (AWS/GCP/Hetzner) с TLS, базовым ILM и мониторингом через Kibana — 3–5 рабочих дней. Миграция существующих данных из одиночного инстанса — ещё 1–2 дня в зависимости от объёма. Настройка hot-warm-cold архитектуры с настройкой ролей — дополнительный день.