Кластер индексатора 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_managerData (узел данных)
Узлы с ролью data хранят шарды индексов и выполняют операции поиска и агрегации:
- Хранение первичных шардов и реплик
- Выполнение поисковых запросов
- Агрегация данных
- Индексация новых документов
Data-узлы потребляют наибольшее количество ресурсов (CPU, RAM, диск).
# opensearch.yml - dedicated data node
node.name: indexer-data-01
node.roles:
- dataIngest (узел приема данных)
Узлы с ролью 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) позволяет автоматизировать управление индексами на основе возраста, размера или количества документов. Типичный жизненный цикл включает состояния:
- Hot - активная запись и чтение, максимальная производительность
- Warm - только чтение, сниженные ресурсы
- Cold - архивное хранение, минимальные ресурсы
- 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=infinityRefresh 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.0 | Elastic License / SSPL |
| Безопасность | OpenSearch Security (встроена) | X-Pack Security (платная в прошлом) |
| ISM | Index State Management | Index Lifecycle Management (ILM) |
| ML | ML Commons plugin | ML features (X-Pack) |
| Стоимость | Бесплатно | Бесплатно (Basic) / Коммерческая |
Splunk Indexer Cluster
| Характеристика | Wazuh Indexer | Splunk Indexer |
|---|---|---|
| Формат хранения | JSON-документы в Lucene-индексах | Проприетарный (tsidx + journal) |
| Шардирование | Настраиваемые шарды и реплики | Репликация через search factor / replication factor |
| Жизненный цикл | ISM-политики (hot/warm/cold/delete) | SmartStore, frozen tier |
| Поиск | DSL-запросы, PPL | SPL (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
Причина: первичные шарды не распределены. Возможные причины: нехватка дискового пространства, сбой узла, повреждение данных.
Решение:
- Проверьте причину нераспределения:
curl -sk -u admin:password \
"https://localhost:9200/_cluster/allocation/explain?pretty"- Проверьте дисковое пространство:
curl -sk -u admin:password \
"https://localhost:9200/_cat/allocation?v"- При необходимости принудительно перераспределите шарды:
curl -sk -u admin:password \
-X POST "https://localhost:9200/_cluster/reroute?retry_failed=true"Disk Watermarks (пороги диска)
OpenSearch прекращает запись при достижении пороговых значений использования диска:
| Порог | Значение по умолчанию | Поведение |
|---|---|---|
| Low watermark | 85% | Новые шарды не размещаются на узле |
| High watermark | 90% | Шарды переносятся с узла |
| Flood stage | 95% | Индексы переводятся в режим 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.
Решение:
Увеличьте JVM heap в
/etc/wazuh-indexer/jvm.options(не более 50% RAM и не более 32 ГБ).Проверьте потребление heap:
curl -sk -u admin:password \
"https://localhost:9200/_cat/nodes?v&h=name,heap.percent,heap.max"Уменьшите количество шардов или индексов (рассмотрите ISM-политику удаления старых данных).
Добавьте 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 .