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 и получили ряд рекомендаций по настройке его для продуктового использования. Тем не менее, очевидно, что практически невозможно описать универсальное решение, подходящее для каждой отдельной среды и варианта использования.
Более подробные инструкции можно найти в официальной документации и на основании опыта использования данного продукта.