Kubernetes deployment customization
Besides configuring OpenSearch itself, you can also customize how the operator deploys the OpenSearch and OpenSearch Dashboards pods.
Data persistence
By default, the operator creates OpenSearch node pools with persistent storage from the default Storage Class. This behavior can be changed per node pool. You may supply an alternative storage class and access mode, or configure hostPath or emptyDir storage.
The available storage options are:
Persistent Volume Claim (PVC)
The default option is persistent storage using PVCs. You can explicitly define the storageClass, annotations, and labels if needed:
nodePools:
- component: masters
replicas: 3
diskSize: "30Gi"
roles:
- "data"
- "master"
persistence:
pvc:
storageClass: mystorageclass # Set the name of the storage class to be used
accessModes: # You can change the accessMode
- ReadWriteOnce
annotations: # You can add annotations
test.io/crypt-key-id: "your-kms-key-id"
labels: # You can add labels
team: "backend-data"
emptyDir
If you do not want to use persistent storage, you can use the emptyDir option. Note that this can lead to data loss, so you should only use this option for testing or for data that is otherwise persisted.
nodePools:
- component: masters
replicas: 3
diskSize: "30Gi"
roles:
- "data"
- "master"
persistence:
emptyDir: {} # This configures emptyDir
If you are using emptyDir, set spec.general.drainDataNodes to true. This ensures that shards are drained from the pods before rolling upgrades or restart operations are performed.
hostPath
As a last option, you can use hostPath. Using hostPath is strongly discouraged. By default, the operator applies pod anti-affinity to prevent multiple pods from scheduling on the same node, which helps when using hostPath. However, if you need stricter control, configure explicit affinity rules for the node pool to ensure that multiple pods do not schedule to the same Kubernetes host.
nodePools:
- component: masters
replicas: 3
diskSize: "30Gi"
roles:
- "data"
- "master"
persistence:
hostPath:
path: "/var/opensearch" # Define the path on the host here
Security context for pods and containers
You can set the security context for the OpenSearch pods and the OpenSearch Dashboards pod to define privilege and access control settings. To specify security settings for pods, include the podSecurityContext field. For containers, include the securityContext field.
The structure is the same for both OpenSearch pods (in spec.general) and the OpenSearch Dashboards pod (in spec.dashboards):
spec:
general:
podSecurityContext:
runAsUser: 1000
runAsGroup: 1000
runAsNonRoot: true
securityContext:
allowPrivilegeEscalation: false
privileged: false
dashboards:
podSecurityContext:
fsGroup: 1000
runAsNonRoot: true
securityContext:
capabilities:
drop:
- ALL
privileged: false
The OpenSearch pods by default launch an init container to configure the volume. This container needs to run with root permissions and does not use a defined securityContext. If your Kubernetes environment does not allow containers with the root user, disable this init helper. In this situation, set general.setVMMaxMapCount to false because this feature also launches an init container with root.
The bootstrap pod started during initial cluster setup uses the same pod securityContext as the OpenSearch pods (with the same limitations for the init containers).
The bootstrap pod uses persistent storage (PVC) to maintain cluster state across restarts during initialization. This prevents cluster formation failures when the bootstrap pod restarts after the security configuration update job completes. The bootstrap PVC is automatically created and deleted along with the bootstrap pod.
Labels or annotations on OpenSearch nodes
You can add additional labels or annotations to the node pool configuration. This is useful for integration with other applications, such as a service mesh, or for configuring a Prometheus scrape endpoint.
Additionally, you can configure annotations globally using the spec.general.annotations field. These annotations apply not only to the node pool but also to Kubernetes services.
spec:
nodePools:
- component: masters
replicas: 3
diskSize: "5Gi"
labels: # Add any extra labels as key-value pairs here
someLabelKey: someLabelValue
annotations: # Add any extra annotations as key-value pairs here
someAnnotationKey: someAnnotationValue
nodeSelector:
resources:
requests:
memory: "2Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "500m"
roles:
- "data"
- "master"
Any annotations and labels defined are added directly to the node pool pods.
Add labels or annotations to the OpenSearch Dashboards deployment
You can add labels or annotations to the OpenSearch Dashboards pod specification. This is helpful if you want OpenSearch Dashboards to be part of a service mesh or integrate with other applications that rely on labels or annotations.
spec:
dashboards:
enable: true
version: 3.0.0
replicas: 1
labels: # Add any extra labels as key-value pairs here
someLabelKey: someLabelValue
annotations: # Add any extra annotations as key-value pairs here
someAnnotationKey: someAnnotationValue
Any annotations and labels defined are added directly to the OpenSearch Dashboards pods.
Priority class on OpenSearch nodes
You can configure OpenSearch nodes to use a PriorityClass by specifying the priority class name. This helps prevent unwanted evictions of your OpenSearch nodes.
spec:
nodePools:
- component: masters
replicas: 3
diskSize: "5Gi"
priorityClassName: somePriorityClassName
resources:
requests:
memory: "2Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "500m"
roles:
- "master"
Pod affinity
By default, the operator applies pod anti-affinity rules to prevent multiple pods from the same OpenSearch cluster from being scheduled on the same node. This improves high availability by reducing the risk of multiple pods being affected by a single node failure.
The default anti-affinity uses PreferredDuringSchedulingIgnoredDuringExecution, which is a soft preference that won’t prevent scheduling if no other nodes are available, but will prefer to spread pods across nodes.
You can override this default behavior by explicitly setting the affinity field in your node pool, bootstrap, or OpenSearch Dashboards configuration:
spec:
nodePools:
- component: masters
replicas: 3
diskSize: "30Gi"
roles:
- "master"
- "data"
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
opensearch.org/opensearch-cluster: my-cluster
topologyKey: kubernetes.io/hostname
bootstrap:
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
opensearch.org/opensearch-cluster: my-cluster
topologyKey: kubernetes.io/hostname
dashboards:
enable: true
affinity:
podAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchLabels:
app: opensearch-dashboards
topologyKey: kubernetes.io/zone
If you set an explicit affinity, it completely replaces the default anti-affinity behavior. To disable anti-affinity entirely, set affinity: {}.
Sidecar containers
You can deploy additional sidecar containers alongside OpenSearch in the same pod. This is useful for log shipping, monitoring agents, or other auxiliary services that need to run alongside OpenSearch nodes.
spec:
nodePools:
- component: masters
replicas: 3
diskSize: "30Gi"
resources:
requests:
memory: "2Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "500m"
roles:
- "master"
- "data"
sidecarContainers:
- name: log-shipper
image: fluent/fluent-bit:latest
resources:
requests:
memory: "64Mi"
cpu: "100m"
limits:
memory: "128Mi"
cpu: "200m"
volumeMounts:
- name: varlog
mountPath: /var/log
- name: monitoring-agent
image: prometheus/node-exporter:latest
ports:
- containerPort: 9100
name: metrics
Sidecar containers share the same network namespace and storage volumes as the OpenSearch container because they run in the same pod.
Additional volumes
You can mount additional volumes into the OpenSearch pods to provide additional configuration (for example, plugin config files). Supported volume types include ConfigMap, Secret, emptyDir, projected volumes, and CSI volumes.
Provide an array of additional volumes in either spec.general.additionalVolumes or spec.dashboards.additionalVolumes:
spec:
general:
additionalVolumes:
- name: example-configmap
path: /path/to/mount/volume
#subPath: mykey # Add this to mount only a specific key of the configmap/secret
configMap:
name: config-map-name
restartPods: true # Set this to true to restart the pods when the content of the configMap changes
- name: temp
path: /tmp
emptyDir: {}
- name: example-csi-volume
path: /path/to/mount/volume
#subPath: "subpath" # Add this to mount the CSI volume at a specific subpath
csi:
driver: csi-driver-name
readOnly: true
volumeAttributes:
secretProviderClass: example-secret-provider-class
- name: example-projected-volume
path: /path/to/mount/volume
projected:
sources:
- serviceAccountToken:
path: "token"
- name: example-persistentvolumeclaim-volume
path: /path/to/mount/volume
persistentVolumeClaim:
claimName: claim-name
- name: nfs-volume
path: /mnt/backups/opensearch
nfs:
server: 192.168.1.233
path: /export/backups/opensearch
readOnly: false # Optional, defaults to false
dashboards:
additionalVolumes:
- name: example-secret
path: /path/to/mount/volume
secret:
secretName: secret-name
NFS volume support
NFS volumes can be mounted directly into OpenSearch pods without requiring external provisioners or CSI drivers. This is particularly useful for snapshot repositories stored on NFS shares. To configure an NFS volume, specify the nfs field with the required server and path parameters:
spec:
general:
additionalVolumes:
- name: nfs-backups
path: /mnt/backups/opensearch
nfs:
server: 192.168.1.233
path: /export/backups/opensearch
readOnly: false # Optional, defaults to false
This can be combined with snapshot repository configuration:
spec:
general:
additionalVolumes:
- name: nfs-backups
path: /mnt/backups/opensearch
nfs:
server: 192.168.1.233
path: /export/backups/opensearch
snapshotRepositories:
- name: nfs-repository
type: fs
settings:
location: /mnt/backups/opensearch
The operator adds the defined volumes to all pods of the OpenSearch cluster. It is currently not possible to define them per node pool (nodePools).
Adding environment variables to pods
You can add your own environment variables to the OpenSearch pods and the OpenSearch Dashboards pods. You can provide the value as a string literal or mount it from a secret or ConfigMap.
The structure is the same for both OpenSearch and OpenSearch Dashboards:
spec:
dashboards:
env:
- name: MY_ENV_VAR
value: "myvalue"
- name: MY_SECRET_VAR
valueFrom:
secretKeyRef:
name: my-secret
key: some_key
- name: MY_CONFIGMAP_VAR
valueFrom:
configMapKeyRef:
name: my-configmap
key: some_key
nodePools:
- component: nodes
env:
- name: MY_ENV_VAR
value: "myvalue"
# The other options are supported here as well.
Custom cluster domain name
If your Kubernetes cluster is configured with a custom domain name (default is cluster.local), configure the operator accordingly for internal routing to work properly. Set manager.dnsBase in the Helm chart values.
manager:
# ...
dnsBase: custom.domain
Custom init helper
During cluster initialization, the operator uses init containers as helpers. For these containers, a busybox image is used (specifically docker.io/busybox:latest). If you are working in an offline environment and the cluster cannot access the registry or you want to customize the image, you can override the image used by specifying the initHelper image in your cluster spec:
spec:
initHelper:
# You can either only specify the version
version: "1.27.2-buildcustom"
# Or specify a totally different image
image: "mycustomrepo.cr/mycustombusybox:myversion"
# Additionally you can define the imagePullPolicy
imagePullPolicy: IfNotPresent
# and imagePullSecrets if needed
imagePullSecrets:
- name: docker-pull-secret
Edit init container resources
Init containers run without any resource constraints, but it’s possible to specify resource requests and limits by adding a resources section to the YAML definition. You can control the amount of CPU and memory allocated to the init container, helping to ensure that it doesn’t starve other containers, by setting appropriate resource limits.
spec:
initHelper:
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
Disabling the init helper
In some cases, you may want to avoid the chmod init container (for example, on OpenShift or if your cluster blocks containers running as root). It can be disabled by adding the following to your values.yaml:
manager:
extraEnv:
- name: SKIP_INIT_CONTAINER
value: "true"
PodDisruptionBudget
The PDB (Pod Disruption Budget) is a Kubernetes resource that helps ensure the high availability of applications by defining the acceptable disruption level during maintenance or unexpected events. It specifies the minimum number of pods that must remain available to maintain the desired level of service. The PDB definition is unique for every node pool (nodePools). Provide either minAvailable or maxUnavailable to configure PDB, but not both.
apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
nodePools:
- component: masters
replicas: 3
diskSize: "30Gi"
pdb:
enable: true
minAvailable: 3
- component: datas
replicas: 7
diskSize: "100Gi"
pdb:
enable: true
maxUnavailable: 2
Exposing OpenSearch Dashboards
To expose the OpenSearch Dashboards instance of your cluster for users or services outside of your Kubernetes cluster, the recommended way is to use ingress.
A simple example:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: opensearch-dashboards
namespace: default
spec:
tls:
- hosts:
- dashboards.my.company
rules:
- host: dashboards.my.company
http:
paths:
- backend:
service:
name: my-cluster-dashboards
port:
number: 5601
path: "/(.*)"
pathType: ImplementationSpecific
If you have enabled HTTPS for OpenSearch Dashboards, instruct your ingress controller to use an HTTPS connection internally. This is specific to the controller you are using (for example, nginx-ingress or traefik).
Configuring the OpenSearch Dashboards Kubernetes service
You can customize the Kubernetes Service object that the operator generates for the OpenSearch Dashboards deployment.
Supported Service Types:
- ClusterIP (default)
- NodePort
- LoadBalancer
When using type LoadBalancer, you can optionally set the load balancer source ranges.
apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
dashboards:
service:
type: LoadBalancer # Set one of the supported types
loadBalancerSourceRanges: "10.0.0.0/24, 192.168.0.0/24" # Optional, add source ranges for a load balancer
Exposing the OpenSearch cluster REST API
To expose the REST API of OpenSearch outside your Kubernetes cluster, the recommended way is to use ingress. Internally, use self-signed certificates (you can let the operator generate them) and then let the ingress use a certificate from an accepted CA (for example, Let’s Encrypt or a company-internal CA). That way you do not have the hassle of supplying custom certificates to the OpenSearch cluster but your users still see valid certificates.
Customizing probe timeouts and thresholds
If the cluster nodes do not start before the threshold is reached and the pod restarts, you can configure the timeouts and thresholds per node as needed.
apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
nodePools:
- component: masters
replicas: 3
diskSize: "30Gi"
probes:
liveness:
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 10
startup:
initialDelaySeconds: 10
periodSeconds: 20
timeoutSeconds: 5
successThreshold: 1
failureThreshold: 10
readiness:
initialDelaySeconds: 60
periodSeconds: 30
timeoutSeconds: 30
successThreshold: 1
failureThreshold: 5
Customize startup and readiness probe command
While the liveness probe is a TCP check, the startup and readiness probes use the OpenSearch API with curl.
If you need to customize the startup or readiness probe commands, you can override them as shown in the following example:
apiVersion: opensearch.org/v1
kind: OpenSearchCluster
...
spec:
nodePools:
- component: masters
...
probes:
startup:
command:
- echo
- "Hello, World!"
readiness:
command:
- echo
- "Hello, World!"
Configuring resource limits and requests
In addition to the information provided in the previous sections on how to specify resource requirements for the node pools, you can also specify resources for all entities created by the operator for more advanced use cases.
The operator generates many pods using resources such as jobs, stateful sets, and replica sets that use init containers. The following configuration lets you specify a default resources configuration for all init containers.
apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
initHelper:
resources:
requests:
memory: "50Mi"
cpu: "50m"
limits:
memory: "200Mi"
cpu: "200m"
You can also configure the resources for the security update job as shown in the following example.
apiVersion: opensearch.org/v1
kind: OpenSearchCluster
---
spec:
security:
config:
updateJob:
resources:
limits:
cpu: "100m"
memory: "100Mi"
requests:
cpu: "100m"
memory: "100Mi"
The examples provided here do not reflect actual resource requirements. You may need to conduct further testing to properly adjust the resources based on your specific needs.