OpenSearch на сервере: частые ошибки и решения
После смены лицензии Elasticsearch многие команды переехали на OpenSearch — форк, который остался под Apache 2.0 и почти полностью совместим по API. На бумаге переезд выглядит безболезненно, но на практике первый же деплой на своём сервере упирается в одни и те же грабли: сервис не стартует из-за лимитов ядра, кластер уходит в жёлтый или красный статус, индекс внезапно становится read-only. Ниже — разбор самых частых ошибок с конкретными командами, которые реально помогают, без теории про архитектуру Lucene.
Содержание
- "max virtual memory areas vm.max_map_count is too low" — сервис не стартует вообще
- Процесс стартует и сразу падает: как читать причину
- Кластер health = yellow или red
- Диск заполнился — индексы ушли в read-only
- Медленная индексация и поиск при большом потоке логов
- Ошибки Security plugin и TLS при подключении
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →"max virtual memory areas vm.max_map_count is too low" — сервис не стартует вообще
Самая частая причина, по которой OpenSearch падает в первые секунды после systemctl start opensearch. Lucene активно использует mmap для работы с сегментами индекса, и ядру Linux по умолчанию не хватает лимита на количество memory-mapped областей.
Проверить текущее значение:
sysctl vm.max_map_count
Если меньше 262144 — поднимаем:
sudo sysctl -w vm.max_map_count=262144
Это разовое изменение, оно слетит после перезагрузки. Закрепляем постоянно:
echo "vm.max_map_count=262144" | sudo tee /etc/sysctl.d/99-opensearch.conf
sudo sysctl --system
Вторая частая связка — лимиты на файловые дескрипторы и заблокированную память. Если в логах видно max file descriptors too low или memory locking requested but is not supported, правим /etc/security/limits.d/opensearch.conf:
opensearch soft nofile 65536
opensearch hard nofile 65536
opensearch soft memlock unlimited
opensearch hard memlock unlimited
Важный нюанс: systemd не читает limits.conf для сервисов, запущенных через unit-файл. Нужно явно прописать лимиты в самом юните:
sudo systemctl edit opensearch
и добавить:
[Service]
LimitMEMLOCK=infinity
LimitNOFILE=65536
После этого systemctl daemon-reload && systemctl restart opensearch.
Процесс стартует и сразу падает: как читать причину
Когда сервис не просто "не стартует", а падает уже после запуска (иногда через минуту-две), самый быстрый способ понять причину — не лезть в конфиги наугад, а смотреть системный журнал:
journalctl -u opensearch -n 200 --no-pager
Если в выводе тишина по делу, но процесс умер — проверьте, не сработал ли OOM killer:
dmesg -T | grep -i "killed process"
Если строка нашлась — это почти всегда неправильно выставленный heap. По умолчанию OpenSearch пытается взять около половины оперативной памяти сервера, но на VPS с 2-4 ГБ этого может быть слишком много с учётом других процессов. Heap задаётся файлом в config/jvm.options.d/, например config/jvm.options.d/heap.options:
-Xms2g
-Xmx2g
Значения Xms и Xmx должны совпадать — это исключает паузы на изменение размера кучи "на лету". Общее правило: heap — не больше 50% от RAM сервера и не больше ~30 ГБ (выше упирается в потерю compressed oops в JVM, и прирост не оправдан). Оставшуюся половину памяти сознательно отдаём под файловый кэш ОС — Lucene активно на него полагается при чтении сегментов с диска.
Если сервер регулярно уходит в своп из-за того, что heap выставлен впритык к лимиту RAM, разберитесь сначала с правильным размером swap — для OpenSearch своп скорее враг: подкачка кучи JVM превращает любую операцию GC в многосекундный стопор кластера.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверКластер health = yellow или red
GET _cluster/health?pretty — первая команда, с которой стоит начинать любой разбор проблем с кластером:
curl -s -u admin:'ВашПароль' -k https://localhost:9200/_cluster/health?pretty
Красный статус означает, что часть данных недоступна вообще (unassigned primary shard), жёлтый — что primary-шарды на месте, но реплики не назначены. Чтобы увидеть, какие именно шарды в проблеме:
curl -s -u admin:'ВашПароль' -k "https://localhost:9200/_cat/shards?v&h=index,shard,prirep,state,unassigned.reason"
Для конкретного индекса причину неназначения объясняет отдельный API:
curl -s -u admin:'ВашПароль' -k -X GET "https://localhost:9200/_cluster/allocation/explain?pretty"
Самая частая причина жёлтого статуса на своём сервере — банальная: кластер состоит из одного узла, а number_of_replicas у индексов по умолчанию равен 1. Реплику ставить некуда — второго узла нет, и кластер повиснет в жёлтом навсегда, хотя данные целы. Решение для single-node установки — явно занулить реплики:
curl -s -u admin:'ВашПароль' -k -X PUT "https://localhost:9200/_all/_settings" \
-H 'Content-Type: application/json' \
-d '{"index": {"number_of_replicas": 0}}'
Если шард завис в состоянии ALLOCATION_FAILED после сбоя (например, ноду убило по OOM в момент записи), после исправления причины часто помогает принудительный ретрай:
curl -s -u admin:'ВашПароль' -k -X POST "https://localhost:9200/_cluster/reroute?retry_failed=true"
Диск заполнился — индексы ушли в read-only
Классический сценарий: логи льются в OpenSearch месяцами, диск подбирается к 90%, и внезапно запись начинает падать с ошибкой вида cluster_block_exception... FORBIDDEN/12/index read-only / allow delete. Это не баг, а защитный механизм — водяные знаки диска (disk watermarks).
По умолчанию:
low— 85% занятого диска: новые шарды перестают размещаться на этой ноде;high— 90%: OpenSearch начинает переносить шарды с ноды;flood_stage— 95%: все индексы на этом диске принудительно переводятся в read-only.
Проверить, что происходит с местом на нодах кластера:
curl -s -u admin:'ВашПароль' -k "https://localhost:9200/_cat/allocation?v"
Дальше — по порядку. Сначала освобождаем место (удаляем старые индексы, настраиваем ILM/ISM-политику на ротацию логов). Потом обязательно снимаем блок read-only вручную — сам по себе он не снимается, даже если места стало достаточно:
curl -s -u admin:'ВашПароль' -k -X PUT "https://localhost:9200/_all/_settings" \
-H 'Content-Type: application/json' \
-d '{"index.blocks.read_only_allow_delete": null}'
Если постоянно упираетесь в этот порог — стоит настроить мониторинг диска на сервере с алертом задолго до 85%, а не разбираться с этим постфактум в 3 часа ночи. Пороги при желании можно сдвинуть в opensearch.yml, но это лечит симптом, а не причину нехватки места:
cluster.routing.allocation.disk.watermark.low: 85%
cluster.routing.allocation.disk.watermark.high: 90%
cluster.routing.allocation.disk.watermark.flood_stage: 95%
Медленная индексация и поиск при большом потоке логов
Если OpenSearch используется под сбор логов (частый сценарий для тех, кто переезжает с ELK), при бурном потоке записи легко упереться в производительность. Несколько рабочих приёмов:
- Во время массовой первичной загрузки временно отключите refresh и реплики — это резко ускоряет bulk-запись:
curl -s -u admin:'ВашПароль' -k -X PUT "https://localhost:9200/my-index/_settings" \
-H 'Content-Type: application/json' \
-d '{"index": {"refresh_interval": "-1", "number_of_replicas": 0}}'
После загрузки верните refresh_interval в разумное значение (обычно 5s-30s для потока логов, а не дефолтную 1s).
- Пишите через
_bulkпакетами, а не по одному документу. Ориентируйтесь на пакеты 5-15 МБ — точную оптимальную цифру лучше подбирать под свою нагрузку и диск (NVMe и обычный SSD дадут разный потолок).
- Ошибка
circuit_breaking_exception: [parent] Data too large— почти всегда следствие того, что запрос (обычно тяжёлая агрегация или глубокая пагинация) пытается вытащить в память больше, чем позволяет heap. Для листания больших выдач используйтеsearch_afterвместоfrom/size— глубокий offset в OpenSearch дорог по памяти на каждой ноде.
- После окончания массовой загрузки старых данных, которые больше не пишутся,
_forcemergeуменьшает число сегментов и ускоряет последующий поиск:
curl -s -u admin:'ВашПароль' -k -X POST "https://localhost:9200/my-index/_forcemerge?max_num_segments=1"
Учтите, что forcemerge — тяжёлая операция по I/O, запускать её на "живом" горячем индексе, который продолжают активно писать, не стоит.
Ошибки Security plugin и TLS при подключении
Свежая установка OpenSearch поднимается с демо-сертификатами и предупреждением в логах вида OpenSearch Security not fully configured. Это нормально для первого запуска, но означает, что сертификаты и пароли — тестовые и не годятся для боевого сервера.
Типичная ошибка при обращении к API без флага -k или сертификата — curl ругается на untrusted certificate, потому что демо-CA не знаком системе:
curl -s -u admin:'ВашПароль' --cacert /etc/opensearch/certs/root-ca.pem \
"https://localhost:9200/_cluster/health?pretty"
Для боевого сервера сертификаты нужно сгенерировать свои (или получить от внутреннего CA) и применить конфигурацию security через securityadmin.sh:
cd /usr/share/opensearch/plugins/opensearch-security/tools
./securityadmin.sh -cd ../securityconfig/ -icl -nhnv \
-cacert /etc/opensearch/certs/root-ca.pem \
-cert /etc/opensearch/certs/admin.pem \
-key /etc/opensearch/certs/admin-key.pem
Отключать security plugin (plugins.security.disabled: true) имеет смысл только в изолированном тестовом окружении, где порт 9200 никогда не смотрит наружу. Если нода слушает 0.0.0.0 без аутентификации — это открытая база с логами и, возможно, персональными данными в интернете; такие инстансы находят сканеры за считаные часы. Обязательно проверьте network.host в opensearch.yml и правила файрвола отдельно от настроек самого security plugin.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Чем OpenSearch принципиально отличается от Elasticsearch?
Исторически это форк Elasticsearch 7.10.2, сделанный после смены лицензии на SSPL. API и большая часть возможностей совместимы, лицензия — Apache 2.0. Дальше проекты развиваются раздельно, и по мере накопления версий различия в фичах и деталях поведения будут расти — при миграции старых конфигов и Kibana-дашбордов это стоит проверять руками, а не считать 1:1.
Сколько RAM нужно под OpenSearch на своём сервере?
Для тестового или небольшого single-node инстанса под логи хватает 4-8 ГБ, из которых половина уйдёт под heap, половина — под файловый кэш ОС. Под серьёзный поток логов или полнотекстовый поиск с индексами в десятки гигабайт стоит закладывать 16 ГБ и выше — точная цифра зависит от объёма и частоты индексации, универсальной формулы тут нет.
Можно ли развернуть OpenSearch на одной ноде без кластера?
Да, это обычный сценарий для небольших проектов — просто явно занулите number_of_replicas, как описано выше, иначе кластер будет вечно висеть в жёлтом статусе. Само по себе это не мешает работе, просто путает при мониторинге.
Нужно ли ставить Java отдельно?
Нет, начиная с современных релизов OpenSearch поставляется с собственным бандлованным JDK, и в норме отдельная установка Java не требуется. Если в системе стоит своя Java и сервис почему-то использует её вместо бандла — проверьте переменную окружения OPENSEARCH_JAVA_HOME.
Как обновить OpenSearch на проде без риска потерять данные?
Перед любым апгрейдом снимите снапшот индексов через Snapshot API в отдельный репозиторий (S3-совместимое хранилище или примонтированный диск), затем обновляйте по одной ноде с проверкой _cluster/health между шагами. На одиночной ноде без резервной копии откатиться после неудачного обновления будет негде.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →