Кластер индексатора Wazuh - OpenSearch и хранение данных

Кластер индексатора Wazuh построен на OpenSearch и обеспечивает хранение, индексацию и полнотекстовый поиск событий безопасности. Индексатор принимает данные от серверов Wazuh через Filebeat, организует их в индексы с настраиваемым количеством шардов и реплик, предоставляет API для поиска и управления жизненным циклом данных.

Архитектура кластера

Роли узлов

Каждый узел кластера OpenSearch выполняет одну или несколько ролей. Правильное распределение ролей критически важно для производительности и отказоустойчивости.

Cluster-manager (менеджер кластера)

Узел с ролью cluster_manager управляет состоянием кластера:

  • Создание и удаление индексов
  • Распределение шардов по узлам
  • Отслеживание состояния узлов
  • Управление шаблонами индексов и ISM-политиками

В продуктивном кластере рекомендуется выделять 3 узла с ролью cluster_manager для кворума. Эти узлы не должны хранить данные (не назначайте им роль data).

# opensearch.yml - dedicated cluster-manager node
node.name: indexer-manager-01
node.roles:
  - cluster_manager

Data (узел данных)

Узлы с ролью data хранят шарды индексов и выполняют операции поиска и агрегации:

  • Хранение первичных шардов и реплик
  • Выполнение поисковых запросов
  • Агрегация данных
  • Индексация новых документов

Data-узлы потребляют наибольшее количество ресурсов (CPU, RAM, диск).

# opensearch.yml - dedicated data node
node.name: indexer-data-01
node.roles:
  - data

Ingest (узел приема данных)

Узлы с ролью ingest выполняют предварительную обработку документов перед индексацией:

  • Трансформация полей
  • Обогащение данных
  • Преобразование форматов

В типичной установке Wazuh роль ingest совмещается с ролью data, поскольку Filebeat передает данные в готовом формате.

Coordinating (координирующий узел)

Узел без явно назначенных ролей выступает координатором:

  • Маршрутизация поисковых запросов к нужным data-узлам
  • Объединение результатов из нескольких шардов
  • Снижение нагрузки на data-узлы при большом количестве параллельных запросов
# opensearch.yml - coordinating-only node
node.name: indexer-coord-01
node.roles: []

Типовые конфигурации кластера

Минимальный кластер (3 узла)

Узел 1: cluster_manager + data
Узел 2: cluster_manager + data
Узел 3: cluster_manager + data

Продуктивный кластер (5+ узлов)

Узлы 1-3: cluster_manager (dedicated, без данных)
Узлы 4-6: data
Узел 7:   coordinating (опционально)

Обнаружение и формирование кластера

Конфигурация discovery

Узлы кластера находят друг друга через механизм обнаружения (discovery). Конфигурация задается в opensearch.yml:

# Список seed-узлов для начального обнаружения
discovery.seed_hosts:
  - 192.168.1.20
  - 192.168.1.21
  - 192.168.1.22

# Узлы, участвующие в начальном формировании кластера (bootstrap)
cluster.initial_cluster_manager_nodes:
  - indexer-01
  - indexer-02
  - indexer-03

Параметр discovery.seed_hosts содержит список IP-адресов или FQDN узлов, к которым новый узел обращается для присоединения к кластеру. Рекомендуется указывать все узлы с ролью cluster_manager.

Параметр cluster.initial_cluster_manager_nodes используется только при первом запуске кластера (bootstrap). После успешного формирования кластера этот параметр можно удалить. Он содержит имена узлов (node.name), а не IP-адреса.

Полный пример opensearch.yml

cluster.name: wazuh-cluster
node.name: indexer-01
node.roles:
  - cluster_manager
  - data

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

discovery.seed_hosts:
  - 192.168.1.20
  - 192.168.1.21
  - 192.168.1.22

cluster.initial_cluster_manager_nodes:
  - indexer-01
  - indexer-02
  - indexer-03

plugins.security.ssl.transport.enabled: true
plugins.security.ssl.http.enabled: true
plugins.security.ssl.transport.pemcert_filepath: /etc/wazuh-indexer/certs/indexer.pem
plugins.security.ssl.transport.pemkey_filepath: /etc/wazuh-indexer/certs/indexer-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: /etc/wazuh-indexer/certs/root-ca.pem
plugins.security.ssl.http.pemcert_filepath: /etc/wazuh-indexer/certs/indexer.pem
plugins.security.ssl.http.pemkey_filepath: /etc/wazuh-indexer/certs/indexer-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: /etc/wazuh-indexer/certs/root-ca.pem

compatibility.override_main_response_version: true

Стратегия шардирования

Принципы шардирования

Шарды (shards) - это единицы хранения и распределения данных в OpenSearch. Каждый индекс состоит из одного или нескольких первичных шардов, каждый из которых может иметь реплики.

Рекомендации по количеству шардов:

  • Количество первичных шардов должно равняться количеству data-узлов в кластере
  • Оптимальный размер одного шарда: 10-50 ГБ
  • Слишком большое количество мелких шардов создает избыточную нагрузку на cluster-manager
  • Слишком малое количество крупных шардов ограничивает параллелизм поиска

Количество шардов нельзя изменить после создания индекса - для изменения требуется переиндексация (reindex).

Конфигурация реплик

Реплики обеспечивают отказоустойчивость и увеличивают пропускную способность чтения:

  • Для однонодового кластера: number_of_replicas: 0
  • Для кластера из 3+ узлов: number_of_replicas: 1
  • Для критически важных данных: number_of_replicas: 2

Количество реплик можно изменить в любой момент без переиндексации:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/wazuh-alerts-*/_settings" \
  -H "Content-Type: application/json" \
  -d '{"index": {"number_of_replicas": 1}}'

Настройка шаблона индексов

Wazuh использует шаблоны индексов для автоматического применения настроек к новым индексам. Настройка выполняется через API индексатора:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_template/wazuh-custom" \
  -H "Content-Type: application/json" \
  -d '{
    "order": 1,
    "index_patterns": ["wazuh-alerts-*"],
    "settings": {
      "index.number_of_shards": 3,
      "index.number_of_replicas": 1,
      "index.refresh_interval": "5s"
    }
  }'

Параметр order: 1 гарантирует, что пользовательский шаблон применяется поверх стандартного шаблона Filebeat.

Индексные шаблоны Wazuh

Wazuh создает несколько типов индексов для различных категорий данных:

Шаблон индексаОписаниеОбъем данных
wazuh-alerts-*Алерты безопасности (результаты срабатывания правил)Основной поток
wazuh-archives-*Все события (включая несработавшие правила)Очень большой (если включен)
wazuh-statistics-*Статистика производительности менеджераНебольшой
wazuh-monitoring-*Данные мониторинга состояния агентовСредний

Индексы wazuh-archives-* по умолчанию отключены. Их включение значительно увеличивает потребление дискового пространства и требует соответствующего масштабирования хранилища.

Управление жизненным циклом индексов (ISM)

Обзор ISM-политик

Index State Management (ISM) позволяет автоматизировать управление индексами на основе возраста, размера или количества документов. Типичный жизненный цикл включает состояния:

  1. Hot - активная запись и чтение, максимальная производительность
  2. Warm - только чтение, сниженные ресурсы
  3. Cold - архивное хранение, минимальные ресурсы
  4. Delete - автоматическое удаление

Создание ISM-политики

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_plugins/_ism/policies/wazuh-alerts-policy" \
  -H "Content-Type: application/json" \
  -d '{
    "policy": {
      "description": "Wazuh alerts lifecycle policy",
      "default_state": "hot",
      "states": [
        {
          "name": "hot",
          "actions": [
            {
              "rollover": {
                "min_size": "25gb",
                "min_index_age": "1d"
              }
            }
          ],
          "transitions": [
            {
              "state_name": "warm",
              "conditions": {
                "min_index_age": "7d"
              }
            }
          ]
        },
        {
          "name": "warm",
          "actions": [
            {
              "replica_count": {
                "number_of_replicas": 0
              }
            },
            {
              "force_merge": {
                "max_num_segments": 1
              }
            }
          ],
          "transitions": [
            {
              "state_name": "cold",
              "conditions": {
                "min_index_age": "30d"
              }
            }
          ]
        },
        {
          "name": "cold",
          "actions": [
            {
              "read_only": {}
            }
          ],
          "transitions": [
            {
              "state_name": "delete",
              "conditions": {
                "min_index_age": "90d"
              }
            }
          ]
        },
        {
          "name": "delete",
          "actions": [
            {
              "delete": {}
            }
          ],
          "transitions": []
        }
      ],
      "ism_template": [
        {
          "index_patterns": ["wazuh-alerts-*"],
          "priority": 100
        }
      ]
    }
  }'

Rollover - ротация индексов

Rollover создает новый индекс при достижении заданных условий:

  • min_size - максимальный размер индекса (например, 25gb)
  • min_index_age - максимальный возраст индекса (например, 1d)
  • min_doc_count - максимальное количество документов

Условия комбинируются по принципу OR - ротация происходит при достижении любого из условий.

Настройка производительности

JVM Heap Size

Размер кучи JVM - критический параметр производительности индексатора.

Правила:

  • Установите -Xms и -Xmx на одинаковое значение для предотвращения изменения размера кучи в рантайме
  • Выделяйте не более 50% оперативной памяти системы (оставшаяся память используется для файловых кешей ОС)
  • Максимальное значение: 32 ГБ (при превышении отключается Compressed OOPs, что снижает эффективность)

Конфигурация в файле /etc/wazuh-indexer/jvm.options:

-Xms4g
-Xmx4g

Рекомендации по размеру:

Оперативная памятьJVM HeapПримечание
8 ГБ4 ГБМинимум для продуктивной среды
16 ГБ8 ГБСредняя нагрузка
32 ГБ16 ГБВысокая нагрузка
64 ГБ32 ГБМаксимальное значение

Блокировка памяти

Для предотвращения свопинга JVM включите блокировку памяти:

# opensearch.yml
bootstrap.memory_lock: true

В конфигурации systemd:

# /etc/systemd/system/wazuh-indexer.service.d/override.conf
[Service]
LimitMEMLOCK=infinity

Refresh Interval

Параметр refresh_interval определяет частоту обновления данных для поиска. Значение по умолчанию - 1 секунда. Увеличение интервала повышает производительность записи:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/wazuh-alerts-*/_settings" \
  -H "Content-Type: application/json" \
  -d '{"index": {"refresh_interval": "5s"}}'

Для массовой загрузки данных можно временно отключить refresh:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/wazuh-alerts-*/_settings" \
  -H "Content-Type: application/json" \
  -d '{"index": {"refresh_interval": "-1"}}'

Настройка merge

Уменьшение количества сегментов через force merge повышает производительность поиска на неизменяемых индексах:

curl -sk -u admin:password \
  -X POST "https://localhost:9200/wazuh-alerts-2024.01.01/_forcemerge?max_num_segments=1"

Применяйте force merge только к индексам, в которые больше не ведется запись (warm/cold состояние).

Количество шардов на узел

Ограничьте максимальное количество шардов на узел для предотвращения деградации:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_cluster/settings" \
  -H "Content-Type: application/json" \
  -d '{"persistent": {"cluster.max_shards_per_node": 1000}}'

Мониторинг здоровья кластера

Основные запросы мониторинга

# Состояние кластера (green/yellow/red)
curl -sk -u admin:password \
  "https://localhost:9200/_cluster/health?pretty"

# Список узлов с ресурсами
curl -sk -u admin:password \
  "https://localhost:9200/_cat/nodes?v&h=name,role,heap.percent,disk.used_percent,cpu"

# Список индексов с размерами
curl -sk -u admin:password \
  "https://localhost:9200/_cat/indices/wazuh-*?v&h=index,health,status,pri,rep,docs.count,store.size&s=index:desc"

# Распределение шардов
curl -sk -u admin:password \
  "https://localhost:9200/_cat/shards/wazuh-*?v&h=index,shard,prirep,state,docs,store,node"

# Нераспределенные шарды
curl -sk -u admin:password \
  "https://localhost:9200/_cat/shards?v&h=index,shard,prirep,state,unassigned.reason&s=state:desc"

# Использование диска
curl -sk -u admin:password \
  "https://localhost:9200/_cat/allocation?v"

Интерпретация статуса кластера

СтатусОписаниеДействие
GreenВсе первичные и реплика-шарды распределеныНет необходимости в действиях
YellowВсе первичные шарды распределены, некоторые реплики нетПроверьте количество узлов и настройки реплик
RedНекоторые первичные шарды не распределеныНемедленное расследование и восстановление

Резервное копирование (Snapshot/Restore)

Регистрация репозитория

Файловая система (NFS):

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_snapshot/wazuh-backups" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "fs",
    "settings": {
      "location": "/mnt/snapshots/wazuh",
      "compress": true
    }
  }'

Amazon S3:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_snapshot/wazuh-s3-backups" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "s3",
    "settings": {
      "bucket": "wazuh-snapshots",
      "region": "us-east-1",
      "base_path": "indexer-snapshots",
      "compress": true
    }
  }'

Путь к файловому репозиторию должен быть указан в opensearch.yml:

path.repo: ["/mnt/snapshots/wazuh"]

Создание снапшота

# Полный снапшот
curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_snapshot/wazuh-backups/snapshot-$(date +%Y%m%d)?wait_for_completion=false" \
  -H "Content-Type: application/json" \
  -d '{
    "indices": "wazuh-alerts-*,wazuh-archives-*",
    "ignore_unavailable": true,
    "include_global_state": false
  }'

# Проверка статуса снапшота
curl -sk -u admin:password \
  "https://localhost:9200/_snapshot/wazuh-backups/_status?pretty"

# Список снапшотов
curl -sk -u admin:password \
  "https://localhost:9200/_snapshot/wazuh-backups/_all?pretty"

Восстановление из снапшота

curl -sk -u admin:password \
  -X POST "https://localhost:9200/_snapshot/wazuh-backups/snapshot-20240101/_restore" \
  -H "Content-Type: application/json" \
  -d '{
    "indices": "wazuh-alerts-2024.01.01",
    "ignore_unavailable": true,
    "include_global_state": false,
    "rename_pattern": "(.+)",
    "rename_replacement": "restored-$1"
  }'

Автоматизация снапшотов

Для автоматического создания снапшотов добавьте задание в cron:

# /etc/cron.d/wazuh-snapshot
0 2 * * * root curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_snapshot/wazuh-backups/snapshot-$(date +\%Y\%m\%d)" \
  -H "Content-Type: application/json" \
  -d '{"indices":"wazuh-alerts-*","ignore_unavailable":true,"include_global_state":false}'

Сравнение с другими платформами

Elasticsearch Cluster

ХарактеристикаWazuh Indexer (OpenSearch)Elasticsearch
ОсноваOpenSearch 2.x (fork Elasticsearch 7.10)Elasticsearch 8.x
ЛицензияApache 2.0Elastic License / SSPL
БезопасностьOpenSearch Security (встроена)X-Pack Security (платная в прошлом)
ISMIndex State ManagementIndex Lifecycle Management (ILM)
MLML Commons pluginML features (X-Pack)
СтоимостьБесплатноБесплатно (Basic) / Коммерческая

Splunk Indexer Cluster

ХарактеристикаWazuh IndexerSplunk Indexer
Формат храненияJSON-документы в Lucene-индексахПроприетарный (tsidx + journal)
ШардированиеНастраиваемые шарды и репликиРепликация через search factor / replication factor
Жизненный циклISM-политики (hot/warm/cold/delete)SmartStore, frozen tier
ПоискDSL-запросы, PPLSPL (Search Processing Language)
МасштабированиеГоризонтальное (добавление data-узлов)Горизонтальное (indexer peers)
СтоимостьБесплатноПо объему данных

Устранение неполадок

Кластер в статусе Yellow

Причина: реплика-шарды не распределены. Типично для однонодового кластера или когда количество реплик превышает количество data-узлов минус один.

Решение:

# Проверка нераспределенных шардов
curl -sk -u admin:password \
  "https://localhost:9200/_cluster/allocation/explain?pretty"

# Установка реплик в 0 для однонодового кластера
curl -sk -u admin:password \
  -X PUT "https://localhost:9200/wazuh-alerts-*/_settings" \
  -H "Content-Type: application/json" \
  -d '{"index": {"number_of_replicas": 0}}'

Кластер в статусе Red

Причина: первичные шарды не распределены. Возможные причины: нехватка дискового пространства, сбой узла, повреждение данных.

Решение:

  1. Проверьте причину нераспределения:
curl -sk -u admin:password \
  "https://localhost:9200/_cluster/allocation/explain?pretty"
  1. Проверьте дисковое пространство:
curl -sk -u admin:password \
  "https://localhost:9200/_cat/allocation?v"
  1. При необходимости принудительно перераспределите шарды:
curl -sk -u admin:password \
  -X POST "https://localhost:9200/_cluster/reroute?retry_failed=true"

Disk Watermarks (пороги диска)

OpenSearch прекращает запись при достижении пороговых значений использования диска:

ПорогЗначение по умолчаниюПоведение
Low watermark85%Новые шарды не размещаются на узле
High watermark90%Шарды переносятся с узла
Flood stage95%Индексы переводятся в режим read-only

Изменение порогов:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/_cluster/settings" \
  -H "Content-Type: application/json" \
  -d '{
    "persistent": {
      "cluster.routing.allocation.disk.watermark.low": "85%",
      "cluster.routing.allocation.disk.watermark.high": "90%",
      "cluster.routing.allocation.disk.watermark.flood_stage": "95%"
    }
  }'

Для снятия блокировки read-only после освобождения пространства:

curl -sk -u admin:password \
  -X PUT "https://localhost:9200/wazuh-alerts-*/_settings" \
  -H "Content-Type: application/json" \
  -d '{"index.blocks.read_only_allow_delete": null}'

JVM Out of Memory (OOM)

Симптомы: узел падает или перестает отвечать, в логах java.lang.OutOfMemoryError.

Решение:

  1. Увеличьте JVM heap в /etc/wazuh-indexer/jvm.options (не более 50% RAM и не более 32 ГБ).

  2. Проверьте потребление heap:

curl -sk -u admin:password \
  "https://localhost:9200/_cat/nodes?v&h=name,heap.percent,heap.max"
  1. Уменьшите количество шардов или индексов (рассмотрите ISM-политику удаления старых данных).

  2. Добавьте data-узлы для распределения нагрузки.

Нераспределенные шарды (Unassigned Shards)

Диагностика причины:

curl -sk -u admin:password \
  "https://localhost:9200/_cluster/allocation/explain?pretty" \
  -H "Content-Type: application/json" \
  -d '{"index":"wazuh-alerts-2024.01.01","shard":0,"primary":true}'

Частые причины:

  • NODE_LEFT - узел покинул кластер (восстановите узел или дождитесь возвращения)
  • ALLOCATION_FAILED - ошибка при размещении (проверьте логи узла)
  • INDEX_CREATED - индекс только что создан, шарды в процессе распределения
  • CLUSTER_RECOVERED - кластер восстанавливается после перезапуска

Для общего обзора инфраструктуры см. раздел инфраструктуры Wazuh . Данные в индексатор поступают из серверного кластера , а управление осуществляется через REST API .

Last updated on