--- apiVersion: apps/v1 kind: StatefulSet metadata: name: {{ template "opensearch.uname" . }} labels: {{- include "opensearch.labels" . | nindent 4 }} annotations: majorVersion: "{{ include "opensearch.majorVersion" . }}" {{- with .Values.openSearchAnnotations }} {{- toYaml . | nindent 4 }} {{- end }} spec: serviceName: {{ template "opensearch.serviceName" . }}-headless selector: matchLabels: {{- include "opensearch.selectorLabels" . | nindent 6 }} {{- if .Values.singleNode }} replicas: 1 {{- else }} replicas: {{ .Values.replicas }} {{- end }} podManagementPolicy: {{ .Values.podManagementPolicy }} updateStrategy: type: {{ .Values.updateStrategy }} {{- if .Values.persistence.enabled }} volumeClaimTemplates: - metadata: name: {{ template "opensearch.uname" . }} {{- if .Values.persistence.labels.enabled }} labels: {{- include "opensearch.labels" . | nindent 8 }} {{- end }} {{- with .Values.persistence.annotations }} annotations: {{ toYaml . | indent 8 }} {{- end }} spec: accessModes: {{- range .Values.persistence.accessModes }} - {{ . | quote }} {{- end }} resources: requests: storage: {{ .Values.persistence.size | quote }} {{- if .Values.persistence.storageClass }} {{- if (eq "-" .Values.persistence.storageClass) }} storageClassName: "" {{- else }} storageClassName: "{{ .Values.persistence.storageClass }}" {{- end }} {{- end }} {{- end }} template: metadata: name: "{{ template "opensearch.uname" . }}" labels: {{- include "opensearch.labels" . | nindent 8 }} annotations: {{- range $key, $value := .Values.podAnnotations }} {{ $key }}: {{ $value | quote }} {{- end }} {{- /* This forces a restart if the configmap has changed */}} {{- if .Values.config }} configchecksum: {{ include (print .Template.BasePath "/configmap.yaml") . | sha256sum | trunc 63 }} {{- end }} {{- if .Values.securityConfig.config.data }} securityconfigchecksum: {{ include (print .Template.BasePath "/securityconfig.yaml") . | sha256sum | trunc 63 }} {{- end }} spec: {{- if .Values.schedulerName }} schedulerName: "{{ .Values.schedulerName }}" {{- end }} securityContext: {{ toYaml .Values.podSecurityContext | indent 8 }} {{- if .Values.sysctl.enabled }} sysctls: - name: vm.max_map_count value: {{ .Values.sysctlVmMaxMapCount | quote }} {{- end }} {{- if .Values.fsGroup }} fsGroup: {{ .Values.fsGroup }} # Deprecated value, please use .Values.podSecurityContext.fsGroup {{- end }} {{- if and .Values.rbac.create (eq .Values.rbac.serviceAccountName "") }} serviceAccountName: "{{ template "opensearch.uname" . }}" automountServiceAccountToken: {{ ne .Values.rbac.automountServiceAccountToken false }} {{- else if and .Values.rbac.create (ne .Values.rbac.serviceAccountName "") }} serviceAccountName: {{ .Values.rbac.serviceAccountName | quote }} automountServiceAccountToken: {{ ne .Values.rbac.automountServiceAccountToken false }} {{- else }} automountServiceAccountToken: {{ ne .Values.rbac.automountServiceAccountToken false }} {{- end }} {{- if .Values.imagePullSecrets }} {{- end }} {{- with .Values.tolerations }} tolerations: {{ toYaml . | indent 6 }} {{- end }} {{- with .Values.nodeSelector }} nodeSelector: {{ toYaml . | indent 8 }} {{- end }} {{- if or (eq .Values.antiAffinity "hard") (eq .Values.antiAffinity "soft") .Values.nodeAffinity }} {{- if .Values.priorityClassName }} priorityClassName: {{ .Values.priorityClassName }} {{- end }} affinity: {{- end }} {{- if eq .Values.antiAffinity "hard" }} podAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: - labelSelector: matchExpressions: - key: app.kubernetes.io/instance operator: In values: - {{ .Release.Name }} - key: app.kubernetes.io/name operator: In values: - {{ include "opensearch.name" . }} topologyKey: {{ .Values.antiAffinityTopologyKey }} {{- else if eq .Values.antiAffinity "soft" }} podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 1 podAffinityTerm: topologyKey: {{ .Values.antiAffinityTopologyKey }} labelSelector: matchExpressions: - key: app.kubernetes.io/instance operator: In values: - {{ .Release.Name }} - key: app.kubernetes.io/name operator: In values: - {{ include "opensearch.name" . }} {{- end }} {{- with .Values.nodeAffinity }} nodeAffinity: {{ toYaml . | indent 10 }} {{- end }} {{- if .Values.topologySpreadConstraints }} topologySpreadConstraints: {{- toYaml .Values.topologySpreadConstraints | nindent 8 }} {{- end }} terminationGracePeriodSeconds: {{ .Values.terminationGracePeriod }} volumes: {{- range .Values.secretMounts }} - name: {{ .name | required "secretMount .name is required" }} secret: secretName: {{ .secretName | required "secretMount .secretName is required" }} {{- if .defaultMode }} defaultMode: {{ .defaultMode }} {{- end }} {{- end }} {{- if .Values.config }} - name: config configMap: name: {{ template "opensearch.uname" . }}-config {{- end }} {{- if and .Values.securityConfig.config.data .Values.securityConfig.config.securityConfigSecret }} {{ fail "Only one of .Values.securityConfig.config.data and .Values.securityConfig.config.securityConfigSecret may be defined. Please see the comment in values.yaml describing usage." }} {{- end }} {{- if .Values.securityConfig.config.data }} - name: security-config-data secret: secretName: {{ include "opensearch.uname" . }}-securityconfig {{- end }} {{- with .Values.securityConfig.config.securityConfigSecret }} - name: security-config-complete secret: secretName: {{ . | quote }} {{- end }} {{- if .Values.securityConfig.actionGroupsSecret }} - name: action-groups secret: secretName: {{ .Values.securityConfig.actionGroupsSecret }} {{- end }} {{- if .Values.securityConfig.configSecret }} - name: security-config secret: secretName: {{ .Values.securityConfig.configSecret }} {{- end }} {{- if .Values.securityConfig.internalUsersSecret }} - name: internal-users-config secret: secretName: {{ .Values.securityConfig.internalUsersSecret }} {{- end }} {{- if .Values.securityConfig.rolesSecret }} - name: roles secret: secretName: {{ .Values.securityConfig.rolesSecret }} {{- end }} {{- if .Values.securityConfig.rolesMappingSecret }} - name: role-mapping secret: secretName: {{ .Values.securityConfig.rolesMappingSecret }} {{- end -}} {{- if .Values.securityConfig.tenantsSecret }} - name: tenants secret: secretName: {{ .Values.securityConfig.tenantsSecret }} {{- end }} {{- if .Values.keystore }} - name: keystore emptyDir: {} {{- range .Values.keystore }} - name: keystore-{{ .secretName }} secret: {{ toYaml . | nindent 12 }} {{- end }} {{ end }} {{- if .Values.extraVolumes }} # Currently some extra blocks accept strings # to continue with backwards compatibility this is being kept # whilst also allowing for yaml to be specified too. {{- if eq "string" (printf "%T" .Values.extraVolumes) }} {{ tpl .Values.extraVolumes . | indent 6 }} {{- else }} {{ toYaml .Values.extraVolumes | indent 6 }} {{- end }} {{- end }} {{- if .Values.imagePullSecrets }} imagePullSecrets: {{ toYaml .Values.imagePullSecrets | indent 8 }} {{- end }} enableServiceLinks: {{ .Values.enableServiceLinks }} {{- if .Values.hostAliases }} hostAliases: {{ toYaml .Values.hostAliases | nindent 8 }} {{- end }} {{- if or (.Values.extraInitContainers) (.Values.keystore) (.Values.persistence.enabled) (.Values.sysctlInit.enabled) }} initContainers: {{- if and .Values.persistence.enabled .Values.persistence.enableInitChown }} - name: fsgroup-volume image: "{{ template "opensearch.dockerRegistry" . }}{{ .Values.persistence.image | default "busybox" }}:{{ .Values.persistence.imageTag | default "latest" }}" imagePullPolicy: "{{ .Values.image.pullPolicy }}" command: ['sh', '-c'] args: - 'chown -R 1000:1000 /usr/share/opensearch/data' securityContext: runAsUser: 0 resources: {{- toYaml .Values.initResources | nindent 10 }} volumeMounts: - name: "{{ template "opensearch.uname" . }}" mountPath: {{ .Values.opensearchHome }}/data {{- end }} {{- if .Values.sysctlInit.enabled }} - name: sysctl image: "{{ template "opensearch.dockerRegistry" . }}{{ .Values.sysctlInit.image | default "busybox" }}:{{ .Values.sysctlInit.imageTag | default "latest" }}" imagePullPolicy: "{{ .Values.image.pullPolicy }}" command: - sh - -c - | set -xe DESIRED="{{ .Values.sysctlVmMaxMapCount }}" CURRENT=$(sysctl -n vm.max_map_count) if [ "$DESIRED" -gt "$CURRENT" ]; then sysctl -w vm.max_map_count=$DESIRED fi securityContext: runAsUser: 0 privileged: true resources: {{- toYaml .Values.initResources | nindent 10 }} {{- end }} {{- if .Values.keystore }} - name: keystore image: "{{ template "opensearch.dockerRegistry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: "{{ .Values.image.pullPolicy }}" command: - sh - -c - | #!/usr/bin/env bash set -euo pipefail {{ .Values.opensearchHome }}/bin/opensearch-keystore create for i in /tmp/keystoreSecrets/*/*; do [ -f "$i" ] || continue key=$(basename $i) echo "Adding file $i to keystore key $key" {{ .Values.opensearchHome }}/bin/opensearch-keystore add-file "$key" "$i" done # Add the bootstrap password since otherwise the opensearch entrypoint tries to do this on startup if [ ! -z ${PASSWORD+x} ]; then echo 'Adding env $PASSWORD to keystore as key bootstrap.password' echo "$PASSWORD" | {{ .Values.opensearchHome }}/bin/opensearch-keystore add -x bootstrap.password fi cp -a {{ .Values.opensearchHome }}/config/opensearch.keystore /tmp/keystore/ env: {{ toYaml .Values.extraEnvs | nindent 10 }} envFrom: {{ toYaml .Values.envFrom | nindent 10 }} resources: {{- toYaml .Values.initResources | nindent 10 }} volumeMounts: - name: keystore mountPath: /tmp/keystore {{- range .Values.keystore }} - name: keystore-{{ .secretName }} mountPath: /tmp/keystoreSecrets/{{ .secretName }} {{- end }} {{- end }} {{- if .Values.extraInitContainers }} # Currently some extra blocks accept strings # to continue with backwards compatibility this is being kept # whilst also allowing for yaml to be specified too. {{- if eq "string" (printf "%T" .Values.extraInitContainers) }} {{ tpl .Values.extraInitContainers . | indent 6 }} {{- else }} {{ toYaml .Values.extraInitContainers | indent 6 }} {{- end }} {{- end }} {{- end }} containers: - name: "{{ template "opensearch.name" . }}" securityContext: {{ toYaml .Values.securityContext | indent 10 }} {{- if .Values.plugins.enabled }} command: - sh - -c - | #!/usr/bin/env bash set -euo pipefail {{- range $plugin := .Values.plugins.installList }} ./bin/opensearch-plugin install -b {{ $plugin }} {{- end }} bash opensearch-docker-entrypoint.sh {{- end }} image: "{{ template "opensearch.dockerRegistry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: "{{ .Values.image.pullPolicy }}" readinessProbe: {{ toYaml .Values.readinessProbe | indent 10 }} {{- if .Values.livenessProbe }} livenessProbe: {{ toYaml .Values.livenessProbe | indent 10 }} {{- end }} {{- if semverCompare ">=1.16-0" .Capabilities.KubeVersion.Version }} startupProbe: {{ toYaml .Values.startupProbe | indent 10 }} {{- end }} ports: - name: http containerPort: {{ .Values.httpPort }} {{- if .Values.httpHostPort }} hostPort: {{ .Values.httpHostPort }} {{- end }} - name: transport containerPort: {{ .Values.transportPort }} {{- if .Values.transportHostPort }} hostPort: {{ .Values.transportHostPort }} {{- end }} - name: metrics containerPort: {{ .Values.metricsPort }} resources: {{- toYaml .Values.resources | nindent 10 }} env: - name: node.name valueFrom: fieldRef: fieldPath: metadata.name {{- if (and (has "master" .Values.roles) (not .Values.singleNode)) }} - name: cluster.initial_master_nodes value: "{{ template "opensearch.endpoints" . }}" {{- end }} - name: discovery.seed_hosts value: "{{ template "opensearch.masterService" . }}-headless" - name: cluster.name value: "{{ .Values.clusterName }}" - name: network.host value: "{{ .Values.networkHost }}" - name: OPENSEARCH_JAVA_OPTS value: "{{ .Values.opensearchJavaOpts }}" - name: node.roles value: "{{ template "opensearch.roles" . }}" {{- if .Values.singleNode }} - name: discovery.type value: "single-node" {{- end }} {{- if .Values.extraEnvs }} {{ toYaml .Values.extraEnvs | indent 8 }} {{- end }} {{- if .Values.envFrom }} envFrom: {{ toYaml .Values.envFrom | indent 8 }} {{- end }} {{- if .Values.opensearchLifecycle }} lifecycle: {{ toYaml .Values.opensearchLifecycle | indent 10 }} {{- end }} volumeMounts: {{- if .Values.persistence.enabled }} - name: "{{ template "opensearch.uname" . }}" mountPath: {{ .Values.opensearchHome }}/data {{- end }} {{- if .Values.keystore }} - name: keystore mountPath: {{ .Values.opensearchHome }}/config/opensearch.keystore subPath: opensearch.keystore {{- end }} {{- if .Values.securityConfig.enabled }} {{- if .Values.securityConfig.actionGroupsSecret }} - mountPath: {{ .Values.securityConfig.path }}/action_groups.yml name: action-groups subPath: action_groups.yml {{- end }} {{- if .Values.securityConfig.configSecret }} - mountPath: {{ .Values.securityConfig.path }}/config.yml name: security-config subPath: config.yml {{- end }} {{- if .Values.securityConfig.internalUsersSecret }} - mountPath: {{ .Values.securityConfig.path }}/internal_users.yml name: internal-users-config subPath: internal_users.yml {{- end }} {{- if .Values.securityConfig.rolesSecret }} - mountPath: {{ .Values.securityConfig.path }}/roles.yml name: roles subPath: roles.yml {{- end }} {{- if .Values.securityConfig.rolesMappingSecret }} - mountPath: {{ .Values.securityConfig.path }}/roles_mapping.yml name: role-mapping subPath: roles_mapping.yml {{- end }} {{- if .Values.securityConfig.tenantsSecret }} - mountPath: {{ .Values.securityConfig.path }}/tenants.yml name: tenants subPath: tenants.yml {{- end }} {{- if .Values.securityConfig.config.data }} {{- if .Values.securityConfig.config.dataComplete }} - mountPath: {{ .Values.securityConfig.path }} name: security-config-data {{- else }} {{- range $key, $_ := .Values.securityConfig.config.data }} - mountPath: {{ $.Values.securityConfig.path }}/{{ $key }} name: security-config-data subPath: {{ $key }} {{- end }} {{- end }} {{- else if .Values.securityConfig.config.securityConfigSecret }} - mountPath: {{ .Values.securityConfig.path }} name: security-config-complete {{- end }} {{- end }} {{- range .Values.secretMounts }} - name: {{ .name | required "secretMount .name is required" }} mountPath: {{ .path | required "secretMount .path is required" }} {{- if .subPath }} subPath: {{ .subPath }} {{- end }} {{- end }} {{- range $path, $config := .Values.config }} - name: config mountPath: {{ $.Values.opensearchHome }}/config/{{ $path }} subPath: {{ $path }} {{- end -}} {{- if .Values.extraVolumeMounts }} # Currently some extra blocks accept strings # to continue with backwards compatibility this is being kept # whilst also allowing for yaml to be specified too. {{- if eq "string" (printf "%T" .Values.extraVolumeMounts) }} {{ tpl .Values.extraVolumeMounts . | indent 8 }} {{- else }} {{ toYaml .Values.extraVolumeMounts | indent 8 }} {{- end }} {{- end }} {{- if .Values.masterTerminationFix }} {{- if has "master" .Values.roles }} # This sidecar will prevent slow master re-election - name: opensearch-master-graceful-termination-handler image: "{{ template "opensearch.dockerRegistry" . }}{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" imagePullPolicy: "{{ .Values.image.pullPolicy }}" command: - "sh" - -c - | #!/usr/bin/env bash set -eo pipefail http () { local path="${1}" if [ -n "${USERNAME}" ] && [ -n "${PASSWORD}" ]; then BASIC_AUTH="-u ${USERNAME}:${PASSWORD}" else BASIC_AUTH='' fi curl -XGET -s -k --fail ${BASIC_AUTH} {{ .Values.protocol }}://{{ template "opensearch.masterService" . }}:{{ .Values.httpPort }}${path} } cleanup () { while true ; do local master="$(http "/_cat/master?h=node" || echo "")" if [[ $master == "{{ template "opensearch.masterService" . }}"* && $master != "${NODE_NAME}" ]]; then echo "This node is not master." break fi echo "This node is still master, waiting gracefully for it to step down" sleep 1 done exit 0 } trap cleanup SIGTERM sleep infinity & wait $! resources: {{- toYaml .Values.sidecarResources | nindent 10 }} env: - name: NODE_NAME valueFrom: fieldRef: fieldPath: metadata.name {{- if .Values.extraEnvs }} {{ toYaml .Values.extraEnvs | indent 8 }} {{- end }} {{- if .Values.envFrom }} envFrom: {{ toYaml .Values.envFrom | indent 8 }} {{- end }} {{- end }} {{- end }} {{- if .Values.lifecycle }} lifecycle: {{ toYaml .Values.lifecycle | indent 10 }} {{- end }} {{- if .Values.extraContainers }} # Currently some extra blocks accept strings # to continue with backwards compatibility this is being kept # whilst also allowing for yaml to be specified too. {{- if eq "string" (printf "%T" .Values.extraContainers) }} {{ tpl .Values.extraContainers . | indent 6 }} {{- else }} {{ toYaml .Values.extraContainers | indent 6 }} {{- end }} {{- end }}