OpenSearch

OpenSearch Plugin

The OpenSearch plugin sets up an OpenSearch environment using the OpenSearch Operator, automating deployment, provisioning, management, and orchestration of OpenSearch clusters and dashboards. It functions as the backend for logs gathered by collectors such as OpenTelemetry collectors, enabling storage and visualization of logs for Greenhouse-onboarded Kubernetes clusters.

The main terminologies used in this document can be found in core-concepts.

Overview

OpenSearch is a distributed search and analytics engine designed for real-time log and event data analysis. The OpenSearch Operator simplifies the management of OpenSearch clusters by providing declarative APIs for configuration and scaling.

Components included in this Plugin:

  • OpenSearch Operator
  • OpenSearch Cluster Management
  • OpenSearch Dashboards Deployment
  • OpenSearch Index Management
  • OpenSearch Security Configuration

Architecture

OpenSearch Architecture

The OpenSearch Operator automates the management of OpenSearch clusters within a Kubernetes environment. The architecture consists of:

  • OpenSearchCluster CRD: Defines the structure and configuration of OpenSearch clusters, including node roles, scaling policies, and version management.
  • OpenSearchDashboards CRD: Manages OpenSearch Dashboards deployments, ensuring high availability and automatic upgrades.
  • OpenSearchISMPolicy CRD: Implements index lifecycle management, defining policies for retention, rollover, and deletion.
  • OpenSearchIndexTemplate CRD: Enables the definition of index mappings, settings, and template structures.
  • Security Configuration via OpenSearchRole and OpenSearchUser: Manages authentication and authorization for OpenSearch users and roles.

Note

More configurations will be added over time, and contributions of custom configurations are highly appreciated. If you discover bugs or want to add functionality to the plugin, feel free to create a pull request.

Quick Start

This guide provides a quick and straightforward way to use OpenSearch as a Greenhouse Plugin on your Kubernetes cluster.

Prerequisites

  • A running and Greenhouse-onboarded Kubernetes cluster. If you don’t have one, follow the Cluster onboarding guide.
  • The OpenSearch Operator installed via Helm or Kubernetes manifests.
  • An OpenTelemetry or similar log ingestion pipeline configured to send logs to OpenSearch.

Installation

Install via Greenhouse

  1. Navigate to the Greenhouse Dashboard.
  2. Select the OpenSearch plugin from the catalog.
  3. Specify the target cluster and configuration options.

Values

KeyTypeDefaultDescription
cluster.actionGroupslist[]List of OpensearchActionGroup. Check values.yaml file for examples.
cluster.cluster.annotationsobject{}OpenSearchCluster annotations
cluster.cluster.bootstrap.additionalConfigobject{}bootstrap additional configuration, key-value pairs that will be added to the opensearch.yml configuration
cluster.cluster.bootstrap.affinityobject{}bootstrap pod affinity rules
cluster.cluster.bootstrap.jvmstring""bootstrap pod jvm options. If jvm is not provided then the java heap size will be set to half of resources.requests.memory which is the recommend value for data nodes. If jvm is not provided and resources.requests.memory does not exist then value will be -Xmx512M -Xms512M
cluster.cluster.bootstrap.nodeSelectorobject{}bootstrap pod node selectors
cluster.cluster.bootstrap.resourcesobject{}bootstrap pod cpu and memory resources
cluster.cluster.bootstrap.tolerationslist[]bootstrap pod tolerations
cluster.cluster.confMgmt.smartScalerbooltrueEnable nodes to be safely removed from the cluster
cluster.cluster.dashboards.additionalConfigobject{}Additional properties for opensearch_dashboards.yaml
cluster.cluster.dashboards.affinityobject{}dashboards pod affinity rules
cluster.cluster.dashboards.annotationsobject{}dashboards annotations
cluster.cluster.dashboards.basePathstring""dashboards Base Path for Opensearch Clusters running behind a reverse proxy
cluster.cluster.dashboards.enablebooltrueEnable dashboards deployment
cluster.cluster.dashboards.envlist[]dashboards pod env variables
cluster.cluster.dashboards.imagestring"docker.io/opensearchproject/opensearch-dashboards"dashboards image
cluster.cluster.dashboards.imagePullPolicystring"IfNotPresent"dashboards image pull policy
cluster.cluster.dashboards.imagePullSecretslist[]dashboards image pull secrets
cluster.cluster.dashboards.labelsobject{"greenhouse.sap/expose":"true"}dashboards labels
cluster.cluster.dashboards.nodeSelectorobject{}dashboards pod node selectors
cluster.cluster.dashboards.opensearchCredentialsSecretobject{}Secret that contains fields username and password for dashboards to use to login to opensearch, must only be supplied if a custom securityconfig is provided
cluster.cluster.dashboards.pluginsListlist[]List of dashboards plugins to install
cluster.cluster.dashboards.podSecurityContextobject{}dasboards pod security context configuration
cluster.cluster.dashboards.replicasint1number of dashboards replicas
cluster.cluster.dashboards.resourcesobject{}dashboards pod cpu and memory resources
cluster.cluster.dashboards.securityContextobject{}dashboards security context configuration
cluster.cluster.dashboards.service.loadBalancerSourceRangeslist[]source ranges for a loadbalancer
cluster.cluster.dashboards.service.typestring"ClusterIP"dashboards service type
cluster.cluster.dashboards.tls.caSecretobject{}Secret that contains the ca certificate as ca.crt. If this and generate=true is set the existing CA cert from that secret is used to generate the node certs. In this case must contain ca.crt and ca.key fields
cluster.cluster.dashboards.tls.enableboolfalseEnable HTTPS for dashboards
cluster.cluster.dashboards.tls.generatebooltruegenerate certificate, if false secret must be provided
cluster.cluster.dashboards.tls.secretstringnilOptional, name of a TLS secret that contains ca.crt, tls.key and tls.crt data. If ca.crt is in a different secret provide it via the caSecret field
cluster.cluster.dashboards.tolerationslist[]dashboards pod tolerations
cluster.cluster.dashboards.versionstring"2.19.1"dashboards version
cluster.cluster.general.additionalConfigobject{}Extra items to add to the opensearch.yml
cluster.cluster.general.additionalVolumeslist[]Additional volumes to mount to all pods in the cluster. Supported volume types configMap, emptyDir, secret (with default Kubernetes configuration schema)
cluster.cluster.general.drainDataNodesbooltrueControls whether to drain data notes on rolling restart operations
cluster.cluster.general.httpPortint9200Opensearch service http port
cluster.cluster.general.imagestring"docker.io/opensearchproject/opensearch"Opensearch image
cluster.cluster.general.imagePullPolicystring"IfNotPresent"Default image pull policy
cluster.cluster.general.keystorelist[]Populate opensearch keystore before startup
cluster.cluster.general.monitoring.enablebooltrueEnable cluster monitoring
cluster.cluster.general.monitoring.monitoringUserSecretstring""Secret with ‘username’ and ‘password’ keys for monitoring user. You could also use OpenSearchUser CRD instead of setting it.
cluster.cluster.general.monitoring.pluginUrlstring"https://github.com/Virtimo/prometheus-exporter-plugin-for-opensearch/releases/download/v2.19.1/prometheus-exporter-2.19.1.0.zip"Custom URL for the monitoring plugin
cluster.cluster.general.monitoring.scrapeIntervalstring"30s"How often to scrape metrics
cluster.cluster.general.monitoring.tlsConfigobject{"insecureSkipVerify":true}Override the tlsConfig of the generated ServiceMonitor
cluster.cluster.general.pluginsListlist[]List of Opensearch plugins to install
cluster.cluster.general.podSecurityContextobject{}Opensearch pod security context configuration
cluster.cluster.general.securityContextobject{}Opensearch securityContext
cluster.cluster.general.serviceAccountstring""Opensearch serviceAccount name. If Service Account doesn’t exist it could be created by setting serviceAccount.create and serviceAccount.name
cluster.cluster.general.serviceNamestring""Opensearch service name
cluster.cluster.general.setVMMaxMapCountbooltrueEnable setVMMaxMapCount. OpenSearch requires the Linux kernel vm.max_map_count option to be set to at least 262144
cluster.cluster.general.snapshotRepositorieslist[]Opensearch snapshot repositories configuration
cluster.cluster.general.vendorstring"Opensearch"
cluster.cluster.general.versionstring"2.19.1"Opensearch version
cluster.cluster.ingress.dashboards.annotationsobject{}dashboards ingress annotations
cluster.cluster.ingress.dashboards.classNamestring""Ingress class name
cluster.cluster.ingress.dashboards.enabledboolfalseEnable ingress for dashboards service
cluster.cluster.ingress.dashboards.hostslist[]Ingress hostnames
cluster.cluster.ingress.dashboards.tlslist[]Ingress tls configuration
cluster.cluster.ingress.opensearch.annotationsobject{}Opensearch ingress annotations
cluster.cluster.ingress.opensearch.classNamestring""Opensearch Ingress class name
cluster.cluster.ingress.opensearch.enabledboolfalseEnable ingress for Opensearch service
cluster.cluster.ingress.opensearch.hostslist[]Opensearch Ingress hostnames
cluster.cluster.ingress.opensearch.tlslist[]Opensearch tls configuration
cluster.cluster.initHelper.imagePullPolicystring"IfNotPresent"initHelper image pull policy
cluster.cluster.initHelper.imagePullSecretslist[]initHelper image pull secret
cluster.cluster.initHelper.resourcesobject{}initHelper pod cpu and memory resources
cluster.cluster.initHelper.versionstring"1.36"initHelper version
cluster.cluster.labelsobject{}OpenSearchCluster labels
cluster.cluster.namestring""OpenSearchCluster name, by default release name is used
cluster.cluster.nodePoolslist[{"component":"main","diskSize":"30Gi","replicas":3,"resources":{"limits":{"cpu":"500m","memory":"1Gi"},"requests":{"cpu":"500m","memory":"1Gi"}},"roles":["cluster_manager"]},{"component":"data","diskSize":"30Gi","replicas":1,"resources":{"limits":{"cpu":"500m","memory":"1Gi"},"requests":{"cpu":"500m","memory":"1Gi"}},"roles":["data"]},{"component":"client","diskSize":"30Gi","replicas":1,"resources":{"limits":{"cpu":"500m","memory":"1Gi"},"requests":{"cpu":"500m","memory":"1Gi"}},"roles":["client"]}]Opensearch nodes configuration
cluster.cluster.security.config.adminCredentialsSecretobject{}Secret that contains fields username and password to be used by the operator to access the opensearch cluster for node draining. Must be set if custom securityconfig is provided.
cluster.cluster.security.config.adminSecretobject{}TLS Secret that contains a client certificate (tls.key, tls.crt, ca.crt) with admin rights in the opensearch cluster. Must be set if transport certificates are provided by user and not generated
cluster.cluster.security.config.securityConfigSecretobject{}Secret that contains the differnt yml files of the opensearch-security config (config.yml, internal_users.yml, etc)
cluster.cluster.security.tls.http.caSecretobject{}Optional, secret that contains the ca certificate as ca.crt. If this and generate=true is set the existing CA cert from that secret is used to generate the node certs. In this case must contain ca.crt and ca.key fields
cluster.cluster.security.tls.http.generatebooltrueIf set to true the operator will generate a CA and certificates for the cluster to use, if false - secrets with existing certificates must be supplied
cluster.cluster.security.tls.http.secretobject{}Optional, name of a TLS secret that contains ca.crt, tls.key and tls.crt data. If ca.crt is in a different secret provide it via the caSecret field
cluster.cluster.security.tls.transport.adminDnlist[]DNs of certificates that should have admin access, mainly used for securityconfig updates via securityadmin.sh, only used when existing certificates are provided
cluster.cluster.security.tls.transport.caSecretobject{}Optional, secret that contains the ca certificate as ca.crt. If this and generate=true is set the existing CA cert from that secret is used to generate the node certs. In this case must contain ca.crt and ca.key fields
cluster.cluster.security.tls.transport.generatebooltrueIf set to true the operator will generate a CA and certificates for the cluster to use, if false secrets with existing certificates must be supplied
cluster.cluster.security.tls.transport.nodesDnlist[]Allowed Certificate DNs for nodes, only used when existing certificates are provided
cluster.cluster.security.tls.transport.perNodebooltrueSeparate certificate per node
cluster.cluster.security.tls.transport.secretobject{}Optional, name of a TLS secret that contains ca.crt, tls.key and tls.crt data. If ca.crt is in a different secret provide it via the caSecret field
cluster.componentTemplateslist[]List of OpensearchComponentTemplate. Check values.yaml file for examples.
cluster.fullnameOverridestring""
cluster.indexTemplateslist[]List of OpensearchIndexTemplate. Check values.yaml file for examples.
cluster.indexTemplatesWorkAroundlist[{"dataStream":{"timestamp_field":{"name":"@timestamp"}},"indexPatterns":["logs*"],"name":"logs-index-template","priority":100,"templateSpec":{"mappings":{"properties":{"@timestamp":{"type":"date"},"message":{"type":"text"}}},"settings":{"index":{"number_of_replicas":1,"number_of_shards":1,"refresh_interval":"1s"}}}}]List of OpensearchIndexTemplate. Check values.yaml file for examples.
cluster.ismPolicieslist[{"defaultState":"hot","description":"Policy to rollover logs after 7d, 30GB or 50M docs and delete after 30d","ismTemplate":{"indexPatterns":["logs*"],"priority":100},"name":"logs-rollover-policy","states":[{"actions":[{"rollover":{"minDocCount":50000000,"minIndexAge":"7d","minSize":"30gb"}}],"name":"hot","transitions":[{"conditions":{"minIndexAge":"30d"},"stateName":"delete"}]},{"actions":[{"delete":{}}],"name":"delete","transitions":[]}]}]List of OpenSearchISMPolicy. Check values.yaml file for examples.
cluster.nameOverridestring""
cluster.roleslist[{"clusterPermissions":["cluster_monitor","cluster_composite_ops","cluster:admin/ingest/pipeline/put","cluster:admin/ingest/pipeline/get","indices:admin/template/get","cluster_manage_index_templates"],"indexPermissions":[{"allowedActions":["indices:admin/template/get","indices:admin/template/put","indices:admin/mapping/put","indices:admin/create","indices:data/write/bulk*","indices:data/write/index","indices:data/read*","indices:monitor*","indices_all"],"indexPatterns":["logs*"]}],"name":"logs-role"}]List of OpensearchRole. Check values.yaml file for examples.
cluster.serviceAccount.annotationsobject{}Service Account annotations
cluster.serviceAccount.createboolfalseCreate Service Account
cluster.serviceAccount.namestring""Service Account name. Set general.serviceAccount to use this Service Account for the Opensearch cluster
cluster.tenantslist[]List of additional tenants. Check values.yaml file for examples.
cluster.userslist[{"backendRoles":[],"name":"logs","opendistroSecurityRoles":["logs-role"],"password":"","secretKey":"password","secretName":"logs-credentials"}]List of OpensearchUser. Check values.yaml file for examples.
cluster.usersRoleBindinglist[{"name":"logs-access","roles":["logs-role"],"users":["logs"]}]Allows to link any number of users, backend roles and roles with a OpensearchUserRoleBinding. Each user in the binding will be granted each role Check values.yaml file for examples.
operator.fullnameOverridestring"opensearch-operator"
operator.installCRDsboolfalse
operator.kubeRbacProxy.enablebooltrue
operator.kubeRbacProxy.image.repositorystring"gcr.io/kubebuilder/kube-rbac-proxy"
operator.kubeRbacProxy.image.tagstring"v0.15.0"
operator.kubeRbacProxy.livenessProbe.failureThresholdint3
operator.kubeRbacProxy.livenessProbe.httpGet.pathstring"/healthz"
operator.kubeRbacProxy.livenessProbe.httpGet.portint10443
operator.kubeRbacProxy.livenessProbe.httpGet.schemestring"HTTPS"
operator.kubeRbacProxy.livenessProbe.initialDelaySecondsint10
operator.kubeRbacProxy.livenessProbe.periodSecondsint15
operator.kubeRbacProxy.livenessProbe.successThresholdint1
operator.kubeRbacProxy.livenessProbe.timeoutSecondsint3
operator.kubeRbacProxy.readinessProbe.failureThresholdint3
operator.kubeRbacProxy.readinessProbe.httpGet.pathstring"/healthz"
operator.kubeRbacProxy.readinessProbe.httpGet.portint10443
operator.kubeRbacProxy.readinessProbe.httpGet.schemestring"HTTPS"
operator.kubeRbacProxy.readinessProbe.initialDelaySecondsint10
operator.kubeRbacProxy.readinessProbe.periodSecondsint15
operator.kubeRbacProxy.readinessProbe.successThresholdint1
operator.kubeRbacProxy.readinessProbe.timeoutSecondsint3
operator.kubeRbacProxy.resources.limits.cpustring"50m"
operator.kubeRbacProxy.resources.limits.memorystring"50Mi"
operator.kubeRbacProxy.resources.requests.cpustring"25m"
operator.kubeRbacProxy.resources.requests.memorystring"25Mi"
operator.kubeRbacProxy.securityContext.allowPrivilegeEscalationboolfalse
operator.kubeRbacProxy.securityContext.capabilities.drop[0]string"ALL"
operator.kubeRbacProxy.securityContext.readOnlyRootFilesystembooltrue
operator.manager.dnsBasestring"cluster.local"
operator.manager.extraEnvlist[]
operator.manager.image.pullPolicystring"Always"
operator.manager.image.repositorystring"opensearchproject/opensearch-operator"
operator.manager.image.tagstring""
operator.manager.imagePullSecretslist[]
operator.manager.livenessProbe.failureThresholdint3
operator.manager.livenessProbe.httpGet.pathstring"/healthz"
operator.manager.livenessProbe.httpGet.portint8081
operator.manager.livenessProbe.initialDelaySecondsint10
operator.manager.livenessProbe.periodSecondsint15
operator.manager.livenessProbe.successThresholdint1
operator.manager.livenessProbe.timeoutSecondsint3
operator.manager.loglevelstring"debug"
operator.manager.parallelRecoveryEnabledbooltrue
operator.manager.pprofEndpointsEnabledboolfalse
operator.manager.readinessProbe.failureThresholdint3
operator.manager.readinessProbe.httpGet.pathstring"/readyz"
operator.manager.readinessProbe.httpGet.portint8081
operator.manager.readinessProbe.initialDelaySecondsint10
operator.manager.readinessProbe.periodSecondsint15
operator.manager.readinessProbe.successThresholdint1
operator.manager.readinessProbe.timeoutSecondsint3
operator.manager.resources.limits.cpustring"200m"
operator.manager.resources.limits.memorystring"500Mi"
operator.manager.resources.requests.cpustring"100m"
operator.manager.resources.requests.memorystring"350Mi"
operator.manager.securityContext.allowPrivilegeEscalationboolfalse
operator.manager.watchNamespacestringnil
operator.nameOverridestring""
operator.namespacestring""
operator.nodeSelectorobject{}
operator.podAnnotationsobject{}
operator.podLabelsobject{}
operator.priorityClassNamestring""
operator.securityContext.runAsNonRootbooltrue
operator.serviceAccount.createbooltrue
operator.serviceAccount.namestring"opensearch-operator-controller-manager"
operator.tolerationslist[]
operator.useRoleBindingsboolfalse

Usage

Once deployed, OpenSearch can be accessed via OpenSearch Dashboards.

kubectl port-forward svc/opensearch-dashboards 5601:5601

Visit http://localhost:5601 in your browser and log in using the configured credentials.

Conclusion

This guide ensures that OpenSearch is fully integrated into the Greenhouse ecosystem, providing scalable log management and visualization. Additional custom configurations can be introduced to meet specific operational needs.

For troubleshooting and further details, check out the OpenSearch documentation.