Проблемы производительности кластера. Оптимизация

Добрый день. Есть кластер (весь кластер базируется на ОС CentOs 6.9) в составе которого:

Дата нода 1 (на хардварном сервере):
24 CPU X5660 @ 2.80GHz
RAM 96Gb
На ней стоит es со следующими параметрами:
elastic (node.master: true, node.data: true, node.ingest: true, node.ml: false) с heap size -Xms30g -Xmx30g
так же задействованы:
bootstrap.memory_lock: true
bootstrap.system_call_filter: false

Дата нода 2 (на хардварном сервере):
24 CPU X5690 @ 3.47GHz
RAM 96Gb
На ней стоит es со следующими параметрами:
elastic (node.master: true, node.data: true, node.ingest: true, node.ml: false) с heap size -Xms30g -Xmx30g
так же задействованы:
bootstrap.memory_lock: true
bootstrap.system_call_filter: false

Есть хранилка (на 7200 дисках) которая разделена на два луна по 18Тб и каждый лун по файбер ченел презентован каждой из дата нод.

Ingest нода (виртуальная машина):
4 CPU E5-2698 v4 @ 2.20GHz
RAM 10Gb
На ней стоит es со следующими параметрами:
elastic (node.master: false, node.data: false, node.ingest: true, node.ml: false) с heap size -Xms6g -Xmx6g
так же задействованы:
bootstrap.memory_lock: true
bootstrap.system_call_filter: false

Мастер Нода (виртуальная машина):
4 CPU E5-2698 v4 @ 2.20GHz
RAM 20Gb
На ней стоит es со следующими параметрами:
elastic (node.master: true, node.data: false, node.ingest: false, node.ml: false, search.remote.connect: false) с heap size -Xms3g -Xmx3g
так же задействованы:

bootstrap.memory_lock: true
bootstrap.system_call_filter: false
cluster.routing.allocation.same_shard.host: true
cluster.routing.allocation.disk.watermark.low: 97%
cluster.routing.allocation.disk.watermark.high: 98%
cluster.routing.allocation.disk.watermark.flood_stage: 99%
discovery.zen.minimum_master_nodes: 2

кроме elastic на этой машине крутиться так же:
redis (из него логсташ забирает данные)
kibana
nginx (с помощью него, трафик от кибаны балансируется между двумя дата нодами)
Logstash (-Xms4g -Xmx4g)

Логсташ слушает по udp порт и принимает нетфлоу трафик (рейт от 1900 до 2300) , а так же ходит в редис и забирает оттуда данные отличные от нетфлоу ( рейст поступающий в редис от 1000 до 3500 в сек) . ТАк же у логсташа есть множество jdbc инпутов ( общим рейтом около 50 евентов в секунду)

нетфлоу пишится в один индекс. Из редиса данные пишутся в несколько индексов, но самых весомых по рейту только два и иногда с высоким рейтом подаются данные на третий.

С учетом реплик, каждая дата нода имеет по 5Тб данных.
Своп на всех серверах кластера отключен.

Наблюдается проблема с высокой утилизацией железа дата нод в результате чего кластер становиться не стабильным: медленно работает кибана, повышается латенси индексации и поисковых запросов, на фоне повышения латенси снижается рейт индексации. В результате данные по udp теряются, а то что в редисе не успевает разбираться из-за чего объем редиса растет, а после достижения редисом максимального значения происходит так же потеря входящих данных. При этом загруженность ингест ноды в любое время стремиться к нулю. Проблем с мастер нодой тоже не наблюдается, хотя утилизация некоторая имеется, но по большей части за счет логсташа, кибаны и прочей обвязки и в меньшей степени расходует ресурсы мастер эластик. ТАк же заметил что последовательный рестарт эластиков на дата нодах заметно улучшает ситуацию и кластер начинает какое-то время работать лучше, к этой крайности приходиться прибегать когда кластер становиться практически полностью недоступным.

Последнюю волну проблем с кластером удалось задокументировать, ниже приложу описание со скриншотами:
метрики с одного из индексов (один из наиболее активно индексирующися индексов данные которого приходят через редис), при этом кластер в момент снятия скриншота желтый, по причине перезагрузки одной из дата ноды в связи с недоступность кластера


есть еще несколько вариантов этого скрина метрик :

метрики с одной из нод (при этом пробел на графиках это не ребут ноды,)


При этом index.refresh_interval на наиболее активных индексах стоит от 20 до 60 секунд.
При этом в момент большого лоад аверейдж на дата нодах вывод команды
iostat -m -t 1
колонка MB_wrtn/s
скачет в диапазоне от 30 то 300

вот еще метрики за тот же день с одной дата ноды (ту на которой рестартил эластик):


и со со второй там где рестарт не делал:

В 19 часов понизил index.refresh_interval до 2-5 секунд на разных наиболее активных индексов.
Все описанное выше происходило 10 числа. АДльше расскажу что происходило с кластером 11 числа:
дата нода 11 числа:


таже самая дата нода 10 числа:

вторая дата нода 11 числа:


таже самая нода 10 числа:

Кластер overview 11 числа:


Кластер overview 10 числа:

Версии эластика везде 6.1.2

Очень прошу помочь понять в чем моя проблема и посоветовать как можно ее решить.

Так же есть лишняя виртуальная машина
4 CPU E5-2698 v4 @ 2.20GHz
RAM 8Gb
Которая никак не задействована. При этом ресурсы между виртуалками можно перекидывать или например сделать одну из трех. Это я к тому, может виртуалки можно как-то более полезно задействовать чем сейчас.

JVM Heap на нестабильных нодах слишком высокий - скорее всего это и вызывает проблемы. Надо смотреть куда этот heap уходит, либо добавлять еще железо

Можно кратенькую инструкцию или ссылку как проверить вашу теорию про heap size ?
Можете дать рекомендации по расширению кластера? В частности хотелось бы услышать мнение на тему добавления двух аналогичных хардварных серверов но с объемом диска по 1.5ТБ каждый ?
Виртуалки я использую корректно? Они в моем кластере несут какую-то полезность? Можно ли как-то помочь кластеру чем-то кроме дата нод?

Теорию? Вы на графики посмотрите - у вас GC почти минуту занимает и почти ничего при этом не освобождает!

У вас не с диском проблема, а с памятью. Если добавить машину с меньшем количеством памяти, чем существующие ноды, будет только хуже.

Не знаю - надо смотреть куда память уходит. Можно начать с анализа nodes stats.

Я не сильно разбираюсь в этом потому и обратился в комьюнити. Буду смотреть nodes stats тогда. ЧТо конкретно там смотреть, jvm? Или где почитать об этом? Надо ли собирать статистику по выводу

GET /_nodes/stats

А если добавить памяти текущим дата нодам?

Кстати сам heap size я так понимаю увеличивать нельзя даже при 64 битной архитектуре?

Начните с https://www.elastic.co/guide/en/elasticsearch/guide/current/heap-sizing.html там про heap хорошо написано

В stats надо основные растратчики памяти проверить

  • indices.segments.*memory
  • indices.request_cache.memory_size
  • indices.fielddata.memory_size
  • indices.completion.size
  • breakers.*.estimated_size

Вот данные по одной из дата нод в момент когда кластеру плохо

++++++++indices.segments.*memory
"memory" : "9.5gb"
"terms_memory" : "7gb"
"stored_fields_memory" : "2.2gb"
"term_vectors_memory" : "0b"
"norms_memory" : "20.6mb"
"points_memory" : "193.4mb"
"doc_values_memory" : "29.7mb"
"index_writer_memory" : "415.6mb"
"version_map_memory" : "37.7mb"
"fixed_bit_set" : "11.1gb"

++++++++indices.request_cache.memory_size
"memory_size" : "304.6mb"

++++++++indices.fielddata.memory_size
"memory_size" : "1.7gb"

++++++++indices.completion.size
"size" : "0b"

++++++++breakers.*.estimated_size
"estimated_size" : "288.2kb"

Сможете что-то подсказать?

А сколько хипа на этой машине было в этот момент (в целом и использованного)? И какая это версия Elasticsearch?

версия 6.1.2
хип сайз был настроен на 30Гб, напомню, всего на машине 100Гб памяти, вот сколько использовано

"jvm" : {
        "timestamp" : 1528099189192,
        "uptime" : "6.7d",
        "uptime_in_millis" : 583694283,
        "mem" : {
          "heap_used" : "29.4gb",
          "heap_used_in_bytes" : 31660352840,
          "heap_used_percent" : 98,
          "heap_committed" : "29.8gb",
          "heap_committed_in_bytes" : 32055230464,
          "heap_max" : "29.8gb",
          "heap_max_in_bytes" : 32055230464,
          "non_heap_used" : "218.4mb",
          "non_heap_used_in_bytes" : 229091664,
          "non_heap_committed" : "230.6mb",
          "non_heap_committed_in_bytes" : 241860608,

Да,18Гб где-то скрываются. Похоже, что память утекает. Я бы попробовал проапгрейдить до 6.2.4 и посмотреть, может уже эта проблема уже исправлена. Если нет - то надо будет искать утечку в heapdump.

Мне кажется что существует зависимость, чем больше данных тем быстрее утекает память. Когда данных было Data: 6.3 TB Indices: 277 Shards: 556, кластер жил после очередного ребута 5-7 дней и GC почти не освобождал память. А вот когда я данных часть удалил и осталось Data: 3.4 TB Indices: 260 Shards: 498, тогда GC стал очищать по 7-10Гб и кластер спокойно работает много дней, т.е. такое впечатление что утечки или нет или она очень маленькая.
Есть ли какая-то зависимость от объема данных, какая?

А heapdump же вроде срабатывает когда эластик вылетает с ошибкой out of memory ? У меня такой ошибки нет, значит и heapdump я не получу.

Я внесу свои 5 копеек.

  1. Необходимо проверить, нет ли затупов по диску. Через тулзу atop (запустить atop -D 1) и смотреть в самый правый столбик по диску параметр avio (среднее время отклика) если более 5ms то это плохо.
  2. Покажите конфиг JVM.
    На 30 Гб оперативы под heap у Вас рано или поздно начнется фрагментация памяти. Это видно по демону kswapd0 в топе, если он всегда в топе процессов и большой систайм (htop посмотреть с отображением потоков ядра) значит у вас система не успевает схлопывать страницы памяти.
    Что у стандарт де факто:
    Для Java Heap использовать Huge Pages для x86 это 2mb одна страница, для ppc64 это 16mb страница. Почему Huge Pages? Большие страницы не фрагментируются и не уходят в swap
    Как включить?
    Через sysctl (Буду приводить для RHEL 7, я думаю на 6-ой не сложно будет переложить)
    В /etc/sysctl.d/

Создаем 3 файлика:
70-hugepages.conf с содержанием:
vm.nr_hugepages=16896
vm.hugetlb_shm_group=992
vm.nr_overcommit_hugepages = 512

Что есть что:
vm.nr_hugepages=16896 (Кол-во страниц по 2 мб (берем с запасом немного))
vm.hugetlb_shm_group=992 (группа эластика в /etc/passwd, чтоб никто не мог кроме него их юзать),
vm.nr_overcommit_hugepages = 512 (оверкоммит, если вдруг все страницы исчерпаны (доп резерв))

Создаем второй файлик 60-shmmem.conf и расчитать самому (это конфиг для 64 Гб RAM):
kernel.shmmax = 64424509440
kernel.shmall = 15728640

Что есть что:
kernel.shmmax = 64424509440 (кол-во разрешенной памяти для использорвания в виде разделяемой в байтах)
kernel.shmall = 15728640 (тот же объем разделяемой памяти с стандартных страницах для x86 это 4096 байт в странице, для ppc64 это 65536 байт) Расчет: kernel.shmmax / 4096 = kernel.shmall

30-mem_defrag.conf:
vm.min_free_kbytes = 1048576

Что есть что:
vm.min_free_kbytes = 1048576 (это минимальный свободный объем оперативы, так же служить low water mark'ом для запуска процесса дефрагментации памяти, чем больше тем раньше начинается процесс дефрагментации
почитать об этом можно тут: https://habr.com/company/odnoklassniki/blog/266005/) Я сразу ставлю 1 Гб на все системы более 64Гб оперативы

Необходио отключить HTP, RedHat рекомендует их выключать, если нет прямого использования: https://www.thegeekdiary.com/centos-rhel-6-how-to-disable-transparent-huge-pages-thp/

Что далее: снести openjdk, поставить провославную Oracle JDK 9
Почему 9? Все просто, GC ускорен в 3 раза по сравнению с 8 (видел такое заявление от Oracle).
И почему JDK Oracle? На openjdk видел неприятный баг, как лечить не нашел. Выражается при использовании хипа более 32 Гб с HugePages Java падает с ошибкой что не может аллоцировать память.
Почему JDK а не JRE? Есть тулзы для визуального просмотра работы GC через VisualVM (с помошью jstatd)

  1. Опции JVM:

-Xms30g
-Xmx30g
-XX:-UseParNewGC (Отключаем sweepGC, будем юзать новый GC G1)
-XX:-UseConcMarkSweepGC (Отключаем sweepGC, будем юзать новый GC G1)
-XX:+UnlockExperimentalVMOptions (Включаем эксперементалье опции)
-XX:+UseG1GC (говорим, что будем юзать G1 GC)
-XX:ParallelGCThreads=8 (кол-во потоков GC по ядрам)
-XX:ConcGCThreads=2 (кол-во потоков маркировщиков CPU core / 4)
-XX:G1HeapRegionSize=15m (размер регионов памяти в Heap 30gb(30720mb) / 2048 регионов = 15mb 1 регион)
-XX:+ScavengeBeforeFullGC (совершать сборку мусора в young поколении перед FullGC)
-XX:MaxGCPauseMillis=200 (мягкая пауза GC)
-XX:G1ReservePercent=15 (Резервируем место в % от общего объема Heap для резких скачков)
-XX:G1MixedGCLiveThresholdPercent=65 (Комбинированя сборка мусора при заполнении heap %)
-XX:InitiatingHeapOccupancyPercent=45 (На каком % заполенения heap запускать процессы маркировщики)
-XX:-G1UseAdaptiveIHOP (отключаем адаптивный % от heap для сборки мусора)
-XX:+DisableExplicitGC (Не даем делать вызов приложению system.gc(), оставим решение сборки мусора самой Java)
-XX:+UseCompressedOops (включаем компрессию указателей)
-XX:+TieredCompilation (компиляция кода, вот тут лучше офф доку почитать)
-XX:+AggressiveOpts (агресивные оптимизации, на самом деле включает несколько доп флагов)
-XX:+UseLargePages (говорим что будем испоьзовать большие страницы)
-XX:+UseNUMA (если есть NUMA то использовать распределение памяти по зонам (2 и более сокетные сервера))
-XX:-UseNUMAInterleaving (говорим, что не использовать Numa Interleaving, зачем и почему надо почитать доки для понимая работы NUMA)
-XX:+AlwaysPreTouch (сразу преалоцировать Heap)
-XX:+PrintCommandLineFlags (Печатать в лог флаги запуска Java)
9-:-Xlog:gc*,gc+age=trace,gc+heap=debug:file=/var/log/elasticsearch/gc.log:time,pid,tags:filecount=32,filesize=64m (новый вид логирования в Java 9)

Затем дать поработать сутки и лог GC загрузить в http://gceasy.io/index.jsp, чтоб оценить работу и проблемы если они есть

Это что касается JVM.
Выложи еще сам конфиг elasticsearch посмотреть и конфиг индекса

1 Like

Я вот на что смотрю:

"heap_used" : "29.4gb",
-
"indices.segments.memory" : "9.5gb"
"indices.fielddata.memory_size": "1.7gb"
"indices.request_cache.memory_size": "304.6mb"

Получается, что половина памяти ушла куда-то. Если уменьшить количество данных, то уменьшится нагрузка на память ("indices.segments.memory" и "indices.fielddata.memory_size"), тогда даже c утечкой все будет работать гораздо лучше и у GC будет больше места развернуться.

Я бы запустил на сервере jstatd и через VisualVM посмотрел как работает GC, как заполняются young и old generations

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.