Comprehensive OpenSearch Deployment Guide
This guide provides detailed instructions for deploying OpenSearch in both single-node and cluster configurations. OpenSearch is a powerful, open-source search and analytics engine that offers enterprise-grade security, powerful monitoring capabilities, and extensive customization options.
Table of Contents
Introduction
OpenSearch is a community-driven, open-source fork of Elasticsearch that provides a secure, high-performance search and analytics engine. Whether you’re deploying a single node for development or a multi-node cluster for production, this guide will help you set up and optimize your OpenSearch deployment.
Prerequisites
System Requirements
- Operating System: Rocky Linux, RHEL, Ubuntu 20.04+, or Amazon Linux 2
- RAM: Minimum 4GB per node (8GB recommended)
- CPU: Minimum 2 cores per node
- Storage: 20GB+ available space
- Java: OpenJDK 11 or later
Required Packages
# For RPM-based systems (Rocky Linux, RHEL)sudo dnf install java-11-openjdk-devel unzip wget curl
# For Debian-based systemssudo apt-get updatesudo apt-get install openjdk-11-jdk unzip wget curl
Network Requirements
- Open ports:
- 9200: HTTP API
- 9300: Node communication
- 9600: Performance Analyzer
- 5601: OpenSearch Dashboards (if installed)
Single Node Installation
Add OpenSearch Repository
# Create repository filesudo bash -c 'cat > /etc/yum.repos.d/opensearch.repo << EOF[opensearch]name=OpenSearchbaseurl=https://artifacts.opensearch.org/releases/bundle/opensearch/2.x/yumenabled=1gpgcheck=1gpgkey=https://artifacts.opensearch.org/publickeys/opensearch.gpgautorefresh=1type=rpm-mdEOF'
Install OpenSearch
sudo dnf install opensearch
Configure OpenSearch
sudo bash -c 'cat > /etc/opensearch/opensearch.yml << EOFcluster.name: opensearch-singlenode.name: single-nodenetwork.host: 0.0.0.0discovery.type: single-nodepath.data: /var/lib/opensearchpath.logs: /var/log/opensearch
# Memory Settingsbootstrap.memory_lock: true
# Security Settingsplugins.security.ssl.http.enabled: trueplugins.security.ssl.http.pemcert_filepath: certs/node.pemplugins.security.ssl.http.pemkey_filepath: certs/node-key.pemplugins.security.ssl.http.pemtrustedcas_filepath: certs/root-ca.pemplugins.security.ssl.transport.pemcert_filepath: certs/node.pemplugins.security.ssl.transport.pemkey_filepath: certs/node-key.pemplugins.security.ssl.transport.pemtrustedcas_filepath: certs/root-ca.pemplugins.security.ssl.transport.enforce_hostname_verification: falseplugins.security.allow_default_init_securityindex: trueplugins.security.authcz.admin_dn: - "CN=admin,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN"
# Performance Settingsindices.memory.index_buffer_size: 10%thread_pool.write.queue_size: 200thread_pool.search.queue_size: 500EOF'
Generate Certificates
# Create directory for certificatessudo mkdir -p /etc/opensearch/certscd /etc/opensearch/certs
# Generate root CAsudo openssl req -x509 -new -nodes -newkey rsa:2048 \ -keyout root-ca.key -out root-ca.pem -days 3650 \ -subj "/C=IN/L=Ahmedabad/O=Invinsense/OU=Invinsense/CN=Root CA"
# Generate node certificatesudo openssl req -new -nodes -newkey rsa:2048 \ -keyout node-key.pem -out node.csr \ -subj "/C=IN/L=Ahmedabad/O=Invinsense/OU=Invinsense/CN=single-node"
sudo openssl x509 -req -in node.csr -CA root-ca.pem \ -CAkey root-ca.key -CAcreateserial -out node.pem \ -days 3650 -sha256
# Generate admin certificatesudo openssl req -new -nodes -newkey rsa:2048 \ -keyout admin-key.pem -out admin.csr \ -subj "/C=IN/L=Ahmedabad/O=Invinsense/OU=Invinsense/CN=admin"
sudo openssl x509 -req -in admin.csr -CA root-ca.pem \ -CAkey root-ca.key -CAcreateserial -out admin.pem \ -days 3650 -sha256
Set Permissions
sudo chown -R opensearch:opensearch /etc/opensearch/certssudo chmod 600 /etc/opensearch/certs/*.pemsudo chmod 600 /etc/opensearch/certs/*.key
Configure System Settings
# Set memory mapping limitssudo bash -c 'cat >> /etc/sysctl.conf << EOFvm.max_map_count=262144vm.swappiness=1EOF'
sudo sysctl -p
# Set memory lock limitssudo bash -c 'cat > /etc/security/limits.d/opensearch.conf << EOFopensearch soft memlock unlimitedopensearch hard memlock unlimitedopensearch soft nofile 65536opensearch hard nofile 65536opensearch soft nproc 4096opensearch hard nproc 4096EOF'
Start OpenSearch
sudo systemctl enable opensearchsudo systemctl start opensearch
Cluster Installation
This section covers setting up a three-node cluster with one master node and two data nodes.
Master Node Configuration (os1)
sudo bash -c 'cat > /etc/opensearch/opensearch.yml << EOF# Basic cluster configurationcluster.name: opensearch-clusternode.name: os1node.roles: [master, data]network.host: 172.17.14.79http.port: 9200transport.port: 9300
# Discovery settingsdiscovery.seed_hosts: ["172.17.14.79:9300", "172.17.14.89:9300", "172.17.14.39:9300"]cluster.initial_master_nodes: ["os1"]
# Memory and path settingsbootstrap.memory_lock: truepath.data: /var/lib/opensearchpath.logs: /var/log/opensearch
# Performance settingsindices.memory.index_buffer_size: 5%thread_pool.write.queue_size: 200thread_pool.search.queue_size: 500
# Security Configurationplugins.security.ssl.transport.pemcert_filepath: certs/node.pemplugins.security.ssl.transport.pemkey_filepath: certs/node-key.pemplugins.security.ssl.transport.pemtrustedcas_filepath: certs/root-ca.pemplugins.security.ssl.transport.enforce_hostname_verification: falseplugins.security.ssl.transport.resolve_hostname: false
plugins.security.ssl.http.enabled: trueplugins.security.ssl.http.pemcert_filepath: certs/node.pemplugins.security.ssl.http.pemkey_filepath: certs/node-key.pemplugins.security.ssl.http.pemtrustedcas_filepath: certs/root-ca.pem
plugins.security.allow_unsafe_democertificates: falseplugins.security.allow_default_init_securityindex: true
# Node Identity Managementplugins.security.nodes_dn: - "CN=opensearch-1,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN" - "CN=opensearch-2,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN" - "CN=opensearch-3,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN"
plugins.security.authcz.admin_dn: - "CN=admin,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN"
# System indices configurationplugins.security.system_indices.enabled: trueplugins.security.system_indices.indices: [ ".plugins-ml-*", ".opendistro-alerting-*", ".opendistro-anomaly-*", ".opendistro-reports-*", ".opensearch-notifications-*", ".opensearch-notebooks", ".opensearch-observability", ".ql-datasources", ".opendistro-asynchronous-search-*", ".replication-metadata-store", ".opensearch-knn-models", ".geospatial-ip2geo-data*", ".plugins-flow-framework-*"]EOF'
Data Node Configuration (os2 and os3)
# Replace IP address and node name for each nodesudo bash -c 'cat > /etc/opensearch/opensearch.yml << EOF# Basic cluster configurationcluster.name: opensearch-clusternode.name: os2 # Change to os3 for the third nodenode.roles: [data, ingest]network.host: 172.17.14.89 # Change to appropriate IPhttp.port: 9200transport.port: 9300
# Discovery settingsdiscovery.seed_hosts: ["172.17.14.79:9300", "172.17.14.89:9300", "172.17.14.39:9300"]cluster.initial_master_nodes: ["os1"]
# Memory and path settingsbootstrap.memory_lock: truepath.data: /var/lib/opensearchpath.logs: /var/log/opensearch
# Performance settingsindices.memory.index_buffer_size: 5%thread_pool.write.queue_size: 200thread_pool.search.queue_size: 500
# Security Configurationplugins.security.ssl.transport.pemcert_filepath: certs/node.pemplugins.security.ssl.transport.pemkey_filepath: certs/node-key.pemplugins.security.ssl.transport.pemtrustedcas_filepath: certs/root-ca.pemplugins.security.ssl.transport.enforce_hostname_verification: falseplugins.security.ssl.transport.resolve_hostname: false
plugins.security.ssl.http.enabled: trueplugins.security.ssl.http.pemcert_filepath: certs/node.pemplugins.security.ssl.http.pemkey_filepath: certs/node-key.pemplugins.security.ssl.http.pemtrustedcas_filepath: certs/root-ca.pem
# Security Settingsplugins.security.allow_unsafe_democertificates: falseplugins.security.allow_default_init_securityindex: true
# Node Identity Managementplugins.security.nodes_dn: - "CN=opensearch-1,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN" - "CN=opensearch-2,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN" - "CN=opensearch-3,OU=Invinsense,O=Invinsense,L=Ahmedabad,C=IN"
# System indices configurationplugins.security.system_indices.enabled: trueplugins.security.system_indices.indices: [ ".plugins-ml-*", ".opendistro-alerting-*", ".opendistro-anomaly-*", ".opendistro-reports-*", ".opensearch-notifications-*", ".opensearch-notebooks", ".opensearch-observability", ".ql-datasources", ".opendistro-asynchronous-search-*", ".replication-metadata-store", ".opensearch-knn-models", ".geospatial-ip2geo-data*", ".plugins-flow-framework-*"]EOF'
Generate and Distribute Certificates
Create a certificate generation script:
#!/bin/bash
CERT_DIR="/tmp/opensearch-certs"mkdir -p "$CERT_DIR"
# Generate root CAopenssl req -x509 -new -nodes -newkey rsa:2048 \ -keyout "$CERT_DIR/root-ca.key" -out "$CERT_DIR/root-ca.pem" \ -days 3650 -subj "/C=IN/L=Ahmedabad/O=Invinsense/OU=Invinsense/CN=Root CA"
# Function to generate node certificategenerate_node_cert() { local node_name=$1 openssl req -new -nodes -newkey rsa:2048 \ -keyout "$CERT_DIR/$node_name-key.pem" -out "$CERT_DIR/$node_name.csr" \ -subj "/C=IN/L=Ahmedabad/O=Invinsense/OU=Invinsense/CN=$node_name"
openssl x509 -req -in "$CERT_DIR/$node_name.csr" \ -CA "$CERT_DIR/root-ca.pem" -CAkey "$CERT_DIR/root-ca.key" \ -CAcreateserial -out "$CERT_DIR/$node_name.pem" \ -days 3650 -sha256}
# Generate certificates for each nodegenerate_node_cert "opensearch-1"generate_node_cert "opensearch-2"generate_node_cert "opensearch-3"
# Generate admin certificateopenssl req -new -nodes -newkey rsa:2048 \ -keyout "$CERT_DIR/admin-key.pem" -out "$CERT_DIR/admin.csr" \ -subj "/C=IN/L=Ahmedabad/O=Invinsense/OU=Invinsense/CN=admin"
openssl x509 -req -in "$CERT_DIR/admin.csr" \ -CA "$CERT_DIR/root-ca.pem" -CAkey "$CERT_DIR/root-ca.key" \ -CAcreateserial -out "$CERT_DIR/admin.pem" \ -days 3650 -sha256
# Set permissionschmod 600 "$CERT_DIR"/*.pem "$CERT_DIR"/*.key
Distribute Certificates
# On each nodesudo mkdir -p /etc/opensearch/certssudo cp /tmp/opensearch-certs/root-ca.pem /etc/opensearch/certs/sudo cp /tmp/opensearch-certs/root-ca.key /etc/opensearch/certs/sudo cp /tmp/opensearch-certs/admin*.pem /etc/opensearch/certs/
# On each node, copy the appropriate node certificate# For os1sudo cp /tmp/opensearch-certs/opensearch-1.pem /etc/opensearch/certs/node.pemsudo cp /tmp/opensearch-certs/opensearch-1-key.pem /etc/opensearch/certs/node-key.pem
# For os2sudo cp /tmp/opensearch-certs/opensearch-2.pem /etc/opensearch/certs/node.pemsudo cp /tmp/opensearch-certs/opensearch-2-key.pem /etc/opensearch/certs/node-key.pem
# For os3sudo cp /tmp/opensearch-certs/opensearch-3.pem /etc/opensearch/certs/node.pemsudo cp /tmp/opensearch-certs/opensearch-3-key.pem /etc/opensearch/certs/node-key.pem
# Set permissions on all nodessudo chown -R opensearch:opensearch /etc/opensearch/certssudo chmod 750 /etc/opensearch/certssudo chmod 600 /etc/opensearch/certs/*
Configure System Settings on All Nodes
# Configure sysctl settingssudo bash -c 'cat >> /etc/sysctl.conf << EOFvm.max_map_count=262144vm.swappiness=1EOF'
sudo sysctl -p
# Configure memory limitssudo bash -c 'cat > /etc/security/limits.d/opensearch.conf << EOFopensearch soft memlock unlimitedopensearch hard memlock unlimitedopensearch soft nofile 65536opensearch hard nofile 65536opensearch soft nproc 4096opensearch hard nproc 4096EOF'
# Create JVM options filesudo mkdir -p /etc/opensearch/jvm.options.d/sudo bash -c 'cat > /etc/opensearch/jvm.options.d/heap.options << EOF-Xms2g-Xmx2gEOF'
Start the Cluster
# On all nodessudo systemctl daemon-reloadsudo systemctl enable opensearchsudo systemctl start opensearch
# Monitor logssudo tail -f /var/log/opensearch/opensearch-cluster.log
Security Configuration
Create Security Configuration Directory
sudo mkdir -p /etc/opensearch/opensearch-security
Configure Internal Users
sudo bash -c 'cat > /etc/opensearch/opensearch-security/internal_users.yml << EOFadmin: hash: "$2y$12$XwI0HxUmgQpR5zIzWUKIBONRPvU1kRUFCaXUa2Z2iCGjBxbqpyKtG" # Change this reserved: true backend_roles: - "admin" description: "Admin user"kibanaserver: hash: "$2y$12$XwI0HxUmgQpR5zIzWUKIBONRPvU1kRUFCaXUa2Z2iCGjBxbqpyKtG" # Change this reserved: true description: "OpenSearch Dashboards user"EOF'
Important: Always change default password hashes in production environments.
Configure Roles
sudo bash -c 'cat > /etc/opensearch/opensearch-security/roles.yml << EOFadmin: cluster: - UNLIMITED indices: "*": allowlist: ["*"] denylist: [] authorized_indices: ["*"] tenants: admin_tenant: RW
kibanaserver: cluster: - CLUSTER_MONITOR - CLUSTER_COMPOSITE_OPS indices: "*": allowlist: [".kibana*", ".opensearch_dashboards*"] denylist: [] authorized_indices: [".kibana*", ".opensearch_dashboards*"]EOF'
Configure Role Mappings
sudo bash -c 'cat > /etc/opensearch/opensearch-security/roles_mapping.yml << EOFadmin: users: - admin backend_roles: - admin hosts: [] and_backend_roles: []
kibanaserver: users: - kibanaserver backend_roles: [] hosts: [] and_backend_roles: []EOF'
Performance Tuning
Memory Settings
For nodes with 4GB RAM:
sudo bash -c 'cat > /etc/opensearch/jvm.options.d/heap.options << EOF-Xms2g-Xmx2gEOF'
Thread Pool Settings
Add the following to opensearch.yml
:
thread_pool: write: queue_size: 200 search: queue_size: 500
Field Data and Query Cache
Add to opensearch.yml
:
indices.fielddata.cache.size: 20%indices.queries.cache.size: 10%
Disk I/O Settings
Add to opensearch.yml
:
index: merge: policy: floor_segment: 2mb max_merge_at_once: 5 max_merged_segment: 5gb refresh_interval: 30s
Troubleshooting
Memory Lock Issues
# Check if memory lock is enabledulimit -l
# If unlimited is not shown, verify /etc/security/limits.conf:sudo bash -c 'cat >> /etc/security/limits.conf << EOFopensearch soft memlock unlimitedopensearch hard memlock unlimitedEOF'
Certificate Issues
# Verify certificate permissionsls -la /etc/opensearch/certs/
# Verify certificate contentopenssl x509 -in /etc/opensearch/certs/node.pem -text -noout
# Check certificate chainopenssl verify -CAfile /etc/opensearch/certs/root-ca.pem /etc/opensearch/certs/node.pem
Cluster Formation Issues
# Check cluster healthcurl -k -X GET "https://localhost:9200/_cluster/health?pretty" -u admin:admin
# Check cluster statecurl -k -X GET "https://localhost:9200/_cluster/state?pretty" -u admin:admin
# Check node infocurl -k -X GET "https://localhost:9200/_nodes?pretty" -u admin:admin
Best Practices
Security Best Practices
-
Certificate Management:
- Rotate certificates every 12 months
- Use strong key sizes (minimum 2048 bits for RSA)
- Implement proper certificate revocation procedures
- Store private keys securely
-
Network Security:
- Use firewalls to restrict access to OpenSearch ports
- Implement VPC or network segmentation
- Use TLS 1.2 or higher for all communications
- Disable plaintext HTTP when possible
-
Authentication and Authorization:
- Use role-based access control (RBAC)
- Follow the principle of least privilege
- Regularly audit user access and permissions
- Implement strong password policies
Performance Best Practices
-
Hardware Recommendations:
- Use SSDs for data nodes
- Provide adequate RAM (minimum 4GB per node)
- Use multiple CPUs/cores for better concurrent processing
- Ensure network bandwidth is sufficient
-
Indexing Best Practices:
- Use bulk indexing when possible
- Optimize refresh intervals based on workload
- Use appropriate shard sizes (10-50GB per shard)
- Implement proper mapping strategies
-
Search Optimization:
- Use filter context when possible
- Implement proper caching strategies
- Optimize query patterns
- Use scroll API for deep pagination
Monitoring Best Practices
-
Key Metrics to Monitor:
- Cluster health status
- Node status and resource usage
- Index performance metrics
- Query performance metrics
- JVM heap usage
- Disk usage and I/O statistics
-
Logging:
- Implement log rotation
- Monitor error logs regularly
- Set appropriate log levels
- Archive logs for compliance and debugging
-
Alerting:
- Set up alerts for cluster state changes
- Monitor disk space usage
- Track JVM heap usage
- Monitor query latency
- Track failed node connections
Backup and Recovery
Snapshot Repository Setup
# Create snapshot repositorycurl -X PUT "localhost:9200/_snapshot/my_backup" -H 'Content-Type: application/json' -d'{ "type": "fs", "settings": { "location": "/mnt/backups" }}'
Automated Backup Script
#!/bin/bashSNAPSHOT_NAME="snapshot_$(date +%Y%m%d_%H%M%S)"curl -X PUT "localhost:9200/_snapshot/my_backup/${SNAPSHOT_NAME}?wait_for_completion=true"
Maintenance Procedures
Rolling Restart Procedure
# For each node in the cluster:# 1. Disable shard allocationcurl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{ "persistent": { "cluster.routing.allocation.enable": "none" }}'
# 2. Stop OpenSearchsudo systemctl stop opensearch
# 3. Perform maintenance
# 4. Start OpenSearchsudo systemctl start opensearch
# 5. Wait for node to join clustercurl -X GET "localhost:9200/_cat/nodes"
# 6. Re-enable shard allocationcurl -X PUT "localhost:9200/_cluster/settings" -H 'Content-Type: application/json' -d'{ "persistent": { "cluster.routing.allocation.enable": "all" }}'
Index Lifecycle Management
# Create index lifecycle policycurl -X PUT "localhost:9200/_ilm/policy/my_policy" -H 'Content-Type: application/json' -d'{ "policy": { "phases": { "hot": { "actions": { "rollover": { "max_size": "50GB", "max_age": "30d" } } }, "warm": { "min_age": "30d", "actions": { "shrink": { "number_of_shards": 1 }, "forcemerge": { "max_num_segments": 1 } } }, "cold": { "min_age": "60d", "actions": { "readonly": {} } }, "delete": { "min_age": "90d", "actions": { "delete": {} } } } }}'
Conclusion
This comprehensive guide should help you deploy, secure, optimize, and maintain OpenSearch in production environments. Remember to regularly check the OpenSearch documentation for updates and new features that might affect your deployment strategy.
Production deployments require careful planning, monitoring, and maintenance. By following the practices outlined in this guide, you can build a robust, high-performance search infrastructure that meets your organization’s needs.