added repo
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
# Various IDEs
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
OWNERS
|
||||
@@ -0,0 +1,18 @@
|
||||
apiVersion: v1
|
||||
appVersion: 3.11.5
|
||||
description: Apache Cassandra is a free and open-source distributed database management
|
||||
system designed to handle large amounts of data across many commodity servers, providing
|
||||
high availability with no single point of failure.
|
||||
home: http://cassandra.apache.org
|
||||
icon: https://upload.wikimedia.org/wikipedia/commons/thumb/5/5e/Cassandra_logo.svg/330px-Cassandra_logo.svg.png
|
||||
keywords:
|
||||
- cassandra
|
||||
- database
|
||||
- nosql
|
||||
maintainers:
|
||||
- email: goonohc@gmail.com
|
||||
name: KongZ
|
||||
- email: maor.friedman@redhat.com
|
||||
name: maorfr
|
||||
name: cassandra
|
||||
version: 0.14.3
|
||||
@@ -0,0 +1,215 @@
|
||||
# Cassandra
|
||||
A Cassandra Chart for Kubernetes
|
||||
|
||||
## Install Chart
|
||||
To install the Cassandra Chart into your Kubernetes cluster (This Chart requires persistent volume by default, you may need to create a storage class before install chart. To create storage class, see [Persist data](#persist_data) section)
|
||||
|
||||
```bash
|
||||
helm install --namespace "cassandra" -n "cassandra" incubator/cassandra
|
||||
```
|
||||
|
||||
After installation succeeds, you can get a status of Chart
|
||||
|
||||
```bash
|
||||
helm status "cassandra"
|
||||
```
|
||||
|
||||
If you want to delete your Chart, use this command
|
||||
```bash
|
||||
helm delete --purge "cassandra"
|
||||
```
|
||||
|
||||
## Upgrading
|
||||
|
||||
To upgrade your Cassandra release, simply run
|
||||
|
||||
```bash
|
||||
helm upgrade "cassandra" incubator/cassandra
|
||||
```
|
||||
|
||||
### 0.12.0
|
||||
|
||||
This version fixes https://github.com/helm/charts/issues/7803 by removing mutable labels in `spec.VolumeClaimTemplate.metadata.labels` so that it is upgradable.
|
||||
|
||||
Until this version, in order to upgrade, you have to delete the Cassandra StatefulSet before upgrading:
|
||||
```bash
|
||||
$ kubectl delete statefulset --cascade=false my-cassandra-release
|
||||
```
|
||||
|
||||
|
||||
## Persist data
|
||||
You need to create `StorageClass` before able to persist data in persistent volume.
|
||||
To create a `StorageClass` on Google Cloud, run the following
|
||||
|
||||
```bash
|
||||
kubectl create -f sample/create-storage-gce.yaml
|
||||
```
|
||||
|
||||
And set the following values in `values.yaml`
|
||||
|
||||
```yaml
|
||||
persistence:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
If you want to create a `StorageClass` on other platform, please see documentation here [https://kubernetes.io/docs/user-guide/persistent-volumes/](https://kubernetes.io/docs/user-guide/persistent-volumes/)
|
||||
|
||||
When running a cluster without persistence, the termination of a pod will first initiate a decommissioning of that pod.
|
||||
Depending on the amount of data stored inside the cluster this may take a while. In order to complete a graceful
|
||||
termination, pods need to get more time for it. Set the following values in `values.yaml`:
|
||||
|
||||
```yaml
|
||||
podSettings:
|
||||
terminationGracePeriodSeconds: 1800
|
||||
```
|
||||
|
||||
## Install Chart with specific cluster size
|
||||
By default, this Chart will create a cassandra with 3 nodes. If you want to change the cluster size during installation, you can use `--set config.cluster_size={value}` argument. Or edit `values.yaml`
|
||||
|
||||
For example:
|
||||
Set cluster size to 5
|
||||
|
||||
```bash
|
||||
helm install --namespace "cassandra" -n "cassandra" --set config.cluster_size=5 incubator/cassandra/
|
||||
```
|
||||
|
||||
## Install Chart with specific resource size
|
||||
By default, this Chart will create a cassandra with CPU 2 vCPU and 4Gi of memory which is suitable for development environment.
|
||||
If you want to use this Chart for production, I would recommend to update the CPU to 4 vCPU and 16Gi. Also increase size of `max_heap_size` and `heap_new_size`.
|
||||
To update the settings, edit `values.yaml`
|
||||
|
||||
## Install Chart with specific node
|
||||
Sometime you may need to deploy your cassandra to specific nodes to allocate resources. You can use node selector by edit `nodes.enabled=true` in `values.yaml`
|
||||
For example, you have 6 vms in node pools and you want to deploy cassandra to node which labeled as `cloud.google.com/gke-nodepool: pool-db`
|
||||
|
||||
Set the following values in `values.yaml`
|
||||
|
||||
```yaml
|
||||
nodes:
|
||||
enabled: true
|
||||
selector:
|
||||
nodeSelector:
|
||||
cloud.google.com/gke-nodepool: pool-db
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
The following table lists the configurable parameters of the Cassandra chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
| ----------------------- | --------------------------------------------- | ---------------------------------------------------------- |
|
||||
| `image.repo` | `cassandra` image repository | `cassandra` |
|
||||
| `image.tag` | `cassandra` image tag | `3.11.5` |
|
||||
| `image.pullPolicy` | Image pull policy | `Always` if `imageTag` is `latest`, else `IfNotPresent` |
|
||||
| `image.pullSecrets` | Image pull secrets | `nil` |
|
||||
| `config.cluster_domain` | The name of the cluster domain. | `cluster.local` |
|
||||
| `config.cluster_name` | The name of the cluster. | `cassandra` |
|
||||
| `config.cluster_size` | The number of nodes in the cluster. | `3` |
|
||||
| `config.seed_size` | The number of seed nodes used to bootstrap new clients joining the cluster. | `2` |
|
||||
| `config.seeds` | The comma-separated list of seed nodes. | Automatically generated according to `.Release.Name` and `config.seed_size` |
|
||||
| `config.num_tokens` | Initdb Arguments | `256` |
|
||||
| `config.dc_name` | Initdb Arguments | `DC1` |
|
||||
| `config.rack_name` | Initdb Arguments | `RAC1` |
|
||||
| `config.endpoint_snitch` | Initdb Arguments | `SimpleSnitch` |
|
||||
| `config.max_heap_size` | Initdb Arguments | `2048M` |
|
||||
| `config.heap_new_size` | Initdb Arguments | `512M` |
|
||||
| `config.ports.cql` | Initdb Arguments | `9042` |
|
||||
| `config.ports.thrift` | Initdb Arguments | `9160` |
|
||||
| `config.ports.agent` | The port of the JVM Agent (if any) | `nil` |
|
||||
| `config.start_rpc` | Initdb Arguments | `false` |
|
||||
| `configOverrides` | Overrides config files in /etc/cassandra dir | `{}` |
|
||||
| `commandOverrides` | Overrides default docker command | `[]` |
|
||||
| `argsOverrides` | Overrides default docker args | `[]` |
|
||||
| `env` | Custom env variables | `{}` |
|
||||
| `schedulerName` | Name of k8s scheduler (other than the default) | `nil` |
|
||||
| `persistence.enabled` | Use a PVC to persist data | `true` |
|
||||
| `persistence.storageClass` | Storage class of backing PVC | `nil` (uses alpha storage class annotation) |
|
||||
| `persistence.accessMode` | Use volume as ReadOnly or ReadWrite | `ReadWriteOnce` |
|
||||
| `persistence.size` | Size of data volume | `10Gi` |
|
||||
| `resources` | CPU/Memory resource requests/limits | Memory: `4Gi`, CPU: `2` |
|
||||
| `service.type` | k8s service type exposing ports, e.g. `NodePort`| `ClusterIP` |
|
||||
| `service.annotations` | Annotations to apply to cassandra service | `""` |
|
||||
| `podManagementPolicy` | podManagementPolicy of the StatefulSet | `OrderedReady` |
|
||||
| `podDisruptionBudget` | Pod distruption budget | `{}` |
|
||||
| `podAnnotations` | pod annotations for the StatefulSet | `{}` |
|
||||
| `updateStrategy.type` | UpdateStrategy of the StatefulSet | `OnDelete` |
|
||||
| `livenessProbe.initialDelaySeconds` | Delay before liveness probe is initiated | `90` |
|
||||
| `livenessProbe.periodSeconds` | How often to perform the probe | `30` |
|
||||
| `livenessProbe.timeoutSeconds` | When the probe times out | `5` |
|
||||
| `livenessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed. | `1` |
|
||||
| `livenessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `3` |
|
||||
| `readinessProbe.initialDelaySeconds` | Delay before readiness probe is initiated | `90` |
|
||||
| `readinessProbe.periodSeconds` | How often to perform the probe | `30` |
|
||||
| `readinessProbe.timeoutSeconds` | When the probe times out | `5` |
|
||||
| `readinessProbe.successThreshold` | Minimum consecutive successes for the probe to be considered successful after having failed. | `1` |
|
||||
| `readinessProbe.failureThreshold` | Minimum consecutive failures for the probe to be considered failed after having succeeded. | `3` |
|
||||
| `readinessProbe.address` | Address to use for checking node has joined the cluster and is ready. | `${POD_IP}` |
|
||||
| `rbac.create` | Specifies whether RBAC resources should be created | `true` |
|
||||
| `serviceAccount.create` | Specifies whether a ServiceAccount should be created | `true` |
|
||||
| `serviceAccount.name` | The name of the ServiceAccount to use | |
|
||||
| `backup.enabled` | Enable backup on chart installation | `false` |
|
||||
| `backup.schedule` | Keyspaces to backup, each with cron time | |
|
||||
| `backup.annotations` | Backup pod annotations | iam.amazonaws.com/role: `cain` |
|
||||
| `backup.image.repository` | Backup image repository | `maorfr/cain` |
|
||||
| `backup.image.tag` | Backup image tag | `0.6.0` |
|
||||
| `backup.extraArgs` | Additional arguments for cain | `[]` |
|
||||
| `backup.env` | Backup environment variables | AWS_REGION: `us-east-1` |
|
||||
| `backup.resources` | Backup CPU/Memory resource requests/limits | Memory: `1Gi`, CPU: `1` |
|
||||
| `backup.destination` | Destination to store backup artifacts | `s3://bucket/cassandra` |
|
||||
| `backup.google.serviceAccountSecret` | Secret containing credentials if GCS is used as destination | |
|
||||
| `exporter.enabled` | Enable Cassandra exporter | `false` |
|
||||
| `exporter.servicemonitor` | Enable ServiceMonitor for exporter | `true` |
|
||||
| `exporter.additionalLabels` | Additional labels for Service Monitor | `{}` |
|
||||
| `exporter.image.repo` | Exporter image repository | `criteord/cassandra_exporter` |
|
||||
| `exporter.image.tag` | Exporter image tag | `2.0.2` |
|
||||
| `exporter.port` | Exporter port | `5556` |
|
||||
| `exporter.jvmOpts` | Exporter additional JVM options | |
|
||||
| `exporter.resources` | Exporter CPU/Memory resource requests/limits | `{}` |
|
||||
| `affinity` | Kubernetes node affinity | `{}` |
|
||||
| `tolerations` | Kubernetes node tolerations | `[]` |
|
||||
|
||||
|
||||
## Scale cassandra
|
||||
When you want to change the cluster size of your cassandra, you can use the helm upgrade command.
|
||||
|
||||
```bash
|
||||
helm upgrade --set config.cluster_size=5 cassandra incubator/cassandra
|
||||
```
|
||||
|
||||
## Get cassandra status
|
||||
You can get your cassandra cluster status by running the command
|
||||
|
||||
```bash
|
||||
kubectl exec -it --namespace cassandra $(kubectl get pods --namespace cassandra -l app=cassandra-cassandra -o jsonpath='{.items[0].metadata.name}') nodetool status
|
||||
```
|
||||
|
||||
Output
|
||||
```bash
|
||||
Datacenter: asia-east1
|
||||
======================
|
||||
Status=Up/Down
|
||||
|/ State=Normal/Leaving/Joining/Moving
|
||||
-- Address Load Tokens Owns (effective) Host ID Rack
|
||||
UN 10.8.1.11 108.45 KiB 256 66.1% 410cc9da-8993-4dc2-9026-1dd381874c54 a
|
||||
UN 10.8.4.12 84.08 KiB 256 68.7% 96e159e1-ef94-406e-a0be-e58fbd32a830 c
|
||||
UN 10.8.3.6 103.07 KiB 256 65.2% 1a42b953-8728-4139-b070-b855b8fff326 b
|
||||
```
|
||||
|
||||
## Benchmark
|
||||
You can use [cassandra-stress](https://docs.datastax.com/en/cassandra/3.0/cassandra/tools/toolsCStress.html) tool to run the benchmark on the cluster by the following command
|
||||
|
||||
```bash
|
||||
kubectl exec -it --namespace cassandra $(kubectl get pods --namespace cassandra -l app=cassandra-cassandra -o jsonpath='{.items[0].metadata.name}') cassandra-stress
|
||||
```
|
||||
|
||||
Example of `cassandra-stress` argument
|
||||
- Run both read and write with ration 9:1
|
||||
- Operator total 1 million keys with uniform distribution
|
||||
- Use QUORUM for read/write
|
||||
- Generate 50 threads
|
||||
- Generate result in graph
|
||||
- Use NetworkTopologyStrategy with replica factor 2
|
||||
|
||||
```bash
|
||||
cassandra-stress mixed ratio\(write=1,read=9\) n=1000000 cl=QUORUM -pop dist=UNIFORM\(1..1000000\) -mode native cql3 -rate threads=50 -log file=~/mixed_autorate_r9w1_1M.log -graph file=test2.html title=test revision=test2 -schema "replication(strategy=NetworkTopologyStrategy, factor=2)"
|
||||
```
|
||||
@@ -0,0 +1,7 @@
|
||||
kind: StorageClass
|
||||
apiVersion: storage.k8s.io/v1
|
||||
metadata:
|
||||
name: generic
|
||||
provisioner: kubernetes.io/gce-pd
|
||||
parameters:
|
||||
type: pd-ssd
|
||||
@@ -0,0 +1,35 @@
|
||||
Cassandra CQL can be accessed via port {{ .Values.config.ports.cql }} on the following DNS name from within your cluster:
|
||||
Cassandra Thrift can be accessed via port {{ .Values.config.ports.thrift }} on the following DNS name from within your cluster:
|
||||
|
||||
If you want to connect to the remote instance with your local Cassandra CQL cli. To forward the API port to localhost:9042 run the following:
|
||||
- kubectl port-forward --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l app={{ template "cassandra.name" . }},release={{ .Release.Name }} -o jsonpath='{ .items[0].metadata.name }') 9042:{{ .Values.config.ports.cql }}
|
||||
|
||||
If you want to connect to the Cassandra CQL run the following:
|
||||
{{- if contains "NodePort" .Values.service.type }}
|
||||
- export CQL_PORT=$(kubectl get --namespace {{ .Release.Namespace }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ template "cassandra.fullname" . }})
|
||||
- export CQL_HOST=$(kubectl get nodes --namespace {{ .Release.Namespace }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
- cqlsh $CQL_HOST $CQL_PORT
|
||||
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
Watch the status with: 'kubectl get svc --namespace {{ .Release.Namespace }} -w {{ template "cassandra.fullname" . }}'
|
||||
- export SERVICE_IP=$(kubectl get svc --namespace {{ .Release.Namespace }} {{ template "cassandra.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
- echo cqlsh $SERVICE_IP
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
- kubectl port-forward --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l "app={{ template "cassandra.name" . }},release={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}") 9042:{{ .Values.config.ports.cql }}
|
||||
echo cqlsh 127.0.0.1 9042
|
||||
{{- end }}
|
||||
|
||||
You can also see the cluster status by run the following:
|
||||
- kubectl exec -it --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l app={{ template "cassandra.name" . }},release={{ .Release.Name }} -o jsonpath='{.items[0].metadata.name}') nodetool status
|
||||
|
||||
To tail the logs for the Cassandra pod run the following:
|
||||
- kubectl logs -f --namespace {{ .Release.Namespace }} $(kubectl get pods --namespace {{ .Release.Namespace }} -l app={{ template "cassandra.name" . }},release={{ .Release.Name }} -o jsonpath='{ .items[0].metadata.name }')
|
||||
|
||||
{{- if not .Values.persistence.enabled }}
|
||||
|
||||
Note that the cluster is running with node-local storage instead of PersistentVolumes. In order to prevent data loss,
|
||||
pods will be decommissioned upon termination. Decommissioning may take some time, so you might also want to adjust the
|
||||
pod termination gace period, which is currently set to {{ .Values.podSettings.terminationGracePeriodSeconds }} seconds.
|
||||
|
||||
{{- end}}
|
||||
@@ -0,0 +1,43 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "cassandra.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "cassandra.fullname" -}}
|
||||
{{- if .Values.fullnameOverride -}}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- if contains $name .Release.Name -}}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- else -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "cassandra.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use
|
||||
*/}}
|
||||
{{- define "cassandra.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{ default (include "cassandra.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,90 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
{{- $release := .Release }}
|
||||
{{- $values := .Values }}
|
||||
{{- $backup := $values.backup }}
|
||||
{{- range $index, $schedule := $backup.schedule }}
|
||||
---
|
||||
apiVersion: batch/v1beta1
|
||||
kind: CronJob
|
||||
metadata:
|
||||
name: {{ template "cassandra.fullname" $ }}-backup-{{ $schedule.keyspace | replace "_" "-" }}
|
||||
labels:
|
||||
app: {{ template "cassandra.name" $ }}-cain
|
||||
chart: {{ template "cassandra.chart" $ }}
|
||||
release: "{{ $release.Name }}"
|
||||
heritage: "{{ $release.Service }}"
|
||||
spec:
|
||||
schedule: {{ $schedule.cron | quote }}
|
||||
concurrencyPolicy: Forbid
|
||||
startingDeadlineSeconds: 120
|
||||
jobTemplate:
|
||||
spec:
|
||||
template:
|
||||
metadata:
|
||||
annotations:
|
||||
{{ toYaml $backup.annotations }}
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
serviceAccountName: {{ template "cassandra.serviceAccountName" $ }}
|
||||
containers:
|
||||
- name: cassandra-backup
|
||||
image: "{{ $backup.image.repository }}:{{ $backup.image.tag }}"
|
||||
command: ["cain"]
|
||||
args:
|
||||
- backup
|
||||
- --namespace
|
||||
- {{ $release.Namespace }}
|
||||
- --selector
|
||||
- release={{ $release.Name }},app={{ template "cassandra.name" $ }}
|
||||
- --keyspace
|
||||
- {{ $schedule.keyspace }}
|
||||
- --dst
|
||||
- {{ $backup.destination }}
|
||||
{{- with $backup.extraArgs }}
|
||||
{{ toYaml . | indent 12 }}
|
||||
{{- end }}
|
||||
env:
|
||||
{{- if $backup.google.serviceAccountSecret }}
|
||||
- name: GOOGLE_APPLICATION_CREDENTIALS
|
||||
value: "/etc/secrets/google/credentials.json"
|
||||
{{- end }}
|
||||
{{- with $backup.env }}
|
||||
{{ toYaml . | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with $backup.resources }}
|
||||
resources:
|
||||
{{ toYaml . | indent 14 }}
|
||||
{{- end }}
|
||||
{{- if $backup.google.serviceAccountSecret }}
|
||||
volumeMounts:
|
||||
- name: google-service-account
|
||||
mountPath: /etc/secrets/google/
|
||||
{{- end }}
|
||||
{{- if $backup.google.serviceAccountSecret }}
|
||||
volumes:
|
||||
- name: google-service-account
|
||||
secret:
|
||||
secretName: {{ $backup.google.serviceAccountSecret | quote }}
|
||||
{{- end }}
|
||||
affinity:
|
||||
podAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 1
|
||||
podAffinityTerm:
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- {{ template "cassandra.fullname" $ }}
|
||||
- key: release
|
||||
operator: In
|
||||
values:
|
||||
- {{ $release.Name }}
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
{{- with $values.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml . | indent 12 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,50 @@
|
||||
{{- if .Values.backup.enabled }}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ template "cassandra.serviceAccountName" . }}
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ template "cassandra.chart" . }}
|
||||
release: "{{ .Release.Name }}"
|
||||
heritage: "{{ .Release.Service }}"
|
||||
---
|
||||
{{- end }}
|
||||
{{- if .Values.rbac.create }}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ template "cassandra.fullname" . }}-backup
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ template "cassandra.chart" . }}
|
||||
release: "{{ .Release.Name }}"
|
||||
heritage: "{{ .Release.Service }}"
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "pods/log"]
|
||||
verbs: ["get", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods/exec"]
|
||||
verbs: ["create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ template "cassandra.fullname" . }}-backup
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ template "cassandra.chart" . }}
|
||||
release: "{{ .Release.Name }}"
|
||||
heritage: "{{ .Release.Service }}"
|
||||
roleRef:
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: {{ template "cassandra.fullname" . }}-backup
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ template "cassandra.serviceAccountName" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,14 @@
|
||||
{{- if .Values.configOverrides }}
|
||||
kind: ConfigMap
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
name: {{ template "cassandra.name" . }}
|
||||
namespace: {{ .Release.Namespace }}
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
data:
|
||||
{{ toYaml .Values.configOverrides | indent 2 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,17 @@
|
||||
{{- if .Values.podDisruptionBudget -}}
|
||||
apiVersion: policy/v1beta1
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ .Chart.Name }}-{{ .Chart.Version }}
|
||||
heritage: {{ .Release.Service }}
|
||||
release: {{ .Release.Name }}
|
||||
name: {{ template "cassandra.fullname" . }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{ toYaml .Values.podDisruptionBudget | indent 2 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,45 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "cassandra.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ template "cassandra.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- with .Values.service.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
clusterIP: None
|
||||
type: {{ .Values.service.type }}
|
||||
ports:
|
||||
{{- if .Values.exporter.enabled }}
|
||||
- name: metrics
|
||||
port: 5556
|
||||
targetPort: {{ .Values.exporter.port }}
|
||||
{{- end }}
|
||||
- name: intra
|
||||
port: 7000
|
||||
targetPort: 7000
|
||||
- name: tls
|
||||
port: 7001
|
||||
targetPort: 7001
|
||||
- name: jmx
|
||||
port: 7199
|
||||
targetPort: 7199
|
||||
- name: cql
|
||||
port: {{ default 9042 .Values.config.ports.cql }}
|
||||
targetPort: {{ default 9042 .Values.config.ports.cql }}
|
||||
- name: thrift
|
||||
port: {{ default 9160 .Values.config.ports.thrift }}
|
||||
targetPort: {{ default 9160 .Values.config.ports.thrift }}
|
||||
{{- if .Values.config.ports.agent }}
|
||||
- name: agent
|
||||
port: {{ .Values.config.ports.agent }}
|
||||
targetPort: {{ .Values.config.ports.agent }}
|
||||
{{- end }}
|
||||
selector:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
@@ -0,0 +1,25 @@
|
||||
{{- if and .Values.exporter.enabled .Values.exporter.servicemonitor }}
|
||||
apiVersion: monitoring.coreos.com/v1
|
||||
kind: ServiceMonitor
|
||||
metadata:
|
||||
name: {{ template "cassandra.fullname" . }}
|
||||
name: hello-prometheus-scraping
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ template "cassandra.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- if .Values.metrics.serviceMonitor.additionalLabels }}
|
||||
{{ toYaml .Values.metrics.serviceMonitor.additionalLabels | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
jobLabel: {{ template "cassandra.name" . }}
|
||||
endpoints:
|
||||
- port: metrics
|
||||
interval: 10s
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
namespaceSelector:
|
||||
any: true
|
||||
{{- end }}
|
||||
@@ -0,0 +1,220 @@
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ template "cassandra.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
chart: {{ template "cassandra.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
serviceName: {{ template "cassandra.fullname" . }}
|
||||
replicas: {{ .Values.config.cluster_size }}
|
||||
podManagementPolicy: {{ .Values.podManagementPolicy }}
|
||||
updateStrategy:
|
||||
type: {{ .Values.updateStrategy.type }}
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
{{- if .Values.podLabels }}
|
||||
{{ toYaml .Values.podLabels | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.podAnnotations }}
|
||||
annotations:
|
||||
{{ toYaml .Values.podAnnotations | indent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.schedulerName }}
|
||||
schedulerName: "{{ .Values.schedulerName }}"
|
||||
{{- end }}
|
||||
hostNetwork: {{ .Values.hostNetwork }}
|
||||
{{- if .Values.selector }}
|
||||
{{ toYaml .Values.selector | indent 6 }}
|
||||
{{- end }}
|
||||
{{- if .Values.securityContext.enabled }}
|
||||
securityContext:
|
||||
fsGroup: {{ .Values.securityContext.fsGroup }}
|
||||
runAsUser: {{ .Values.securityContext.runAsUser }}
|
||||
{{- end }}
|
||||
{{- if .Values.affinity }}
|
||||
affinity:
|
||||
{{ toYaml .Values.affinity | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml .Values.tolerations | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.configOverrides }}
|
||||
initContainers:
|
||||
- name: config-copier
|
||||
image: busybox
|
||||
command: [ 'sh', '-c', 'cp /configmap-files/* /cassandra-configs/ && chown 999:999 /cassandra-configs/*']
|
||||
volumeMounts:
|
||||
{{- range $key, $value := .Values.configOverrides }}
|
||||
- name: cassandra-config-{{ $key | replace "." "-" | replace "_" "--" }}
|
||||
mountPath: /configmap-files/{{ $key }}
|
||||
subPath: {{ $key }}
|
||||
{{- end }}
|
||||
- name: cassandra-configs
|
||||
mountPath: /cassandra-configs/
|
||||
{{- end }}
|
||||
containers:
|
||||
{{- if .Values.exporter.enabled }}
|
||||
- name: cassandra-exporter
|
||||
image: "{{ .Values.exporter.image.repo }}:{{ .Values.exporter.image.tag }}"
|
||||
resources:
|
||||
{{ toYaml .Values.exporter.resources | indent 10 }}
|
||||
env:
|
||||
- name: CASSANDRA_EXPORTER_CONFIG_listenPort
|
||||
value: {{ .Values.exporter.port | quote }}
|
||||
- name: JVM_OPTS
|
||||
value: {{ .Values.exporter.jvmOpts | quote }}
|
||||
ports:
|
||||
- name: metrics
|
||||
containerPort: {{ .Values.exporter.port }}
|
||||
protocol: TCP
|
||||
- name: jmx
|
||||
containerPort: 5555
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: {{ .Values.exporter.port }}
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /metrics
|
||||
port: {{ .Values.exporter.port }}
|
||||
initialDelaySeconds: 20
|
||||
timeoutSeconds: 45
|
||||
{{- end }}
|
||||
- name: {{ template "cassandra.fullname" . }}
|
||||
image: "{{ .Values.image.repo }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
|
||||
{{- if .Values.commandOverrides }}
|
||||
command: {{ .Values.commandOverrides }}
|
||||
{{- end }}
|
||||
{{- if .Values.argsOverrides }}
|
||||
args: {{ .Values.argsOverrides }}
|
||||
{{- end }}
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 10 }}
|
||||
env:
|
||||
{{- $seed_size := default 1 .Values.config.seed_size | int -}}
|
||||
{{- $global := . }}
|
||||
- name: CASSANDRA_SEEDS
|
||||
{{- if .Values.hostNetwork }}
|
||||
value: {{ required "You must fill \".Values.config.seeds\" with list of Cassandra seeds when hostNetwork is set to true" .Values.config.seeds | quote }}
|
||||
{{- else }}
|
||||
value: "{{- range $i, $e := until $seed_size }}{{ template "cassandra.fullname" $global }}-{{ $i }}.{{ template "cassandra.fullname" $global }}.{{ $global.Release.Namespace }}.svc.{{ $global.Values.config.cluster_domain }}{{- if (lt ( add1 $i ) $seed_size ) }},{{- end }}{{- end }}"
|
||||
{{- end }}
|
||||
- name: MAX_HEAP_SIZE
|
||||
value: {{ default "8192M" .Values.config.max_heap_size | quote }}
|
||||
- name: HEAP_NEWSIZE
|
||||
value: {{ default "200M" .Values.config.heap_new_size | quote }}
|
||||
- name: CASSANDRA_ENDPOINT_SNITCH
|
||||
value: {{ default "SimpleSnitch" .Values.config.endpoint_snitch | quote }}
|
||||
- name: CASSANDRA_CLUSTER_NAME
|
||||
value: {{ default "Cassandra" .Values.config.cluster_name | quote }}
|
||||
- name: CASSANDRA_DC
|
||||
value: {{ default "DC1" .Values.config.dc_name | quote }}
|
||||
- name: CASSANDRA_RACK
|
||||
value: {{ default "RAC1" .Values.config.rack_name | quote }}
|
||||
- name: CASSANDRA_START_RPC
|
||||
value: {{ default "false" .Values.config.start_rpc | quote }}
|
||||
- name: POD_IP
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: status.podIP
|
||||
{{- range $key, $value := .Values.env }}
|
||||
- name: {{ $key | quote }}
|
||||
value: {{ $value | quote }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
exec:
|
||||
command: [ "/bin/sh", "-c", "nodetool status" ]
|
||||
initialDelaySeconds: {{ .Values.livenessProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.livenessProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.livenessProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.livenessProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.livenessProbe.failureThreshold }}
|
||||
readinessProbe:
|
||||
exec:
|
||||
command: [ "/bin/sh", "-c", "nodetool status | grep -E \"^UN\\s+{{ .Values.readinessProbe.address }}\"" ]
|
||||
initialDelaySeconds: {{ .Values.readinessProbe.initialDelaySeconds }}
|
||||
periodSeconds: {{ .Values.readinessProbe.periodSeconds }}
|
||||
timeoutSeconds: {{ .Values.readinessProbe.timeoutSeconds }}
|
||||
successThreshold: {{ .Values.readinessProbe.successThreshold }}
|
||||
failureThreshold: {{ .Values.readinessProbe.failureThreshold }}
|
||||
ports:
|
||||
- name: intra
|
||||
containerPort: 7000
|
||||
- name: tls
|
||||
containerPort: 7001
|
||||
- name: jmx
|
||||
containerPort: 7199
|
||||
- name: cql
|
||||
containerPort: {{ default 9042 .Values.config.ports.cql }}
|
||||
- name: thrift
|
||||
containerPort: {{ default 9160 .Values.config.ports.thrift }}
|
||||
{{- if .Values.config.ports.agent }}
|
||||
- name: agent
|
||||
containerPort: {{ .Values.config.ports.agent }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
- name: data
|
||||
mountPath: /var/lib/cassandra
|
||||
{{- if .Values.configOverrides }}
|
||||
- name: cassandra-configs
|
||||
mountPath: /etc/cassandra
|
||||
{{- end }}
|
||||
{{- if not .Values.persistence.enabled }}
|
||||
lifecycle:
|
||||
preStop:
|
||||
exec:
|
||||
command: ["/bin/sh", "-c", "exec nodetool decommission"]
|
||||
{{- end }}
|
||||
terminationGracePeriodSeconds: {{ default 30 .Values.podSettings.terminationGracePeriodSeconds }}
|
||||
{{- if .Values.image.pullSecrets }}
|
||||
imagePullSecrets:
|
||||
- name: {{ .Values.image.pullSecrets }}
|
||||
{{- end }}
|
||||
{{- if or .Values.configOverrides (not .Values.persistence.enabled) }}
|
||||
volumes:
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.configOverrides }}
|
||||
- configMap:
|
||||
name: cassandra
|
||||
name: cassandra-config-{{ $key | replace "." "-" | replace "_" "--" }}
|
||||
{{- end }}
|
||||
{{- if .Values.configOverrides }}
|
||||
- name: cassandra-configs
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if not .Values.persistence.enabled }}
|
||||
- name: data
|
||||
emptyDir: {}
|
||||
{{- else }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: data
|
||||
labels:
|
||||
app: {{ template "cassandra.name" . }}
|
||||
release: {{ .Release.Name }}
|
||||
spec:
|
||||
accessModes:
|
||||
- {{ .Values.persistence.accessMode | quote }}
|
||||
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 }}
|
||||
@@ -0,0 +1,231 @@
|
||||
## Cassandra image version
|
||||
## ref: https://hub.docker.com/r/library/cassandra/
|
||||
image:
|
||||
repo: cassandra
|
||||
tag: 3.11.5
|
||||
pullPolicy: IfNotPresent
|
||||
## Specify ImagePullSecrets for Pods
|
||||
## ref: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod
|
||||
# pullSecrets: myregistrykey
|
||||
|
||||
## Specify a service type
|
||||
## ref: http://kubernetes.io/docs/user-guide/services/
|
||||
service:
|
||||
type: ClusterIP
|
||||
annotations: ""
|
||||
|
||||
## Use an alternate scheduler, e.g. "stork".
|
||||
## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/
|
||||
##
|
||||
# schedulerName:
|
||||
|
||||
## Persist data to a persistent volume
|
||||
persistence:
|
||||
enabled: true
|
||||
## cassandra data Persistent Volume Storage Class
|
||||
## If defined, storageClassName: <storageClass>
|
||||
## If set to "-", storageClassName: "", which disables dynamic provisioning
|
||||
## If undefined (the default) or set to null, no storageClassName spec is
|
||||
## set, choosing the default provisioner. (gp2 on AWS, standard on
|
||||
## GKE, AWS & OpenStack)
|
||||
##
|
||||
# storageClass: "-"
|
||||
accessMode: ReadWriteOnce
|
||||
size: 10Gi
|
||||
|
||||
## Configure resource requests and limits
|
||||
## ref: http://kubernetes.io/docs/user-guide/compute-resources/
|
||||
## Minimum memory for development is 4GB and 2 CPU cores
|
||||
## Minimum memory for production is 8GB and 4 CPU cores
|
||||
## ref: http://docs.datastax.com/en/archived/cassandra/2.0/cassandra/architecture/architecturePlanningHardware_c.html
|
||||
resources: {}
|
||||
# requests:
|
||||
# memory: 4Gi
|
||||
# cpu: 2
|
||||
# limits:
|
||||
# memory: 4Gi
|
||||
# cpu: 2
|
||||
|
||||
## Change cassandra configuration parameters below:
|
||||
## ref: http://docs.datastax.com/en/cassandra/3.0/cassandra/configuration/configCassandra_yaml.html
|
||||
## Recommended max heap size is 1/2 of system memory
|
||||
## Recommended heap new size is 1/4 of max heap size
|
||||
## ref: http://docs.datastax.com/en/cassandra/3.0/cassandra/operations/opsTuneJVM.html
|
||||
config:
|
||||
cluster_domain: cluster.local
|
||||
cluster_name: cassandra
|
||||
cluster_size: 3
|
||||
seed_size: 2
|
||||
num_tokens: 256
|
||||
# If you want Cassandra to use this datacenter and rack name,
|
||||
# you need to set endpoint_snitch to GossipingPropertyFileSnitch.
|
||||
# Otherwise, these values are ignored and datacenter1 and rack1
|
||||
# are used.
|
||||
dc_name: DC1
|
||||
rack_name: RAC1
|
||||
endpoint_snitch: SimpleSnitch
|
||||
max_heap_size: 2048M
|
||||
heap_new_size: 512M
|
||||
start_rpc: false
|
||||
ports:
|
||||
cql: 9042
|
||||
thrift: 9160
|
||||
# If a JVM Agent is in place
|
||||
# agent: 61621
|
||||
|
||||
## Cassandra config files overrides
|
||||
configOverrides: {}
|
||||
|
||||
## Cassandra docker command overrides
|
||||
commandOverrides: []
|
||||
|
||||
## Cassandra docker args overrides
|
||||
argsOverrides: []
|
||||
|
||||
## Custom env variables.
|
||||
## ref: https://hub.docker.com/_/cassandra/
|
||||
env: {}
|
||||
|
||||
## Liveness and Readiness probe values.
|
||||
## ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
|
||||
livenessProbe:
|
||||
initialDelaySeconds: 90
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
initialDelaySeconds: 90
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
successThreshold: 1
|
||||
failureThreshold: 3
|
||||
address: "${POD_IP}"
|
||||
|
||||
## Configure node selector. Edit code below for adding selector to pods
|
||||
## ref: https://kubernetes.io/docs/user-guide/node-selection/
|
||||
# selector:
|
||||
# nodeSelector:
|
||||
# cloud.google.com/gke-nodepool: pool-db
|
||||
|
||||
## Additional pod annotations
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
|
||||
podAnnotations: {}
|
||||
|
||||
## Additional pod labels
|
||||
## ref: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
podLabels: {}
|
||||
|
||||
## Additional pod-level settings
|
||||
podSettings:
|
||||
# Change this to give pods more time to properly leave the cluster when not using persistent storage.
|
||||
terminationGracePeriodSeconds: 30
|
||||
|
||||
## Pod distruption budget
|
||||
podDisruptionBudget: {}
|
||||
# maxUnavailable: 1
|
||||
# minAvailable: 2
|
||||
|
||||
podManagementPolicy: OrderedReady
|
||||
updateStrategy:
|
||||
type: OnDelete
|
||||
|
||||
## Pod Security Context
|
||||
securityContext:
|
||||
enabled: false
|
||||
fsGroup: 999
|
||||
runAsUser: 999
|
||||
|
||||
## Affinity for pod assignment
|
||||
## Ref: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
affinity: {}
|
||||
|
||||
## Node tolerations for pod assignment
|
||||
## Ref: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
tolerations: []
|
||||
|
||||
rbac:
|
||||
# Specifies whether RBAC resources should be created
|
||||
create: true
|
||||
|
||||
serviceAccount:
|
||||
# Specifies whether a ServiceAccount should be created
|
||||
create: true
|
||||
# The name of the ServiceAccount to use.
|
||||
# If not set and create is true, a name is generated using the fullname template
|
||||
# name:
|
||||
|
||||
# Use host network for Cassandra pods
|
||||
# You must pass seed list into config.seeds property if set to true
|
||||
hostNetwork: false
|
||||
|
||||
## Backup cronjob configuration
|
||||
## Ref: https://github.com/maorfr/cain
|
||||
backup:
|
||||
enabled: false
|
||||
|
||||
# Schedule to run jobs. Must be in cron time format
|
||||
# Ref: https://crontab.guru/
|
||||
schedule:
|
||||
- keyspace: keyspace1
|
||||
cron: "0 7 * * *"
|
||||
- keyspace: keyspace2
|
||||
cron: "30 7 * * *"
|
||||
|
||||
annotations:
|
||||
# Example for authorization to AWS S3 using kube2iam
|
||||
# Can also be done using environment variables
|
||||
iam.amazonaws.com/role: cain
|
||||
|
||||
image:
|
||||
repository: maorfr/cain
|
||||
tag: 0.6.0
|
||||
|
||||
# Additional arguments for cain
|
||||
# Ref: https://github.com/maorfr/cain#usage
|
||||
extraArgs: []
|
||||
|
||||
# Add additional environment variables
|
||||
env:
|
||||
# Example environment variable required for AWS credentials chain
|
||||
- name: AWS_REGION
|
||||
value: us-east-1
|
||||
|
||||
resources:
|
||||
requests:
|
||||
memory: 1Gi
|
||||
cpu: 1
|
||||
limits:
|
||||
memory: 1Gi
|
||||
cpu: 1
|
||||
|
||||
# Name of the secret containing the credentials of the service account used by GOOGLE_APPLICATION_CREDENTIALS, as a credentials.json file
|
||||
# google:
|
||||
# serviceAccountSecret:
|
||||
|
||||
# Destination to store the backup artifacts
|
||||
# Supported cloud storage services: AWS S3, Minio S3, Azure Blob Storage, Google Cloud Storage
|
||||
# Additional support can added. Visit this repository for details
|
||||
# Ref: https://github.com/maorfr/skbn
|
||||
destination: s3://bucket/cassandra
|
||||
|
||||
## Cassandra exported configuration
|
||||
## ref: https://github.com/criteo/cassandra_exporter
|
||||
exporter:
|
||||
# If exporter is enabled this will create a ServiceMonitor by default as well
|
||||
servicemonitor: true
|
||||
enabled: false
|
||||
additionalLabels: {}
|
||||
# prometheus: default
|
||||
image:
|
||||
repo: criteord/cassandra_exporter
|
||||
tag: 2.0.2
|
||||
port: 5556
|
||||
jvmOpts: ""
|
||||
resources: {}
|
||||
# limits:
|
||||
# cpu: 1
|
||||
# memory: 1Gi
|
||||
# requests:
|
||||
# cpu: 1
|
||||
# memory: 1Gi
|
||||
@@ -0,0 +1,2 @@
|
||||
tests/
|
||||
.pytest_cache/
|
||||
@@ -0,0 +1,12 @@
|
||||
apiVersion: v1
|
||||
appVersion: 7.17.3
|
||||
description: Official Elastic helm chart for Elasticsearch
|
||||
home: https://github.com/elastic/helm-charts
|
||||
icon: https://helm.elastic.co/icons/elasticsearch.png
|
||||
maintainers:
|
||||
- email: helm-charts@elastic.co
|
||||
name: Elastic
|
||||
name: elasticsearch
|
||||
sources:
|
||||
- https://github.com/elastic/elasticsearch
|
||||
version: 7.17.3
|
||||
@@ -0,0 +1 @@
|
||||
include ../helpers/common.mk
|
||||
@@ -0,0 +1,459 @@
|
||||
# Elasticsearch Helm Chart
|
||||
|
||||
[](https://devops-ci.elastic.co/job/elastic+helm-charts+master/) [](https://artifacthub.io/packages/search?repo=elastic)
|
||||
|
||||
This Helm chart is a lightweight way to configure and run our official
|
||||
[Elasticsearch Docker image][].
|
||||
|
||||
<!-- development warning placeholder -->
|
||||
|
||||
<!-- START doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->
|
||||
|
||||
|
||||
- [Requirements](#requirements)
|
||||
- [Installing](#installing)
|
||||
- [Install released version using Helm repository](#install-released-version-using-helm-repository)
|
||||
- [Install development version from a branch](#install-development-version-from-a-branch)
|
||||
- [Upgrading](#upgrading)
|
||||
- [Usage notes](#usage-notes)
|
||||
- [Configuration](#configuration)
|
||||
- [Deprecated](#deprecated)
|
||||
- [FAQ](#faq)
|
||||
- [How to deploy this chart on a specific K8S distribution?](#how-to-deploy-this-chart-on-a-specific-k8s-distribution)
|
||||
- [How to deploy dedicated nodes types?](#how-to-deploy-dedicated-nodes-types)
|
||||
- [Clustering and Node Discovery](#clustering-and-node-discovery)
|
||||
- [How to deploy clusters with security (authentication and TLS) enabled?](#how-to-deploy-clusters-with-security-authentication-and-tls-enabled)
|
||||
- [How to migrate from helm/charts stable chart?](#how-to-migrate-from-helmcharts-stable-chart)
|
||||
- [How to install plugins?](#how-to-install-plugins)
|
||||
- [How to use the keystore?](#how-to-use-the-keystore)
|
||||
- [Basic example](#basic-example)
|
||||
- [Multiple keys](#multiple-keys)
|
||||
- [Custom paths and keys](#custom-paths-and-keys)
|
||||
- [How to enable snapshotting?](#how-to-enable-snapshotting)
|
||||
- [How to configure templates post-deployment?](#how-to-configure-templates-post-deployment)
|
||||
- [Contributing](#contributing)
|
||||
|
||||
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
|
||||
<!-- Use this to update TOC: -->
|
||||
<!-- docker run --rm -it -v $(pwd):/usr/src jorgeandrada/doctoc --github -->
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
* Kubernetes >= 1.14
|
||||
* [Helm][] >= 2.17.0
|
||||
* Minimum cluster requirements include the following to run this chart with
|
||||
default settings. All of these settings are configurable.
|
||||
* Three Kubernetes nodes to respect the default "hard" affinity settings
|
||||
* 1GB of RAM for the JVM heap
|
||||
|
||||
See [supported configurations][] for more details.
|
||||
|
||||
## Installing
|
||||
|
||||
This chart is tested with the latest 7.17.3 version.
|
||||
|
||||
### Install released version using Helm repository
|
||||
|
||||
* Add the Elastic Helm charts repo:
|
||||
`helm repo add elastic https://helm.elastic.co`
|
||||
|
||||
* Install it:
|
||||
- with Helm 3: `helm install elasticsearch --version <version> elastic/elasticsearch`
|
||||
- with Helm 2 (deprecated): `helm install --name elasticsearch --version <version> elastic/elasticsearch`
|
||||
|
||||
### Install development version from a branch
|
||||
|
||||
* Clone the git repo: `git clone git@github.com:elastic/helm-charts.git`
|
||||
|
||||
* Checkout the branch : `git checkout 7.17`
|
||||
|
||||
* Install it:
|
||||
- with Helm 3: `helm install elasticsearch ./helm-charts/elasticsearch --set imageTag=7.17.3`
|
||||
- with Helm 2 (deprecated): `helm install --name elasticsearch ./helm-charts/elasticsearch --set imageTag=7.17.3`
|
||||
|
||||
|
||||
## Upgrading
|
||||
|
||||
Please always check [CHANGELOG.md][] and [BREAKING_CHANGES.md][] before
|
||||
upgrading to a new chart version.
|
||||
|
||||
|
||||
## Usage notes
|
||||
|
||||
* This repo includes a number of [examples][] configurations which can be used
|
||||
as a reference. They are also used in the automated testing of this chart.
|
||||
* Automated testing of this chart is currently only run against GKE (Google
|
||||
Kubernetes Engine).
|
||||
* The chart deploys a StatefulSet and by default will do an automated rolling
|
||||
update of your cluster. It does this by waiting for the cluster health to become
|
||||
green after each instance is updated. If you prefer to update manually you can
|
||||
set `OnDelete` [updateStrategy][].
|
||||
* It is important to verify that the JVM heap size in `esJavaOpts` and to set
|
||||
the CPU/Memory `resources` to something suitable for your cluster.
|
||||
* To simplify chart and maintenance each set of node groups is deployed as a
|
||||
separate Helm release. Take a look at the [multi][] example to get an idea for
|
||||
how this works. Without doing this it isn't possible to resize persistent
|
||||
volumes in a StatefulSet. By setting it up this way it makes it possible to add
|
||||
more nodes with a new storage size then drain the old ones. It also solves the
|
||||
problem of allowing the user to determine which node groups to update first when
|
||||
doing upgrades or changes.
|
||||
* We have designed this chart to be very un-opinionated about how to configure
|
||||
Elasticsearch. It exposes ways to set environment variables and mount secrets
|
||||
inside of the container. Doing this makes it much easier for this chart to
|
||||
support multiple versions with minimal changes.
|
||||
|
||||
|
||||
## Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|------------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------|
|
||||
| `antiAffinityTopologyKey` | The [anti-affinity][] topology key. By default this will prevent multiple Elasticsearch nodes from running on the same Kubernetes node | `kubernetes.io/hostname` |
|
||||
| `antiAffinity` | Setting this to hard enforces the [anti-affinity][] rules. If it is set to soft it will be done "best effort". Other values will be ignored | `hard` |
|
||||
| `clusterHealthCheckParams` | The [Elasticsearch cluster health status params][] that will be used by readiness [probe][] command | `wait_for_status=green&timeout=1s` |
|
||||
| `clusterName` | This will be used as the Elasticsearch [cluster.name][] and should be unique per cluster in the namespace | `elasticsearch` |
|
||||
| `clusterDeprecationIndexing` | Enable or disable deprecation logs to be indexed (should be disabled when deploying master only node groups) | `false` |
|
||||
| `enableServiceLinks` | Set to false to disabling service links, which can cause slow pod startup times when there are many services in the current namespace. | `true` |
|
||||
| `envFrom` | Templatable string to be passed to the [environment from variables][] which will be appended to the `envFrom:` definition for the container | `[]` |
|
||||
| `esConfig` | Allows you to add any config files in `/usr/share/elasticsearch/config/` such as `elasticsearch.yml` and `log4j2.properties`. See [values.yaml][] for an example of the formatting | `{}` |
|
||||
| `esJavaOpts` | [Java options][] for Elasticsearch. This is where you could configure the [jvm heap size][] | `""` |
|
||||
| `esJvmOptions` | [Java options][] for Elasticsearch. Override the default JVM options by adding custom options files . See [values.yaml][] for an example of the formatting | `{}` |
|
||||
| `esMajorVersion` | Deprecated. Instead, use the version of the chart corresponding to your ES minor version. Used to set major version specific configuration. If you are using a custom image and not running the default Elasticsearch version you will need to set this to the version you are running (e.g. `esMajorVersion: 6`) | `""` |
|
||||
| `extraContainers` | Templatable string of additional `containers` to be passed to the `tpl` function | `""` |
|
||||
| `extraEnvs` | Extra [environment variables][] which will be appended to the `env:` definition for the container | `[]` |
|
||||
| `extraInitContainers` | Templatable string of additional `initContainers` to be passed to the `tpl` function | `""` |
|
||||
| `extraVolumeMounts` | Templatable string of additional `volumeMounts` to be passed to the `tpl` function | `""` |
|
||||
| `extraVolumes` | Templatable string of additional `volumes` to be passed to the `tpl` function | `""` |
|
||||
| `fullnameOverride` | Overrides the `clusterName` and `nodeGroup` when used in the naming of resources. This should only be used when using a single `nodeGroup`, otherwise you will have name conflicts | `""` |
|
||||
| `healthNameOverride` | Overrides `test-elasticsearch-health` pod name | `""` |
|
||||
| `hostAliases` | Configurable [hostAliases][] | `[]` |
|
||||
| `httpPort` | The http port that Kubernetes will use for the healthchecks and the service. If you change this you will also need to set [http.port][] in `extraEnvs` | `9200` |
|
||||
| `imagePullPolicy` | The Kubernetes [imagePullPolicy][] value | `IfNotPresent` |
|
||||
| `imagePullSecrets` | Configuration for [imagePullSecrets][] so that you can use a private registry for your image | `[]` |
|
||||
| `imageTag` | The Elasticsearch Docker image tag | `7.17.3` |
|
||||
| `image` | The Elasticsearch Docker image | `docker.elastic.co/elasticsearch/elasticsearch` |
|
||||
| `ingress` | Configurable [ingress][] to expose the Elasticsearch service. See [values.yaml][] for an example | see [values.yaml][] |
|
||||
| `initResources` | Allows you to set the [resources][] for the `initContainer` in the StatefulSet | `{}` |
|
||||
| `keystore` | Allows you map Kubernetes secrets into the keystore. See the [config example][] and [how to use the keystore][] | `[]` |
|
||||
| `labels` | Configurable [labels][] applied to all Elasticsearch pods | `{}` |
|
||||
| `lifecycle` | Allows you to add [lifecycle hooks][]. See [values.yaml][] for an example of the formatting | `{}` |
|
||||
| `masterService` | The service name used to connect to the masters. You only need to set this if your master `nodeGroup` is set to something other than `master`. See [Clustering and Node Discovery][] for more information | `""` |
|
||||
| `maxUnavailable` | The [maxUnavailable][] value for the pod disruption budget. By default this will prevent Kubernetes from having more than 1 unhealthy pod in the node group | `1` |
|
||||
| `minimumMasterNodes` | The value for [discovery.zen.minimum_master_nodes][]. Should be set to `(master_eligible_nodes / 2) + 1`. Ignored in Elasticsearch versions >= 7 | `2` |
|
||||
| `nameOverride` | Overrides the `clusterName` when used in the naming of resources | `""` |
|
||||
| `networkHost` | Value for the [network.host Elasticsearch setting][] | `0.0.0.0` |
|
||||
| `networkPolicy` | The [NetworkPolicy](https://kubernetes.io/docs/concepts/services-networking/network-policies/) to set. See [`values.yaml`](./values.yaml) for an example | `{http.enabled: false,transport.enabled: false}` |
|
||||
| `nodeAffinity` | Value for the [node affinity settings][] | `{}` |
|
||||
| `nodeGroup` | This is the name that will be used for each group of nodes in the cluster. The name will be `clusterName-nodeGroup-X` , `nameOverride-nodeGroup-X` if a `nameOverride` is specified, and `fullnameOverride-X` if a `fullnameOverride` is specified | `master` |
|
||||
| `nodeSelector` | Configurable [nodeSelector][] so that you can target specific nodes for your Elasticsearch cluster | `{}` |
|
||||
| `persistence` | Enables a persistent volume for Elasticsearch data. Can be disabled for nodes that only have [roles][] which don't require persistent data | see [values.yaml][] |
|
||||
| `podAnnotations` | Configurable [annotations][] applied to all Elasticsearch pods | `{}` |
|
||||
| `podManagementPolicy` | By default Kubernetes [deploys StatefulSets serially][]. This deploys them in parallel so that they can discover each other | `Parallel` |
|
||||
| `podSecurityContext` | Allows you to set the [securityContext][] for the pod | see [values.yaml][] |
|
||||
| `podSecurityPolicy` | Configuration for create a pod security policy with minimal permissions to run this Helm chart with `create: true`. Also can be used to reference an external pod security policy with `name: "externalPodSecurityPolicy"` | see [values.yaml][] |
|
||||
| `priorityClassName` | The name of the [PriorityClass][]. No default is supplied as the PriorityClass must be created first | `""` |
|
||||
| `protocol` | The protocol that will be used for the readiness [probe][]. Change this to `https` if you have `xpack.security.http.ssl.enabled` set | `http` |
|
||||
| `rbac` | Configuration for creating a role, role binding and ServiceAccount as part of this Helm chart with `create: true`. Also can be used to reference an external ServiceAccount with `serviceAccountName: "externalServiceAccountName"`, or automount the service account token | see [values.yaml][] |
|
||||
| `readinessProbe` | Configuration fields for the readiness [probe][] | see [values.yaml][] |
|
||||
| `replicas` | Kubernetes replica count for the StatefulSet (i.e. how many pods) | `3` |
|
||||
| `resources` | Allows you to set the [resources][] for the StatefulSet | see [values.yaml][] |
|
||||
| `roles` | A hash map with the specific [roles][] for the `nodeGroup` | see [values.yaml][] |
|
||||
| `schedulerName` | Name of the [alternate scheduler][] | `""` |
|
||||
| `secretMounts` | Allows you easily mount a secret as a file inside the StatefulSet. Useful for mounting certificates and other secrets. See [values.yaml][] for an example | `[]` |
|
||||
| `securityContext` | Allows you to set the [securityContext][] for the container | see [values.yaml][] |
|
||||
| `service.annotations` | [LoadBalancer annotations][] that Kubernetes will use for the service. This will configure load balancer if `service.type` is `LoadBalancer` | `{}` |
|
||||
| `service.enabled` | Enable non-headless service | `true` |
|
||||
| `service.externalTrafficPolicy` | Some cloud providers allow you to specify the [LoadBalancer externalTrafficPolicy][]. Kubernetes will use this to preserve the client source IP. This will configure load balancer if `service.type` is `LoadBalancer` | `""` |
|
||||
| `service.httpPortName` | The name of the http port within the service | `http` |
|
||||
| `service.labelsHeadless` | Labels to be added to headless service | `{}` |
|
||||
| `service.labels` | Labels to be added to non-headless service | `{}` |
|
||||
| `service.loadBalancerIP` | Some cloud providers allow you to specify the [loadBalancer][] IP. If the `loadBalancerIP` field is not specified, the IP is dynamically assigned. If you specify a `loadBalancerIP` but your cloud provider does not support the feature, it is ignored. | `""` |
|
||||
| `service.loadBalancerSourceRanges` | The IP ranges that are allowed to access | `[]` |
|
||||
| `service.nodePort` | Custom [nodePort][] port that can be set if you are using `service.type: nodePort` | `""` |
|
||||
| `service.transportPortName` | The name of the transport port within the service | `transport` |
|
||||
| `service.publishNotReadyAddresses` | Consider that all endpoints are considered "ready" even if the Pods themselves are not | `false` |
|
||||
| `service.type` | Elasticsearch [Service Types][] | `ClusterIP` |
|
||||
| `sysctlInitContainer` | Allows you to disable the `sysctlInitContainer` if you are setting [sysctl vm.max_map_count][] with another method | `enabled: true` |
|
||||
| `sysctlVmMaxMapCount` | Sets the [sysctl vm.max_map_count][] needed for Elasticsearch | `262144` |
|
||||
| `terminationGracePeriod` | The [terminationGracePeriod][] in seconds used when trying to stop the pod | `120` |
|
||||
| `tests.enabled` | Enable creating test related resources when running `helm template` or `helm test` | `true` |
|
||||
| `tolerations` | Configurable [tolerations][] | `[]` |
|
||||
| `transportPort` | The transport port that Kubernetes will use for the service. If you change this you will also need to set [transport port configuration][] in `extraEnvs` | `9300` |
|
||||
| `updateStrategy` | The [updateStrategy][] for the StatefulSet. By default Kubernetes will wait for the cluster to be green after upgrading each pod. Setting this to `OnDelete` will allow you to manually delete each pod during upgrades | `RollingUpdate` |
|
||||
| `volumeClaimTemplate` | Configuration for the [volumeClaimTemplate for StatefulSets][]. You will want to adjust the storage (default `30Gi` ) and the `storageClassName` if you are using a different storage class | see [values.yaml][] |
|
||||
|
||||
### Deprecated
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------|---------------------------------------------------------------------------------------------------------------|---------|
|
||||
| `fsGroup` | The Group ID (GID) for [securityContext][] so that the Elasticsearch user can read from the persistent volume | `""` |
|
||||
|
||||
|
||||
## FAQ
|
||||
|
||||
### How to deploy this chart on a specific K8S distribution?
|
||||
|
||||
This chart is designed to run on production scale Kubernetes clusters with
|
||||
multiple nodes, lots of memory and persistent storage. For that reason it can be
|
||||
a bit tricky to run them against local Kubernetes environments such as
|
||||
[Minikube][].
|
||||
|
||||
This chart is highly tested with [GKE][], but some K8S distribution also
|
||||
requires specific configurations.
|
||||
|
||||
We provide examples of configuration for the following K8S providers:
|
||||
|
||||
- [Docker for Mac][]
|
||||
- [KIND][]
|
||||
- [Minikube][]
|
||||
- [MicroK8S][]
|
||||
- [OpenShift][]
|
||||
|
||||
### How to deploy dedicated nodes types?
|
||||
|
||||
All the Elasticsearch pods deployed share the same configuration. If you need to
|
||||
deploy dedicated [nodes types][] (for example dedicated master and data nodes),
|
||||
you can deploy multiple releases of this chart with different configurations
|
||||
while they share the same `clusterName` value.
|
||||
|
||||
For each Helm release, the nodes types can then be defined using `roles` value.
|
||||
|
||||
An example of Elasticsearch cluster using 2 different Helm releases for master
|
||||
and data nodes can be found in [examples/multi][].
|
||||
|
||||
#### Clustering and Node Discovery
|
||||
|
||||
This chart facilitates Elasticsearch node discovery and services by creating two
|
||||
`Service` definitions in Kubernetes, one with the name `$clusterName-$nodeGroup`
|
||||
and another named `$clusterName-$nodeGroup-headless`.
|
||||
Only `Ready` pods are a part of the `$clusterName-$nodeGroup` service, while all
|
||||
pods ( `Ready` or not) are a part of `$clusterName-$nodeGroup-headless`.
|
||||
|
||||
If your group of master nodes has the default `nodeGroup: master` then you can
|
||||
just add new groups of nodes with a different `nodeGroup` and they will
|
||||
automatically discover the correct master. If your master nodes have a different
|
||||
`nodeGroup` name then you will need to set `masterService` to
|
||||
`$clusterName-$masterNodeGroup`.
|
||||
|
||||
The chart value for `masterService` is used to populate
|
||||
`discovery.zen.ping.unicast.hosts` , which Elasticsearch nodes will use to
|
||||
contact master nodes and form a cluster.
|
||||
Therefore, to add a group of nodes to an existing cluster, setting
|
||||
`masterService` to the desired `Service` name of the related cluster is
|
||||
sufficient.
|
||||
|
||||
### How to deploy clusters with security (authentication and TLS) enabled?
|
||||
|
||||
This Helm chart can use existing [Kubernetes secrets][] to setup
|
||||
credentials or certificates for examples. These secrets should be created
|
||||
outside of this chart and accessed using [environment variables][] and volumes.
|
||||
|
||||
An example of Elasticsearch cluster using security can be found in
|
||||
[examples/security][].
|
||||
|
||||
### How to migrate from helm/charts stable chart?
|
||||
|
||||
If you currently have a cluster deployed with the [helm/charts stable][] chart
|
||||
you can follow the [migration guide][].
|
||||
|
||||
### How to install plugins?
|
||||
|
||||
The recommended way to install plugins into our Docker images is to create a
|
||||
[custom Docker image][].
|
||||
|
||||
The Dockerfile would look something like:
|
||||
|
||||
```
|
||||
ARG elasticsearch_version
|
||||
FROM docker.elastic.co/elasticsearch/elasticsearch:${elasticsearch_version}
|
||||
|
||||
RUN bin/elasticsearch-plugin install --batch repository-gcs
|
||||
```
|
||||
|
||||
And then updating the `image` in values to point to your custom image.
|
||||
|
||||
There are a couple reasons we recommend this.
|
||||
|
||||
1. Tying the availability of Elasticsearch to the download service to install
|
||||
plugins is not a great idea or something that we recommend. Especially in
|
||||
Kubernetes where it is normal and expected for a container to be moved to
|
||||
another host at random times.
|
||||
2. Mutating the state of a running Docker image (by installing plugins) goes
|
||||
against best practices of containers and immutable infrastructure.
|
||||
|
||||
### How to use the keystore?
|
||||
|
||||
#### Basic example
|
||||
|
||||
Create the secret, the key name needs to be the keystore key path. In this
|
||||
example we will create a secret from a file and from a literal string.
|
||||
|
||||
```
|
||||
kubectl create secret generic encryption-key --from-file=xpack.watcher.encryption_key=./watcher_encryption_key
|
||||
kubectl create secret generic slack-hook --from-literal=xpack.notification.slack.account.monitoring.secure_url='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd'
|
||||
```
|
||||
|
||||
To add these secrets to the keystore:
|
||||
|
||||
```
|
||||
keystore:
|
||||
- secretName: encryption-key
|
||||
- secretName: slack-hook
|
||||
```
|
||||
|
||||
#### Multiple keys
|
||||
|
||||
All keys in the secret will be added to the keystore. To create the previous
|
||||
example in one secret you could also do:
|
||||
|
||||
```
|
||||
kubectl create secret generic keystore-secrets --from-file=xpack.watcher.encryption_key=./watcher_encryption_key --from-literal=xpack.notification.slack.account.monitoring.secure_url='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd'
|
||||
```
|
||||
|
||||
```
|
||||
keystore:
|
||||
- secretName: keystore-secrets
|
||||
```
|
||||
|
||||
#### Custom paths and keys
|
||||
|
||||
If you are using these secrets for other applications (besides the Elasticsearch
|
||||
keystore) then it is also possible to specify the keystore path and which keys
|
||||
you want to add. Everything specified under each `keystore` item will be passed
|
||||
through to the `volumeMounts` section for mounting the [secret][]. In this
|
||||
example we will only add the `slack_hook` key from a secret that also has other
|
||||
keys. Our secret looks like this:
|
||||
|
||||
```
|
||||
kubectl create secret generic slack-secrets --from-literal=slack_channel='#general' --from-literal=slack_hook='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd'
|
||||
```
|
||||
|
||||
We only want to add the `slack_hook` key to the keystore at path
|
||||
`xpack.notification.slack.account.monitoring.secure_url`:
|
||||
|
||||
```
|
||||
keystore:
|
||||
- secretName: slack-secrets
|
||||
items:
|
||||
- key: slack_hook
|
||||
path: xpack.notification.slack.account.monitoring.secure_url
|
||||
```
|
||||
|
||||
You can also take a look at the [config example][] which is used as part of the
|
||||
automated testing pipeline.
|
||||
|
||||
### How to enable snapshotting?
|
||||
|
||||
1. Install your [snapshot plugin][] into a custom Docker image following the
|
||||
[how to install plugins guide][].
|
||||
2. Add any required secrets or credentials into an Elasticsearch keystore
|
||||
following the [how to use the keystore][] guide.
|
||||
3. Configure the [snapshot repository][] as you normally would.
|
||||
4. To automate snapshots you can use [Snapshot Lifecycle Management][] or a tool
|
||||
like [curator][].
|
||||
|
||||
### How to configure templates post-deployment?
|
||||
|
||||
You can use `postStart` [lifecycle hooks][] to run code triggered after a
|
||||
container is created.
|
||||
|
||||
Here is an example of `postStart` hook to configure templates:
|
||||
|
||||
```yaml
|
||||
lifecycle:
|
||||
postStart:
|
||||
exec:
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
#!/bin/bash
|
||||
# Add a template to adjust number of shards/replicas
|
||||
TEMPLATE_NAME=my_template
|
||||
INDEX_PATTERN="logstash-*"
|
||||
SHARD_COUNT=8
|
||||
REPLICA_COUNT=1
|
||||
ES_URL=http://localhost:9200
|
||||
while [[ "$(curl -s -o /dev/null -w '%{http_code}\n' $ES_URL)" != "200" ]]; do sleep 1; done
|
||||
curl -XPUT "$ES_URL/_template/$TEMPLATE_NAME" -H 'Content-Type: application/json' -d'{"index_patterns":['\""$INDEX_PATTERN"\"'],"settings":{"number_of_shards":'$SHARD_COUNT',"number_of_replicas":'$REPLICA_COUNT'}}'
|
||||
```
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Please check [CONTRIBUTING.md][] before any contribution or for any questions
|
||||
about our development and testing process.
|
||||
|
||||
[7.17]: https://github.com/elastic/helm-charts/releases
|
||||
[#63]: https://github.com/elastic/helm-charts/issues/63
|
||||
[BREAKING_CHANGES.md]: https://github.com/elastic/helm-charts/blob/master/BREAKING_CHANGES.md
|
||||
[CHANGELOG.md]: https://github.com/elastic/helm-charts/blob/master/CHANGELOG.md
|
||||
[CONTRIBUTING.md]: https://github.com/elastic/helm-charts/blob/master/CONTRIBUTING.md
|
||||
[alternate scheduler]: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/#specify-schedulers-for-pods
|
||||
[annotations]: https://kubernetes.io/docs/concepts/overview/working-with-objects/annotations/
|
||||
[anti-affinity]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
[cluster.name]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/important-settings.html#cluster-name
|
||||
[clustering and node discovery]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/README.md#clustering-and-node-discovery
|
||||
[config example]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/config/values.yaml
|
||||
[curator]: https://www.elastic.co/guide/en/elasticsearch/client/curator/7.9/snapshot.html
|
||||
[custom docker image]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html#_c_customized_image
|
||||
[deploys statefulsets serially]: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies
|
||||
[discovery.zen.minimum_master_nodes]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/discovery-settings.html#minimum_master_nodes
|
||||
[docker for mac]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/docker-for-mac
|
||||
[elasticsearch cluster health status params]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-health.html#request-params
|
||||
[elasticsearch docker image]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/docker.html
|
||||
[environment variables]: https://kubernetes.io/docs/tasks/inject-data-application/define-environment-variable-container/#using-environment-variables-inside-of-your-config
|
||||
[environment from variables]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#configure-all-key-value-pairs-in-a-configmap-as-container-environment-variables
|
||||
[examples]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/
|
||||
[examples/multi]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/multi
|
||||
[examples/security]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/security
|
||||
[gke]: https://cloud.google.com/kubernetes-engine
|
||||
[helm]: https://helm.sh
|
||||
[helm/charts stable]: https://github.com/helm/charts/tree/master/stable/elasticsearch/
|
||||
[how to install plugins guide]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/README.md#how-to-install-plugins
|
||||
[how to use the keystore]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/README.md#how-to-use-the-keystore
|
||||
[http.port]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-http.html#_settings
|
||||
[imagePullPolicy]: https://kubernetes.io/docs/concepts/containers/images/#updating-images
|
||||
[imagePullSecrets]: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/#create-a-pod-that-uses-your-secret
|
||||
[ingress]: https://kubernetes.io/docs/concepts/services-networking/ingress/
|
||||
[java options]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/jvm-options.html
|
||||
[jvm heap size]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/heap-size.html
|
||||
[hostAliases]: https://kubernetes.io/docs/concepts/services-networking/add-entries-to-pod-etc-hosts-with-host-aliases/
|
||||
[kind]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/kubernetes-kind
|
||||
[kubernetes secrets]: https://kubernetes.io/docs/concepts/configuration/secret/
|
||||
[labels]: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/
|
||||
[lifecycle hooks]: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/
|
||||
[loadBalancer annotations]: https://kubernetes.io/docs/concepts/services-networking/service/#ssl-support-on-aws
|
||||
[loadBalancer externalTrafficPolicy]: https://kubernetes.io/docs/tasks/access-application-cluster/create-external-load-balancer/#preserving-the-client-source-ip
|
||||
[loadBalancer]: https://kubernetes.io/docs/concepts/services-networking/service/#loadbalancer
|
||||
[maxUnavailable]: https://kubernetes.io/docs/tasks/run-application/configure-pdb/#specifying-a-poddisruptionbudget
|
||||
[migration guide]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/migration/README.md
|
||||
[minikube]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/minikube
|
||||
[microk8s]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/microk8s
|
||||
[multi]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/multi/
|
||||
[network.host elasticsearch setting]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/network.host.html
|
||||
[node affinity settings]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature
|
||||
[node-certificates]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/configuring-tls.html#node-certificates
|
||||
[nodePort]: https://kubernetes.io/docs/concepts/services-networking/service/#nodeport
|
||||
[nodes types]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-node.html
|
||||
[nodeSelector]: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
|
||||
[openshift]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/openshift
|
||||
[priorityClass]: https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
|
||||
[probe]: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-probes/
|
||||
[resources]: https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
|
||||
[roles]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-node.html
|
||||
[secret]: https://kubernetes.io/docs/concepts/configuration/secret/#using-secrets
|
||||
[securityContext]: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/
|
||||
[service types]: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types
|
||||
[snapshot lifecycle management]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/snapshot-lifecycle-management.html
|
||||
[snapshot plugin]: https://www.elastic.co/guide/en/elasticsearch/plugins/7.17/repository.html
|
||||
[snapshot repository]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-snapshots.html
|
||||
[supported configurations]: https://github.com/elastic/helm-charts/tree/7.17/README.md#supported-configurations
|
||||
[sysctl vm.max_map_count]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/vm-max-map-count.html#vm-max-map-count
|
||||
[terminationGracePeriod]: https://kubernetes.io/docs/concepts/workloads/pods/pod/#termination-of-pods
|
||||
[tolerations]: https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
[transport port configuration]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/modules-transport.html#_transport_settings
|
||||
[updateStrategy]: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/
|
||||
[values.yaml]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/values.yaml
|
||||
[volumeClaimTemplate for statefulsets]: https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#stable-storage
|
||||
@@ -0,0 +1,21 @@
|
||||
default: test
|
||||
|
||||
include ../../../helpers/examples.mk
|
||||
|
||||
RELEASE := helm-es-config
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
secrets:
|
||||
kubectl delete secret elastic-config-credentials elastic-config-secret elastic-config-slack elastic-config-custom-path || true
|
||||
kubectl create secret generic elastic-config-credentials --from-literal=password=changeme --from-literal=username=elastic
|
||||
kubectl create secret generic elastic-config-slack --from-literal=xpack.notification.slack.account.monitoring.secure_url='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd'
|
||||
kubectl create secret generic elastic-config-secret --from-file=xpack.watcher.encryption_key=./watcher_encryption_key
|
||||
kubectl create secret generic elastic-config-custom-path --from-literal=slack_url='https://hooks.slack.com/services/asdasdasd/asdasdas/asdasd' --from-literal=thing_i_don_tcare_about=test
|
||||
|
||||
test: secrets install goss
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,27 @@
|
||||
# Config
|
||||
|
||||
This example deploy a single node Elasticsearch 7.17.3 with authentication and
|
||||
custom [values][].
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
* Create the required secrets: `make secrets`
|
||||
|
||||
* Deploy Elasticsearch chart with the default values: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/config-master 9200
|
||||
curl -u elastic:changeme http://localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
You can also run [goss integration tests][] using `make test`
|
||||
|
||||
|
||||
[goss integration tests]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/config/test/goss.yaml
|
||||
[values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/config/values.yaml
|
||||
@@ -0,0 +1,29 @@
|
||||
http:
|
||||
http://localhost:9200/_cluster/health:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
username: elastic
|
||||
password: "{{ .Env.ELASTIC_PASSWORD }}"
|
||||
body:
|
||||
- "green"
|
||||
- '"number_of_nodes":1'
|
||||
- '"number_of_data_nodes":1'
|
||||
|
||||
http://localhost:9200:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
username: elastic
|
||||
password: "{{ .Env.ELASTIC_PASSWORD }}"
|
||||
body:
|
||||
- '"cluster_name" : "config"'
|
||||
- "You Know, for Search"
|
||||
|
||||
command:
|
||||
"elasticsearch-keystore list":
|
||||
exit-status: 0
|
||||
stdout:
|
||||
- keystore.seed
|
||||
- bootstrap.password
|
||||
- xpack.notification.slack.account.monitoring.secure_url
|
||||
- xpack.notification.slack.account.otheraccount.secure_url
|
||||
- xpack.watcher.encryption_key
|
||||
@@ -0,0 +1,27 @@
|
||||
---
|
||||
|
||||
clusterName: "config"
|
||||
replicas: 1
|
||||
|
||||
extraEnvs:
|
||||
- name: ELASTIC_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: elastic-config-credentials
|
||||
key: password
|
||||
|
||||
# This is just a dummy file to make sure that
|
||||
# the keystore can be mounted at the same time
|
||||
# as a custom elasticsearch.yml
|
||||
esConfig:
|
||||
elasticsearch.yml: |
|
||||
xpack.security.enabled: true
|
||||
path.data: /usr/share/elasticsearch/data
|
||||
|
||||
keystore:
|
||||
- secretName: elastic-config-secret
|
||||
- secretName: elastic-config-slack
|
||||
- secretName: elastic-config-custom-path
|
||||
items:
|
||||
- key: slack_url
|
||||
path: xpack.notification.slack.account.otheraccount.secure_url
|
||||
@@ -0,0 +1 @@
|
||||
supersecret
|
||||
@@ -0,0 +1,14 @@
|
||||
default: test
|
||||
|
||||
include ../../../helpers/examples.mk
|
||||
|
||||
RELEASE := helm-es-default
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install $(RELEASE) ../../
|
||||
|
||||
test: install goss
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,25 @@
|
||||
# Default
|
||||
|
||||
This example deploy a 3 nodes Elasticsearch 7.17.3 cluster using
|
||||
[default values][].
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
* Deploy Elasticsearch chart with the default values: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/elasticsearch-master 9200
|
||||
curl localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
You can also run [goss integration tests][] using `make test`
|
||||
|
||||
|
||||
[goss integration tests]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/default/test/goss.yaml
|
||||
[default values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/values.yaml
|
||||
@@ -0,0 +1,19 @@
|
||||
#!/usr/bin/env bash -x
|
||||
|
||||
kubectl proxy || true &
|
||||
|
||||
make &
|
||||
PROC_ID=$!
|
||||
|
||||
while kill -0 "$PROC_ID" >/dev/null 2>&1; do
|
||||
echo "PROCESS IS RUNNING"
|
||||
if curl --fail 'http://localhost:8001/api/v1/proxy/namespaces/default/services/elasticsearch-master:9200/_search' ; then
|
||||
echo "cluster is healthy"
|
||||
else
|
||||
echo "cluster not healthy!"
|
||||
exit 1
|
||||
fi
|
||||
sleep 1
|
||||
done
|
||||
echo "PROCESS TERMINATED"
|
||||
exit 0
|
||||
@@ -0,0 +1,38 @@
|
||||
kernel-param:
|
||||
vm.max_map_count:
|
||||
value: "262144"
|
||||
|
||||
http:
|
||||
http://elasticsearch-master:9200/_cluster/health:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
body:
|
||||
- "green"
|
||||
- '"number_of_nodes":3'
|
||||
- '"number_of_data_nodes":3'
|
||||
|
||||
http://localhost:9200:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
body:
|
||||
- '"number" : "7.17.3"'
|
||||
- '"cluster_name" : "elasticsearch"'
|
||||
- "You Know, for Search"
|
||||
|
||||
file:
|
||||
/usr/share/elasticsearch/data:
|
||||
exists: true
|
||||
mode: "2775"
|
||||
owner: root
|
||||
group: elasticsearch
|
||||
filetype: directory
|
||||
|
||||
mount:
|
||||
/usr/share/elasticsearch/data:
|
||||
exists: true
|
||||
|
||||
user:
|
||||
elasticsearch:
|
||||
exists: true
|
||||
uid: 1000
|
||||
gid: 1000
|
||||
@@ -0,0 +1,13 @@
|
||||
default: test
|
||||
|
||||
RELEASE := helm-es-docker-for-mac
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
test: install
|
||||
helm test $(RELEASE)
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,23 @@
|
||||
# Docker for Mac
|
||||
|
||||
This example deploy a 3 nodes Elasticsearch 7.17.3 cluster on [Docker for Mac][]
|
||||
using [custom values][].
|
||||
|
||||
Note that this configuration should be used for test only and isn't recommended
|
||||
for production.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
* Deploy Elasticsearch chart with the default values: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/elasticsearch-master 9200
|
||||
curl localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
|
||||
[custom values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/docker-for-mac/values.yaml
|
||||
[docker for mac]: https://docs.docker.com/docker-for-mac/kubernetes/
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# Permit co-located instances for solitary minikube virtual machines.
|
||||
antiAffinity: "soft"
|
||||
|
||||
# Shrink default JVM heap.
|
||||
esJavaOpts: "-Xmx128m -Xms128m"
|
||||
|
||||
# Allocate smaller chunks of memory per pod.
|
||||
resources:
|
||||
requests:
|
||||
cpu: "100m"
|
||||
memory: "512M"
|
||||
limits:
|
||||
cpu: "1000m"
|
||||
memory: "512M"
|
||||
|
||||
# Request smaller persistent volumes.
|
||||
volumeClaimTemplate:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "hostpath"
|
||||
resources:
|
||||
requests:
|
||||
storage: 100M
|
||||
@@ -0,0 +1,17 @@
|
||||
default: test
|
||||
|
||||
RELEASE := helm-es-kind
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
install-local-path:
|
||||
kubectl apply -f https://raw.githubusercontent.com/rancher/local-path-provisioner/master/deploy/local-path-storage.yaml
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values-local-path.yaml $(RELEASE) ../../
|
||||
|
||||
test: install
|
||||
helm test $(RELEASE)
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,36 @@
|
||||
# KIND
|
||||
|
||||
This example deploy a 3 nodes Elasticsearch 7.17.3 cluster on [Kind][]
|
||||
using [custom values][].
|
||||
|
||||
Note that this configuration should be used for test only and isn't recommended
|
||||
for production.
|
||||
|
||||
Note that Kind < 0.7.0 are affected by a [kind issue][] with mount points
|
||||
created from PVCs not writable by non-root users. [kubernetes-sigs/kind#1157][]
|
||||
fix it in Kind 0.7.0.
|
||||
|
||||
The workaround for Kind < 0.7.0 is to install manually
|
||||
[Rancher Local Path Provisioner][] and use `local-path` storage class for
|
||||
Elasticsearch volumes (see [Makefile][] instructions).
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
* For Kind >= 0.7.0: Deploy Elasticsearch chart with the default values: `make install`
|
||||
* For Kind < 0.7.0: Deploy Elasticsearch chart with `local-path` storage class: `make install-local-path`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/elasticsearch-master 9200
|
||||
curl localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
|
||||
[custom values]: https://github.com/elastic/helm-charts/blob/7.17/elasticsearch/examples/kubernetes-kind/values.yaml
|
||||
[kind]: https://kind.sigs.k8s.io/
|
||||
[kind issue]: https://github.com/kubernetes-sigs/kind/issues/830
|
||||
[kubernetes-sigs/kind#1157]: https://github.com/kubernetes-sigs/kind/pull/1157
|
||||
[rancher local path provisioner]: https://github.com/rancher/local-path-provisioner
|
||||
[Makefile]: https://github.com/elastic/helm-charts/blob/7.17/elasticsearch/examples/kubernetes-kind/Makefile#L5
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# Permit co-located instances for solitary minikube virtual machines.
|
||||
antiAffinity: "soft"
|
||||
|
||||
# Shrink default JVM heap.
|
||||
esJavaOpts: "-Xmx128m -Xms128m"
|
||||
|
||||
# Allocate smaller chunks of memory per pod.
|
||||
resources:
|
||||
requests:
|
||||
cpu: "100m"
|
||||
memory: "512M"
|
||||
limits:
|
||||
cpu: "1000m"
|
||||
memory: "512M"
|
||||
|
||||
# Request smaller persistent volumes.
|
||||
volumeClaimTemplate:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "local-path"
|
||||
resources:
|
||||
requests:
|
||||
storage: 100M
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# Permit co-located instances for solitary minikube virtual machines.
|
||||
antiAffinity: "soft"
|
||||
|
||||
# Shrink default JVM heap.
|
||||
esJavaOpts: "-Xmx128m -Xms128m"
|
||||
|
||||
# Allocate smaller chunks of memory per pod.
|
||||
resources:
|
||||
requests:
|
||||
cpu: "100m"
|
||||
memory: "512M"
|
||||
limits:
|
||||
cpu: "1000m"
|
||||
memory: "512M"
|
||||
|
||||
# Request smaller persistent volumes.
|
||||
volumeClaimTemplate:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "local-path"
|
||||
resources:
|
||||
requests:
|
||||
storage: 100M
|
||||
@@ -0,0 +1,13 @@
|
||||
default: test
|
||||
|
||||
RELEASE := helm-es-microk8s
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
test: install
|
||||
helm test $(RELEASE)
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,32 @@
|
||||
# MicroK8S
|
||||
|
||||
This example deploy a 3 nodes Elasticsearch 7.17.3 cluster on [MicroK8S][]
|
||||
using [custom values][].
|
||||
|
||||
Note that this configuration should be used for test only and isn't recommended
|
||||
for production.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
The following MicroK8S [addons][] need to be enabled:
|
||||
- `dns`
|
||||
- `helm`
|
||||
- `storage`
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
* Deploy Elasticsearch chart with the default values: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/elasticsearch-master 9200
|
||||
curl localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
|
||||
[addons]: https://microk8s.io/docs/addons
|
||||
[custom values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/microk8s/values.yaml
|
||||
[MicroK8S]: https://microk8s.io
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
# Disable privileged init Container creation.
|
||||
sysctlInitContainer:
|
||||
enabled: false
|
||||
|
||||
# Restrict the use of the memory-mapping when sysctlInitContainer is disabled.
|
||||
esConfig:
|
||||
elasticsearch.yml: |
|
||||
node.store.allow_mmap: false
|
||||
|
||||
# Permit co-located instances for solitary minikube virtual machines.
|
||||
antiAffinity: "soft"
|
||||
|
||||
# Shrink default JVM heap.
|
||||
esJavaOpts: "-Xmx128m -Xms128m"
|
||||
|
||||
# Allocate smaller chunks of memory per pod.
|
||||
resources:
|
||||
requests:
|
||||
cpu: "100m"
|
||||
memory: "512M"
|
||||
limits:
|
||||
cpu: "1000m"
|
||||
memory: "512M"
|
||||
|
||||
# Request smaller persistent volumes.
|
||||
volumeClaimTemplate:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "microk8s-hostpath"
|
||||
resources:
|
||||
requests:
|
||||
storage: 100M
|
||||
@@ -0,0 +1,10 @@
|
||||
PREFIX := helm-es-migration
|
||||
|
||||
data:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values data.yaml $(PREFIX)-data ../../
|
||||
|
||||
master:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values master.yaml $(PREFIX)-master ../../
|
||||
|
||||
client:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values client.yaml $(PREFIX)-client ../../
|
||||
@@ -0,0 +1,167 @@
|
||||
# Migration Guide from helm/charts
|
||||
|
||||
There are two viable options for migrating from the community Elasticsearch Helm
|
||||
chart from the [helm/charts][] repo.
|
||||
|
||||
1. Restoring from Snapshot to a fresh cluster
|
||||
2. Live migration by joining a new cluster to the existing cluster.
|
||||
|
||||
## Restoring from Snapshot
|
||||
|
||||
This is the recommended and preferred option. The downside is that it will
|
||||
involve a period of write downtime during the migration. If you have a way to
|
||||
temporarily stop writes to your cluster then this is the way to go. This is also
|
||||
a lot simpler as it just involves launching a fresh cluster and restoring a
|
||||
snapshot following the [restoring to a different cluster guide][].
|
||||
|
||||
## Live migration
|
||||
|
||||
If restoring from a snapshot is not possible due to the write downtime then a
|
||||
live migration is also possible. It is very important to first test this in a
|
||||
testing environment to make sure you are comfortable with the process and fully
|
||||
understand what is happening.
|
||||
|
||||
This process will involve joining a new set of master, data and client nodes to
|
||||
an existing cluster that has been deployed using the [helm/charts][] community
|
||||
chart. Nodes will then be replaced one by one in a controlled fashion to
|
||||
decommission the old cluster.
|
||||
|
||||
This example will be using the default values for the existing helm/charts
|
||||
release and for the Elastic helm-charts release. If you have changed any of the
|
||||
default values then you will need to first make sure that your values are
|
||||
configured in a compatible way before starting the migration.
|
||||
|
||||
The process will involve a re-sync and a rolling restart of all of your data
|
||||
nodes. Therefore it is important to disable shard allocation and perform a synced
|
||||
flush like you normally would during any other rolling upgrade. See the
|
||||
[rolling upgrades guide][] for more information.
|
||||
|
||||
* The default image for this chart is
|
||||
`docker.elastic.co/elasticsearch/elasticsearch` which contains the default
|
||||
distribution of Elasticsearch with a [basic license][]. Make sure to update the
|
||||
`image` and `imageTag` values to the correct Docker image and Elasticsearch
|
||||
version that you currently have deployed.
|
||||
|
||||
* Convert your current helm/charts configuration into something that is
|
||||
compatible with this chart.
|
||||
|
||||
* Take a fresh snapshot of your cluster. If something goes wrong you want to be
|
||||
able to restore your data no matter what.
|
||||
|
||||
* Check that your clusters health is green. If not abort and make sure your
|
||||
cluster is healthy before continuing:
|
||||
|
||||
```
|
||||
curl localhost:9200/_cluster/health
|
||||
```
|
||||
|
||||
* Deploy new data nodes which will join the existing cluster. Take a look at the
|
||||
configuration in [data.yaml][]:
|
||||
|
||||
```
|
||||
make data
|
||||
```
|
||||
|
||||
* Check that the new nodes have joined the cluster (run this and any other curl
|
||||
commands from within one of your pods):
|
||||
|
||||
```
|
||||
curl localhost:9200/_cat/nodes
|
||||
```
|
||||
|
||||
* Check that your cluster is still green. If so we can now start to scale down
|
||||
the existing data nodes. Assuming you have the default amount of data nodes (2)
|
||||
we now want to scale it down to 1:
|
||||
|
||||
```
|
||||
kubectl scale statefulsets my-release-elasticsearch-data --replicas=1
|
||||
```
|
||||
|
||||
* Wait for your cluster to become green again:
|
||||
|
||||
```
|
||||
watch 'curl -s localhost:9200/_cluster/health'
|
||||
```
|
||||
|
||||
* Once the cluster is green we can scale down again:
|
||||
|
||||
```
|
||||
kubectl scale statefulsets my-release-elasticsearch-data --replicas=0
|
||||
```
|
||||
|
||||
* Wait for the cluster to be green again.
|
||||
* OK. We now have all data nodes running in the new cluster. Time to replace the
|
||||
masters by firstly scaling down the masters from 3 to 2. Between each step make
|
||||
sure to wait for the cluster to become green again, and check with
|
||||
`curl localhost:9200/_cat/nodes` that you see the correct amount of master
|
||||
nodes. During this process we will always make sure to keep at least 2 master
|
||||
nodes as to not lose quorum:
|
||||
|
||||
```
|
||||
kubectl scale statefulsets my-release-elasticsearch-master --replicas=2
|
||||
```
|
||||
|
||||
* Now deploy a single new master so that we have 3 masters again. See
|
||||
[master.yaml][] for the configuration:
|
||||
|
||||
```
|
||||
make master
|
||||
```
|
||||
|
||||
* Scale down old masters to 1:
|
||||
|
||||
```
|
||||
kubectl scale statefulsets my-release-elasticsearch-master --replicas=1
|
||||
```
|
||||
|
||||
* Edit the masters in [masters.yaml][] to 2 and redeploy:
|
||||
|
||||
```
|
||||
make master
|
||||
```
|
||||
|
||||
* Scale down the old masters to 0:
|
||||
|
||||
```
|
||||
kubectl scale statefulsets my-release-elasticsearch-master --replicas=0
|
||||
```
|
||||
|
||||
* Edit the [masters.yaml][] to have 3 replicas and remove the
|
||||
`discovery.zen.ping.unicast.hosts` entry from `extraEnvs` then redeploy the
|
||||
masters. This will make sure all 3 masters are running in the new cluster and
|
||||
are pointing at each other for discovery:
|
||||
|
||||
```
|
||||
make master
|
||||
```
|
||||
|
||||
* Remove the `discovery.zen.ping.unicast.hosts` entry from `extraEnvs` then
|
||||
redeploy the data nodes to make sure they are pointing at the new masters:
|
||||
|
||||
```
|
||||
make data
|
||||
```
|
||||
|
||||
* Deploy the client nodes:
|
||||
|
||||
```
|
||||
make client
|
||||
```
|
||||
|
||||
* Update any processes that are talking to the existing client nodes and point
|
||||
them to the new client nodes. Once this is done you can scale down the old
|
||||
client nodes:
|
||||
|
||||
```
|
||||
kubectl scale deployment my-release-elasticsearch-client --replicas=0
|
||||
```
|
||||
|
||||
* The migration should now be complete. After verifying that everything is
|
||||
working correctly you can cleanup leftover resources from your old cluster.
|
||||
|
||||
[basic license]: https://www.elastic.co/subscriptions
|
||||
[data.yaml]: https://github.com/elastic/helm-charts/blob/7.17/elasticsearch/examples/migration/data.yaml
|
||||
[helm/charts]: https://github.com/helm/charts/tree/7.17/stable/elasticsearch
|
||||
[master.yaml]: https://github.com/elastic/helm-charts/blob/7.17/elasticsearch/examples/migration/master.yaml
|
||||
[restoring to a different cluster guide]: https://www.elastic.co/guide/en/elasticsearch/reference/6.8/modules-snapshots.html#_restoring_to_a_different_cluster
|
||||
[rolling upgrades guide]: https://www.elastic.co/guide/en/elasticsearch/reference/6.8/rolling-upgrades.html
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
|
||||
replicas: 2
|
||||
|
||||
clusterName: "elasticsearch"
|
||||
nodeGroup: "client"
|
||||
|
||||
esMajorVersion: 6
|
||||
|
||||
roles:
|
||||
master: "false"
|
||||
ingest: "false"
|
||||
data: "false"
|
||||
|
||||
volumeClaimTemplate:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "standard"
|
||||
resources:
|
||||
requests:
|
||||
storage: 1Gi # Currently needed till pvcs are made optional
|
||||
|
||||
persistence:
|
||||
enabled: false
|
||||
@@ -0,0 +1,17 @@
|
||||
---
|
||||
|
||||
replicas: 2
|
||||
|
||||
esMajorVersion: 6
|
||||
|
||||
extraEnvs:
|
||||
- name: discovery.zen.ping.unicast.hosts
|
||||
value: "my-release-elasticsearch-discovery"
|
||||
|
||||
clusterName: "elasticsearch"
|
||||
nodeGroup: "data"
|
||||
|
||||
roles:
|
||||
master: "false"
|
||||
ingest: "false"
|
||||
data: "true"
|
||||
@@ -0,0 +1,26 @@
|
||||
---
|
||||
|
||||
# Temporarily set to 3 so we can scale up/down the old a new cluster
|
||||
# one at a time whilst always keeping 3 masters running
|
||||
replicas: 1
|
||||
|
||||
esMajorVersion: 6
|
||||
|
||||
extraEnvs:
|
||||
- name: discovery.zen.ping.unicast.hosts
|
||||
value: "my-release-elasticsearch-discovery"
|
||||
|
||||
clusterName: "elasticsearch"
|
||||
nodeGroup: "master"
|
||||
|
||||
roles:
|
||||
master: "true"
|
||||
ingest: "false"
|
||||
data: "false"
|
||||
|
||||
volumeClaimTemplate:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "standard"
|
||||
resources:
|
||||
requests:
|
||||
storage: 4Gi
|
||||
@@ -0,0 +1,13 @@
|
||||
default: test
|
||||
|
||||
RELEASE := helm-es-minikube
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
test: install
|
||||
helm test $(RELEASE)
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,38 @@
|
||||
# Minikube
|
||||
|
||||
This example deploy a 3 nodes Elasticsearch 7.17.3 cluster on [Minikube][]
|
||||
using [custom values][].
|
||||
|
||||
If helm or kubectl timeouts occur, you may consider creating a minikube VM with
|
||||
more CPU cores or memory allocated.
|
||||
|
||||
Note that this configuration should be used for test only and isn't recommended
|
||||
for production.
|
||||
|
||||
|
||||
## Requirements
|
||||
|
||||
In order to properly support the required persistent volume claims for the
|
||||
Elasticsearch StatefulSet, the `default-storageclass` and `storage-provisioner`
|
||||
minikube addons must be enabled.
|
||||
|
||||
```
|
||||
minikube addons enable default-storageclass
|
||||
minikube addons enable storage-provisioner
|
||||
```
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
* Deploy Elasticsearch chart with the default values: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/elasticsearch-master 9200
|
||||
curl localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
|
||||
[custom values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/minikube/values.yaml
|
||||
[minikube]: https://minikube.sigs.k8s.io/docs/
|
||||
@@ -0,0 +1,23 @@
|
||||
---
|
||||
# Permit co-located instances for solitary minikube virtual machines.
|
||||
antiAffinity: "soft"
|
||||
|
||||
# Shrink default JVM heap.
|
||||
esJavaOpts: "-Xmx128m -Xms128m"
|
||||
|
||||
# Allocate smaller chunks of memory per pod.
|
||||
resources:
|
||||
requests:
|
||||
cpu: "100m"
|
||||
memory: "512M"
|
||||
limits:
|
||||
cpu: "1000m"
|
||||
memory: "512M"
|
||||
|
||||
# Request smaller persistent volumes.
|
||||
volumeClaimTemplate:
|
||||
accessModes: [ "ReadWriteOnce" ]
|
||||
storageClassName: "standard"
|
||||
resources:
|
||||
requests:
|
||||
storage: 100M
|
||||
@@ -0,0 +1,19 @@
|
||||
default: test
|
||||
|
||||
include ../../../helpers/examples.mk
|
||||
|
||||
PREFIX := helm-es-multi
|
||||
RELEASE := helm-es-multi-master
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values master.yaml $(PREFIX)-master ../../
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values data.yaml $(PREFIX)-data ../../
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values client.yaml $(PREFIX)-client ../../
|
||||
|
||||
test: install goss
|
||||
|
||||
purge:
|
||||
helm del $(PREFIX)-master
|
||||
helm del $(PREFIX)-data
|
||||
helm del $(PREFIX)-client
|
||||
@@ -0,0 +1,29 @@
|
||||
# Multi
|
||||
|
||||
This example deploy an Elasticsearch 7.17.3 cluster composed of 3 different Helm
|
||||
releases:
|
||||
|
||||
- `helm-es-multi-master` for the 3 master nodes using [master values][]
|
||||
- `helm-es-multi-data` for the 3 data nodes using [data values][]
|
||||
- `helm-es-multi-client` for the 3 client nodes using [client values][]
|
||||
|
||||
## Usage
|
||||
|
||||
* Deploy the 3 Elasticsearch releases: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/multi-master 9200
|
||||
curl -u elastic:changeme http://localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
You can also run [goss integration tests][] using `make test`
|
||||
|
||||
|
||||
[client values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/multi/client.yaml
|
||||
[data values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/multi/data.yaml
|
||||
[goss integration tests]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/multi/test/goss.yaml
|
||||
[master values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/multi/master.yaml
|
||||
@@ -0,0 +1,14 @@
|
||||
---
|
||||
|
||||
clusterName: "multi"
|
||||
nodeGroup: "client"
|
||||
|
||||
roles:
|
||||
master: "false"
|
||||
ingest: "false"
|
||||
data: "false"
|
||||
ml: "false"
|
||||
remote_cluster_client: "false"
|
||||
|
||||
persistence:
|
||||
enabled: false
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
|
||||
clusterName: "multi"
|
||||
nodeGroup: "data"
|
||||
|
||||
roles:
|
||||
master: "false"
|
||||
ingest: "true"
|
||||
data: "true"
|
||||
ml: "false"
|
||||
remote_cluster_client: "false"
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
|
||||
clusterName: "multi"
|
||||
nodeGroup: "master"
|
||||
|
||||
roles:
|
||||
master: "true"
|
||||
ingest: "false"
|
||||
data: "false"
|
||||
ml: "false"
|
||||
remote_cluster_client: "false"
|
||||
@@ -0,0 +1,9 @@
|
||||
http:
|
||||
http://localhost:9200/_cluster/health:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
body:
|
||||
- 'green'
|
||||
- '"cluster_name":"multi"'
|
||||
- '"number_of_nodes":9'
|
||||
- '"number_of_data_nodes":3'
|
||||
@@ -0,0 +1,14 @@
|
||||
default: test
|
||||
|
||||
include ../../../helpers/examples.mk
|
||||
|
||||
RELEASE := helm-es-networkpolicy
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
test: install goss
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,37 @@
|
||||
networkPolicy:
|
||||
http:
|
||||
enabled: true
|
||||
explicitNamespacesSelector:
|
||||
# Accept from namespaces with all those different rules (from whitelisted Pods)
|
||||
matchLabels:
|
||||
role: frontend-http
|
||||
matchExpressions:
|
||||
- {key: role, operator: In, values: [frontend-http]}
|
||||
additionalRules:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
role: frontend-http
|
||||
- podSelector:
|
||||
matchExpressions:
|
||||
- key: role
|
||||
operator: In
|
||||
values:
|
||||
- frontend-http
|
||||
transport:
|
||||
enabled: true
|
||||
allowExternal: true
|
||||
explicitNamespacesSelector:
|
||||
matchLabels:
|
||||
role: frontend-transport
|
||||
matchExpressions:
|
||||
- {key: role, operator: In, values: [frontend-transport]}
|
||||
additionalRules:
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
role: frontend-transport
|
||||
- podSelector:
|
||||
matchExpressions:
|
||||
- key: role
|
||||
operator: In
|
||||
values:
|
||||
- frontend-transport
|
||||
@@ -0,0 +1,13 @@
|
||||
default: test
|
||||
|
||||
include ../../../helpers/examples.mk
|
||||
|
||||
RELEASE := elasticsearch
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
test: install goss
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,24 @@
|
||||
# OpenShift
|
||||
|
||||
This example deploy a 3 nodes Elasticsearch 7.17.3 cluster on [OpenShift][]
|
||||
using [custom values][].
|
||||
|
||||
## Usage
|
||||
|
||||
* Deploy Elasticsearch chart with the default values: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/elasticsearch-master 9200
|
||||
curl localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
You can also run [goss integration tests][] using `make test`
|
||||
|
||||
|
||||
[custom values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/openshift/values.yaml
|
||||
[goss integration tests]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/openshift/test/goss.yaml
|
||||
[openshift]: https://www.openshift.com/
|
||||
@@ -0,0 +1,16 @@
|
||||
http:
|
||||
http://localhost:9200/_cluster/health:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
body:
|
||||
- "green"
|
||||
- '"number_of_nodes":3'
|
||||
- '"number_of_data_nodes":3'
|
||||
|
||||
http://localhost:9200:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
body:
|
||||
- '"number" : "7.17.3"'
|
||||
- '"cluster_name" : "elasticsearch"'
|
||||
- "You Know, for Search"
|
||||
@@ -0,0 +1,11 @@
|
||||
---
|
||||
|
||||
securityContext:
|
||||
runAsUser: null
|
||||
|
||||
podSecurityContext:
|
||||
fsGroup: null
|
||||
runAsUser: null
|
||||
|
||||
sysctlInitContainer:
|
||||
enabled: false
|
||||
@@ -0,0 +1,38 @@
|
||||
default: test
|
||||
|
||||
include ../../../helpers/examples.mk
|
||||
|
||||
RELEASE := helm-es-security
|
||||
ELASTICSEARCH_IMAGE := docker.elastic.co/elasticsearch/elasticsearch:$(STACK_VERSION)
|
||||
TIMEOUT := 1200s
|
||||
|
||||
install:
|
||||
helm upgrade --wait --timeout=$(TIMEOUT) --install --values values.yaml $(RELEASE) ../../
|
||||
|
||||
test: secrets install goss
|
||||
|
||||
purge:
|
||||
kubectl delete secrets elastic-credentials elastic-certificates elastic-certificate-pem elastic-certificate-crt|| true
|
||||
helm del $(RELEASE)
|
||||
|
||||
pull-elasticsearch-image:
|
||||
docker pull $(ELASTICSEARCH_IMAGE)
|
||||
|
||||
secrets:
|
||||
docker rm -f elastic-helm-charts-certs || true
|
||||
rm -f elastic-certificates.p12 elastic-certificate.pem elastic-certificate.crt elastic-stack-ca.p12 || true
|
||||
password=$$([ ! -z "$$ELASTIC_PASSWORD" ] && echo $$ELASTIC_PASSWORD || echo $$(docker run --rm busybox:1.31.1 /bin/sh -c "< /dev/urandom tr -cd '[:alnum:]' | head -c20")) && \
|
||||
docker run --name elastic-helm-charts-certs -i -w /app \
|
||||
$(ELASTICSEARCH_IMAGE) \
|
||||
/bin/sh -c " \
|
||||
elasticsearch-certutil ca --out /app/elastic-stack-ca.p12 --pass '' && \
|
||||
elasticsearch-certutil cert --name security-master --dns security-master --ca /app/elastic-stack-ca.p12 --pass '' --ca-pass '' --out /app/elastic-certificates.p12" && \
|
||||
docker cp elastic-helm-charts-certs:/app/elastic-certificates.p12 ./ && \
|
||||
docker rm -f elastic-helm-charts-certs && \
|
||||
openssl pkcs12 -nodes -passin pass:'' -in elastic-certificates.p12 -out elastic-certificate.pem && \
|
||||
openssl x509 -outform der -in elastic-certificate.pem -out elastic-certificate.crt && \
|
||||
kubectl create secret generic elastic-certificates --from-file=elastic-certificates.p12 && \
|
||||
kubectl create secret generic elastic-certificate-pem --from-file=elastic-certificate.pem && \
|
||||
kubectl create secret generic elastic-certificate-crt --from-file=elastic-certificate.crt && \
|
||||
kubectl create secret generic elastic-credentials --from-literal=password=$$password --from-literal=username=elastic && \
|
||||
rm -f elastic-certificates.p12 elastic-certificate.pem elastic-certificate.crt elastic-stack-ca.p12
|
||||
@@ -0,0 +1,29 @@
|
||||
# Security
|
||||
|
||||
This example deploy a 3 nodes Elasticsearch 7.17.3 with authentication and
|
||||
autogenerated certificates for TLS (see [values][]).
|
||||
|
||||
Note that this configuration should be used for test only. For a production
|
||||
deployment you should generate SSL certificates following the [official docs][].
|
||||
|
||||
## Usage
|
||||
|
||||
* Create the required secrets: `make secrets`
|
||||
|
||||
* Deploy Elasticsearch chart with the default values: `make install`
|
||||
|
||||
* You can now setup a port forward to query Elasticsearch API:
|
||||
|
||||
```
|
||||
kubectl port-forward svc/security-master 9200
|
||||
curl -u elastic:changeme https://localhost:9200/_cat/indices
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
You can also run [goss integration tests][] using `make test`
|
||||
|
||||
|
||||
[goss integration tests]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/security/test/goss.yaml
|
||||
[official docs]: https://www.elastic.co/guide/en/elasticsearch/reference/7.17/configuring-tls.html#node-certificates
|
||||
[values]: https://github.com/elastic/helm-charts/tree/7.17/elasticsearch/examples/security/values.yaml
|
||||
@@ -0,0 +1,44 @@
|
||||
http:
|
||||
https://security-master:9200/_cluster/health:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
allow-insecure: true
|
||||
username: elastic
|
||||
password: "{{ .Env.ELASTIC_PASSWORD }}"
|
||||
body:
|
||||
- "green"
|
||||
- '"number_of_nodes":3'
|
||||
- '"number_of_data_nodes":3'
|
||||
|
||||
https://localhost:9200/:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
allow-insecure: true
|
||||
username: elastic
|
||||
password: "{{ .Env.ELASTIC_PASSWORD }}"
|
||||
body:
|
||||
- '"cluster_name" : "security"'
|
||||
- "You Know, for Search"
|
||||
|
||||
https://localhost:9200/_xpack/license:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
allow-insecure: true
|
||||
username: elastic
|
||||
password: "{{ .Env.ELASTIC_PASSWORD }}"
|
||||
body:
|
||||
- "active"
|
||||
- "basic"
|
||||
|
||||
file:
|
||||
/usr/share/elasticsearch/config/elasticsearch.yml:
|
||||
exists: true
|
||||
contains:
|
||||
- "xpack.security.enabled: true"
|
||||
- "xpack.security.transport.ssl.enabled: true"
|
||||
- "xpack.security.transport.ssl.verification_mode: certificate"
|
||||
- "xpack.security.transport.ssl.keystore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12"
|
||||
- "xpack.security.transport.ssl.truststore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12"
|
||||
- "xpack.security.http.ssl.enabled: true"
|
||||
- "xpack.security.http.ssl.truststore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12"
|
||||
- "xpack.security.http.ssl.keystore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12"
|
||||
@@ -0,0 +1,33 @@
|
||||
---
|
||||
clusterName: "security"
|
||||
nodeGroup: "master"
|
||||
|
||||
roles:
|
||||
master: "true"
|
||||
ingest: "true"
|
||||
data: "true"
|
||||
|
||||
protocol: https
|
||||
|
||||
esConfig:
|
||||
elasticsearch.yml: |
|
||||
xpack.security.enabled: true
|
||||
xpack.security.transport.ssl.enabled: true
|
||||
xpack.security.transport.ssl.verification_mode: certificate
|
||||
xpack.security.transport.ssl.keystore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12
|
||||
xpack.security.transport.ssl.truststore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12
|
||||
xpack.security.http.ssl.enabled: true
|
||||
xpack.security.http.ssl.truststore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12
|
||||
xpack.security.http.ssl.keystore.path: /usr/share/elasticsearch/config/certs/elastic-certificates.p12
|
||||
|
||||
extraEnvs:
|
||||
- name: ELASTIC_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: elastic-credentials
|
||||
key: password
|
||||
|
||||
secretMounts:
|
||||
- name: elastic-certificates
|
||||
secretName: elastic-certificates
|
||||
path: /usr/share/elasticsearch/config/certs
|
||||
@@ -0,0 +1,16 @@
|
||||
default: test
|
||||
|
||||
include ../../../helpers/examples.mk
|
||||
|
||||
CHART := elasticsearch
|
||||
RELEASE := helm-es-upgrade
|
||||
FROM := 7.4.0 # versions before 7.4.O aren't compatible with Kubernetes >= 1.16.0
|
||||
|
||||
install:
|
||||
../../../helpers/upgrade.sh --chart $(CHART) --release $(RELEASE) --from $(FROM)
|
||||
kubectl rollout status statefulset upgrade-master
|
||||
|
||||
test: install goss
|
||||
|
||||
purge:
|
||||
helm del $(RELEASE)
|
||||
@@ -0,0 +1,17 @@
|
||||
# Upgrade
|
||||
|
||||
This example will deploy a 3 node Elasticsearch cluster chart using an old chart
|
||||
version, then upgrade it.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
* Deploy and upgrade Elasticsearch chart with the default values: `make install`
|
||||
|
||||
|
||||
## Testing
|
||||
|
||||
You can also run [goss integration tests][] using `make test`.
|
||||
|
||||
|
||||
[goss integration tests]: https://github.com/elastic/helm-charts/tree/master/elasticsearch/examples/upgrade/test/goss.yaml
|
||||
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
usage() {
|
||||
cat <<-EOF
|
||||
USAGE:
|
||||
$0 [--release <release-name>] [--from <elasticsearch-version>]
|
||||
$0 --help
|
||||
|
||||
OPTIONS:
|
||||
--release <release-name>
|
||||
Name of the Helm release to install
|
||||
--from <elasticsearch-version>
|
||||
Elasticsearch version to use for first install
|
||||
EOF
|
||||
exit 1
|
||||
}
|
||||
|
||||
RELEASE="helm-es-upgrade"
|
||||
FROM=""
|
||||
|
||||
while [[ $# -gt 0 ]]
|
||||
do
|
||||
key="$1"
|
||||
|
||||
case $key in
|
||||
--help)
|
||||
usage
|
||||
;;
|
||||
--release)
|
||||
RELEASE="$2"
|
||||
shift 2
|
||||
;;
|
||||
--from)
|
||||
FROM="$2"
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
log "Unrecognized argument: '$key'"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if ! command -v jq > /dev/null
|
||||
then
|
||||
echo 'jq is required to use this script'
|
||||
echo 'please check https://stedolan.github.io/jq/download/ to install it'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Elasticsearch chart < 7.4.0 are not compatible with K8S >= 1.16)
|
||||
if [[ -z $FROM ]]
|
||||
then
|
||||
KUBE_MINOR_VERSION=$(kubectl version -o json | jq --raw-output --exit-status '.serverVersion.minor' | sed 's/[^0-9]*//g')
|
||||
|
||||
if [ "$KUBE_MINOR_VERSION" -lt 16 ]
|
||||
then
|
||||
FROM="7.0.0-alpha1"
|
||||
else
|
||||
FROM="7.4.0"
|
||||
fi
|
||||
fi
|
||||
|
||||
helm repo add elastic https://helm.elastic.co
|
||||
|
||||
# Initial install
|
||||
printf "Installing Elasticsearch chart %s\n" "$FROM"
|
||||
helm upgrade --wait --timeout=600s --install "$RELEASE" elastic/elasticsearch --version "$FROM" --set clusterName=upgrade
|
||||
kubectl rollout status sts/upgrade-master --timeout=600s
|
||||
|
||||
# Upgrade
|
||||
printf "Upgrading Elasticsearch chart\n"
|
||||
helm upgrade --wait --timeout=600s --set terminationGracePeriod=121 --install "$RELEASE" ../../ --set clusterName=upgrade
|
||||
kubectl rollout status sts/upgrade-master --timeout=600s
|
||||
@@ -0,0 +1,16 @@
|
||||
http:
|
||||
http://localhost:9200/_cluster/health:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
body:
|
||||
- "green"
|
||||
- '"number_of_nodes":3'
|
||||
- '"number_of_data_nodes":3'
|
||||
|
||||
http://localhost:9200:
|
||||
status: 200
|
||||
timeout: 2000
|
||||
body:
|
||||
- '"number" : "7.17.3"'
|
||||
- '"cluster_name" : "upgrade"'
|
||||
- "You Know, for Search"
|
||||
@@ -0,0 +1,2 @@
|
||||
---
|
||||
clusterName: upgrade
|
||||
@@ -0,0 +1,6 @@
|
||||
1. Watch all cluster members come up.
|
||||
$ kubectl get pods --namespace={{ .Release.Namespace }} -l app={{ template "elasticsearch.uname" . }} -w
|
||||
{{- if .Values.tests.enabled -}}
|
||||
2. Test cluster health using Helm test.
|
||||
$ helm --namespace={{ .Release.Namespace }} test {{ .Release.Name }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,84 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "elasticsearch.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
*/}}
|
||||
{{- define "elasticsearch.fullname" -}}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride -}}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "elasticsearch.uname" -}}
|
||||
{{- if empty .Values.fullnameOverride -}}
|
||||
{{- if empty .Values.nameOverride -}}
|
||||
{{ .Values.clusterName }}-{{ .Values.nodeGroup }}
|
||||
{{- else -}}
|
||||
{{ .Values.nameOverride }}-{{ .Values.nodeGroup }}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{ .Values.fullnameOverride }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Generate certificates
|
||||
*/}}
|
||||
{{- define "elasticsearch.gen-certs" -}}
|
||||
{{- $altNames := list ( printf "%s.%s" (include "elasticsearch.name" .) .Release.Namespace ) ( printf "%s.%s.svc" (include "elasticsearch.name" .) .Release.Namespace ) -}}
|
||||
{{- $ca := genCA "elasticsearch-ca" 365 -}}
|
||||
{{- $cert := genSignedCert ( include "elasticsearch.name" . ) nil $altNames 365 $ca -}}
|
||||
tls.crt: {{ $cert.Cert | toString | b64enc }}
|
||||
tls.key: {{ $cert.Key | toString | b64enc }}
|
||||
ca.crt: {{ $ca.Cert | toString | b64enc }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "elasticsearch.masterService" -}}
|
||||
{{- if empty .Values.masterService -}}
|
||||
{{- if empty .Values.fullnameOverride -}}
|
||||
{{- if empty .Values.nameOverride -}}
|
||||
{{ .Values.clusterName }}-master
|
||||
{{- else -}}
|
||||
{{ .Values.nameOverride }}-master
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{ .Values.fullnameOverride }}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{ .Values.masterService }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "elasticsearch.endpoints" -}}
|
||||
{{- $replicas := int (toString (.Values.replicas)) }}
|
||||
{{- $uname := (include "elasticsearch.uname" .) }}
|
||||
{{- range $i, $e := untilStep 0 $replicas 1 -}}
|
||||
{{ $uname }}-{{ $i }},
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "elasticsearch.esMajorVersion" -}}
|
||||
{{- if .Values.esMajorVersion -}}
|
||||
{{ .Values.esMajorVersion }}
|
||||
{{- else -}}
|
||||
{{- $version := int (index (.Values.imageTag | splitList ".") 0) -}}
|
||||
{{- if and (contains "docker.elastic.co/elasticsearch/elasticsearch" .Values.image) (not (eq $version 0)) -}}
|
||||
{{ $version }}
|
||||
{{- else -}}
|
||||
7
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Use the fullname if the serviceAccount value is not set
|
||||
*/}}
|
||||
{{- define "elasticsearch.serviceAccount" -}}
|
||||
{{- .Values.rbac.serviceAccountName | default (include "elasticsearch.uname" .) -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,34 @@
|
||||
{{- if .Values.esConfig }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "elasticsearch.uname" . }}-config
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
data:
|
||||
{{- range $path, $config := .Values.esConfig }}
|
||||
{{ $path }}: |
|
||||
{{ $config | indent 4 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- if .Values.esJvmOptions }}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ template "elasticsearch.uname" . }}-jvm-options
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
data:
|
||||
{{- range $path, $config := .Values.esJvmOptions }}
|
||||
{{ $path }}: |
|
||||
{{ $config | indent 4 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,64 @@
|
||||
{{- if .Values.ingress.enabled -}}
|
||||
{{- $fullName := include "elasticsearch.uname" . -}}
|
||||
{{- $httpPort := .Values.httpPort -}}
|
||||
{{- $pathtype := .Values.ingress.pathtype -}}
|
||||
{{- $ingressPath := .Values.ingress.path -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
labels:
|
||||
app: {{ .Chart.Name }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- with .Values.ingress.annotations }}
|
||||
annotations:
|
||||
{{ toYaml . | indent 4 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.ingress.className }}
|
||||
ingressClassName: {{ .Values.ingress.className | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.ingress.tls }}
|
||||
tls:
|
||||
{{- if .ingressPath }}
|
||||
{{- range .Values.ingress.tls }}
|
||||
- hosts:
|
||||
{{- range .hosts }}
|
||||
- {{ . }}
|
||||
{{- end }}
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
{{ toYaml .Values.ingress.tls | indent 4 }}
|
||||
{{- end }}
|
||||
{{- end}}
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
{{- if $ingressPath }}
|
||||
- host: {{ . }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ $ingressPath }}
|
||||
pathType: {{ $pathtype }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ $httpPort }}
|
||||
{{- else }}
|
||||
- host: {{ .host }}
|
||||
http:
|
||||
paths:
|
||||
{{- range .paths }}
|
||||
- path: {{ .path }}
|
||||
pathType: {{ $pathtype }}
|
||||
backend:
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: {{ .servicePort | default $httpPort }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,61 @@
|
||||
{{- if (or .Values.networkPolicy.http.enabled .Values.networkPolicy.transport.enabled) }}
|
||||
kind: NetworkPolicy
|
||||
apiVersion: networking.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ template "elasticsearch.uname" . }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
spec:
|
||||
podSelector:
|
||||
matchLabels:
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
ingress: # Allow inbound connections
|
||||
|
||||
{{- if .Values.networkPolicy.http.enabled }}
|
||||
# For HTTP access
|
||||
- ports:
|
||||
- port: {{ .Values.httpPort }}
|
||||
from:
|
||||
# From authorized Pods (having the correct label)
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
{{ template "elasticsearch.uname" . }}-http-client: "true"
|
||||
{{- with .Values.networkPolicy.http.explicitNamespacesSelector }}
|
||||
# From authorized namespaces
|
||||
namespaceSelector:
|
||||
{{ toYaml . | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.networkPolicy.http.additionalRules }}
|
||||
# Or from custom additional rules
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.networkPolicy.transport.enabled }}
|
||||
# For transport access
|
||||
- ports:
|
||||
- port: {{ .Values.transportPort }}
|
||||
from:
|
||||
# From authorized Pods (having the correct label)
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
{{ template "elasticsearch.uname" . }}-transport-client: "true"
|
||||
{{- with .Values.networkPolicy.transport.explicitNamespacesSelector }}
|
||||
# From authorized namespaces
|
||||
namespaceSelector:
|
||||
{{ toYaml . | indent 12 }}
|
||||
{{- end }}
|
||||
{{- with .Values.networkPolicy.transport.additionalRules }}
|
||||
# Or from custom additional rules
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
# Or from other ElasticSearch Pods
|
||||
- podSelector:
|
||||
matchLabels:
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
{{- end }}
|
||||
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if .Values.maxUnavailable }}
|
||||
{{- if .Capabilities.APIVersions.Has "policy/v1" -}}
|
||||
apiVersion: policy/v1
|
||||
{{- else}}
|
||||
apiVersion: policy/v1beta1
|
||||
{{- end }}
|
||||
kind: PodDisruptionBudget
|
||||
metadata:
|
||||
name: "{{ template "elasticsearch.uname" . }}-pdb"
|
||||
spec:
|
||||
maxUnavailable: {{ .Values.maxUnavailable }}
|
||||
selector:
|
||||
matchLabels:
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
{{- end }}
|
||||
@@ -0,0 +1,18 @@
|
||||
{{- if .Values.podSecurityPolicy.create -}}
|
||||
{{- $fullName := include "elasticsearch.uname" . -}}
|
||||
{{- if .Capabilities.APIVersions.Has "policy/v1" -}}
|
||||
apiVersion: policy/v1
|
||||
{{- else}}
|
||||
apiVersion: policy/v1beta1
|
||||
{{- end }}
|
||||
kind: PodSecurityPolicy
|
||||
metadata:
|
||||
name: {{ default $fullName .Values.podSecurityPolicy.name | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
app: {{ $fullName | quote }}
|
||||
spec:
|
||||
{{ toYaml .Values.podSecurityPolicy.spec | indent 2 }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,25 @@
|
||||
{{- if .Values.rbac.create -}}
|
||||
{{- $fullName := include "elasticsearch.uname" . -}}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
name: {{ $fullName | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
app: {{ $fullName | quote }}
|
||||
rules:
|
||||
- apiGroups:
|
||||
- extensions
|
||||
resources:
|
||||
- podsecuritypolicies
|
||||
resourceNames:
|
||||
{{- if eq .Values.podSecurityPolicy.name "" }}
|
||||
- {{ $fullName | quote }}
|
||||
{{- else }}
|
||||
- {{ .Values.podSecurityPolicy.name | quote }}
|
||||
{{- end }}
|
||||
verbs:
|
||||
- use
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,20 @@
|
||||
{{- if .Values.rbac.create -}}
|
||||
{{- $fullName := include "elasticsearch.uname" . -}}
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: {{ $fullName | quote }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
app: {{ $fullName | quote }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: "{{ template "elasticsearch.serviceAccount" . }}"
|
||||
namespace: {{ .Release.Namespace | quote }}
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: {{ $fullName | quote }}
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,78 @@
|
||||
{{- if .Values.service.enabled -}}
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
{{- if eq .Values.nodeGroup "master" }}
|
||||
name: {{ template "elasticsearch.masterService" . }}
|
||||
{{- else }}
|
||||
name: {{ template "elasticsearch.uname" . }}
|
||||
{{- end }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
{{- if .Values.service.labels }}
|
||||
{{ toYaml .Values.service.labels | indent 4}}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{ toYaml .Values.service.annotations | indent 4 }}
|
||||
spec:
|
||||
type: {{ .Values.service.type }}
|
||||
selector:
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
publishNotReadyAddresses: {{ .Values.service.publishNotReadyAddresses }}
|
||||
ports:
|
||||
- name: {{ .Values.service.httpPortName | default "http" }}
|
||||
protocol: TCP
|
||||
port: {{ .Values.httpPort }}
|
||||
{{- if .Values.service.nodePort }}
|
||||
nodePort: {{ .Values.service.nodePort }}
|
||||
{{- end }}
|
||||
- name: {{ .Values.service.transportPortName | default "transport" }}
|
||||
protocol: TCP
|
||||
port: {{ .Values.transportPort }}
|
||||
{{- if .Values.service.loadBalancerIP }}
|
||||
loadBalancerIP: {{ .Values.service.loadBalancerIP }}
|
||||
{{- end }}
|
||||
{{- with .Values.service.loadBalancerSourceRanges }}
|
||||
loadBalancerSourceRanges:
|
||||
{{ toYaml . | indent 4 }}
|
||||
{{- end }}
|
||||
{{- if .Values.service.externalTrafficPolicy }}
|
||||
externalTrafficPolicy: {{ .Values.service.externalTrafficPolicy }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
---
|
||||
kind: Service
|
||||
apiVersion: v1
|
||||
metadata:
|
||||
{{- if eq .Values.nodeGroup "master" }}
|
||||
name: {{ template "elasticsearch.masterService" . }}-headless
|
||||
{{- else }}
|
||||
name: {{ template "elasticsearch.uname" . }}-headless
|
||||
{{- end }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
{{- if .Values.service.labelsHeadless }}
|
||||
{{ toYaml .Values.service.labelsHeadless | indent 4 }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
|
||||
spec:
|
||||
clusterIP: None # This is needed for statefulset hostnames like elasticsearch-0 to resolve
|
||||
# Create endpoints also if the related pod isn't ready
|
||||
publishNotReadyAddresses: true
|
||||
selector:
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
ports:
|
||||
- name: {{ .Values.service.httpPortName | default "http" }}
|
||||
port: {{ .Values.httpPort }}
|
||||
- name: {{ .Values.service.transportPortName | default "transport" }}
|
||||
port: {{ .Values.transportPort }}
|
||||
@@ -0,0 +1,16 @@
|
||||
{{- if .Values.rbac.create -}}
|
||||
{{- $fullName := include "elasticsearch.uname" . -}}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: "{{ template "elasticsearch.serviceAccount" . }}"
|
||||
annotations:
|
||||
{{- with .Values.rbac.serviceAccountAnnotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
|
||||
app: {{ $fullName | quote }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,390 @@
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ template "elasticsearch.uname" . }}
|
||||
labels:
|
||||
heritage: {{ .Release.Service | quote }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
{{- range $key, $value := .Values.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
esMajorVersion: "{{ include "elasticsearch.esMajorVersion" . }}"
|
||||
spec:
|
||||
serviceName: {{ template "elasticsearch.uname" . }}-headless
|
||||
selector:
|
||||
matchLabels:
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
replicas: {{ .Values.replicas }}
|
||||
podManagementPolicy: {{ .Values.podManagementPolicy }}
|
||||
updateStrategy:
|
||||
type: {{ .Values.updateStrategy }}
|
||||
{{- if .Values.persistence.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: {{ template "elasticsearch.uname" . }}
|
||||
{{- if .Values.persistence.labels.enabled }}
|
||||
labels:
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
{{- range $key, $value := .Values.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- with .Values.persistence.annotations }}
|
||||
annotations:
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{ toYaml .Values.volumeClaimTemplate | indent 6 }}
|
||||
{{- end }}
|
||||
template:
|
||||
metadata:
|
||||
name: "{{ template "elasticsearch.uname" . }}"
|
||||
labels:
|
||||
release: {{ .Release.Name | quote }}
|
||||
chart: "{{ .Chart.Name }}"
|
||||
app: "{{ template "elasticsearch.uname" . }}"
|
||||
{{- range $key, $value := .Values.labels }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
annotations:
|
||||
{{- range $key, $value := .Values.podAnnotations }}
|
||||
{{ $key }}: {{ $value | quote }}
|
||||
{{- end }}
|
||||
{{/* This forces a restart if the configmap has changed */}}
|
||||
{{- if or .Values.esConfig .Values.esJvmOptions }}
|
||||
configchecksum: {{ include (print .Template.BasePath "/configmap.yaml") . | sha256sum | trunc 63 }}
|
||||
{{- end }}
|
||||
spec:
|
||||
{{- if .Values.schedulerName }}
|
||||
schedulerName: "{{ .Values.schedulerName }}"
|
||||
{{- end }}
|
||||
securityContext:
|
||||
{{ toYaml .Values.podSecurityContext | indent 8 }}
|
||||
{{- if .Values.fsGroup }}
|
||||
fsGroup: {{ .Values.fsGroup }} # Deprecated value, please use .Values.podSecurityContext.fsGroup
|
||||
{{- end }}
|
||||
{{- if or .Values.rbac.create .Values.rbac.serviceAccountName }}
|
||||
serviceAccountName: "{{ template "elasticsearch.serviceAccount" . }}"
|
||||
{{- end }}
|
||||
automountServiceAccountToken: {{ .Values.rbac.automountToken }}
|
||||
{{- 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
|
||||
operator: In
|
||||
values:
|
||||
- "{{ template "elasticsearch.uname" .}}"
|
||||
topologyKey: {{ .Values.antiAffinityTopologyKey }}
|
||||
{{- else if eq .Values.antiAffinity "soft" }}
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 1
|
||||
podAffinityTerm:
|
||||
topologyKey: {{ .Values.antiAffinityTopologyKey }}
|
||||
labelSelector:
|
||||
matchExpressions:
|
||||
- key: app
|
||||
operator: In
|
||||
values:
|
||||
- "{{ template "elasticsearch.uname" . }}"
|
||||
{{- end }}
|
||||
{{- with .Values.nodeAffinity }}
|
||||
nodeAffinity:
|
||||
{{ toYaml . | indent 10 }}
|
||||
{{- end }}
|
||||
terminationGracePeriodSeconds: {{ .Values.terminationGracePeriod }}
|
||||
volumes:
|
||||
{{- range .Values.secretMounts }}
|
||||
- name: {{ .name }}
|
||||
secret:
|
||||
secretName: {{ .secretName }}
|
||||
{{- if .defaultMode }}
|
||||
defaultMode: {{ .defaultMode }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if .Values.esConfig }}
|
||||
- name: esconfig
|
||||
configMap:
|
||||
name: {{ template "elasticsearch.uname" . }}-config
|
||||
{{- end }}
|
||||
{{- if .Values.esJvmOptions }}
|
||||
- name: esjvmoptions
|
||||
configMap:
|
||||
name: {{ template "elasticsearch.uname" . }}-jvm-options
|
||||
{{- 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 8 }}
|
||||
{{- else }}
|
||||
{{ toYaml .Values.extraVolumes | indent 8 }}
|
||||
{{- 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.sysctlInitContainer.enabled) (.Values.keystore) }}
|
||||
initContainers:
|
||||
{{- if .Values.sysctlInitContainer.enabled }}
|
||||
- name: configure-sysctl
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
privileged: true
|
||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||
imagePullPolicy: "{{ .Values.imagePullPolicy }}"
|
||||
command: ["sysctl", "-w", "vm.max_map_count={{ .Values.sysctlVmMaxMapCount}}"]
|
||||
resources:
|
||||
{{ toYaml .Values.initResources | indent 10 }}
|
||||
{{- end }}
|
||||
{{ if .Values.keystore }}
|
||||
- name: keystore
|
||||
securityContext:
|
||||
{{ toYaml .Values.securityContext | indent 10 }}
|
||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||
imagePullPolicy: "{{ .Values.imagePullPolicy }}"
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
set -euo pipefail
|
||||
|
||||
elasticsearch-keystore create
|
||||
|
||||
for i in /tmp/keystoreSecrets/*/*; do
|
||||
key=$(basename $i)
|
||||
echo "Adding file $i to keystore key $key"
|
||||
elasticsearch-keystore add-file "$key" "$i"
|
||||
done
|
||||
|
||||
# Add the bootstrap password since otherwise the Elasticsearch entrypoint tries to do this on startup
|
||||
if [ ! -z ${ELASTIC_PASSWORD+x} ]; then
|
||||
echo 'Adding env $ELASTIC_PASSWORD to keystore as key bootstrap.password'
|
||||
echo "$ELASTIC_PASSWORD" | elasticsearch-keystore add -x bootstrap.password
|
||||
fi
|
||||
|
||||
cp -a /usr/share/elasticsearch/config/elasticsearch.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 "elasticsearch.name" . }}"
|
||||
securityContext:
|
||||
{{ toYaml .Values.securityContext | indent 10 }}
|
||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||
imagePullPolicy: "{{ .Values.imagePullPolicy }}"
|
||||
readinessProbe:
|
||||
exec:
|
||||
command:
|
||||
- bash
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
# If the node is starting up wait for the cluster to be ready (request params: "{{ .Values.clusterHealthCheckParams }}" )
|
||||
# Once it has started only check that the node itself is responding
|
||||
START_FILE=/tmp/.es_start_file
|
||||
|
||||
# Disable nss cache to avoid filling dentry cache when calling curl
|
||||
# This is required with Elasticsearch Docker using nss < 3.52
|
||||
export NSS_SDB_USE_CACHE=no
|
||||
|
||||
http () {
|
||||
local path="${1}"
|
||||
local args="${2}"
|
||||
set -- -XGET -s
|
||||
|
||||
if [ "$args" != "" ]; then
|
||||
set -- "$@" $args
|
||||
fi
|
||||
|
||||
if [ -n "${ELASTIC_PASSWORD}" ]; then
|
||||
set -- "$@" -u "elastic:${ELASTIC_PASSWORD}"
|
||||
fi
|
||||
|
||||
curl --output /dev/null -k "$@" "{{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}${path}"
|
||||
}
|
||||
|
||||
if [ -f "${START_FILE}" ]; then
|
||||
echo 'Elasticsearch is already running, lets check the node is healthy'
|
||||
HTTP_CODE=$(http "/" "-w %{http_code}")
|
||||
RC=$?
|
||||
if [[ ${RC} -ne 0 ]]; then
|
||||
echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}/ failed with RC ${RC}"
|
||||
exit ${RC}
|
||||
fi
|
||||
# ready if HTTP code 200, 503 is tolerable if ES version is 6.x
|
||||
if [[ ${HTTP_CODE} == "200" ]]; then
|
||||
exit 0
|
||||
elif [[ ${HTTP_CODE} == "503" && "{{ include "elasticsearch.esMajorVersion" . }}" == "6" ]]; then
|
||||
exit 0
|
||||
else
|
||||
echo "curl --output /dev/null -k -XGET -s -w '%{http_code}' \${BASIC_AUTH} {{ .Values.protocol }}://127.0.0.1:{{ .Values.httpPort }}/ failed with HTTP code ${HTTP_CODE}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
else
|
||||
echo 'Waiting for elasticsearch cluster to become ready (request params: "{{ .Values.clusterHealthCheckParams }}" )'
|
||||
if http "/_cluster/health?{{ .Values.clusterHealthCheckParams }}" "--fail" ; then
|
||||
touch ${START_FILE}
|
||||
exit 0
|
||||
else
|
||||
echo 'Cluster is not yet ready (request params: "{{ .Values.clusterHealthCheckParams }}" )'
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
{{ toYaml .Values.readinessProbe | indent 10 }}
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: {{ .Values.httpPort }}
|
||||
- name: transport
|
||||
containerPort: {{ .Values.transportPort }}
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 10 }}
|
||||
env:
|
||||
- name: node.name
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
fieldPath: metadata.name
|
||||
{{- if eq .Values.roles.master "true" }}
|
||||
{{- if ge (int (include "elasticsearch.esMajorVersion" .)) 7 }}
|
||||
- name: cluster.initial_master_nodes
|
||||
value: "{{ template "elasticsearch.endpoints" . }}"
|
||||
{{- else }}
|
||||
- name: discovery.zen.minimum_master_nodes
|
||||
value: "{{ .Values.minimumMasterNodes }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if lt (int (include "elasticsearch.esMajorVersion" .)) 7 }}
|
||||
- name: discovery.zen.ping.unicast.hosts
|
||||
value: "{{ template "elasticsearch.masterService" . }}-headless"
|
||||
{{- else }}
|
||||
- name: discovery.seed_hosts
|
||||
value: "{{ template "elasticsearch.masterService" . }}-headless"
|
||||
{{- end }}
|
||||
- name: cluster.name
|
||||
value: "{{ .Values.clusterName }}"
|
||||
- name: network.host
|
||||
value: "{{ .Values.networkHost }}"
|
||||
- name: cluster.deprecation_indexing.enabled
|
||||
value: "{{ .Values.clusterDeprecationIndexing }}"
|
||||
{{- if .Values.esJavaOpts }}
|
||||
- name: ES_JAVA_OPTS
|
||||
value: "{{ .Values.esJavaOpts }}"
|
||||
{{- end }}
|
||||
{{- range $role, $enabled := .Values.roles }}
|
||||
- name: node.{{ $role }}
|
||||
value: "{{ $enabled }}"
|
||||
{{- end }}
|
||||
{{- if .Values.extraEnvs }}
|
||||
{{ toYaml .Values.extraEnvs | indent 10 }}
|
||||
{{- end }}
|
||||
{{- if .Values.envFrom }}
|
||||
envFrom:
|
||||
{{ toYaml .Values.envFrom | indent 10 }}
|
||||
{{- end }}
|
||||
volumeMounts:
|
||||
{{- if .Values.persistence.enabled }}
|
||||
- name: "{{ template "elasticsearch.uname" . }}"
|
||||
mountPath: /usr/share/elasticsearch/data
|
||||
{{- end }}
|
||||
{{ if .Values.keystore }}
|
||||
- name: keystore
|
||||
mountPath: /usr/share/elasticsearch/config/elasticsearch.keystore
|
||||
subPath: elasticsearch.keystore
|
||||
{{ end }}
|
||||
{{- range .Values.secretMounts }}
|
||||
- name: {{ .name }}
|
||||
mountPath: {{ .path }}
|
||||
{{- if .subPath }}
|
||||
subPath: {{ .subPath }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $path, $config := .Values.esConfig }}
|
||||
- name: esconfig
|
||||
mountPath: /usr/share/elasticsearch/config/{{ $path }}
|
||||
subPath: {{ $path }}
|
||||
{{- end -}}
|
||||
{{- range $path, $config := .Values.esJvmOptions }}
|
||||
- name: esjvmoptions
|
||||
mountPath: /usr/share/elasticsearch/config/jvm.options.d/{{ $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 10 }}
|
||||
{{- else }}
|
||||
{{ toYaml .Values.extraVolumeMounts | indent 10 }}
|
||||
{{- 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 }}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
{{- if .Values.tests.enabled -}}
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
{{- if .Values.healthNameOverride }}
|
||||
name: {{ .Values.healthNameOverride | quote }}
|
||||
{{- else }}
|
||||
name: "{{ .Release.Name }}-{{ randAlpha 5 | lower }}-test"
|
||||
{{- end }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
spec:
|
||||
securityContext:
|
||||
{{ toYaml .Values.podSecurityContext | indent 4 }}
|
||||
containers:
|
||||
{{- if .Values.healthNameOverride }}
|
||||
- name: {{ .Values.healthNameOverride | quote }}
|
||||
{{- else }}
|
||||
- name: "{{ .Release.Name }}-{{ randAlpha 5 | lower }}-test"
|
||||
{{- end }}
|
||||
image: "{{ .Values.image }}:{{ .Values.imageTag }}"
|
||||
imagePullPolicy: "{{ .Values.imagePullPolicy }}"
|
||||
command:
|
||||
- "sh"
|
||||
- "-c"
|
||||
- |
|
||||
#!/usr/bin/env bash -e
|
||||
curl -XGET --fail '{{ template "elasticsearch.uname" . }}:{{ .Values.httpPort }}/_cluster/health?{{ .Values.clusterHealthCheckParams }}'
|
||||
{{- if .Values.imagePullSecrets }}
|
||||
imagePullSecrets:
|
||||
{{ toYaml .Values.imagePullSecrets | indent 4 }}
|
||||
{{- end }}
|
||||
restartPolicy: Never
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,355 @@
|
||||
---
|
||||
clusterName: "elasticsearch"
|
||||
nodeGroup: "master"
|
||||
|
||||
# The service that non master groups will try to connect to when joining the cluster
|
||||
# This should be set to clusterName + "-" + nodeGroup for your master group
|
||||
masterService: ""
|
||||
|
||||
# Elasticsearch roles that will be applied to this nodeGroup
|
||||
# These will be set as environment variables. E.g. node.master=true
|
||||
roles:
|
||||
master: "true"
|
||||
ingest: "true"
|
||||
data: "true"
|
||||
remote_cluster_client: "true"
|
||||
ml: "true"
|
||||
|
||||
replicas: 3
|
||||
minimumMasterNodes: 2
|
||||
|
||||
esMajorVersion: ""
|
||||
|
||||
clusterDeprecationIndexing: "false"
|
||||
|
||||
# Allows you to add any config files in /usr/share/elasticsearch/config/
|
||||
# such as elasticsearch.yml and log4j2.properties
|
||||
esConfig: {}
|
||||
# elasticsearch.yml: |
|
||||
# key:
|
||||
# nestedkey: value
|
||||
# log4j2.properties: |
|
||||
# key = value
|
||||
|
||||
esJvmOptions: {}
|
||||
# processors.options: |
|
||||
# -XX:ActiveProcessorCount=3
|
||||
|
||||
# Extra environment variables to append to this nodeGroup
|
||||
# This will be appended to the current 'env:' key. You can use any of the kubernetes env
|
||||
# syntax here
|
||||
extraEnvs: []
|
||||
# - name: MY_ENVIRONMENT_VAR
|
||||
# value: the_value_goes_here
|
||||
|
||||
# Allows you to load environment variables from kubernetes secret or config map
|
||||
envFrom: []
|
||||
# - secretRef:
|
||||
# name: env-secret
|
||||
# - configMapRef:
|
||||
# name: config-map
|
||||
|
||||
# A list of secrets and their paths to mount inside the pod
|
||||
# This is useful for mounting certificates for security and for mounting
|
||||
# the X-Pack license
|
||||
secretMounts: []
|
||||
# - name: elastic-certificates
|
||||
# secretName: elastic-certificates
|
||||
# path: /usr/share/elasticsearch/config/certs
|
||||
# defaultMode: 0755
|
||||
|
||||
hostAliases: []
|
||||
#- ip: "127.0.0.1"
|
||||
# hostnames:
|
||||
# - "foo.local"
|
||||
# - "bar.local"
|
||||
|
||||
image: "docker.elastic.co/elasticsearch/elasticsearch"
|
||||
imageTag: "7.17.3"
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
|
||||
podAnnotations:
|
||||
{}
|
||||
# iam.amazonaws.com/role: es-cluster
|
||||
|
||||
# additionals labels
|
||||
labels: {}
|
||||
|
||||
esJavaOpts: "" # example: "-Xmx1g -Xms1g"
|
||||
|
||||
resources:
|
||||
requests:
|
||||
cpu: "1000m"
|
||||
memory: "2Gi"
|
||||
limits:
|
||||
cpu: "1000m"
|
||||
memory: "2Gi"
|
||||
|
||||
initResources:
|
||||
{}
|
||||
# limits:
|
||||
# cpu: "25m"
|
||||
# # memory: "128Mi"
|
||||
# requests:
|
||||
# cpu: "25m"
|
||||
# memory: "128Mi"
|
||||
|
||||
networkHost: "0.0.0.0"
|
||||
|
||||
volumeClaimTemplate:
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources:
|
||||
requests:
|
||||
storage: 30Gi
|
||||
|
||||
rbac:
|
||||
create: false
|
||||
serviceAccountAnnotations: {}
|
||||
serviceAccountName: ""
|
||||
automountToken: true
|
||||
|
||||
podSecurityPolicy:
|
||||
create: false
|
||||
name: ""
|
||||
spec:
|
||||
privileged: true
|
||||
fsGroup:
|
||||
rule: RunAsAny
|
||||
runAsUser:
|
||||
rule: RunAsAny
|
||||
seLinux:
|
||||
rule: RunAsAny
|
||||
supplementalGroups:
|
||||
rule: RunAsAny
|
||||
volumes:
|
||||
- secret
|
||||
- configMap
|
||||
- persistentVolumeClaim
|
||||
- emptyDir
|
||||
|
||||
persistence:
|
||||
enabled: true
|
||||
labels:
|
||||
# Add default labels for the volumeClaimTemplate of the StatefulSet
|
||||
enabled: false
|
||||
annotations: {}
|
||||
|
||||
extraVolumes:
|
||||
[]
|
||||
# - name: extras
|
||||
# emptyDir: {}
|
||||
|
||||
extraVolumeMounts:
|
||||
[]
|
||||
# - name: extras
|
||||
# mountPath: /usr/share/extras
|
||||
# readOnly: true
|
||||
|
||||
extraContainers:
|
||||
[]
|
||||
# - name: do-something
|
||||
# image: busybox
|
||||
# command: ['do', 'something']
|
||||
|
||||
extraInitContainers:
|
||||
[]
|
||||
# - name: do-something
|
||||
# image: busybox
|
||||
# command: ['do', 'something']
|
||||
|
||||
# This is the PriorityClass settings as defined in
|
||||
# https://kubernetes.io/docs/concepts/configuration/pod-priority-preemption/#priorityclass
|
||||
priorityClassName: ""
|
||||
|
||||
# By default this will make sure two pods don't end up on the same node
|
||||
# Changing this to a region would allow you to spread pods across regions
|
||||
antiAffinityTopologyKey: "kubernetes.io/hostname"
|
||||
|
||||
# Hard means that by default pods will only be scheduled if there are enough nodes for them
|
||||
# and that they will never end up on the same node. Setting this to soft will do this "best effort"
|
||||
antiAffinity: "hard"
|
||||
|
||||
# This is the node affinity settings as defined in
|
||||
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#node-affinity-beta-feature
|
||||
nodeAffinity: {}
|
||||
|
||||
# The default is to deploy all pods serially. By setting this to parallel all pods are started at
|
||||
# the same time when bootstrapping the cluster
|
||||
podManagementPolicy: "Parallel"
|
||||
|
||||
# The environment variables injected by service links are not used, but can lead to slow Elasticsearch boot times when
|
||||
# there are many services in the current namespace.
|
||||
# If you experience slow pod startups you probably want to set this to `false`.
|
||||
enableServiceLinks: true
|
||||
|
||||
protocol: http
|
||||
httpPort: 9200
|
||||
transportPort: 9300
|
||||
|
||||
service:
|
||||
enabled: true
|
||||
labels: {}
|
||||
labelsHeadless: {}
|
||||
type: ClusterIP
|
||||
# Consider that all endpoints are considered "ready" even if the Pods themselves are not
|
||||
# https://kubernetes.io/docs/reference/kubernetes-api/service-resources/service-v1/#ServiceSpec
|
||||
publishNotReadyAddresses: false
|
||||
nodePort: ""
|
||||
annotations: {}
|
||||
httpPortName: http
|
||||
transportPortName: transport
|
||||
loadBalancerIP: ""
|
||||
loadBalancerSourceRanges: []
|
||||
externalTrafficPolicy: ""
|
||||
|
||||
updateStrategy: RollingUpdate
|
||||
|
||||
# This is the max unavailable setting for the pod disruption budget
|
||||
# The default value of 1 will make sure that kubernetes won't allow more than 1
|
||||
# of your pods to be unavailable during maintenance
|
||||
maxUnavailable: 1
|
||||
|
||||
podSecurityContext:
|
||||
fsGroup: 1000
|
||||
runAsUser: 1000
|
||||
|
||||
securityContext:
|
||||
capabilities:
|
||||
drop:
|
||||
- ALL
|
||||
# readOnlyRootFilesystem: true
|
||||
runAsNonRoot: true
|
||||
runAsUser: 1000
|
||||
|
||||
# How long to wait for elasticsearch to stop gracefully
|
||||
terminationGracePeriod: 120
|
||||
|
||||
sysctlVmMaxMapCount: 262144
|
||||
|
||||
readinessProbe:
|
||||
failureThreshold: 3
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
successThreshold: 3
|
||||
timeoutSeconds: 5
|
||||
|
||||
# https://www.elastic.co/guide/en/elasticsearch/reference/7.17/cluster-health.html#request-params wait_for_status
|
||||
clusterHealthCheckParams: "wait_for_status=green&timeout=1s"
|
||||
|
||||
## Use an alternate scheduler.
|
||||
## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/
|
||||
##
|
||||
schedulerName: ""
|
||||
|
||||
imagePullSecrets: []
|
||||
nodeSelector: {}
|
||||
tolerations: []
|
||||
|
||||
# Enabling this will publicly expose your Elasticsearch instance.
|
||||
# Only enable this if you have security enabled on your cluster
|
||||
ingress:
|
||||
enabled: false
|
||||
annotations: {}
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
className: "nginx"
|
||||
pathtype: ImplementationSpecific
|
||||
hosts:
|
||||
- host: chart-example.local
|
||||
paths:
|
||||
- path: /
|
||||
tls: []
|
||||
# - secretName: chart-example-tls
|
||||
# hosts:
|
||||
# - chart-example.local
|
||||
|
||||
nameOverride: ""
|
||||
fullnameOverride: ""
|
||||
healthNameOverride: ""
|
||||
|
||||
lifecycle:
|
||||
{}
|
||||
# preStop:
|
||||
# exec:
|
||||
# command: ["/bin/sh", "-c", "echo Hello from the postStart handler > /usr/share/message"]
|
||||
# postStart:
|
||||
# exec:
|
||||
# command:
|
||||
# - bash
|
||||
# - -c
|
||||
# - |
|
||||
# #!/bin/bash
|
||||
# # Add a template to adjust number of shards/replicas
|
||||
# TEMPLATE_NAME=my_template
|
||||
# INDEX_PATTERN="logstash-*"
|
||||
# SHARD_COUNT=8
|
||||
# REPLICA_COUNT=1
|
||||
# ES_URL=http://localhost:9200
|
||||
# while [[ "$(curl -s -o /dev/null -w '%{http_code}\n' $ES_URL)" != "200" ]]; do sleep 1; done
|
||||
# curl -XPUT "$ES_URL/_template/$TEMPLATE_NAME" -H 'Content-Type: application/json' -d'{"index_patterns":['\""$INDEX_PATTERN"\"'],"settings":{"number_of_shards":'$SHARD_COUNT',"number_of_replicas":'$REPLICA_COUNT'}}'
|
||||
|
||||
sysctlInitContainer:
|
||||
enabled: true
|
||||
|
||||
keystore: []
|
||||
|
||||
networkPolicy:
|
||||
## Enable creation of NetworkPolicy resources. Only Ingress traffic is filtered for now.
|
||||
## In order for a Pod to access Elasticsearch, it needs to have the following label:
|
||||
## {{ template "uname" . }}-client: "true"
|
||||
## Example for default configuration to access HTTP port:
|
||||
## elasticsearch-master-http-client: "true"
|
||||
## Example for default configuration to access transport port:
|
||||
## elasticsearch-master-transport-client: "true"
|
||||
|
||||
http:
|
||||
enabled: false
|
||||
## if explicitNamespacesSelector is not set or set to {}, only client Pods being in the networkPolicy's namespace
|
||||
## and matching all criteria can reach the DB.
|
||||
## But sometimes, we want the Pods to be accessible to clients from other namespaces, in this case, we can use this
|
||||
## parameter to select these namespaces
|
||||
##
|
||||
# explicitNamespacesSelector:
|
||||
# # Accept from namespaces with all those different rules (only from whitelisted Pods)
|
||||
# matchLabels:
|
||||
# role: frontend
|
||||
# matchExpressions:
|
||||
# - {key: role, operator: In, values: [frontend]}
|
||||
## Additional NetworkPolicy Ingress "from" rules to set. Note that all rules are OR-ed.
|
||||
##
|
||||
# additionalRules:
|
||||
# - podSelector:
|
||||
# matchLabels:
|
||||
# role: frontend
|
||||
# - podSelector:
|
||||
# matchExpressions:
|
||||
# - key: role
|
||||
# operator: In
|
||||
# values:
|
||||
# - frontend
|
||||
|
||||
transport:
|
||||
## Note that all Elasticsearch Pods can talk to themselves using transport port even if enabled.
|
||||
enabled: false
|
||||
# explicitNamespacesSelector:
|
||||
# matchLabels:
|
||||
# role: frontend
|
||||
# matchExpressions:
|
||||
# - {key: role, operator: In, values: [frontend]}
|
||||
# additionalRules:
|
||||
# - podSelector:
|
||||
# matchLabels:
|
||||
# role: frontend
|
||||
# - podSelector:
|
||||
# matchExpressions:
|
||||
# - key: role
|
||||
# operator: In
|
||||
# values:
|
||||
# - frontend
|
||||
|
||||
tests:
|
||||
enabled: true
|
||||
|
||||
# Deprecated
|
||||
# please use the above podSecurityContext.fsGroup instead
|
||||
fsGroup: ""
|
||||
@@ -0,0 +1,23 @@
|
||||
# Patterns to ignore when building packages.
|
||||
# This supports shell glob matching, relative path matching, and
|
||||
# negation (prefixed with !). Only one pattern per line.
|
||||
.DS_Store
|
||||
# Common VCS dirs
|
||||
.git/
|
||||
.gitignore
|
||||
.bzr/
|
||||
.bzrignore
|
||||
.hg/
|
||||
.hgignore
|
||||
.svn/
|
||||
# Common backup files
|
||||
*.swp
|
||||
*.bak
|
||||
*.tmp
|
||||
*~
|
||||
# Various IDEs
|
||||
.vscode
|
||||
.project
|
||||
.idea/
|
||||
*.tmproj
|
||||
OWNERS
|
||||
@@ -0,0 +1,33 @@
|
||||
annotations:
|
||||
artifacthub.io/license: Apache-2.0
|
||||
artifacthub.io/links: |
|
||||
- name: Chart Source
|
||||
url: https://github.com/grafana/helm-charts
|
||||
- name: Upstream Project
|
||||
url: https://github.com/grafana/grafana
|
||||
apiVersion: v2
|
||||
appVersion: 11.0.0
|
||||
description: The leading tool for querying and visualizing time series and metrics.
|
||||
home: https://grafana.com
|
||||
icon: https://artifacthub.io/image/b4fed1a7-6c8f-4945-b99d-096efa3e4116
|
||||
keywords:
|
||||
- monitoring
|
||||
- metric
|
||||
kubeVersion: ^1.8.0-0
|
||||
maintainers:
|
||||
- email: zanhsieh@gmail.com
|
||||
name: zanhsieh
|
||||
- email: rluckie@cisco.com
|
||||
name: rtluckie
|
||||
- email: maor.friedman@redhat.com
|
||||
name: maorfr
|
||||
- email: miroslav.hadzhiev@gmail.com
|
||||
name: Xtigyro
|
||||
- email: mail@torstenwalter.de
|
||||
name: torstenwalter
|
||||
name: grafana
|
||||
sources:
|
||||
- https://github.com/grafana/grafana
|
||||
- https://github.com/grafana/helm-charts
|
||||
type: application
|
||||
version: 8.0.2
|
||||
@@ -0,0 +1,771 @@
|
||||
# Grafana Helm Chart
|
||||
|
||||
* Installs the web dashboarding system [Grafana](http://grafana.org/)
|
||||
|
||||
## Get Repo Info
|
||||
|
||||
```console
|
||||
helm repo add grafana https://grafana.github.io/helm-charts
|
||||
helm repo update
|
||||
```
|
||||
|
||||
_See [helm repo](https://helm.sh/docs/helm/helm_repo/) for command documentation._
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `my-release`:
|
||||
|
||||
```console
|
||||
helm install my-release grafana/grafana
|
||||
```
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
To uninstall/delete the my-release deployment:
|
||||
|
||||
```console
|
||||
helm delete my-release
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and deletes the release.
|
||||
|
||||
## Upgrading an existing Release to a new major version
|
||||
|
||||
A major chart version change (like v1.2.3 -> v2.0.0) indicates that there is an
|
||||
incompatible breaking change needing manual actions.
|
||||
|
||||
### To 4.0.0 (And 3.12.1)
|
||||
|
||||
This version requires Helm >= 2.12.0.
|
||||
|
||||
### To 5.0.0
|
||||
|
||||
You have to add --force to your helm upgrade command as the labels of the chart have changed.
|
||||
|
||||
### To 6.0.0
|
||||
|
||||
This version requires Helm >= 3.1.0.
|
||||
|
||||
### To 7.0.0
|
||||
|
||||
For consistency with other Helm charts, the `global.image.registry` parameter was renamed
|
||||
to `global.imageRegistry`. If you were not previously setting `global.image.registry`, no action
|
||||
is required on upgrade. If you were previously setting `global.image.registry`, you will
|
||||
need to instead set `global.imageRegistry`.
|
||||
|
||||
## Configuration
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-------------------------------------------|-----------------------------------------------|---------------------------------------------------------|
|
||||
| `replicas` | Number of nodes | `1` |
|
||||
| `podDisruptionBudget.minAvailable` | Pod disruption minimum available | `nil` |
|
||||
| `podDisruptionBudget.maxUnavailable` | Pod disruption maximum unavailable | `nil` |
|
||||
| `podDisruptionBudget.apiVersion` | Pod disruption apiVersion | `nil` |
|
||||
| `deploymentStrategy` | Deployment strategy | `{ "type": "RollingUpdate" }` |
|
||||
| `livenessProbe` | Liveness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } "initialDelaySeconds": 60, "timeoutSeconds": 30, "failureThreshold": 10 }` |
|
||||
| `readinessProbe` | Readiness Probe settings | `{ "httpGet": { "path": "/api/health", "port": 3000 } }`|
|
||||
| `securityContext` | Deployment securityContext | `{"runAsUser": 472, "runAsGroup": 472, "fsGroup": 472}` |
|
||||
| `priorityClassName` | Name of Priority Class to assign pods | `nil` |
|
||||
| `image.registry` | Image registry | `docker.io` |
|
||||
| `image.repository` | Image repository | `grafana/grafana` |
|
||||
| `image.tag` | Overrides the Grafana image tag whose default is the chart appVersion (`Must be >= 5.0.0`) | `` |
|
||||
| `image.sha` | Image sha (optional) | `` |
|
||||
| `image.pullPolicy` | Image pull policy | `IfNotPresent` |
|
||||
| `image.pullSecrets` | Image pull secrets (can be templated) | `[]` |
|
||||
| `service.enabled` | Enable grafana service | `true` |
|
||||
| `service.type` | Kubernetes service type | `ClusterIP` |
|
||||
| `service.port` | Kubernetes port where service is exposed | `80` |
|
||||
| `service.portName` | Name of the port on the service | `service` |
|
||||
| `service.appProtocol` | Adds the appProtocol field to the service | `` |
|
||||
| `service.targetPort` | Internal service is port | `3000` |
|
||||
| `service.nodePort` | Kubernetes service nodePort | `nil` |
|
||||
| `service.annotations` | Service annotations (can be templated) | `{}` |
|
||||
| `service.labels` | Custom labels | `{}` |
|
||||
| `service.clusterIP` | internal cluster service IP | `nil` |
|
||||
| `service.loadBalancerIP` | IP address to assign to load balancer (if supported) | `nil` |
|
||||
| `service.loadBalancerSourceRanges` | list of IP CIDRs allowed access to lb (if supported) | `[]` |
|
||||
| `service.externalIPs` | service external IP addresses | `[]` |
|
||||
| `service.externalTrafficPolicy` | change the default externalTrafficPolicy | `nil` |
|
||||
| `headlessService` | Create a headless service | `false` |
|
||||
| `extraExposePorts` | Additional service ports for sidecar containers| `[]` |
|
||||
| `hostAliases` | adds rules to the pod's /etc/hosts | `[]` |
|
||||
| `ingress.enabled` | Enables Ingress | `false` |
|
||||
| `ingress.annotations` | Ingress annotations (values are templated) | `{}` |
|
||||
| `ingress.labels` | Custom labels | `{}` |
|
||||
| `ingress.path` | Ingress accepted path | `/` |
|
||||
| `ingress.pathType` | Ingress type of path | `Prefix` |
|
||||
| `ingress.hosts` | Ingress accepted hostnames | `["chart-example.local"]` |
|
||||
| `ingress.extraPaths` | Ingress extra paths to prepend to every host configuration. Useful when configuring [custom actions with AWS ALB Ingress Controller](https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.6/guide/ingress/annotations/#actions). Requires `ingress.hosts` to have one or more host entries. | `[]` |
|
||||
| `ingress.tls` | Ingress TLS configuration | `[]` |
|
||||
| `ingress.ingressClassName` | Ingress Class Name. MAY be required for Kubernetes versions >= 1.18 | `""` |
|
||||
| `resources` | CPU/Memory resource requests/limits | `{}` |
|
||||
| `nodeSelector` | Node labels for pod assignment | `{}` |
|
||||
| `tolerations` | Toleration labels for pod assignment | `[]` |
|
||||
| `affinity` | Affinity settings for pod assignment | `{}` |
|
||||
| `extraInitContainers` | Init containers to add to the grafana pod | `{}` |
|
||||
| `extraContainers` | Sidecar containers to add to the grafana pod | `""` |
|
||||
| `extraContainerVolumes` | Volumes that can be mounted in sidecar containers | `[]` |
|
||||
| `extraLabels` | Custom labels for all manifests | `{}` |
|
||||
| `schedulerName` | Name of the k8s scheduler (other than default) | `nil` |
|
||||
| `persistence.enabled` | Use persistent volume to store data | `false` |
|
||||
| `persistence.type` | Type of persistence (`pvc` or `statefulset`) | `pvc` |
|
||||
| `persistence.size` | Size of persistent volume claim | `10Gi` |
|
||||
| `persistence.existingClaim` | Use an existing PVC to persist data (can be templated) | `nil` |
|
||||
| `persistence.storageClassName` | Type of persistent volume claim | `nil` |
|
||||
| `persistence.accessModes` | Persistence access modes | `[ReadWriteOnce]` |
|
||||
| `persistence.annotations` | PersistentVolumeClaim annotations | `{}` |
|
||||
| `persistence.finalizers` | PersistentVolumeClaim finalizers | `[ "kubernetes.io/pvc-protection" ]` |
|
||||
| `persistence.extraPvcLabels` | Extra labels to apply to a PVC. | `{}` |
|
||||
| `persistence.subPath` | Mount a sub dir of the persistent volume (can be templated) | `nil` |
|
||||
| `persistence.inMemory.enabled` | If persistence is not enabled, whether to mount the local storage in-memory to improve performance | `false` |
|
||||
| `persistence.inMemory.sizeLimit` | SizeLimit for the in-memory local storage | `nil` |
|
||||
| `initChownData.enabled` | If false, don't reset data ownership at startup | true |
|
||||
| `initChownData.image.registry` | init-chown-data container image registry | `docker.io` |
|
||||
| `initChownData.image.repository` | init-chown-data container image repository | `busybox` |
|
||||
| `initChownData.image.tag` | init-chown-data container image tag | `1.31.1` |
|
||||
| `initChownData.image.sha` | init-chown-data container image sha (optional)| `""` |
|
||||
| `initChownData.image.pullPolicy` | init-chown-data container image pull policy | `IfNotPresent` |
|
||||
| `initChownData.resources` | init-chown-data pod resource requests & limits | `{}` |
|
||||
| `schedulerName` | Alternate scheduler name | `nil` |
|
||||
| `env` | Extra environment variables passed to pods | `{}` |
|
||||
| `envValueFrom` | Environment variables from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` |
|
||||
| `envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` |
|
||||
| `envFromSecrets` | List of Kubernetes secrets (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` |
|
||||
| `envFromConfigMaps` | List of Kubernetes ConfigMaps (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `[]` |
|
||||
| `envRenderSecret` | Sensible environment variables passed to pods and stored as secret. (passed through [tpl](https://helm.sh/docs/howto/charts_tips_and_tricks/#using-the-tpl-function)) | `{}` |
|
||||
| `enableServiceLinks` | Inject Kubernetes services as environment variables. | `true` |
|
||||
| `extraSecretMounts` | Additional grafana server secret mounts | `[]` |
|
||||
| `extraVolumeMounts` | Additional grafana server volume mounts | `[]` |
|
||||
| `extraVolumes` | Additional Grafana server volumes | `[]` |
|
||||
| `automountServiceAccountToken` | Mounted the service account token on the grafana pod. Mandatory, if sidecars are enabled | `true` |
|
||||
| `createConfigmap` | Enable creating the grafana configmap | `true` |
|
||||
| `extraConfigmapMounts` | Additional grafana server configMap volume mounts (values are templated) | `[]` |
|
||||
| `extraEmptyDirMounts` | Additional grafana server emptyDir volume mounts | `[]` |
|
||||
| `plugins` | Plugins to be loaded along with Grafana | `[]` |
|
||||
| `datasources` | Configure grafana datasources (passed through tpl) | `{}` |
|
||||
| `alerting` | Configure grafana alerting (passed through tpl) | `{}` |
|
||||
| `notifiers` | Configure grafana notifiers | `{}` |
|
||||
| `dashboardProviders` | Configure grafana dashboard providers | `{}` |
|
||||
| `dashboards` | Dashboards to import | `{}` |
|
||||
| `dashboardsConfigMaps` | ConfigMaps reference that contains dashboards | `{}` |
|
||||
| `grafana.ini` | Grafana's primary configuration | `{}` |
|
||||
| `global.imageRegistry` | Global image pull registry for all images. | `null` |
|
||||
| `global.imagePullSecrets` | Global image pull secrets (can be templated). Allows either an array of {name: pullSecret} maps (k8s-style), or an array of strings (more common helm-style). | `[]` |
|
||||
| `ldap.enabled` | Enable LDAP authentication | `false` |
|
||||
| `ldap.existingSecret` | The name of an existing secret containing the `ldap.toml` file, this must have the key `ldap-toml`. | `""` |
|
||||
| `ldap.config` | Grafana's LDAP configuration | `""` |
|
||||
| `annotations` | Deployment annotations | `{}` |
|
||||
| `labels` | Deployment labels | `{}` |
|
||||
| `podAnnotations` | Pod annotations | `{}` |
|
||||
| `podLabels` | Pod labels | `{}` |
|
||||
| `podPortName` | Name of the grafana port on the pod | `grafana` |
|
||||
| `lifecycleHooks` | Lifecycle hooks for podStart and preStop [Example](https://kubernetes.io/docs/tasks/configure-pod-container/attach-handler-lifecycle-event/#define-poststart-and-prestop-handlers) | `{}` |
|
||||
| `sidecar.image.registry` | Sidecar image registry | `quay.io` |
|
||||
| `sidecar.image.repository` | Sidecar image repository | `kiwigrid/k8s-sidecar` |
|
||||
| `sidecar.image.tag` | Sidecar image tag | `1.26.0` |
|
||||
| `sidecar.image.sha` | Sidecar image sha (optional) | `""` |
|
||||
| `sidecar.imagePullPolicy` | Sidecar image pull policy | `IfNotPresent` |
|
||||
| `sidecar.resources` | Sidecar resources | `{}` |
|
||||
| `sidecar.securityContext` | Sidecar securityContext | `{}` |
|
||||
| `sidecar.enableUniqueFilenames` | Sets the kiwigrid/k8s-sidecar UNIQUE_FILENAMES environment variable. If set to `true` the sidecar will create unique filenames where duplicate data keys exist between ConfigMaps and/or Secrets within the same or multiple Namespaces. | `false` |
|
||||
| `sidecar.alerts.enabled` | Enables the cluster wide search for alerts and adds/updates/deletes them in grafana |`false` |
|
||||
| `sidecar.alerts.label` | Label that config maps with alerts should have to be added | `grafana_alert` |
|
||||
| `sidecar.alerts.labelValue` | Label value that config maps with alerts should have to be added | `""` |
|
||||
| `sidecar.alerts.searchNamespace` | Namespaces list. If specified, the sidecar will search for alerts config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` |
|
||||
| `sidecar.alerts.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` |
|
||||
| `sidecar.alerts.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` |
|
||||
| `sidecar.alerts.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/alerting/reload"` |
|
||||
| `sidecar.alerts.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` |
|
||||
| `sidecar.alerts.initAlerts` | Set to true to deploy the alerts sidecar as an initContainer. This is needed if skipReload is true, to load any alerts defined at startup time. | `false` |
|
||||
| `sidecar.alerts.extraMounts` | Additional alerts sidecar volume mounts. | `[]` |
|
||||
| `sidecar.dashboards.enabled` | Enables the cluster wide search for dashboards and adds/updates/deletes them in grafana | `false` |
|
||||
| `sidecar.dashboards.SCProvider` | Enables creation of sidecar provider | `true` |
|
||||
| `sidecar.dashboards.provider.name` | Unique name of the grafana provider | `sidecarProvider` |
|
||||
| `sidecar.dashboards.provider.orgid` | Id of the organisation, to which the dashboards should be added | `1` |
|
||||
| `sidecar.dashboards.provider.folder` | Logical folder in which grafana groups dashboards | `""` |
|
||||
| `sidecar.dashboards.provider.folderUid` | Allows you to specify the static UID for the logical folder above | `""` |
|
||||
| `sidecar.dashboards.provider.disableDelete` | Activate to avoid the deletion of imported dashboards | `false` |
|
||||
| `sidecar.dashboards.provider.allowUiUpdates` | Allow updating provisioned dashboards from the UI | `false` |
|
||||
| `sidecar.dashboards.provider.type` | Provider type | `file` |
|
||||
| `sidecar.dashboards.provider.foldersFromFilesStructure` | Allow Grafana to replicate dashboard structure from filesystem. | `false` |
|
||||
| `sidecar.dashboards.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` |
|
||||
| `sidecar.skipTlsVerify` | Set to true to skip tls verification for kube api calls | `nil` |
|
||||
| `sidecar.dashboards.label` | Label that config maps with dashboards should have to be added | `grafana_dashboard` |
|
||||
| `sidecar.dashboards.labelValue` | Label value that config maps with dashboards should have to be added | `""` |
|
||||
| `sidecar.dashboards.folder` | Folder in the pod that should hold the collected dashboards (unless `sidecar.dashboards.defaultFolderName` is set). This path will be mounted. | `/tmp/dashboards` |
|
||||
| `sidecar.dashboards.folderAnnotation` | The annotation the sidecar will look for in configmaps to override the destination folder for files | `nil` |
|
||||
| `sidecar.dashboards.defaultFolderName` | The default folder name, it will create a subfolder under the `sidecar.dashboards.folder` and put dashboards in there instead | `nil` |
|
||||
| `sidecar.dashboards.searchNamespace` | Namespaces list. If specified, the sidecar will search for dashboards config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` |
|
||||
| `sidecar.dashboards.script` | Absolute path to shell script to execute after a configmap got reloaded. | `nil` |
|
||||
| `sidecar.dashboards.reloadURL` | Full url of dashboards configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/dashboards/reload"` |
|
||||
| `sidecar.dashboards.skipReload` | Enabling this omits defining the REQ_USERNAME, REQ_PASSWORD, REQ_URL and REQ_METHOD environment variables | `false` |
|
||||
| `sidecar.dashboards.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` |
|
||||
| `sidecar.dashboards.extraMounts` | Additional dashboard sidecar volume mounts. | `[]` |
|
||||
| `sidecar.datasources.enabled` | Enables the cluster wide search for datasources and adds/updates/deletes them in grafana |`false` |
|
||||
| `sidecar.datasources.label` | Label that config maps with datasources should have to be added | `grafana_datasource` |
|
||||
| `sidecar.datasources.labelValue` | Label value that config maps with datasources should have to be added | `""` |
|
||||
| `sidecar.datasources.searchNamespace` | Namespaces list. If specified, the sidecar will search for datasources config-maps inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` |
|
||||
| `sidecar.datasources.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` |
|
||||
| `sidecar.datasources.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` |
|
||||
| `sidecar.datasources.reloadURL` | Full url of datasource configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/datasources/reload"` |
|
||||
| `sidecar.datasources.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` |
|
||||
| `sidecar.datasources.initDatasources` | Set to true to deploy the datasource sidecar as an initContainer in addition to a container. This is needed if skipReload is true, to load any datasources defined at startup time. | `false` |
|
||||
| `sidecar.notifiers.enabled` | Enables the cluster wide search for notifiers and adds/updates/deletes them in grafana | `false` |
|
||||
| `sidecar.notifiers.label` | Label that config maps with notifiers should have to be added | `grafana_notifier` |
|
||||
| `sidecar.notifiers.labelValue` | Label value that config maps with notifiers should have to be added | `""` |
|
||||
| `sidecar.notifiers.searchNamespace` | Namespaces list. If specified, the sidecar will search for notifiers config-maps (or secrets) inside these namespaces. Otherwise the namespace in which the sidecar is running will be used. It's also possible to specify ALL to search in all namespaces. | `nil` |
|
||||
| `sidecar.notifiers.watchMethod` | Method to use to detect ConfigMap changes. With WATCH the sidecar will do a WATCH requests, with SLEEP it will list all ConfigMaps, then sleep for 60 seconds. | `WATCH` |
|
||||
| `sidecar.notifiers.resource` | Should the sidecar looks into secrets, configmaps or both. | `both` |
|
||||
| `sidecar.notifiers.reloadURL` | Full url of notifier configuration reload API endpoint, to invoke after a config-map change | `"http://localhost:3000/api/admin/provisioning/notifications/reload"` |
|
||||
| `sidecar.notifiers.skipReload` | Enabling this omits defining the REQ_URL and REQ_METHOD environment variables | `false` |
|
||||
| `sidecar.notifiers.initNotifiers` | Set to true to deploy the notifier sidecar as an initContainer in addition to a container. This is needed if skipReload is true, to load any notifiers defined at startup time. | `false` |
|
||||
| `smtp.existingSecret` | The name of an existing secret containing the SMTP credentials. | `""` |
|
||||
| `smtp.userKey` | The key in the existing SMTP secret containing the username. | `"user"` |
|
||||
| `smtp.passwordKey` | The key in the existing SMTP secret containing the password. | `"password"` |
|
||||
| `admin.existingSecret` | The name of an existing secret containing the admin credentials (can be templated). | `""` |
|
||||
| `admin.userKey` | The key in the existing admin secret containing the username. | `"admin-user"` |
|
||||
| `admin.passwordKey` | The key in the existing admin secret containing the password. | `"admin-password"` |
|
||||
| `serviceAccount.automountServiceAccountToken` | Automount the service account token on all pods where is service account is used | `false` |
|
||||
| `serviceAccount.annotations` | ServiceAccount annotations | |
|
||||
| `serviceAccount.create` | Create service account | `true` |
|
||||
| `serviceAccount.labels` | ServiceAccount labels | `{}` |
|
||||
| `serviceAccount.name` | Service account name to use, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `` |
|
||||
| `serviceAccount.nameTest` | Service account name to use for test, when empty will be set to created account if `serviceAccount.create` is set else to `default` | `nil` |
|
||||
| `rbac.create` | Create and use RBAC resources | `true` |
|
||||
| `rbac.namespaced` | Creates Role and Rolebinding instead of the default ClusterRole and ClusteRoleBindings for the grafana instance | `false` |
|
||||
| `rbac.useExistingRole` | Set to a rolename to use existing role - skipping role creating - but still doing serviceaccount and rolebinding to the rolename set here. | `nil` |
|
||||
| `rbac.pspEnabled` | Create PodSecurityPolicy (with `rbac.create`, grant roles permissions as well) | `false` |
|
||||
| `rbac.pspUseAppArmor` | Enforce AppArmor in created PodSecurityPolicy (requires `rbac.pspEnabled`) | `false` |
|
||||
| `rbac.extraRoleRules` | Additional rules to add to the Role | [] |
|
||||
| `rbac.extraClusterRoleRules` | Additional rules to add to the ClusterRole | [] |
|
||||
| `command` | Define command to be executed by grafana container at startup | `nil` |
|
||||
| `args` | Define additional args if command is used | `nil` |
|
||||
| `testFramework.enabled` | Whether to create test-related resources | `true` |
|
||||
| `testFramework.image.registry` | `test-framework` image registry. | `docker.io` |
|
||||
| `testFramework.image.repository` | `test-framework` image repository. | `bats/bats` |
|
||||
| `testFramework.image.tag` | `test-framework` image tag. | `v1.4.1` |
|
||||
| `testFramework.imagePullPolicy` | `test-framework` image pull policy. | `IfNotPresent` |
|
||||
| `testFramework.securityContext` | `test-framework` securityContext | `{}` |
|
||||
| `downloadDashboards.env` | Environment variables to be passed to the `download-dashboards` container | `{}` |
|
||||
| `downloadDashboards.envFromSecret` | Name of a Kubernetes secret (must be manually created in the same namespace) containing values to be added to the environment. Can be templated | `""` |
|
||||
| `downloadDashboards.resources` | Resources of `download-dashboards` container | `{}` |
|
||||
| `downloadDashboardsImage.registry` | Curl docker image registry | `docker.io` |
|
||||
| `downloadDashboardsImage.repository` | Curl docker image repository | `curlimages/curl` |
|
||||
| `downloadDashboardsImage.tag` | Curl docker image tag | `7.73.0` |
|
||||
| `downloadDashboardsImage.sha` | Curl docker image sha (optional) | `""` |
|
||||
| `downloadDashboardsImage.pullPolicy` | Curl docker image pull policy | `IfNotPresent` |
|
||||
| `namespaceOverride` | Override the deployment namespace | `""` (`Release.Namespace`) |
|
||||
| `serviceMonitor.enabled` | Use servicemonitor from prometheus operator | `false` |
|
||||
| `serviceMonitor.namespace` | Namespace this servicemonitor is installed in | |
|
||||
| `serviceMonitor.interval` | How frequently Prometheus should scrape | `1m` |
|
||||
| `serviceMonitor.path` | Path to scrape | `/metrics` |
|
||||
| `serviceMonitor.scheme` | Scheme to use for metrics scraping | `http` |
|
||||
| `serviceMonitor.tlsConfig` | TLS configuration block for the endpoint | `{}` |
|
||||
| `serviceMonitor.labels` | Labels for the servicemonitor passed to Prometheus Operator | `{}` |
|
||||
| `serviceMonitor.scrapeTimeout` | Timeout after which the scrape is ended | `30s` |
|
||||
| `serviceMonitor.relabelings` | RelabelConfigs to apply to samples before scraping. | `[]` |
|
||||
| `serviceMonitor.metricRelabelings` | MetricRelabelConfigs to apply to samples before ingestion. | `[]` |
|
||||
| `revisionHistoryLimit` | Number of old ReplicaSets to retain | `10` |
|
||||
| `imageRenderer.enabled` | Enable the image-renderer deployment & service | `false` |
|
||||
| `imageRenderer.image.registry` | image-renderer Image registry | `docker.io` |
|
||||
| `imageRenderer.image.repository` | image-renderer Image repository | `grafana/grafana-image-renderer` |
|
||||
| `imageRenderer.image.tag` | image-renderer Image tag | `latest` |
|
||||
| `imageRenderer.image.sha` | image-renderer Image sha (optional) | `""` |
|
||||
| `imageRenderer.image.pullPolicy` | image-renderer ImagePullPolicy | `Always` |
|
||||
| `imageRenderer.env` | extra env-vars for image-renderer | `{}` |
|
||||
| `imageRenderer.envValueFrom` | Environment variables for image-renderer from alternate sources. See the API docs on [EnvVarSource](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.17/#envvarsource-v1-core) for format details. Can be templated | `{}` |
|
||||
| `imageRenderer.serviceAccountName` | image-renderer deployment serviceAccountName | `""` |
|
||||
| `imageRenderer.securityContext` | image-renderer deployment securityContext | `{}` |
|
||||
| `imageRenderer.podAnnotations ` | image-renderer image-renderer pod annotation | `{}` |
|
||||
| `imageRenderer.hostAliases` | image-renderer deployment Host Aliases | `[]` |
|
||||
| `imageRenderer.priorityClassName` | image-renderer deployment priority class | `''` |
|
||||
| `imageRenderer.service.enabled` | Enable the image-renderer service | `true` |
|
||||
| `imageRenderer.service.portName` | image-renderer service port name | `http` |
|
||||
| `imageRenderer.service.port` | image-renderer port used by deployment | `8081` |
|
||||
| `imageRenderer.service.targetPort` | image-renderer service port used by service | `8081` |
|
||||
| `imageRenderer.appProtocol` | Adds the appProtocol field to the service | `` |
|
||||
| `imageRenderer.grafanaSubPath` | Grafana sub path to use for image renderer callback url | `''` |
|
||||
| `imageRenderer.podPortName` | name of the image-renderer port on the pod | `http` |
|
||||
| `imageRenderer.revisionHistoryLimit` | number of image-renderer replica sets to keep | `10` |
|
||||
| `imageRenderer.networkPolicy.limitIngress` | Enable a NetworkPolicy to limit inbound traffic from only the created grafana pods | `true` |
|
||||
| `imageRenderer.networkPolicy.limitEgress` | Enable a NetworkPolicy to limit outbound traffic to only the created grafana pods | `false` |
|
||||
| `imageRenderer.resources` | Set resource limits for image-renderer pods | `{}` |
|
||||
| `imageRenderer.nodeSelector` | Node labels for pod assignment | `{}` |
|
||||
| `imageRenderer.tolerations` | Toleration labels for pod assignment | `[]` |
|
||||
| `imageRenderer.affinity` | Affinity settings for pod assignment | `{}` |
|
||||
| `networkPolicy.enabled` | Enable creation of NetworkPolicy resources. | `false` |
|
||||
| `networkPolicy.allowExternal` | Don't require client label for connections | `true` |
|
||||
| `networkPolicy.explicitNamespacesSelector` | A Kubernetes LabelSelector to explicitly select namespaces from which traffic could be allowed | `{}` |
|
||||
| `networkPolicy.ingress` | Enable the creation of an ingress network policy | `true` |
|
||||
| `networkPolicy.egress.enabled` | Enable the creation of an egress network policy | `false` |
|
||||
| `networkPolicy.egress.ports` | An array of ports to allow for the egress | `[]` |
|
||||
| `enableKubeBackwardCompatibility` | Enable backward compatibility of kubernetes where pod's defintion version below 1.13 doesn't have the enableServiceLinks option | `false` |
|
||||
|
||||
### Example ingress with path
|
||||
|
||||
With grafana 6.3 and above
|
||||
|
||||
```yaml
|
||||
grafana.ini:
|
||||
server:
|
||||
domain: monitoring.example.com
|
||||
root_url: "%(protocol)s://%(domain)s/grafana"
|
||||
serve_from_sub_path: true
|
||||
ingress:
|
||||
enabled: true
|
||||
hosts:
|
||||
- "monitoring.example.com"
|
||||
path: "/grafana"
|
||||
```
|
||||
|
||||
### Example of extraVolumeMounts and extraVolumes
|
||||
|
||||
Configure additional volumes with `extraVolumes` and volume mounts with `extraVolumeMounts`.
|
||||
|
||||
Example for `extraVolumeMounts` and corresponding `extraVolumes`:
|
||||
|
||||
```yaml
|
||||
extraVolumeMounts:
|
||||
- name: plugins
|
||||
mountPath: /var/lib/grafana/plugins
|
||||
subPath: configs/grafana/plugins
|
||||
readOnly: false
|
||||
- name: dashboards
|
||||
mountPath: /var/lib/grafana/dashboards
|
||||
hostPath: /usr/shared/grafana/dashboards
|
||||
readOnly: false
|
||||
|
||||
extraVolumes:
|
||||
- name: plugins
|
||||
existingClaim: existing-grafana-claim
|
||||
- name: dashboards
|
||||
hostPath: /usr/shared/grafana/dashboards
|
||||
```
|
||||
|
||||
Volumes default to `emptyDir`. Set to `persistentVolumeClaim`,
|
||||
`hostPath`, `csi`, or `configMap` for other types. For a
|
||||
`persistentVolumeClaim`, specify an existing claim name with
|
||||
`existingClaim`.
|
||||
|
||||
## Import dashboards
|
||||
|
||||
There are a few methods to import dashboards to Grafana. Below are some examples and explanations as to how to use each method:
|
||||
|
||||
```yaml
|
||||
dashboards:
|
||||
default:
|
||||
some-dashboard:
|
||||
json: |
|
||||
{
|
||||
"annotations":
|
||||
|
||||
...
|
||||
# Complete json file here
|
||||
...
|
||||
|
||||
"title": "Some Dashboard",
|
||||
"uid": "abcd1234",
|
||||
"version": 1
|
||||
}
|
||||
custom-dashboard:
|
||||
# This is a path to a file inside the dashboards directory inside the chart directory
|
||||
file: dashboards/custom-dashboard.json
|
||||
prometheus-stats:
|
||||
# Ref: https://grafana.com/dashboards/2
|
||||
gnetId: 2
|
||||
revision: 2
|
||||
datasource: Prometheus
|
||||
loki-dashboard-quick-search:
|
||||
gnetId: 12019
|
||||
revision: 2
|
||||
datasource:
|
||||
- name: DS_PROMETHEUS
|
||||
value: Prometheus
|
||||
- name: DS_LOKI
|
||||
value: Loki
|
||||
local-dashboard:
|
||||
url: https://raw.githubusercontent.com/user/repository/master/dashboards/dashboard.json
|
||||
```
|
||||
|
||||
## BASE64 dashboards
|
||||
|
||||
Dashboards could be stored on a server that does not return JSON directly and instead of it returns a Base64 encoded file (e.g. Gerrit)
|
||||
A new parameter has been added to the url use case so if you specify a b64content value equals to true after the url entry a Base64 decoding is applied before save the file to disk.
|
||||
If this entry is not set or is equals to false not decoding is applied to the file before saving it to disk.
|
||||
|
||||
### Gerrit use case
|
||||
|
||||
Gerrit API for download files has the following schema: <https://yourgerritserver/a/{project-name}/branches/{branch-id}/files/{file-id}/content> where {project-name} and
|
||||
{file-id} usually has '/' in their values and so they MUST be replaced by %2F so if project-name is user/repo, branch-id is master and file-id is equals to dir1/dir2/dashboard
|
||||
the url value is <https://yourgerritserver/a/user%2Frepo/branches/master/files/dir1%2Fdir2%2Fdashboard/content>
|
||||
|
||||
## Sidecar for dashboards
|
||||
|
||||
If the parameter `sidecar.dashboards.enabled` is set, a sidecar container is deployed in the grafana
|
||||
pod. This container watches all configmaps (or secrets) in the cluster and filters out the ones with
|
||||
a label as defined in `sidecar.dashboards.label`. The files defined in those configmaps are written
|
||||
to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported
|
||||
dashboards are deleted/updated.
|
||||
|
||||
A recommendation is to use one configmap per dashboard, as a reduction of multiple dashboards inside
|
||||
one configmap is currently not properly mirrored in grafana.
|
||||
|
||||
Example dashboard config:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: sample-grafana-dashboard
|
||||
labels:
|
||||
grafana_dashboard: "1"
|
||||
data:
|
||||
k8s-dashboard.json: |-
|
||||
[...]
|
||||
```
|
||||
|
||||
## Sidecar for datasources
|
||||
|
||||
If the parameter `sidecar.datasources.enabled` is set, an init container is deployed in the grafana
|
||||
pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and
|
||||
filters out the ones with a label as defined in `sidecar.datasources.label`. The files defined in
|
||||
those secrets are written to a folder and accessed by grafana on startup. Using these yaml files,
|
||||
the data sources in grafana can be imported.
|
||||
|
||||
Should you aim for reloading datasources in Grafana each time the config is changed, set `sidecar.datasources.skipReload: false` and adjust `sidecar.datasources.reloadURL` to `http://<svc-name>.<namespace>.svc.cluster.local/api/admin/provisioning/datasources/reload`.
|
||||
|
||||
Secrets are recommended over configmaps for this usecase because datasources usually contain private
|
||||
data like usernames and passwords. Secrets are the more appropriate cluster resource to manage those.
|
||||
|
||||
Example values to add a postgres datasource as a kubernetes secret:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: grafana-datasources
|
||||
labels:
|
||||
grafana_datasource: 'true' # default value for: sidecar.datasources.label
|
||||
stringData:
|
||||
pg-db.yaml: |-
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
- name: My pg db datasource
|
||||
type: postgres
|
||||
url: my-postgresql-db:5432
|
||||
user: db-readonly-user
|
||||
secureJsonData:
|
||||
password: 'SUperSEcretPa$$word'
|
||||
jsonData:
|
||||
database: my_datase
|
||||
sslmode: 'disable' # disable/require/verify-ca/verify-full
|
||||
maxOpenConns: 0 # Grafana v5.4+
|
||||
maxIdleConns: 2 # Grafana v5.4+
|
||||
connMaxLifetime: 14400 # Grafana v5.4+
|
||||
postgresVersion: 1000 # 903=9.3, 904=9.4, 905=9.5, 906=9.6, 1000=10
|
||||
timescaledb: false
|
||||
# <bool> allow users to edit datasources from the UI.
|
||||
editable: false
|
||||
```
|
||||
|
||||
Example values to add a datasource adapted from [Grafana](http://docs.grafana.org/administration/provisioning/#example-datasource-config-file):
|
||||
|
||||
```yaml
|
||||
datasources:
|
||||
datasources.yaml:
|
||||
apiVersion: 1
|
||||
datasources:
|
||||
# <string, required> name of the datasource. Required
|
||||
- name: Graphite
|
||||
# <string, required> datasource type. Required
|
||||
type: graphite
|
||||
# <string, required> access mode. proxy or direct (Server or Browser in the UI). Required
|
||||
access: proxy
|
||||
# <int> org id. will default to orgId 1 if not specified
|
||||
orgId: 1
|
||||
# <string> url
|
||||
url: http://localhost:8080
|
||||
# <string> database password, if used
|
||||
password:
|
||||
# <string> database user, if used
|
||||
user:
|
||||
# <string> database name, if used
|
||||
database:
|
||||
# <bool> enable/disable basic auth
|
||||
basicAuth:
|
||||
# <string> basic auth username
|
||||
basicAuthUser:
|
||||
# <string> basic auth password
|
||||
basicAuthPassword:
|
||||
# <bool> enable/disable with credentials headers
|
||||
withCredentials:
|
||||
# <bool> mark as default datasource. Max one per org
|
||||
isDefault:
|
||||
# <map> fields that will be converted to json and stored in json_data
|
||||
jsonData:
|
||||
graphiteVersion: "1.1"
|
||||
tlsAuth: true
|
||||
tlsAuthWithCACert: true
|
||||
# <string> json object of data that will be encrypted.
|
||||
secureJsonData:
|
||||
tlsCACert: "..."
|
||||
tlsClientCert: "..."
|
||||
tlsClientKey: "..."
|
||||
version: 1
|
||||
# <bool> allow users to edit datasources from the UI.
|
||||
editable: false
|
||||
```
|
||||
|
||||
## Sidecar for notifiers
|
||||
|
||||
If the parameter `sidecar.notifiers.enabled` is set, an init container is deployed in the grafana
|
||||
pod. This container lists all secrets (or configmaps, though not recommended) in the cluster and
|
||||
filters out the ones with a label as defined in `sidecar.notifiers.label`. The files defined in
|
||||
those secrets are written to a folder and accessed by grafana on startup. Using these yaml files,
|
||||
the notification channels in grafana can be imported. The secrets must be created before
|
||||
`helm install` so that the notifiers init container can list the secrets.
|
||||
|
||||
Secrets are recommended over configmaps for this usecase because alert notification channels usually contain
|
||||
private data like SMTP usernames and passwords. Secrets are the more appropriate cluster resource to manage those.
|
||||
|
||||
Example datasource config adapted from [Grafana](https://grafana.com/docs/grafana/latest/administration/provisioning/#alert-notification-channels):
|
||||
|
||||
```yaml
|
||||
notifiers:
|
||||
- name: notification-channel-1
|
||||
type: slack
|
||||
uid: notifier1
|
||||
# either
|
||||
org_id: 2
|
||||
# or
|
||||
org_name: Main Org.
|
||||
is_default: true
|
||||
send_reminder: true
|
||||
frequency: 1h
|
||||
disable_resolve_message: false
|
||||
# See `Supported Settings` section for settings supporter for each
|
||||
# alert notification type.
|
||||
settings:
|
||||
recipient: 'XXX'
|
||||
token: 'xoxb'
|
||||
uploadImage: true
|
||||
url: https://slack.com
|
||||
|
||||
delete_notifiers:
|
||||
- name: notification-channel-1
|
||||
uid: notifier1
|
||||
org_id: 2
|
||||
- name: notification-channel-2
|
||||
# default org_id: 1
|
||||
```
|
||||
|
||||
## Sidecar for alerting resources
|
||||
|
||||
If the parameter `sidecar.alerts.enabled` is set, a sidecar container is deployed in the grafana
|
||||
pod. This container watches all configmaps (or secrets) in the cluster (namespace defined by `sidecar.alerts.searchNamespace`) and filters out the ones with
|
||||
a label as defined in `sidecar.alerts.label` (default is `grafana_alert`). The files defined in those configmaps are written
|
||||
to a folder and accessed by grafana. Changes to the configmaps are monitored and the imported alerting resources are updated, however, deletions are a little more complicated (see below).
|
||||
|
||||
This sidecar can be used to provision alert rules, contact points, notification policies, notification templates and mute timings as shown in [Grafana Documentation](https://grafana.com/docs/grafana/next/alerting/set-up/provision-alerting-resources/file-provisioning/).
|
||||
|
||||
To fetch the alert config which will be provisioned, use the alert provisioning API ([Grafana Documentation](https://grafana.com/docs/grafana/next/developers/http_api/alerting_provisioning/)).
|
||||
You can use either JSON or YAML format.
|
||||
|
||||
Example config for an alert rule:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: sample-grafana-alert
|
||||
labels:
|
||||
grafana_alert: "1"
|
||||
data:
|
||||
k8s-alert.yml: |-
|
||||
apiVersion: 1
|
||||
groups:
|
||||
- orgId: 1
|
||||
name: k8s-alert
|
||||
[...]
|
||||
```
|
||||
|
||||
To delete provisioned alert rules is a two step process, you need to delete the configmap which defined the alert rule
|
||||
and then create a configuration which deletes the alert rule.
|
||||
|
||||
Example deletion configuration:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: delete-sample-grafana-alert
|
||||
namespace: monitoring
|
||||
labels:
|
||||
grafana_alert: "1"
|
||||
data:
|
||||
delete-k8s-alert.yml: |-
|
||||
apiVersion: 1
|
||||
deleteRules:
|
||||
- orgId: 1
|
||||
uid: 16624780-6564-45dc-825c-8bded4ad92d3
|
||||
```
|
||||
|
||||
## Statically provision alerting resources
|
||||
If you don't need to change alerting resources (alert rules, contact points, notification policies and notification templates) regularly you could use the `alerting` config option instead of the sidecar option above.
|
||||
This will grab the alerting config and apply it statically at build time for the helm file.
|
||||
|
||||
There are two methods to statically provision alerting configuration in Grafana. Below are some examples and explanations as to how to use each method:
|
||||
|
||||
```yaml
|
||||
alerting:
|
||||
team1-alert-rules.yaml:
|
||||
file: alerting/team1/rules.yaml
|
||||
team2-alert-rules.yaml:
|
||||
file: alerting/team2/rules.yaml
|
||||
team3-alert-rules.yaml:
|
||||
file: alerting/team3/rules.yaml
|
||||
notification-policies.yaml:
|
||||
file: alerting/shared/notification-policies.yaml
|
||||
notification-templates.yaml:
|
||||
file: alerting/shared/notification-templates.yaml
|
||||
contactpoints.yaml:
|
||||
apiVersion: 1
|
||||
contactPoints:
|
||||
- orgId: 1
|
||||
name: Slack channel
|
||||
receivers:
|
||||
- uid: default-receiver
|
||||
type: slack
|
||||
settings:
|
||||
# Webhook URL to be filled in
|
||||
url: ""
|
||||
# We need to escape double curly braces for the tpl function.
|
||||
text: '{{ `{{ template "default.message" . }}` }}'
|
||||
title: '{{ `{{ template "default.title" . }}` }}'
|
||||
```
|
||||
|
||||
The two possibilities for static alerting resource provisioning are:
|
||||
|
||||
* Inlining the file contents as shown for contact points in the above example.
|
||||
* Importing a file using a relative path starting from the chart root directory as shown for the alert rules in the above example.
|
||||
|
||||
### Important notes on file provisioning
|
||||
|
||||
* The format of the files is defined in the [Grafana documentation](https://grafana.com/docs/grafana/next/alerting/set-up/provision-alerting-resources/file-provisioning/) on file provisioning.
|
||||
* The chart supports importing YAML and JSON files.
|
||||
* The filename must be unique, otherwise one volume mount will overwrite the other.
|
||||
* In case of inlining, double curly braces that arise from the Grafana configuration format and are not intended as templates for the chart must be escaped.
|
||||
* The number of total files under `alerting:` is not limited. Each file will end up as a volume mount in the corresponding provisioning folder of the deployed Grafana instance.
|
||||
* The file size for each import is limited by what the function `.Files.Get` can handle, which suffices for most cases.
|
||||
|
||||
## How to serve Grafana with a path prefix (/grafana)
|
||||
|
||||
In order to serve Grafana with a prefix (e.g., <http://example.com/grafana>), add the following to your values.yaml.
|
||||
|
||||
```yaml
|
||||
ingress:
|
||||
enabled: true
|
||||
annotations:
|
||||
kubernetes.io/ingress.class: "nginx"
|
||||
nginx.ingress.kubernetes.io/rewrite-target: /$1
|
||||
nginx.ingress.kubernetes.io/use-regex: "true"
|
||||
|
||||
path: /grafana/?(.*)
|
||||
hosts:
|
||||
- k8s.example.dev
|
||||
|
||||
grafana.ini:
|
||||
server:
|
||||
root_url: http://localhost:3000/grafana # this host can be localhost
|
||||
```
|
||||
|
||||
## How to securely reference secrets in grafana.ini
|
||||
|
||||
This example uses Grafana [file providers](https://grafana.com/docs/grafana/latest/administration/configuration/#file-provider) for secret values and the `extraSecretMounts` configuration flag (Additional grafana server secret mounts) to mount the secrets.
|
||||
|
||||
In grafana.ini:
|
||||
|
||||
```yaml
|
||||
grafana.ini:
|
||||
[auth.generic_oauth]
|
||||
enabled = true
|
||||
client_id = $__file{/etc/secrets/auth_generic_oauth/client_id}
|
||||
client_secret = $__file{/etc/secrets/auth_generic_oauth/client_secret}
|
||||
```
|
||||
|
||||
Existing secret, or created along with helm:
|
||||
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: auth-generic-oauth-secret
|
||||
type: Opaque
|
||||
stringData:
|
||||
client_id: <value>
|
||||
client_secret: <value>
|
||||
```
|
||||
|
||||
Include in the `extraSecretMounts` configuration flag:
|
||||
|
||||
```yaml
|
||||
- extraSecretMounts:
|
||||
- name: auth-generic-oauth-secret-mount
|
||||
secretName: auth-generic-oauth-secret
|
||||
defaultMode: 0440
|
||||
mountPath: /etc/secrets/auth_generic_oauth
|
||||
readOnly: true
|
||||
```
|
||||
|
||||
### extraSecretMounts using a Container Storage Interface (CSI) provider
|
||||
|
||||
This example uses a CSI driver e.g. retrieving secrets using [Azure Key Vault Provider](https://github.com/Azure/secrets-store-csi-driver-provider-azure)
|
||||
|
||||
```yaml
|
||||
- extraSecretMounts:
|
||||
- name: secrets-store-inline
|
||||
mountPath: /run/secrets
|
||||
readOnly: true
|
||||
csi:
|
||||
driver: secrets-store.csi.k8s.io
|
||||
readOnly: true
|
||||
volumeAttributes:
|
||||
secretProviderClass: "my-provider"
|
||||
nodePublishSecretRef:
|
||||
name: akv-creds
|
||||
```
|
||||
|
||||
## Image Renderer Plug-In
|
||||
|
||||
This chart supports enabling [remote image rendering](https://github.com/grafana/grafana-image-renderer/blob/master/README.md#run-in-docker)
|
||||
|
||||
```yaml
|
||||
imageRenderer:
|
||||
enabled: true
|
||||
```
|
||||
|
||||
### Image Renderer NetworkPolicy
|
||||
|
||||
By default the image-renderer pods will have a network policy which only allows ingress traffic from the created grafana instance
|
||||
|
||||
### High Availability for unified alerting
|
||||
|
||||
If you want to run Grafana in a high availability cluster you need to enable
|
||||
the headless service by setting `headlessService: true` in your `values.yaml`
|
||||
file.
|
||||
|
||||
As next step you have to setup the `grafana.ini` in your `values.yaml` in a way
|
||||
that it will make use of the headless service to obtain all the IPs of the
|
||||
cluster. You should replace ``{{ Name }}`` with the name of your helm deployment.
|
||||
|
||||
```yaml
|
||||
grafana.ini:
|
||||
...
|
||||
unified_alerting:
|
||||
enabled: true
|
||||
ha_peers: {{ Name }}-headless:9094
|
||||
ha_listen_address: ${POD_IP}:9094
|
||||
ha_advertise_address: ${POD_IP}:9094
|
||||
|
||||
alerting:
|
||||
enabled: false
|
||||
```
|
||||
@@ -0,0 +1 @@
|
||||
# Leave this file empty to ensure that CI runs builds against the default configuration in values.yaml.
|
||||
@@ -0,0 +1,16 @@
|
||||
affinity:
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- podAffinityTerm:
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: grafana-test
|
||||
app.kubernetes.io/name: grafana
|
||||
topologyKey: failure-domain.beta.kubernetes.io/zone
|
||||
weight: 100
|
||||
requiredDuringSchedulingIgnoredDuringExecution:
|
||||
- labelSelector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: grafana-test
|
||||
app.kubernetes.io/name: grafana
|
||||
topologyKey: kubernetes.io/hostname
|
||||
@@ -0,0 +1,53 @@
|
||||
dashboards:
|
||||
my-provider:
|
||||
my-awesome-dashboard:
|
||||
# An empty but valid dashboard
|
||||
json: |
|
||||
{
|
||||
"__inputs": [],
|
||||
"__requires": [
|
||||
{
|
||||
"type": "grafana",
|
||||
"id": "grafana",
|
||||
"name": "Grafana",
|
||||
"version": "6.3.5"
|
||||
}
|
||||
],
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": null,
|
||||
"links": [],
|
||||
"panels": [],
|
||||
"schemaVersion": 19,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": ["5s"]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "Dummy Dashboard",
|
||||
"uid": "IdcYQooWk",
|
||||
"version": 1
|
||||
}
|
||||
datasource: Prometheus
|
||||
@@ -0,0 +1,19 @@
|
||||
dashboards:
|
||||
my-provider:
|
||||
my-awesome-dashboard:
|
||||
gnetId: 10000
|
||||
revision: 1
|
||||
datasource: Prometheus
|
||||
dashboardProviders:
|
||||
dashboardproviders.yaml:
|
||||
apiVersion: 1
|
||||
providers:
|
||||
- name: 'my-provider'
|
||||
orgId: 1
|
||||
folder: ''
|
||||
type: file
|
||||
updateIntervalSeconds: 10
|
||||
disableDeletion: true
|
||||
editable: true
|
||||
options:
|
||||
path: /var/lib/grafana/dashboards/my-provider
|
||||
@@ -0,0 +1,7 @@
|
||||
extraConfigmapMounts:
|
||||
- name: '{{ include "grafana.fullname" . }}'
|
||||
configMap: '{{ include "grafana.fullname" . }}'
|
||||
mountPath: /var/lib/grafana/dashboards/test-dashboard.json
|
||||
# This is not a realistic test, but for this we only care about extraConfigmapMounts not being empty and pointing to an existing ConfigMap
|
||||
subPath: grafana.ini
|
||||
readOnly: true
|
||||
@@ -0,0 +1,19 @@
|
||||
podLabels:
|
||||
customLableA: Aaaaa
|
||||
imageRenderer:
|
||||
enabled: true
|
||||
env:
|
||||
RENDERING_ARGS: --disable-gpu,--window-size=1280x758
|
||||
RENDERING_MODE: clustered
|
||||
podLabels:
|
||||
customLableB: Bbbbb
|
||||
networkPolicy:
|
||||
limitIngress: true
|
||||
limitEgress: true
|
||||
resources:
|
||||
limits:
|
||||
cpu: 1000m
|
||||
memory: 1000Mi
|
||||
requests:
|
||||
cpu: 500m
|
||||
memory: 50Mi
|
||||
@@ -0,0 +1,3 @@
|
||||
persistence:
|
||||
type: pvc
|
||||
enabled: true
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,55 @@
|
||||
1. Get your '{{ .Values.adminUser }}' user password by running:
|
||||
|
||||
kubectl get secret --namespace {{ include "grafana.namespace" . }} {{ .Values.admin.existingSecret | default (include "grafana.fullname" .) }} -o jsonpath="{.data.{{ .Values.admin.passwordKey | default "admin-password" }}}" | base64 --decode ; echo
|
||||
|
||||
|
||||
2. The Grafana server can be accessed via port {{ .Values.service.port }} on the following DNS name from within your cluster:
|
||||
|
||||
{{ include "grafana.fullname" . }}.{{ include "grafana.namespace" . }}.svc.cluster.local
|
||||
{{ if .Values.ingress.enabled }}
|
||||
If you bind grafana to 80, please update values in values.yaml and reinstall:
|
||||
```
|
||||
securityContext:
|
||||
runAsUser: 0
|
||||
runAsGroup: 0
|
||||
fsGroup: 0
|
||||
|
||||
command:
|
||||
- "setcap"
|
||||
- "'cap_net_bind_service=+ep'"
|
||||
- "/usr/sbin/grafana-server &&"
|
||||
- "sh"
|
||||
- "/run.sh"
|
||||
```
|
||||
Details refer to https://grafana.com/docs/installation/configuration/#http-port.
|
||||
Or grafana would always crash.
|
||||
|
||||
From outside the cluster, the server URL(s) are:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
http://{{ . }}
|
||||
{{- end }}
|
||||
{{- else }}
|
||||
Get the Grafana URL to visit by running these commands in the same shell:
|
||||
{{- if contains "NodePort" .Values.service.type }}
|
||||
export NODE_PORT=$(kubectl get --namespace {{ include "grafana.namespace" . }} -o jsonpath="{.spec.ports[0].nodePort}" services {{ include "grafana.fullname" . }})
|
||||
export NODE_IP=$(kubectl get nodes --namespace {{ include "grafana.namespace" . }} -o jsonpath="{.items[0].status.addresses[0].address}")
|
||||
echo http://$NODE_IP:$NODE_PORT
|
||||
{{- else if contains "LoadBalancer" .Values.service.type }}
|
||||
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
|
||||
You can watch the status of by running 'kubectl get svc --namespace {{ include "grafana.namespace" . }} -w {{ include "grafana.fullname" . }}'
|
||||
export SERVICE_IP=$(kubectl get svc --namespace {{ include "grafana.namespace" . }} {{ include "grafana.fullname" . }} -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
|
||||
http://$SERVICE_IP:{{ .Values.service.port -}}
|
||||
{{- else if contains "ClusterIP" .Values.service.type }}
|
||||
export POD_NAME=$(kubectl get pods --namespace {{ include "grafana.namespace" . }} -l "app.kubernetes.io/name={{ include "grafana.name" . }},app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
|
||||
kubectl --namespace {{ include "grafana.namespace" . }} port-forward $POD_NAME 3000
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
3. Login with the password from step 1 and the username: {{ .Values.adminUser }}
|
||||
|
||||
{{- if not .Values.persistence.enabled }}
|
||||
#################################################################################
|
||||
###### WARNING: Persistence is disabled!!! You will lose your data when #####
|
||||
###### the Grafana pod is terminated. #####
|
||||
#################################################################################
|
||||
{{- end }}
|
||||
@@ -0,0 +1,172 @@
|
||||
{{/*
|
||||
Generate config map data
|
||||
*/}}
|
||||
{{- define "grafana.configData" -}}
|
||||
{{ include "grafana.assertNoLeakedSecrets" . }}
|
||||
{{- $files := .Files }}
|
||||
{{- $root := . -}}
|
||||
{{- with .Values.plugins }}
|
||||
plugins: {{ join "," . }}
|
||||
{{- end }}
|
||||
grafana.ini: |
|
||||
{{- range $elem, $elemVal := index .Values "grafana.ini" }}
|
||||
{{- if not (kindIs "map" $elemVal) }}
|
||||
{{- if kindIs "invalid" $elemVal }}
|
||||
{{ $elem }} =
|
||||
{{- else if kindIs "string" $elemVal }}
|
||||
{{ $elem }} = {{ tpl $elemVal $ }}
|
||||
{{- else }}
|
||||
{{ $elem }} = {{ $elemVal }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := index .Values "grafana.ini" }}
|
||||
{{- if kindIs "map" $value }}
|
||||
[{{ $key }}]
|
||||
{{- range $elem, $elemVal := $value }}
|
||||
{{- if kindIs "invalid" $elemVal }}
|
||||
{{ $elem }} =
|
||||
{{- else if kindIs "string" $elemVal }}
|
||||
{{ $elem }} = {{ tpl $elemVal $ }}
|
||||
{{- else }}
|
||||
{{ $elem }} = {{ $elemVal }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $key, $value := .Values.datasources }}
|
||||
{{- if not (hasKey $value "secret") }}
|
||||
{{ $key }}: |
|
||||
{{- tpl (toYaml $value | nindent 2) $root }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $key, $value := .Values.notifiers }}
|
||||
{{- if not (hasKey $value "secret") }}
|
||||
{{ $key }}: |
|
||||
{{- toYaml $value | nindent 2 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $key, $value := .Values.alerting }}
|
||||
{{- if (hasKey $value "file") }}
|
||||
{{ $key }}:
|
||||
{{- toYaml ( $files.Get $value.file ) | nindent 2 }}
|
||||
{{- else if (or (hasKey $value "secret") (hasKey $value "secretFile"))}}
|
||||
{{/* will be stored inside secret generated by "configSecret.yaml"*/}}
|
||||
{{- else }}
|
||||
{{ $key }}: |
|
||||
{{- tpl (toYaml $value | nindent 2) $root }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- range $key, $value := .Values.dashboardProviders }}
|
||||
{{ $key }}: |
|
||||
{{- toYaml $value | nindent 2 }}
|
||||
{{- end }}
|
||||
|
||||
{{- if .Values.dashboards }}
|
||||
download_dashboards.sh: |
|
||||
#!/usr/bin/env sh
|
||||
set -euf
|
||||
{{- if .Values.dashboardProviders }}
|
||||
{{- range $key, $value := .Values.dashboardProviders }}
|
||||
{{- range $value.providers }}
|
||||
mkdir -p {{ .options.path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{ $dashboardProviders := .Values.dashboardProviders }}
|
||||
{{- range $provider, $dashboards := .Values.dashboards }}
|
||||
{{- range $key, $value := $dashboards }}
|
||||
{{- if (or (hasKey $value "gnetId") (hasKey $value "url")) }}
|
||||
curl -skf \
|
||||
--connect-timeout 60 \
|
||||
--max-time 60 \
|
||||
{{- if not $value.b64content }}
|
||||
{{- if not $value.acceptHeader }}
|
||||
-H "Accept: application/json" \
|
||||
{{- else }}
|
||||
-H "Accept: {{ $value.acceptHeader }}" \
|
||||
{{- end }}
|
||||
{{- if $value.token }}
|
||||
-H "Authorization: token {{ $value.token }}" \
|
||||
{{- end }}
|
||||
{{- if $value.bearerToken }}
|
||||
-H "Authorization: Bearer {{ $value.bearerToken }}" \
|
||||
{{- end }}
|
||||
{{- if $value.basic }}
|
||||
-H "Authorization: Basic {{ $value.basic }}" \
|
||||
{{- end }}
|
||||
{{- if $value.gitlabToken }}
|
||||
-H "PRIVATE-TOKEN: {{ $value.gitlabToken }}" \
|
||||
{{- end }}
|
||||
-H "Content-Type: application/json;charset=UTF-8" \
|
||||
{{- end }}
|
||||
{{- $dpPath := "" -}}
|
||||
{{- range $kd := (index $dashboardProviders "dashboardproviders.yaml").providers }}
|
||||
{{- if eq $kd.name $provider }}
|
||||
{{- $dpPath = $kd.options.path }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $value.url }}
|
||||
"{{ $value.url }}" \
|
||||
{{- else }}
|
||||
"https://grafana.com/api/dashboards/{{ $value.gnetId }}/revisions/{{- if $value.revision -}}{{ $value.revision }}{{- else -}}1{{- end -}}/download" \
|
||||
{{- end }}
|
||||
{{- if $value.datasource }}
|
||||
{{- if kindIs "string" $value.datasource }}
|
||||
| sed '/-- .* --/! s/"datasource":.*,/"datasource": "{{ $value.datasource }}",/g' \
|
||||
{{- end }}
|
||||
{{- if kindIs "slice" $value.datasource }}
|
||||
{{- range $value.datasource }}
|
||||
| sed '/-- .* --/! s/${{"{"}}{{ .name }}}/{{ .value }}/g' \
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if $value.b64content }}
|
||||
| base64 -d \
|
||||
{{- end }}
|
||||
> "{{- if $dpPath -}}{{ $dpPath }}{{- else -}}/var/lib/grafana/dashboards/{{ $provider }}{{- end -}}/{{ $key }}.json"
|
||||
{{ end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Generate dashboard json config map data
|
||||
*/}}
|
||||
{{- define "grafana.configDashboardProviderData" -}}
|
||||
provider.yaml: |-
|
||||
apiVersion: 1
|
||||
providers:
|
||||
- name: '{{ .Values.sidecar.dashboards.provider.name }}'
|
||||
orgId: {{ .Values.sidecar.dashboards.provider.orgid }}
|
||||
{{- if not .Values.sidecar.dashboards.provider.foldersFromFilesStructure }}
|
||||
folder: '{{ .Values.sidecar.dashboards.provider.folder }}'
|
||||
folderUid: '{{ .Values.sidecar.dashboards.provider.folderUid }}'
|
||||
{{- end }}
|
||||
type: {{ .Values.sidecar.dashboards.provider.type }}
|
||||
disableDeletion: {{ .Values.sidecar.dashboards.provider.disableDelete }}
|
||||
allowUiUpdates: {{ .Values.sidecar.dashboards.provider.allowUiUpdates }}
|
||||
updateIntervalSeconds: {{ .Values.sidecar.dashboards.provider.updateIntervalSeconds | default 30 }}
|
||||
options:
|
||||
foldersFromFilesStructure: {{ .Values.sidecar.dashboards.provider.foldersFromFilesStructure }}
|
||||
path: {{ .Values.sidecar.dashboards.folder }}{{- with .Values.sidecar.dashboards.defaultFolderName }}/{{ . }}{{- end }}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "grafana.secretsData" -}}
|
||||
{{- if and (not .Values.env.GF_SECURITY_DISABLE_INITIAL_ADMIN_CREATION) (not .Values.admin.existingSecret) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD__FILE) (not .Values.env.GF_SECURITY_ADMIN_PASSWORD) }}
|
||||
admin-user: {{ .Values.adminUser | b64enc | quote }}
|
||||
{{- if .Values.adminPassword }}
|
||||
admin-password: {{ .Values.adminPassword | b64enc | quote }}
|
||||
{{- else }}
|
||||
admin-password: {{ include "grafana.password" . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- if not .Values.ldap.existingSecret }}
|
||||
ldap-toml: {{ tpl .Values.ldap.config $ | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,276 @@
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "grafana.name" -}}
|
||||
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create a default fully qualified app name.
|
||||
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
|
||||
If release name contains chart name it will be used as a full name.
|
||||
*/}}
|
||||
{{- define "grafana.fullname" -}}
|
||||
{{- if .Values.fullnameOverride }}
|
||||
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- $name := default .Chart.Name .Values.nameOverride }}
|
||||
{{- if contains $name .Release.Name }}
|
||||
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
|
||||
{{- else }}
|
||||
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "grafana.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account
|
||||
*/}}
|
||||
{{- define "grafana.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (include "grafana.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- define "grafana.serviceAccountNameTest" -}}
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
{{- default (print (include "grafana.fullname" .) "-test") .Values.serviceAccount.nameTest }}
|
||||
{{- else }}
|
||||
{{- default "default" .Values.serviceAccount.nameTest }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Allow the release namespace to be overridden for multi-namespace deployments in combined charts
|
||||
*/}}
|
||||
{{- define "grafana.namespace" -}}
|
||||
{{- if .Values.namespaceOverride }}
|
||||
{{- .Values.namespaceOverride }}
|
||||
{{- else }}
|
||||
{{- .Release.Namespace }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "grafana.labels" -}}
|
||||
helm.sh/chart: {{ include "grafana.chart" . }}
|
||||
{{ include "grafana.selectorLabels" . }}
|
||||
{{- if or .Chart.AppVersion .Values.image.tag }}
|
||||
app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- with .Values.extraLabels }}
|
||||
{{ toYaml . }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels
|
||||
*/}}
|
||||
{{- define "grafana.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "grafana.name" . }}
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Common labels
|
||||
*/}}
|
||||
{{- define "grafana.imageRenderer.labels" -}}
|
||||
helm.sh/chart: {{ include "grafana.chart" . }}
|
||||
{{ include "grafana.imageRenderer.selectorLabels" . }}
|
||||
{{- if or .Chart.AppVersion .Values.image.tag }}
|
||||
app.kubernetes.io/version: {{ mustRegexReplaceAllLiteral "@sha.*" .Values.image.tag "" | default .Chart.AppVersion | quote }}
|
||||
{{- end }}
|
||||
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Selector labels ImageRenderer
|
||||
*/}}
|
||||
{{- define "grafana.imageRenderer.selectorLabels" -}}
|
||||
app.kubernetes.io/name: {{ include "grafana.name" . }}-image-renderer
|
||||
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Looks if there's an existing secret and reuse its password. If not it generates
|
||||
new password and use it.
|
||||
*/}}
|
||||
{{- define "grafana.password" -}}
|
||||
{{- $secret := (lookup "v1" "Secret" (include "grafana.namespace" .) (include "grafana.fullname" .) ) }}
|
||||
{{- if $secret }}
|
||||
{{- index $secret "data" "admin-password" }}
|
||||
{{- else }}
|
||||
{{- (randAlphaNum 40) | b64enc | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for rbac.
|
||||
*/}}
|
||||
{{- define "grafana.rbac.apiVersion" -}}
|
||||
{{- if $.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1" }}
|
||||
{{- print "rbac.authorization.k8s.io/v1" }}
|
||||
{{- else }}
|
||||
{{- print "rbac.authorization.k8s.io/v1beta1" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for ingress.
|
||||
*/}}
|
||||
{{- define "grafana.ingress.apiVersion" -}}
|
||||
{{- if and ($.Capabilities.APIVersions.Has "networking.k8s.io/v1") (semverCompare ">= 1.19-0" .Capabilities.KubeVersion.Version) }}
|
||||
{{- print "networking.k8s.io/v1" }}
|
||||
{{- else if $.Capabilities.APIVersions.Has "networking.k8s.io/v1beta1" }}
|
||||
{{- print "networking.k8s.io/v1beta1" }}
|
||||
{{- else }}
|
||||
{{- print "extensions/v1beta1" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for Horizontal Pod Autoscaler.
|
||||
*/}}
|
||||
{{- define "grafana.hpa.apiVersion" -}}
|
||||
{{- if .Capabilities.APIVersions.Has "autoscaling/v2" }}
|
||||
{{- print "autoscaling/v2" }}
|
||||
{{- else }}
|
||||
{{- print "autoscaling/v2beta2" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return the appropriate apiVersion for podDisruptionBudget.
|
||||
*/}}
|
||||
{{- define "grafana.podDisruptionBudget.apiVersion" -}}
|
||||
{{- if $.Values.podDisruptionBudget.apiVersion }}
|
||||
{{- print $.Values.podDisruptionBudget.apiVersion }}
|
||||
{{- else if $.Capabilities.APIVersions.Has "policy/v1/PodDisruptionBudget" }}
|
||||
{{- print "policy/v1" }}
|
||||
{{- else }}
|
||||
{{- print "policy/v1beta1" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return if ingress is stable.
|
||||
*/}}
|
||||
{{- define "grafana.ingress.isStable" -}}
|
||||
{{- eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1" }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return if ingress supports ingressClassName.
|
||||
*/}}
|
||||
{{- define "grafana.ingress.supportsIngressClassName" -}}
|
||||
{{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Return if ingress supports pathType.
|
||||
*/}}
|
||||
{{- define "grafana.ingress.supportsPathType" -}}
|
||||
{{- or (eq (include "grafana.ingress.isStable" .) "true") (and (eq (include "grafana.ingress.apiVersion" .) "networking.k8s.io/v1beta1") (semverCompare ">= 1.18-0" .Capabilities.KubeVersion.Version)) }}
|
||||
{{- end }}
|
||||
|
||||
{{/*
|
||||
Formats imagePullSecrets. Input is (dict "root" . "imagePullSecrets" .{specific imagePullSecrets})
|
||||
*/}}
|
||||
{{- define "grafana.imagePullSecrets" -}}
|
||||
{{- $root := .root }}
|
||||
{{- range (concat .root.Values.global.imagePullSecrets .imagePullSecrets) }}
|
||||
{{- if eq (typeOf .) "map[string]interface {}" }}
|
||||
- {{ toYaml (dict "name" (tpl .name $root)) | trim }}
|
||||
{{- else }}
|
||||
- name: {{ tpl . $root }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
|
||||
{{/*
|
||||
Checks whether or not the configSecret secret has to be created
|
||||
*/}}
|
||||
{{- define "grafana.shouldCreateConfigSecret" -}}
|
||||
{{- $secretFound := false -}}
|
||||
{{- range $key, $value := .Values.datasources }}
|
||||
{{- if hasKey $value "secret" }}
|
||||
{{- $secretFound = true}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.notifiers }}
|
||||
{{- if hasKey $value "secret" }}
|
||||
{{- $secretFound = true}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.alerting }}
|
||||
{{- if (or (hasKey $value "secret") (hasKey $value "secretFile")) }}
|
||||
{{- $secretFound = true}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- $secretFound}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Checks whether the user is attempting to store secrets in plaintext
|
||||
in the grafana.ini configmap
|
||||
*/}}
|
||||
{{/* grafana.assertNoLeakedSecrets checks for sensitive keys in values */}}
|
||||
{{- define "grafana.assertNoLeakedSecrets" -}}
|
||||
{{- $sensitiveKeysYaml := `
|
||||
sensitiveKeys:
|
||||
- path: ["database", "password"]
|
||||
- path: ["smtp", "password"]
|
||||
- path: ["security", "secret_key"]
|
||||
- path: ["security", "admin_password"]
|
||||
- path: ["auth.basic", "password"]
|
||||
- path: ["auth.ldap", "bind_password"]
|
||||
- path: ["auth.google", "client_secret"]
|
||||
- path: ["auth.github", "client_secret"]
|
||||
- path: ["auth.gitlab", "client_secret"]
|
||||
- path: ["auth.generic_oauth", "client_secret"]
|
||||
- path: ["auth.okta", "client_secret"]
|
||||
- path: ["auth.azuread", "client_secret"]
|
||||
- path: ["auth.grafana_com", "client_secret"]
|
||||
- path: ["auth.grafananet", "client_secret"]
|
||||
- path: ["azure", "user_identity_client_secret"]
|
||||
- path: ["unified_alerting", "ha_redis_password"]
|
||||
- path: ["metrics", "basic_auth_password"]
|
||||
- path: ["external_image_storage.s3", "secret_key"]
|
||||
- path: ["external_image_storage.webdav", "password"]
|
||||
- path: ["external_image_storage.azure_blob", "account_key"]
|
||||
` | fromYaml -}}
|
||||
{{- if $.Values.assertNoLeakedSecrets -}}
|
||||
{{- $grafanaIni := index .Values "grafana.ini" -}}
|
||||
{{- range $_, $secret := $sensitiveKeysYaml.sensitiveKeys -}}
|
||||
{{- $currentMap := $grafanaIni -}}
|
||||
{{- $shouldContinue := true -}}
|
||||
{{- range $index, $elem := $secret.path -}}
|
||||
{{- if and $shouldContinue (hasKey $currentMap $elem) -}}
|
||||
{{- if eq (len $secret.path) (add1 $index) -}}
|
||||
{{- if not (regexMatch "\\$(?:__(?:env|file|vault))?{[^}]+}" (index $currentMap $elem)) -}}
|
||||
{{- fail (printf "Sensitive key '%s' should not be defined explicitly in values. Use variable expansion instead. You can disable this client-side validation by changing the value of assertNoLeakedSecrets." (join "." $secret.path)) -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- $currentMap = index $currentMap $elem -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- $shouldContinue = false -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,25 @@
|
||||
{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) (not .Values.rbac.useExistingClusterRole) }}
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "grafana.labels" . | nindent 4 }}
|
||||
{{- with .Values.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
name: {{ include "grafana.fullname" . }}-clusterrole
|
||||
{{- if or .Values.sidecar.dashboards.enabled .Values.rbac.extraClusterRoleRules .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled .Values.sidecar.alerts.enabled }}
|
||||
rules:
|
||||
{{- if or .Values.sidecar.dashboards.enabled .Values.sidecar.datasources.enabled .Values.sidecar.plugins.enabled .Values.sidecar.alerts.enabled }}
|
||||
- apiGroups: [""] # "" indicates the core API group
|
||||
resources: ["configmaps", "secrets"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
{{- end}}
|
||||
{{- with .Values.rbac.extraClusterRoleRules }}
|
||||
{{- toYaml . | nindent 2 }}
|
||||
{{- end}}
|
||||
{{- else }}
|
||||
rules: []
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
@@ -0,0 +1,24 @@
|
||||
{{- if and .Values.rbac.create (or (not .Values.rbac.namespaced) .Values.rbac.extraClusterRoleRules) }}
|
||||
kind: ClusterRoleBinding
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: {{ include "grafana.fullname" . }}-clusterrolebinding
|
||||
labels:
|
||||
{{- include "grafana.labels" . | nindent 4 }}
|
||||
{{- with .Values.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: {{ include "grafana.serviceAccountName" . }}
|
||||
namespace: {{ include "grafana.namespace" . }}
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
{{- if .Values.rbac.useExistingClusterRole }}
|
||||
name: {{ .Values.rbac.useExistingClusterRole }}
|
||||
{{- else }}
|
||||
name: {{ include "grafana.fullname" . }}-clusterrole
|
||||
{{- end }}
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
{{- end }}
|
||||
@@ -0,0 +1,43 @@
|
||||
{{- $createConfigSecret := eq (include "grafana.shouldCreateConfigSecret" .) "true" -}}
|
||||
{{- if and .Values.createConfigmap $createConfigSecret }}
|
||||
{{- $files := .Files }}
|
||||
{{- $root := . -}}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: "{{ include "grafana.fullname" . }}-config-secret"
|
||||
namespace: {{ include "grafana.namespace" . }}
|
||||
labels:
|
||||
{{- include "grafana.labels" . | nindent 4 }}
|
||||
{{- with .Values.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
data:
|
||||
{{- range $key, $value := .Values.alerting }}
|
||||
{{- if (hasKey $value "secretFile") }}
|
||||
{{- $key | nindent 2 }}:
|
||||
{{- toYaml ( $files.Get $value.secretFile ) | b64enc | nindent 4}}
|
||||
{{/* as of https://helm.sh/docs/chart_template_guide/accessing_files/ this will only work if you fork this chart and add files to it*/}}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
stringData:
|
||||
{{- range $key, $value := .Values.datasources }}
|
||||
{{- if (hasKey $value "secret") }}
|
||||
{{- $key | nindent 2 }}: |
|
||||
{{- tpl (toYaml $value.secret | nindent 4) $root }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.notifiers }}
|
||||
{{- if (hasKey $value "secret") }}
|
||||
{{- $key | nindent 2 }}: |
|
||||
{{- tpl (toYaml $value.secret | nindent 4) $root }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- range $key, $value := .Values.alerting }}
|
||||
{{ if (hasKey $value "secret") }}
|
||||
{{- $key | nindent 2 }}: |
|
||||
{{- tpl (toYaml $value.secret | nindent 4) $root }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,15 @@
|
||||
{{- if and .Values.sidecar.dashboards.enabled .Values.sidecar.dashboards.SCProvider }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
labels:
|
||||
{{- include "grafana.labels" . | nindent 4 }}
|
||||
{{- with .Values.annotations }}
|
||||
annotations:
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
name: {{ include "grafana.fullname" . }}-config-dashboards
|
||||
namespace: {{ include "grafana.namespace" . }}
|
||||
data:
|
||||
{{- include "grafana.configDashboardProviderData" . | nindent 2 }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,20 @@
|
||||
{{- if .Values.createConfigmap }}
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: {{ include "grafana.fullname" . }}
|
||||
namespace: {{ include "grafana.namespace" . }}
|
||||
labels:
|
||||
{{- include "grafana.labels" . | nindent 4 }}
|
||||
{{- if or .Values.configMapAnnotations .Values.annotations }}
|
||||
annotations:
|
||||
{{- with .Values.annotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- with .Values.configMapAnnotations }}
|
||||
{{- toYaml . | nindent 4 }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
data:
|
||||
{{- include "grafana.configData" . | nindent 2 }}
|
||||
{{- end }}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user