
Elasticsearch — это масштабируемый полнотекстовый поисковый и аналитический поисковый движок с открытым исходным кодом, позволяющий хранить большие объемы данных, проводить среди них быстрый поиск и аналитику. Он является чрезвычайно мощным инструментом для поиска и анализа данных, благодаря его способности к масштабированию. Описание всех преимуществ этого движка доступно на официальном сайте.
Статья является переводом и адаптацией англоязычной статьи.
Что такое кластер Elasticsearch
Как следует из названия, кластер Elasticsearch — это группа из нескольких связанных друг с другом экземпляров Elasticsearch. Основное преимущество кластера Elasticsearch заключается в распределении задач, поиске и индексации по всем узлам кластера, а так же обеспечении высокой доступности за счет отсутствия единой точки отказа в специальных отказоустойчивых конфигурациях.
Узлы в кластере Elasticsearch имеют различные роли:
- Узел данных (Data node) хранит данные и выполняет связанные с ними операции, такие как поиск и агрегация;
- Главный узел (Master node) отвечает за действия по управлению и настройке всего кластера, такие как добавление и удаление узлов;
- Клиентский узел (Client node) перенаправляет запросы кластера на главный узел, а запросы, связанные с данными, на узлы данных;
- Выделенный узел вставки данных (Ingest node) служит для предварительной обработки документов перед индексацией.
По умолчанию каждому узлу автоматически присваивается уникальный идентификатор или имя, которое используется в целях управления кластером и играет важную роль в многоузловой или кластерной среде.
После первоначальной установки Elasticsearch, формируется новый одноузловой кластер под названием «elasticsearch». В этой статье мы познакомимся с тем, как его настроить для присоединения к кластеру.
Установка кластера Elasticsearch
Как правило, существует несколько способов настройки кластера Elasticsearch. Для автоматизации процесса можно использовать инструмент управления конфигурациями, например, Puppet или Ansible. В данной статье мы рассмотрим, как вручную настроить кластер, состоящий из одного главного узла и двух узлов данных в Ubuntu 16.04, 18.04 или Debian 9.
Установка Java
Elasticsearch реализован с использованием Java и требует для запуска Java 8 или Java 9. Первым делом необходимо установить Java на всех узлах кластера. На всех узлах Elasticsearch в кластере должна быть установлена одна и та же версия Java.
Повторите следующие шаги на всех серверах кластера.
Обновите систему:
sudo apt-get update
Установите Java:
sudo apt-get install default-jre
Проверьте, что установлена корректная версия Java. Вы должны увидеть подобный ответ:
java -version java version "1.8.0_181" Java(TM) SE Runtime Environment (build 1.8.0_181-b13) Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
Установка Elasticsearch
Следующий шаг — установка Elasticsearch. Повторите указанные ниже шаги на всех серверах.
Добавьте ключ цифровой подписи Elastic, чтобы загружаемый пакет был принят системой без предупреждения:
wget -qO - https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo apt-key add -
Для Debian установите пакет apt-transport-https:
sudo apt-get install apt-transport-https
Следующим шагом добавьте определение репозитория в систему:
echo "deb https://artifacts.elastic.co/packages/6.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-6.x.list
Осталось только обновить репозитории и установить Elasticsearch:
sudo apt-get update sudo apt-get install elasticsearch
Настройка кластера Elasticsearch с одним главным узлом и двумя узлами данных
Следующий шаг — настройка кластера таким образом, чтобы узлы могли подключаться и устанавливать соединение друг с другом.
Для каждого узла откройте файл конфигурации Elasticsearch:
sudo nano /etc/elasticsearch/elasticsearch.yml
Этот файл довольно длинный и содержит ряд настроек для разных разделов. Просмотрите файл и измените его содержимое для каждого узла, как указано далее.
es-node-1:
# назовите кластер cluster.name: my-cluster node.name: es-node-1 node.master: true node.data: false # введите частный IP и порт узла: network.host: 172.11.61.27 http.port: 9200 # укажите IP узлов для сборки кластера: discovery.zen.ping.unicast.hosts: ["172.11.61.27", "172.31.22.131","172.31.32.221"]
es-node-2:
# назовите кластер cluster.name: my-cluster node.name: es-node-2 node.master: false node.data: true # введите частный IP и порт узла: network.host: 172.31.22.131 http.port: 9200 # укажите IP узлов для сборки кластера: discovery.zen.ping.unicast.hosts: ["172.11.61.27", "172.31.22.131","172.31.32.221"]
es-node-3:
# назовите кластер cluster.name: my-cluster node.name: es-node-3 node.master: false node.data: true network.host: 172.31.32.221 http.port: 9200 # укажите IP узлов для сборки кластера: discovery.zen.ping.unicast.hosts: ["172.11.61.27", "172.31.22.131","172.31.32.221"]
Запуск кластера Elasticsearch
Теперь все готово для того, чтобы запустить узлы Elasticsearch и убедиться, что они взаимодействуют друг с другом как кластер.
На каждом сервере выполните следующую команду:
sudo service elasticsearch start
Если все настроено правильно, кластер Elasticsearch должен запуститься. Чтобы убедиться, что все работает корректно, запросите Elasticsearch с любого из узлов:
curl -XGET 'http://localhost:9200/_cluster/state?pretty'
Ответ должен вернуть информацию о кластере и его узлах:
{
"cluster_name" : "my-cluster",
"compressed_size_in_bytes" : 351,
"version" : 4,
"state_uuid" : "3LSnpinFQbCDHnsFv-Z8nw",
"master_node" : "IwEK2o1-Ss6mtx50MripkA",
"blocks" : { },
"nodes" : {
"IwEK2o1-Ss6mtx50MripkA" : {
"name" : "es-node-2",
"ephemeral_id" : "x9kUrr0yRh--3G0ckESsEA",
"transport_address" : "172.31.50.123:9300",
"attributes" : { }
},
"txM57a42Q0Ggayo4g7-pSg" : {
"name" : "es-node-1",
"ephemeral_id" : "Q370o4FLQ4yKPX4_rOIlYQ",
"transport_address" : "172.31.62.172:9300",
"attributes" : { }
},
"6YNZvQW6QYO-DX31uIvaBg" : {
"name" : "es-node-3",
"ephemeral_id" : "mH034-P0Sku6Vr1DXBOQ5A",
"transport_address" : "172.31.52.220:9300",
"attributes" : { }
}
},
…
Дополнительные настройки для обеспечения высокой доступности и производительности кластера Elasticsearch
Предотвращение ситуации split brain
Split brain — это ситуация, при которой соединение между узлами в кластере прерывается из-за сбоя в сети или внутреннего сбоя одного из узлов. В таком случае сразу несколько узлов могут назначить себя главным, что приведет к состоянию несогласованности данных.
Чтобы избежать данной ситуации, необходимо изменить директиву discovery.zen.minimum_master_nodes в файле конфигурации Elasticsearch, которая определяет, сколько узлов должно объединиться друг с другом (создать кворум) для выбора главного узла.
Чтобы определить это число, рекомендуется использовать следующую формулу: ОКРУГЛЕНИЕ_ВНИЗ [N / 2] + 1, где N — это общее число главных узлов в кластере.
Например, для кластера с тремя узлами:
discovery.zen.minimum_master_nodes: 2
Настройка размера JVM heap
Чтобы снизить риск появления ошибки в работе кластера Elasticsearch по причине недостаточности ресурсов, необходимо изменить размер кучи (JVM heap), заданный по умолчанию (минимум/максимум 1 Гбайт).
Как правило, максимальный размер кучи должен составлять не более 50% оперативной памяти, и не более 32 Гбайт (из-за неэффективности указателя Java в больших кучах). Elastic также рекомендует, чтобы значение для максимального и минимального размера было одинаковым.
Эти значения можно настроить с помощью параметров Xmx и Xms в файле jvm.options:
sudo nano /etc/elasticsearch/jvm.options -Xms2g -Xmx2g
Отключение подкачки
Подкачка в контексте Elasticsearch может привести к разрыву соединения, плохой производительности и в целом нестабильности кластера.
Чтобы не использовать подкачку, можно либо полностью отключить ее (рекомендуется, если Elasticsearch — единственная служба, работающая на сервере), либо использовать mlockall для блокировки оперативной памяти процесса Elasticsearch.
Для этого откройте файл конфигурации Elasticsearch на всех узлах кластера:
sudo vim /etc/elasticsearch/elasticsearch.yml
Раскомментируйте строку:
bootstrap.mlockall: true
Затем откройте файл /etc/default/elasticsearch:
sudo vim /etc/default/elasticsearch
Задайте настройку:
MAX_LOCKED_MEMORY=unlimited
Перезапустите Elasticsearch.
Настройка виртуальной памяти
Чтобы избежать ситуации, при которой виртуальной памяти становится недостаточно, увеличьте количество ограничений на счетчики mmap:
sudo vim /etc/sysctl.conf
Обновите соответствующие настройки:
vm.max_map_count=262144
Увеличение предела количества дескрипторов открытых файлов
Другая важная конфигурация — ограничение на количество дескрипторов открытых файлов. Поскольку Elasticsearch использует большое количество файловых дескрипторов, необходимо убедиться, что установленного предела достаточно, иначе можно потерять данные.
Рекомендуемое значение для этого параметра — 65536 и выше. Настройки по умолчанию уже заданы в соответствии с этим требованием, но, конечно, их можно уточнить.
sudo nano /etc/security/limits.conf
Установите лимит:
- nofile 65536
API кластера Elasticsearch
Elasticsearch поддерживает большое количество специфичных для кластера операций API, которые позволяют управлять кластером Elasticsearch и отслеживать его работу.
Далее приведен список полезных методов API, которые часто полезны при администрировании кластера Elasticsearch.
Проверка доступности кластера
Данный API можно использовать для просмотра общей информации о кластере и оценки его работоспособности:
curl -XGET 'localhost:9200/_cluster/health?pretty'
Ответ:
{
"cluster_name" : "my-cluster",
"status" : "green",
"timed_out" : false,
"number_of_nodes" : 3,
"number_of_data_nodes" : 3,
"active_primary_shards" : 0,
"active_shards" : 0,
"relocating_shards" : 0,
"initializing_shards" : 0,
"unassigned_shards" : 0,
"delayed_unassigned_shards" : 0,
"number_of_pending_tasks" : 0,
"number_of_in_flight_fetch" : 0,
"task_max_waiting_in_queue_millis" : 0,
"active_shards_percent_as_number" : 100.0
}
Проверка состояния кластера
Данный API можно использовать для просмотра подробного отчета о состоянии всего кластера. Результаты можно отфильтровать, указав нужные параметры в URL вызова.
curl -XGET 'localhost:9200/_cluster/state?pretty'
Ответ:
{
"cluster_name" : "my-cluster",
"compressed_size_in_bytes" : 347,
"version" : 4,
"state_uuid" : "uMi5OBtAS8SSRJ9hw1-gUg",
"master_node" : "sqT_y5ENQ9SdjHiE0oco_g",
"blocks" : { },
"nodes" : {
"sqT_y5ENQ9SdjHiE0oco_g" : {
"name" : "node-1",
"ephemeral_id" : "-HDzovR0S0e-Nn8XJ-GWPA",
"transport_address" : "172.31.56.131:9300",
"attributes" : { }
},
"mO0d0hYiS1uB--NoWuWyHg" : {
"name" : "node-3",
"ephemeral_id" : "LXjx86Q5TrmefDoq06MY1A",
"transport_address" : "172.31.58.61:9300",
"attributes" : { }
},
"it1V-5bGT9yQh19d8aAO0g" : {
"name" : "node-2",
"ephemeral_id" : "lCJja_QtTYauP3xEWg5NBQ",
"transport_address" : "172.31.62.65:9300",
"attributes" : { }
}
},
"metadata" : {
"cluster_uuid" : "8AqSmmKdQgmRVPsVxyxKrw",
"templates" : { },
"indices" : { },
"index-graveyard" : {
"tombstones" : [ ]
}
},
"routing_table" : {
"indices" : { }
},
"routing_nodes" : {
"unassigned" : [ ],
"nodes" : {
"it1V-5bGT9yQh19d8aAO0g" : [ ],
"sqT_y5ENQ9SdjHiE0oco_g" : [ ],
"mO0d0hYiS1uB--NoWuWyHg" : [ ]
}
},
"snapshots" : {
"snapshots" : [ ]
},
"restore" : {
"snapshots" : [ ]
},
"snapshot_deletions" : {
"snapshot_deletions" : [ ]
}
}
Получение статистики кластера
Чрезвычайно полезный метод API для мониторинга показателей производительности всего кластера:
curl -XGET 'localhost:9200/_cluster/stats?human&pretty'
Ответ:
{
"_nodes" : {
"total" : 3,
"successful" : 3,
"failed" : 0
},
"cluster_name" : "my-cluster",
"timestamp" : 1517224098451,
"status" : "green",
"indices" : {
"count" : 0,
"shards" : { },
"docs" : {
"count" : 0,
"deleted" : 0
},
"store" : {
"size" : "0b",
"size_in_bytes" : 0
},
"fielddata" : {
"memory_size" : "0b",
"memory_size_in_bytes" : 0,
"evictions" : 0
},
"query_cache" : {
"memory_size" : "0b",
"memory_size_in_bytes" : 0,
"total_count" : 0,
"hit_count" : 0,
"miss_count" : 0,
"cache_size" : 0,
"cache_count" : 0,
"evictions" : 0
},
"completion" : {
"size" : "0b",
"size_in_bytes" : 0
},
"segments" : {
"count" : 0,
"memory" : "0b",
"memory_in_bytes" : 0,
"terms_memory" : "0b",
"terms_memory_in_bytes" : 0,
"stored_fields_memory" : "0b",
"stored_fields_memory_in_bytes" : 0,
"term_vectors_memory" : "0b",
"term_vectors_memory_in_bytes" : 0,
"norms_memory" : "0b",
"norms_memory_in_bytes" : 0,
"points_memory" : "0b",
"points_memory_in_bytes" : 0,
"doc_values_memory" : "0b",
"doc_values_memory_in_bytes" : 0,
"index_writer_memory" : "0b",
"index_writer_memory_in_bytes" : 0,
"version_map_memory" : "0b",
"version_map_memory_in_bytes" : 0,
"fixed_bit_set" : "0b",
"fixed_bit_set_memory_in_bytes" : 0,
"max_unsafe_auto_id_timestamp" : -9223372036854775808,
"file_sizes" : { }
}
},
"nodes" : {
"count" : {
"total" : 3,
"data" : 3,
"coordinating_only" : 0,
"master" : 3,
"ingest" : 3
},
"versions" : [
"6.1.2"
],
"os" : {
"available_processors" : 3,
"allocated_processors" : 3,
"names" : [
{
"name" : "Linux",
"count" : 3
}
],
"mem" : {
"total" : "10.4gb",
"total_in_bytes" : 11247157248,
"free" : "4.5gb",
"free_in_bytes" : 4915200000,
"used" : "5.8gb",
"used_in_bytes" : 6331957248,
"free_percent" : 44,
"used_percent" : 56
}
},
"process" : {
"cpu" : {
"percent" : 10
},
"open_file_descriptors" : {
"min" : 177,
"max" : 178,
"avg" : 177
}
},
"jvm" : {
"max_uptime" : "6m",
"max_uptime_in_millis" : 361766,
"versions" : [
{
"version" : "1.8.0_151",
"vm_name" : "OpenJDK 64-Bit Server VM",
"vm_version" : "25.151-b12",
"vm_vendor" : "Oracle Corporation",
"count" : 3
}
],
"mem" : {
"heap_used" : "252.1mb",
"heap_used_in_bytes" : 264450008,
"heap_max" : "2.9gb",
"heap_max_in_bytes" : 3195076608
},
"threads" : 63
},
"fs" : {
"total" : "23.2gb",
"total_in_bytes" : 24962703360,
"free" : "19.4gb",
"free_in_bytes" : 20908818432,
"available" : "18.2gb",
"available_in_bytes" : 19570003968
},
"plugins" : [ ],
"network_types" : {
"transport_types" : {
"netty4" : 3
},
"http_types" : {
"netty4" : 3
}
}
}
}
Статистика узлов
Используйте данный метод API, если нужно проверить показатели для определенных узлов в кластере. Вы можете просмотреть информацию обо всех узлах, конкретном узле или запросить просмотр статистики по индексу или ОС/процессу.
Для всех узлов:
curl -XGET 'localhost:9200/_nodes/stats?pretty'
Для конктретного узла:
curl -XGET 'localhost:9200/_nodes/node-1/stats?pretty'
Статистика только по индексу:
curl -XGET 'localhost:9200/_nodes/stats/indices?pretty'
Больше методов API можно найти в официальной документации API кластера.
Заключение
Из статьи вы узнали как настроить кластер Elasticsearch и получили ряд рекомендаций по настройке его для продуктового использования. Тем не менее, очевидно, что практически невозможно описать универсальное решение, подходящее для каждой отдельной среды и варианта использования.
Более подробные инструкции можно найти в официальной документации и на основании опыта использования данного продукта.