Table of Contents
Introduction
OpenSearch is a community-driven, open-source search and analytics suite derived from Elasticsearch 7.10.2. This guide provides comprehensive configuration recommendations for deploying OpenSearch in production environments, focusing on performance, security, and reliability.
Essential opensearch.yml Configuration
Here’s a production-ready opensearch.yml
configuration with detailed explanations:
# ======================== OpenSearch Configuration =========================## NOTE: OpenSearch comes with reasonable defaults for most settings.# Before you set out to tweak and tune the configuration, make sure you# understand what are you trying to accomplish and the consequences.## The primary way of configuring a node is via this file. This template lists# the most important settings you may want to configure for a production cluster.## Please consult the documentation for further information on configuration options:# https://opensearch.org/docs/latest/## ---------------------------------- Cluster -----------------------------------## Use a descriptive name for your cluster:#cluster.name: wazuh-cluster## ------------------------------------ Node ------------------------------------## Use a descriptive name for the node:#node.name: node-1## Add custom attributes to the node:##node.attr.rack: r1#node.max_local_storage_nodes: "3"## ----------------------------------- Paths ------------------------------------## Path to directory where to store the data (separate multiple locations by comma):#path.data: /var/lib/opensearch## Path to log files:#path.logs: /var/log/opensearch## ----------------------------------- Memory -----------------------------------## Lock the memory on startup:##bootstrap.memory_lock: true## Make sure that the heap size is set to about half the memory available# on the system and that the owner of the process is allowed to use this# limit.## OpenSearch performs poorly when the system is swapping the memory.## ---------------------------------- Network -----------------------------------## Set the bind address to a specific IP (IPv4 or IPv6):#network.host: "0.0.0.0"## Set a custom port for HTTP:#http.port: 9200## For more information, consult the network module documentation.## --------------------------------- Discovery ----------------------------------## Pass an initial list of hosts to perform discovery when this node is started:# The default list of hosts is ["127.0.0.1", "[::1]"]##discovery.seed_hosts: ["host1", "host2"]## Bootstrap the cluster using an initial set of master-eligible nodes:##cluster.initial_master_nodes: ["node-1", "node-2"]## For more information, consult the discovery and cluster formation module documentation.## ---------------------------------- Gateway -----------------------------------## Block initial recovery after a full cluster restart until N nodes are started:##gateway.recover_after_nodes: 3## For more information, consult the gateway module documentation.## ---------------------------------- Various -----------------------------------## Require explicit names when deleting indices:##action.destructive_requires_name: true
######## Start OpenSearch Security Demo Configuration ######### WARNING: revise all the lines below before you go into productionplugins.security.ssl.transport.pemcert_filepath: /etc/opensearch/certs/indexer.pemplugins.security.ssl.transport.pemkey_filepath: /etc/opensearch/certs/indexer-key.pemplugins.security.ssl.transport.pemtrustedcas_filepath: /etc/opensearch/certs/root-ca.pemplugins.security.ssl.transport.enforce_hostname_verification: falseplugins.security.ssl.transport.resolve_hostname: falseplugins.security.ssl.http.enabled: trueplugins.security.ssl.http.pemcert_filepath: /etc/opensearch/certs/indexer.pemplugins.security.ssl.http.pemkey_filepath: /etc/opensearch/certs/indexer-key.pemplugins.security.ssl.http.pemtrustedcas_filepath: /etc/opensearch/certs/root-ca.pemplugins.security.allow_unsafe_democertificates: falseplugins.security.allow_default_init_securityindex: trueplugins.security.authcz.admin_dn: - CN=admin,OU=Wazuh,O=Wazuh,L=California,C=USplugins.security.enable_snapshot_restore_privilege: trueplugins.security.check_snapshot_restore_write_privileges: trueplugins.security.restapi.roles_enabled: ["all_access", "security_rest_api_access"]plugins.security.system_indices.enabled: trueplugins.security.system_indices.indices: [ ".plugins-ml-model", ".plugins-ml-task", ".opendistro-alerting-config", ".opendistro-alerting-alert*", ".opendistro-anomaly-results*", ".opendistro-anomaly-detector*", ".opendistro-anomaly-checkpoints", ".opendistro-anomaly-detection-state", ".opendistro-reports-*", ".opensearch-notifications-*", ".opensearch-notebooks", ".opensearch-observability", ".opendistro-asynchronous-search-response*", ".replication-metadata-store", ]######## End OpenSearch Security Demo Configuration ########
plugins.security.nodes_dn: - CN=node-1,OU=Wazuh,O=Wazuh,L=California,C=US
### Option to allow Filebeat-oss 7.10.2 to work ###compatibility.override_main_response_version: true
Production-Ready Configuration
Complete Production opensearch.yml
# ======================== OpenSearch Production Configuration =========================
# ---------------------------------- Cluster -----------------------------------cluster.name: production-opensearch
# Prevent split braincluster.initial_master_nodes: - master-node-1 - master-node-2 - master-node-3
# Cluster routing settingscluster.routing.allocation.disk.threshold_enabled: truecluster.routing.allocation.disk.watermark.low: 85%cluster.routing.allocation.disk.watermark.high: 90%cluster.routing.allocation.disk.watermark.flood_stage: 95%
# ------------------------------------ Node ------------------------------------node.name: ${NODE_NAME}node.roles: [data, ingest, master, ml, remote_cluster_client]
# Node attributes for shard allocation awarenessnode.attr.zone: ${ZONE}node.attr.temp: hot
# ----------------------------------- Paths ------------------------------------path.data: /var/lib/opensearchpath.logs: /var/log/opensearchpath.repo: /backup/opensearch
# ----------------------------------- Memory -----------------------------------# Lock memory to prevent swappingbootstrap.memory_lock: true
# ---------------------------------- Network -----------------------------------network.host: ${NETWORK_HOST}http.port: 9200transport.port: 9300
# Bind to both loopback and externalnetwork.bind_host: 0.0.0.0network.publish_host: ${EXTERNAL_IP}
# --------------------------------- Discovery ----------------------------------discovery.seed_hosts: - master-node-1:9300 - master-node-2:9300 - master-node-3:9300
# Minimum master nodes to prevent split braindiscovery.zen.minimum_master_nodes: 2
# ---------------------------------- Security ----------------------------------plugins.security.ssl.transport.pemcert_filepath: /etc/opensearch/certs/node.pemplugins.security.ssl.transport.pemkey_filepath: /etc/opensearch/certs/node-key.pemplugins.security.ssl.transport.pemtrustedcas_filepath: /etc/opensearch/certs/root-ca.pemplugins.security.ssl.transport.enforce_hostname_verification: trueplugins.security.ssl.transport.resolve_hostname: true
plugins.security.ssl.http.enabled: trueplugins.security.ssl.http.pemcert_filepath: /etc/opensearch/certs/node.pemplugins.security.ssl.http.pemkey_filepath: /etc/opensearch/certs/node-key.pemplugins.security.ssl.http.pemtrustedcas_filepath: /etc/opensearch/certs/root-ca.pem
# Security plugin settingsplugins.security.authcz.admin_dn: - CN=admin,OU=IT,O=Company,L=City,C=US
plugins.security.nodes_dn: - CN=*.opensearch.company.com,OU=IT,O=Company,L=City,C=US
plugins.security.audit.enable_rest: trueplugins.security.audit.enable_transport: falseplugins.security.audit.resolve_bulk_requests: trueplugins.security.audit.config.disabled_rest_categories: NONEplugins.security.audit.config.disabled_transport_categories: NONE
# ---------------------------------- Performance -------------------------------# Thread pool settingsthread_pool.search.size: 50thread_pool.search.queue_size: 1000thread_pool.write.size: 30thread_pool.write.queue_size: 500
# Indexing bufferindices.memory.index_buffer_size: 20%indices.memory.min_index_buffer_size: 96mb
# Field data cacheindices.fielddata.cache.size: 30%
# Query cacheindices.queries.cache.size: 10%
# Request cacheindices.requests.cache.size: 2%
# Recovery settingsindices.recovery.max_bytes_per_sec: 100mb
# ---------------------------------- Monitoring --------------------------------# Enable monitoringhttp.cors.enabled: truehttp.cors.allow-origin: "*"http.cors.allow-headers: "X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization"http.cors.allow-credentials: true
# ---------------------------------- Snapshot ----------------------------------# Repository settingsrepositories.url.allowed_urls: - "http://backup.company.com/*" - "https://s3.amazonaws.com/*"
# ----------------------------------- Misc -------------------------------------# Prevent accidental cluster deletionaction.destructive_requires_name: true
# Script settingsscript.allowed_types: inline, storedscript.allowed_contexts: search, update, ingest
# Machine learningnode.ml: truexpack.ml.enabled: true
JVM Configuration
jvm.options Configuration
## JVM configuration
################################################################## IMPORTANT: JVM heap size#################################################################### You should always set the min and max JVM heap## size to the same value. For example, to set## the heap to 4 GB, set:#### -Xms4g## -Xmx4g#### See https://opensearch.org/docs/latest/opensearch/install/important-settings/## for more information##################################################################
# Xms represents the initial size of total heap space# Xmx represents the maximum size of total heap space
-Xms16g-Xmx16g
################################################################## Expert settings#################################################################### All settings below this section are considered## expert settings. Don't tamper with them unless## you understand what you are doing##################################################################
## GC configuration8-13:-XX:+UseConcMarkSweepGC8-13:-XX:CMSInitiatingOccupancyFraction=758-13:-XX:+UseCMSInitiatingOccupancyOnly
## G1GC Configuration# NOTE: G1 GC is only supported on JDK version 10 or later# to use G1GC, uncomment the next two lines and update the version on the# following three lines to your version of the JDK# 10-13:-XX:-UseConcMarkSweepGC# 10-13:-XX:-UseCMSInitiatingOccupancyOnly14-:-XX:+UseG1GC14-:-XX:G1ReservePercent=2514-:-XX:InitiatingHeapOccupancyPercent=30
## JVM temporary directory-Djava.io.tmpdir=${OPENSEARCH_TMPDIR}
## heap dumps
# generate a heap dump when an allocation from the Java heap fails# heap dumps are created in the working directory of the JVM-XX:+HeapDumpOnOutOfMemoryError
# specify an alternative path for heap dumps; ensure the directory exists and# has sufficient space-XX:HeapDumpPath=/var/lib/opensearch
# specify an alternative path for JVM fatal error logs-XX:ErrorFile=/var/log/opensearch/hs_err_pid%p.log
## JDK 8 GC logging8:-XX:+PrintGCDetails8:-XX:+PrintGCDateStamps8:-XX:+PrintTenuringDistribution8:-XX:+PrintGCApplicationStoppedTime8:-Xloggc:/var/log/opensearch/gc.log8:-XX:+UseGCLogFileRotation8:-XX:NumberOfGCLogFiles=328:-XX:GCLogFileSize=64m
# JDK 9+ GC logging9-:-Xlog:gc*,gc+age=trace,safepoint:file=/var/log/opensearch/gc.log:utctime,pid,tags:filecount=32,filesize=64m
# Enable preview features for Java 14+14-:--enable-preview
# Performance settings-XX:MaxDirectMemorySize=8g-XX:+AlwaysPreTouch-XX:+DisableExplicitGC-XX:+UseStringDeduplication
Security Configuration
Setting Up SSL/TLS
#!/bin/bash# Generate certificates for OpenSearch cluster
# Create CAopenssl genrsa -out root-ca-key.pem 2048openssl req -new -x509 -sha256 -key root-ca-key.pem -out root-ca.pem -days 3650 \ -subj "/C=US/ST=State/L=City/O=Company/OU=IT/CN=OpenSearch Root CA"
# Create node certificateopenssl genrsa -out node-key-temp.pem 2048openssl pkcs8 -inform PEM -outform PEM -in node-key-temp.pem -topk8 -nocrypt -v1 PBE-SHA1-3DES -out node-key.pemopenssl req -new -key node-key.pem -out node.csr \ -subj "/C=US/ST=State/L=City/O=Company/OU=IT/CN=*.opensearch.company.com"
# Sign certificateopenssl x509 -req -in node.csr -CA root-ca.pem -CAkey root-ca-key.pem -CAcreateserial -sha256 -out node.pem -days 3650
# Set permissionschmod 600 *-key.pemchmod 644 *.pem
Security Plugin Configuration
_meta: type: "config" config_version: 2
config: dynamic: authc: basic_internal_auth_domain: description: "Authenticate via HTTP Basic against internal users database" http_enabled: true transport_enabled: true order: 0 http_authenticator: type: basic challenge: true authentication_backend: type: intern
ldap: description: "Authenticate via LDAP" http_enabled: true transport_enabled: true order: 1 http_authenticator: type: basic challenge: true authentication_backend: type: ldap config: enable_ssl: true enable_start_tls: false enable_ssl_client_auth: false verify_hostnames: true hosts: - ldap.company.com:636 bind_dn: cn=admin,dc=company,dc=com password: "ldap_password" userbase: ou=people,dc=company,dc=com usersearch: (uid={0}) username_attribute: uid
authz: roles_from_myldap: description: "Authorize via LDAP" http_enabled: true transport_enabled: true authorization_backend: type: ldap config: enable_ssl: true enable_start_tls: false enable_ssl_client_auth: false verify_hostnames: true hosts: - ldap.company.com:636 bind_dn: cn=admin,dc=company,dc=com password: "ldap_password" rolebase: ou=groups,dc=company,dc=com rolesearch: (member={0}) userroleattribute: null userrolename: memberOf rolename: cn resolve_nested_roles: true
Performance Tuning
System Settings
#!/bin/bash# System performance tuning for OpenSearch
# Disable swapsudo swapoff -asudo sed -i '/ swap / s/^/#/' /etc/fstab
# Set vm.max_map_countecho "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
# Set file descriptorsecho "* soft nofile 65535" | sudo tee -a /etc/security/limits.confecho "* hard nofile 65535" | sudo tee -a /etc/security/limits.confecho "* soft nproc 4096" | sudo tee -a /etc/security/limits.confecho "* hard nproc 4096" | sudo tee -a /etc/security/limits.conf
# Set memlock for opensearch userecho "opensearch soft memlock unlimited" | sudo tee -a /etc/security/limits.confecho "opensearch hard memlock unlimited" | sudo tee -a /etc/security/limits.conf
# Apply sysctl settingssudo sysctl -p
# Configure transparent huge pagesecho never | sudo tee /sys/kernel/mm/transparent_hugepage/enabledecho never | sudo tee /sys/kernel/mm/transparent_hugepage/defrag
# Create systemd drop-in for OpenSearchsudo mkdir -p /etc/systemd/system/opensearch.service.dcat <<EOF | sudo tee /etc/systemd/system/opensearch.service.d/override.conf[Service]LimitNOFILE=65535LimitNPROC=4096LimitMEMLOCK=infinityEOF
sudo systemctl daemon-reload
Index Settings for Performance
{ "settings": { "index": { "number_of_shards": 3, "number_of_replicas": 1, "refresh_interval": "30s", "translog": { "durability": "async", "sync_interval": "30s", "flush_threshold_size": "512mb" }, "merge": { "scheduler": { "max_thread_count": 1 }, "policy": { "max_merged_segment": "5gb" } }, "unassigned": { "node_left": { "delayed_timeout": "5m" } } }, "analysis": { "analyzer": { "default": { "type": "standard", "stopwords": "_english_" } } } }, "mappings": { "properties": { "@timestamp": { "type": "date" }, "message": { "type": "text", "fields": { "keyword": { "type": "keyword", "ignore_above": 256 } } } } }}
Monitoring and Alerting
Monitoring Configuration
# Enable monitoring APIshttp.detailed_errors.enabled: truerest.action.multi.allow_explicit_index: true
# Monitoring settingsmonitoring.enabled: truemonitoring.collection.enabled: truemonitoring.collection.interval: 10smonitoring.history.duration: 7d
Setting Up Alerts
{ "trigger": { "schedule": { "interval": { "period": 1, "unit": "MINUTES" } } }, "input": { "search": { "request": { "indices": [".opensearch-cluster-stats*"], "body": { "query": { "bool": { "filter": [ { "range": { "@timestamp": { "gte": "now-5m" } } }, { "range": { "nodes.jvm.mem.heap_used_percent": { "gte": 90 } } } ] } } } } } }, "condition": { "compare": { "ctx.payload.hits.total.value": { "gt": 0 } } }, "actions": { "send_email": { "email": { "to": ["ops-team@company.com"], "subject": "High JVM Memory Usage Alert", "body": "OpenSearch cluster is experiencing high JVM memory usage (>90%)" } } }}
Backup and Recovery
Snapshot Repository Configuration
# Create S3 repositorycurl -XPUT "https://localhost:9200/_snapshot/s3_backup" \ -H 'Content-Type: application/json' \ -u admin:password \ --insecure \ -d '{ "type": "s3", "settings": { "bucket": "opensearch-backups", "region": "us-east-1", "base_path": "snapshots", "compress": true, "chunk_size": "100mb", "max_restore_bytes_per_sec": "40mb", "max_snapshot_bytes_per_sec": "40mb" } }'
# Create snapshot policycurl -XPUT "https://localhost:9200/_plugins/_sm/policies/daily_backup" \ -H 'Content-Type: application/json' \ -u admin:password \ --insecure \ -d '{ "description": "Daily backup policy", "creation": { "schedule": { "cron": { "expression": "0 0 2 * * ?", "timezone": "UTC" } }, "time_limit": "1h" }, "deletion": { "condition": { "max_age": "30d", "max_count": 30, "min_count": 7 }, "time_limit": "1h" }, "snapshot_config": { "indices": "*", "ignore_unavailable": true, "include_global_state": false, "partial": true } }'
Cluster Management
Shard Allocation Filtering
# Exclude a node from allocationcurl -XPUT "https://localhost:9200/_cluster/settings" \ -H 'Content-Type: application/json' \ -u admin:password \ --insecure \ -d '{ "transient": { "cluster.routing.allocation.exclude._ip": "192.168.1.100" } }'
# Set allocation awarenesscurl -XPUT "https://localhost:9200/_cluster/settings" \ -H 'Content-Type: application/json' \ -u admin:password \ --insecure \ -d '{ "persistent": { "cluster.routing.allocation.awareness.attributes": "zone", "cluster.routing.allocation.awareness.force.zone.values": ["zone1", "zone2"] } }'
Index Lifecycle Management
{ "policy": { "description": "Hot-Warm-Cold architecture policy", "default_state": "hot", "states": [ { "name": "hot", "actions": [ { "rollover": { "min_size": "50gb", "min_index_age": "7d" } } ], "transitions": [ { "state_name": "warm", "conditions": { "min_index_age": "7d" } } ] }, { "name": "warm", "actions": [ { "replica_count": { "number_of_replicas": 1 } }, { "shrink": { "number_of_shards": 1 } }, { "allocation": { "require": { "temp": "warm" } } } ], "transitions": [ { "state_name": "cold", "conditions": { "min_index_age": "30d" } } ] }, { "name": "cold", "actions": [ { "replica_count": { "number_of_replicas": 0 } }, { "allocation": { "require": { "temp": "cold" } } } ], "transitions": [ { "state_name": "delete", "conditions": { "min_index_age": "90d" } } ] }, { "name": "delete", "actions": [ { "delete": {} } ] } ] }}
Troubleshooting
Common Issues and Solutions
-
High JVM Memory Usage
Terminal window # Check heap usagecurl -XGET "https://localhost:9200/_nodes/stats/jvm?pretty" \-u admin:password --insecure# Force garbage collection (use with caution)curl -XPOST "https://localhost:9200/_nodes/_local/_hot_threads" \-u admin:password --insecure -
Slow Queries
Terminal window # Enable slow logcurl -XPUT "https://localhost:9200/_all/_settings" \-H 'Content-Type: application/json' \-u admin:password \--insecure \-d '{"index.search.slowlog.threshold.query.warn": "10s","index.search.slowlog.threshold.query.info": "5s","index.search.slowlog.threshold.query.debug": "2s","index.search.slowlog.threshold.query.trace": "500ms","index.search.slowlog.threshold.fetch.warn": "1s","index.search.slowlog.threshold.fetch.info": "800ms","index.search.slowlog.threshold.fetch.debug": "500ms","index.search.slowlog.threshold.fetch.trace": "200ms"}' -
Shard Allocation Issues
Terminal window # Check allocation explanationcurl -XGET "https://localhost:9200/_cluster/allocation/explain?pretty" \-u admin:password --insecure# Enable allocationcurl -XPUT "https://localhost:9200/_cluster/settings" \-H 'Content-Type: application/json' \-u admin:password \--insecure \-d '{"transient": {"cluster.routing.allocation.enable": "all"}}'
Best Practices
-
Hardware Recommendations
- Use SSDs for data storage
- Minimum 64GB RAM for production
- Dedicate 50% of RAM to JVM heap (max 32GB)
- Use multiple data paths for better I/O
-
Index Design
- Use time-based indices for logs
- Implement proper mapping before indexing
- Use index templates for consistent settings
- Consider hot-warm-cold architecture
-
Security
- Always use TLS/SSL in production
- Implement strong authentication
- Regular security audits
- Keep OpenSearch updated
-
Monitoring
- Monitor cluster health continuously
- Set up alerts for critical metrics
- Regular backup verification
- Track query performance
Conclusion
Proper OpenSearch configuration is crucial for building a reliable, performant, and secure search infrastructure. This guide provides a comprehensive foundation for production deployments, but remember to adjust settings based on your specific workload, hardware, and requirements. Regular monitoring, maintenance, and optimization are key to maintaining a healthy OpenSearch cluster.