Настройка OpenSearch как альтернативы Elasticsearch
OpenSearch — форк Elasticsearch 7.10, созданный Amazon после смены лицензии Elastic в 2021 году. Технически почти идентичен ES 7.x, лицензирован под Apache 2.0, активно развивается AWS и сообществом. Если вы не можете использовать проприетарный Elastic Stack (X-Pack) или привязаны к AWS, OpenSearch — практичная альтернатива. Ключевые отличия от ES 8.x: нет некоторых ES 8.x фич, но есть свои ML-возможности через OpenSearch ML Commons.
Сравнение с Elasticsearch
OpenSearch сохранил совместимость с Elasticsearch 7.x API — большинство клиентов ES 7.x работают без изменений. ES 8.x добавил breaking changes (обязательный TLS, изменения в security API, переименование типов), поэтому прямая совместимость нарушена.
Что есть в OpenSearch, чего нет в бесплатном Elasticsearch:
- Security (TLS, аутентификация, RBAC) без платной лицензии
- Alerting, anomaly detection в базовой версии
- Index Management (жизненный цикл индексов) без Elastic платного уровня
- SQL поддержка
Что есть только в Elasticsearch:
- EQL (Event Query Language)
- Esql
- Некоторые ML фичи Elastic
Установка OpenSearch
Docker Compose для production-like кластера:
version: '3'
services:
opensearch-node1:
image: opensearchproject/opensearch:2.13.0
container_name: opensearch-node1
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node1
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g"
- DISABLE_INSTALL_DEMO_CONFIG=true
- DISABLE_SECURITY_PLUGIN=false
ulimits:
memlock:
soft: -1
hard: -1
nofile:
soft: 65536
hard: 65536
volumes:
- opensearch-data1:/usr/share/opensearch/data
- ./opensearch.yml:/usr/share/opensearch/config/opensearch.yml
- ./certs/root-ca.pem:/usr/share/opensearch/config/root-ca.pem
- ./certs/node1.pem:/usr/share/opensearch/config/node1.pem
- ./certs/node1-key.pem:/usr/share/opensearch/config/node1-key.pem
ports:
- 9200:9200
- 9600:9600
opensearch-node2:
image: opensearchproject/opensearch:2.13.0
container_name: opensearch-node2
environment:
- cluster.name=opensearch-cluster
- node.name=opensearch-node2
- discovery.seed_hosts=opensearch-node1,opensearch-node2
- cluster.initial_cluster_manager_nodes=opensearch-node1,opensearch-node2
- bootstrap.memory_lock=true
- "OPENSEARCH_JAVA_OPTS=-Xms2g -Xmx2g"
- DISABLE_INSTALL_DEMO_CONFIG=true
- DISABLE_SECURITY_PLUGIN=false
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- opensearch-data2:/usr/share/opensearch/data
- ./opensearch.yml:/usr/share/opensearch/config/opensearch.yml
- ./certs/root-ca.pem:/usr/share/opensearch/config/root-ca.pem
- ./certs/node2.pem:/usr/share/opensearch/config/node2.pem
- ./certs/node2-key.pem:/usr/share/opensearch/config/node2-key.pem
opensearch-dashboards:
image: opensearchproject/opensearch-dashboards:2.13.0
container_name: opensearch-dashboards
ports:
- 5601:5601
environment:
OPENSEARCH_HOSTS: '["https://opensearch-node1:9200","https://opensearch-node2:9200"]'
DISABLE_SECURITY_DASHBOARDS_PLUGIN: "false"
volumes:
opensearch-data1:
opensearch-data2:
opensearch.yml:
cluster.name: opensearch-cluster
network.host: 0.0.0.0
plugins.security.ssl.transport.pemcert_filepath: node1.pem
plugins.security.ssl.transport.pemkey_filepath: node1-key.pem
plugins.security.ssl.transport.pemtrustedcas_filepath: root-ca.pem
plugins.security.ssl.transport.enforce_hostname_verification: false
plugins.security.ssl.http.enabled: true
plugins.security.ssl.http.pemcert_filepath: node1.pem
plugins.security.ssl.http.pemkey_filepath: node1-key.pem
plugins.security.ssl.http.pemtrustedcas_filepath: root-ca.pem
plugins.security.allow_unsafe_democertificates: false
plugins.security.allow_default_init_securityindex: true
plugins.security.authcz.admin_dn:
- 'CN=admin,OU=client,O=client,L=test,C=de'
plugins.security.nodes_dn:
- 'CN=node1.example.com,OU=test,O=test,L=test,C=de'
- 'CN=node2.example.com,OU=test,O=test,L=test,C=de'
plugins.security.audit.type: internal_opensearch
plugins.security.enable_snapshot_restore_privilege: true
plugins.security.check_snapshot_restore_write_privileges: true
plugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]
Генерация TLS сертификатов
OpenSearch предоставляет утилиту для генерации demo-сертификатов (только для тестов):
# Для продакшена — собственный CA
openssl genrsa -out root-ca-key.pem 2048
openssl req -new -x509 -sha256 -key root-ca-key.pem -out root-ca.pem \
-days 3650 -subj "/C=UA/O=MyOrg/CN=root-ca"
# Сертификат узла
openssl genrsa -out node1-key.pem 2048
openssl req -new -key node1-key.pem -out node1.csr \
-subj "/C=UA/O=MyOrg/CN=node1.example.com/OU=test"
openssl x509 -req -in node1.csr -CA root-ca.pem -CAkey root-ca-key.pem \
-CAcreateserial -out node1.pem -days 3650 -sha256
Настройка Security Plugin
После первого запуска инициализировать security index:
# Внутри контейнера
docker exec -it opensearch-node1 bash
/usr/share/opensearch/plugins/opensearch-security/tools/securityadmin.sh \
-cd /usr/share/opensearch/config/opensearch-security/ \
-icl -nhnv \
-cacert /usr/share/opensearch/config/root-ca.pem \
-cert /usr/share/opensearch/config/admin.pem \
-key /usr/share/opensearch/config/admin-key.pem
# Изменить пароль admin пользователя
curl -XPUT "https://localhost:9200/_plugins/_security/api/internalusers/admin" \
-H 'Content-Type: application/json' \
-u 'admin:admin' \
--cacert root-ca.pem \
-d '{"password": "NewSecurePassword123!", "backend_roles": ["admin"]}'
ISM (Index State Management)
OpenSearch замена для Elastic ILM — Index State Management:
PUT _plugins/_ism/policies/logs-policy
{
"policy": {
"description": "Logs lifecycle policy",
"default_state": "hot",
"states": [
{
"name": "hot",
"actions": [
{
"rollover": {
"min_index_age": "7d",
"min_size": "50gb"
}
}
],
"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": "delete",
"conditions": { "min_index_age": "60d" }
}
]
},
{
"name": "delete",
"actions": [{ "delete": {} }],
"transitions": []
}
],
"ism_template": [{
"index_patterns": ["logs-*"],
"priority": 100
}]
}
}
Подключение клиентов
OpenSearch предоставляет собственные клиенты, совместимые с ES 7.x API:
PHP:
composer require opensearch-project/opensearch-php
use OpenSearch\ClientBuilder;
$client = ClientBuilder::create()
->setHosts(['https://opensearch-node1:9200'])
->setBasicAuthentication('admin', 'NewSecurePassword123!')
->setSSLVerification('/path/to/root-ca.pem')
->build();
Python:
pip install opensearch-py
from opensearchpy import OpenSearch
client = OpenSearch(
hosts=['https://opensearch-node1:9200'],
http_auth=('admin', 'NewSecurePassword123!'),
use_ssl=True,
verify_certs=True,
ca_certs='/path/to/root-ca.pem',
)
Если уже используется elasticsearch-php 7.x — он работает с OpenSearch без изменений (API совместим). Для ES 8.x клиента нужен именно opensearch-php.
Миграция с Elasticsearch
Снапшот-восстановление работает между ES 7.x и OpenSearch:
# На ES: создать снапшот
PUT /_snapshot/backup_repo
{
"type": "fs",
"settings": { "location": "/mnt/backup" }
}
POST /_snapshot/backup_repo/snapshot_1
{ "indices": "products,orders" }
# Смонтировать тот же volume на OpenSearch ноде
# В OpenSearch: зарегистрировать репозиторий и восстановить
PUT /_snapshot/backup_repo
{
"type": "fs",
"settings": { "location": "/mnt/backup" }
}
POST /_snapshot/backup_repo/snapshot_1/_restore
{ "indices": "products,orders" }
Прямая миграция ES 8.x → OpenSearch через снапшоты невозможна из-за несовместимости формата. Нужен reindex через _reindex API или экспорт/импорт через logstash.
Сроки
Разворачивание OpenSearch кластера из 3 узлов с TLS и Security plugin — 2–3 рабочих дня. Миграция существующих данных с Elasticsearch 7.x — 1 дополнительный день. Настройка ISM политик и OpenSearch Dashboards — ещё 1 день.







