Skip to content

OpenSearch - Log Aggregation and Search

OpenSearch is a distributed search and analytics engine derived from Elasticsearch. It's used for log aggregation, full-text search, and real-time analytics.

Overview

OpenSearch provides:

  • Centralized log storage - Aggregate logs from all services
  • Full-text search - Fast search across log data
  • Real-time analytics - Analyze logs as they arrive
  • Dashboards - OpenSearch Dashboards for visualization
  • Scalability - Handle large volumes of logs

Architecture

┌─────────────────────────────────────────────────┐
│              Application Services                 │
│  (Pods, Containers, Applications)                │
└──────────────────┬──────────────────────────────┘


         ┌──────────────────┐
         │  OpenSearch      │
         │  (Data Nodes)     │
         └────────┬──────────┘


         ┌──────────────────┐
         │  OpenSearch       │
         │  Dashboards       │
         │  (UI)             │
         └──────────────────┘

Installation

bash
# Add OpenSearch Helm repository
helm repo add opensearch https://opensearch-project.github.io/helm-charts/
helm repo update

# Install OpenSearch cluster
helm install opensearch opensearch/opensearch \
  --namespace observability \
  --create-namespace \
  --set persistence.enabled=true \
  --set persistence.size=20Gi

# Install OpenSearch Dashboards
helm install opensearch-dashboards opensearch/opensearch-dashboards \
  --namespace observability \
  --set opensearchHosts=https://opensearch:9200

Using Kubernetes Manifests

bash
# Apply OpenSearch manifests
kubectl apply -f manifests/opensearch-cluster.yaml
kubectl apply -f manifests/opensearch-dashboards.yaml

# Wait for pods to be ready
kubectl wait --for=condition=ready pod -l app=opensearch -n observability --timeout=300s

Configuration

Basic Configuration

The OpenSearch cluster is configured via the Kubernetes manifests in manifests/opensearch-cluster.yaml. Key configuration options are set via environment variables:

  • Cluster name: opensearch-cluster
  • Initial master nodes: opensearch-0, opensearch-1, opensearch-2
  • Node roles: Master, Data, and Ingest (all-in-one nodes)
  • Heap size: 2GB (adjustable via OPENSEARCH_JAVA_OPTS)

To customize, edit the StatefulSet in manifests/opensearch-cluster.yaml.

Resource Requirements

Minimum for development:

  • CPU: 2 cores per node
  • Memory: 4GB per node
  • Storage: 20GB per node

Production recommendations:

  • CPU: 4+ cores per node
  • Memory: 8GB+ per node
  • Storage: 100GB+ per node (SSD recommended)

Usage

Access OpenSearch Dashboards

bash
# Port forward to access UI
kubectl port-forward svc/opensearch-dashboards -n observability 5601:5601

# Open in browser
open http://localhost:5601

Default credentials:

  • Username: admin
  • Password: admin (change in production!)

Send Logs to OpenSearch

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: fluent-bit-config
  namespace: observability
data:
  fluent-bit.conf: |
    [SERVICE]
        Flush         1
        Log_Level     info
        Daemon        off

    [INPUT]
        Name              tail
        Path              /var/log/containers/*.log
        Parser            docker
        Tag               kube.*
        Refresh_Interval  5

    [OUTPUT]
        Name  opensearch
        Match *
        Host  opensearch.observability.svc.cluster.local
        Port  9200
        Index kubernetes-logs
        Type  _doc

Using Logstash

ruby
input {
  beats {
    port => 5044
  }
}

output {
  opensearch {
    hosts => ["opensearch:9200"]
    index => "logs-%{+YYYY.MM.dd}"
  }
}

Query Logs

Using OpenSearch Dashboards

  1. Navigate to Discover
  2. Select index pattern (e.g., kubernetes-logs-*)
  3. Search using KQL (Kibana Query Language):
    level: ERROR AND service: api-gateway

Using cURL

bash
# Search for errors
curl -X GET "opensearch:9200/kubernetes-logs/_search?q=level:ERROR" \
  -u admin:admin

# Get log count by service
curl -X GET "opensearch:9200/kubernetes-logs/_search" \
  -u admin:admin \
  -H 'Content-Type: application/json' \
  -d '{
    "size": 0,
    "aggs": {
      "by_service": {
        "terms": {
          "field": "service.keyword"
        }
      }
    }
  }'

Integration with Other Tools

Grafana Integration

Add OpenSearch as a data source in Grafana:

  1. Go to Configuration > Data Sources
  2. Add OpenSearch data source
  3. Configure:
    • URL: http://opensearch:9200
    • Access: Server (default)
    • Index name: kubernetes-logs-*
    • Time field: @timestamp

Prometheus Integration

OpenSearch exposes metrics that Prometheus can scrape:

yaml
# prometheus-config.yaml
scrape_configs:
  - job_name: 'opensearch'
    static_configs:
      - targets: ['opensearch:9200']
    metrics_path: '/_prometheus/metrics'

Best Practices

Index Management

  1. Use index templates for consistent structure
  2. Set up index lifecycle management (ILM) for retention
  3. Use date-based indices (e.g., logs-2024-01-15)

Performance Optimization

  1. Shard sizing: 20-50GB per shard
  2. Replica count: 1 for dev, 2+ for production
  3. Refresh interval: Increase for high-volume logs
  4. Use hot/warm/cold tiers for cost optimization

Security

  1. Enable authentication (required in production)
  2. Use TLS for transport security
  3. Implement RBAC for access control
  4. Rotate credentials regularly

Troubleshooting

Pods Not Starting

bash
# Check pod status
kubectl get pods -n observability -l app=opensearch

# Check logs
kubectl logs -n observability opensearch-0

# Check events
kubectl describe pod -n observability opensearch-0

High Memory Usage

bash
# Check memory usage
kubectl top pods -n observability

# Adjust heap size in config
# heap_size: 2g  # Should be ~50% of container memory

Connection Issues

bash
# Test connectivity
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- \
  curl -u admin:admin http://opensearch:9200/_cluster/health

# Check service endpoints
kubectl get endpoints -n observability opensearch

Cost Considerations

Storage Costs

  • Development: ~$5-10/month (20GB storage)
  • Production: ~$50-200/month (100-500GB storage)
  • Backup: Additional S3 costs

Optimization Tips

  1. Set retention policies (delete old logs)
  2. Use compression for indices
  3. Archive old logs to S3
  4. Use smaller node sizes for dev/test

Additional Resources

Released under the MIT License.