feat(charts):完成第一版helm charts
This commit is contained in:
1
charts/.helmignore
Normal file
1
charts/.helmignore
Normal file
@@ -0,0 +1 @@
|
||||
*.png
|
||||
21
charts/Chart.yaml
Normal file
21
charts/Chart.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
apiVersion: v1
|
||||
name: timescaledb-multinode
|
||||
description: 'TimescaleDB Multinode Deployment.'
|
||||
version: 0.8.0
|
||||
# appVersion specifies the version of the software, which can vary wildly,
|
||||
# e.g. TimescaleDB 1.4.1 on PostgreSQL 11 or TimescaleDB 1.5.0 on PostgreSQL 12.
|
||||
# https://github.com/helm/helm/blob/master/docs/charts.md#the-appversion-field
|
||||
# To avoid confusion, we will not expose appVersion
|
||||
# appVersion: 0.0.1
|
||||
home: https://github.com/timescale/helm-charts
|
||||
sources:
|
||||
- https://github.com/timescale/helm-charts
|
||||
- https://github.com/timescale/timescaledb-docker-ha
|
||||
- https://github.com/zalando/patroni
|
||||
|
||||
# The chart is deprecated. We are looking for maintainers to remove this field.
|
||||
# More in https://github.com/timescale/helm-charts/blob/main/charts/timescaledb-multinode/README.md#call-for-maintainers
|
||||
deprecated: false
|
||||
134
charts/admin-guide.md
Normal file
134
charts/admin-guide.md
Normal file
@@ -0,0 +1,134 @@
|
||||
<!---
|
||||
This file and its contents are licensed under the Apache License 2.0.
|
||||
Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
-->
|
||||
|
||||
# TimescaleDB Single Administrator Guide
|
||||
|
||||
##### Table of Contents
|
||||
- [Configuration](#configuration)
|
||||
- [Backups](#backups)
|
||||
- [Cleanup](#cleanup)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
|
||||
## Configuration
|
||||
The following table lists the configurable parameters of the TimescaleDB Helm chart and their default values.
|
||||
|
||||
| Parameter | Description | Default |
|
||||
|-----------------------------------|---------------------------------------------|-----------------------------------------------------|
|
||||
| `nameOverride` | Override the name of the chart | `timescaledb` |
|
||||
| `fullnameOverride` | Override the fullname of the chart | `nil` |
|
||||
| `replicaCount` | Amount of pods to spawn | `3` |
|
||||
| `image.repository` | The image to pull | `timescale/timescaledb-ha` |
|
||||
| `image.tag` | The version of the image to pull | `pg12.5-ts2.0.0-p0`
|
||||
| `image.pullPolicy` | The pull policy | `IfNotPresent` |
|
||||
| `credentials.accessNode.superuser`| Password of the superuser for the Access Node | `tea` |
|
||||
| `credentials.dataNode.superuser` | Password of the superuser for the Data Nodes | `coffee` |
|
||||
| `env` | Extra custom environment variables, expressed as [EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#envvarsource-v1-core) | `PGDATA` and some language settings |
|
||||
| `resources` | Any resources you wish to assign to the pod | `{}` |
|
||||
| `nodeSelector` | Node label to use for scheduling | `{}` |
|
||||
| `tolerations` | List of node taints to tolerate | `[]` |
|
||||
| `affinityTemplate` | A template string to use to generate the affinity settings | Anti-affinity preferred on hostname |
|
||||
| `affinity` | Affinity settings. Overrides `affinityTemplate` if set. | `{}` |
|
||||
| `postgresql.databases` | List of databases to automatically create a multinode setup for | `["postgres", "example"]` |
|
||||
| `postgresql.parameters` | [PostgreSQL parameters](https://www.postgresql.org/docs/current/config-setting.html#CONFIG-SETTING-CONFIGURATION-FILE)) | Some required and preferred settings |
|
||||
| `schedulerName` | Alternate scheduler name | `nil` |
|
||||
| `persistentVolume.accessModes` | Persistent Volume access modes | `[ReadWriteOnce]` |
|
||||
| `persistentVolume.annotations` | Annotations for Persistent Volume Claim` | `{}` |
|
||||
| `persistentVolume.mountPath` | Persistent Volume mount root path | `/var/lib/postgresql` |
|
||||
| `persistentVolume.size` | Persistent Volume size | `5Gi` |
|
||||
| `persistentVolume.storageClass` | Persistent Volume Storage Class | `volume.alpha.kubernetes.io/storage-class: default` |
|
||||
| `persistentVolume.subPath` | Subdirectory of Persistent Volume to mount | `""` |
|
||||
| `rbac.create` | Create required role and rolebindings | `true` |
|
||||
| `serviceAccount.create` | If true, create a new service account | `true` |
|
||||
| `serviceAccount.name` | Service account to be used. If not set and `serviceAccount.create` is `true`, a name is generated using the fullname template | `nil` |
|
||||
|
||||
### Examples
|
||||
- Override value using commandline parameters
|
||||
```console
|
||||
helm upgrade --install my-release . --set image.tag=pg12.5-ts2.0.0-p0 --set image.pullPolicy=Always
|
||||
```
|
||||
- Override values using `myvalues.yaml`
|
||||
```yaml
|
||||
# Filename: myvalues.yaml
|
||||
image:
|
||||
tag: pg12.5-ts2.0.0-p0
|
||||
pullPolicy: Always
|
||||
postgresql:
|
||||
databases:
|
||||
- postgres
|
||||
- proddb
|
||||
parameters:
|
||||
checkpoint_completion_target: 32MB
|
||||
work_mem: 16MB
|
||||
shared_buffers: 512MB
|
||||
```
|
||||
```console
|
||||
helm upgrade --install my-release . -f myvalues.yaml
|
||||
```
|
||||
|
||||
## Cleanup
|
||||
|
||||
Removing a deployment can be done by deleting a Helm deployment, however, removing the deployment does not remove:
|
||||
- the Persistent Volume Claims (pvc) belonging to the cluster
|
||||
|
||||
To fully purge a deployment in Kubernetes, you should do the following:
|
||||
```console
|
||||
# Delete the Helm deployment
|
||||
helm delete my-release
|
||||
# Delete pvc and the headless Patroni service
|
||||
kubectl delete $(kubectl get pvc -l release=my-release -o name)
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
||||
### List Resources
|
||||
All the resources that are deployed can be listed by providing the filter `-l release=my-release`.
|
||||
|
||||
```console
|
||||
kubectl get all -l release=my-release
|
||||
```
|
||||
The output should be similar to the below output:
|
||||
```console
|
||||
NAME READY STATUS RESTARTS AGE
|
||||
pod/my-release-timescaledb-access-0 1/1 Running 0 11m
|
||||
pod/my-release-timescaledb-data-0 1/1 Running 0 11m
|
||||
pod/my-release-timescaledb-data-1 1/1 Running 0 11m
|
||||
pod/my-release-timescaledb-data-2 1/1 Running 0 11m
|
||||
|
||||
|
||||
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
|
||||
service/my-release-timescaledb LoadBalancer 10.152.183.60 <pending> 5432:31819/TCP 11m
|
||||
service/my-release-timescaledb-data ClusterIP None <none> 5432/TCP 11m
|
||||
|
||||
NAME READY AGE
|
||||
statefulset.apps/my-release-timescaledb-access 1/1 11m
|
||||
statefulset.apps/my-release-timescaledb-data 3/3 11m
|
||||
```
|
||||
|
||||
> **INFO** When listing resources within minutes of deploying a new Helm chart, you may see a list of jobs and its pods;
|
||||
these jobs are there to create the database, and to attach the data nodes to the access node. There will be quite a few,
|
||||
but these should disappear within minutes after successful deployment.
|
||||
|
||||
### Investigate TimescaleDB logs
|
||||
|
||||
The logs for the Access Node of TimescaleDB can be accessed as follows:
|
||||
|
||||
```console
|
||||
kubectl logs $(kubectl get pod -l release=my-release,timescaleNodeType=access) timescaledb
|
||||
```
|
||||
|
||||
### Verify multinode topology
|
||||
```console
|
||||
$ kubectl exec -ti $(kubectl get pod -l timescaleNodeType=access -o name) -c timescaledb -- psql -d example -c 'select node_name from timescaledb_information.data_nodes'
|
||||
```
|
||||
```text
|
||||
node_name
|
||||
-------------------------------
|
||||
my-release-timescaledb-data-0
|
||||
my-release-timescaledb-data-1
|
||||
my-release-timescaledb-data-2
|
||||
(3 rows)
|
||||
|
||||
```
|
||||
28
charts/templates/NOTES.txt
Normal file
28
charts/templates/NOTES.txt
Normal file
@@ -0,0 +1,28 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
TimescaleDB can be accessed via port 5432 on the following DNS name from within your cluster:
|
||||
{{ template "timescaledb.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local
|
||||
|
||||
To get your password for superuser run:
|
||||
|
||||
# superuser password
|
||||
PGPASSWORD_SUPERUSER=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "timescaledb.fullname" . }} -o jsonpath="{.data.password-superuser}" | base64 --decode)
|
||||
|
||||
# admin password
|
||||
PGPASSWORD_ADMIN=$(kubectl get secret --namespace {{ .Release.Namespace }} {{ template "timescaledb.fullname" . }} -o jsonpath="{.data.password-admin}" | base64 --decode)
|
||||
|
||||
To connect to your database:
|
||||
|
||||
1. Run a postgres pod and connect using the psql cli:
|
||||
# login as superuser
|
||||
kubectl run -i --tty --rm psql --image=postgres \
|
||||
--env "PGPASSWORD=$PGPASSWORD_SUPERUSER" \
|
||||
--command -- psql -U postgres \
|
||||
-h {{ template "timescaledb.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local postgres
|
||||
|
||||
# login as admin
|
||||
kubectl run -i -tty --rm psql --image=postgres \
|
||||
--env "PGPASSWORD=$PGPASSWORD_ADMIN" \
|
||||
--command -- psql -U admin \
|
||||
-h {{ template "timescaledb.fullname" . }}.{{ .Release.Namespace }}.svc.cluster.local postgres
|
||||
60
charts/templates/_helpers.tpl
Normal file
60
charts/templates/_helpers.tpl
Normal file
@@ -0,0 +1,60 @@
|
||||
{{/*
|
||||
This file and its contents are licensed under the Apache License 2.0.
|
||||
Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
*/}}
|
||||
{{/* vim: set filetype=mustache: */}}
|
||||
{{/*
|
||||
Expand the name of the chart.
|
||||
*/}}
|
||||
{{- define "timescaledb.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 "timescaledb.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 -}}
|
||||
|
||||
{{- define "timescaledb.dataname" -}}
|
||||
{{ template "timescaledb.fullname" . }}-data
|
||||
{{- end -}}
|
||||
|
||||
|
||||
{{- define "timescaledb.accessname" -}}
|
||||
{{ template "timescaledb.fullname" . }}-access
|
||||
{{- end -}}
|
||||
|
||||
{{- define "postgres.uid" -}}
|
||||
{{- default .Values.uid "1000" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create chart name and version as used by the chart label.
|
||||
*/}}
|
||||
{{- define "timescaledb.chart" -}}
|
||||
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Create the name of the service account to use.
|
||||
*/}}
|
||||
{{- define "timescaledb.serviceAccountName" -}}
|
||||
{{- if .Values.serviceAccount.create -}}
|
||||
{{ default (include "timescaledb.fullname" .) .Values.serviceAccount.name }}
|
||||
{{- else -}}
|
||||
{{ default "default" .Values.serviceAccount.name }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
77
charts/templates/job-attach-datanode.yaml
Normal file
77
charts/templates/job-attach-datanode.yaml
Normal file
@@ -0,0 +1,77 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
{{- range $pod, $e := until ( .Values.dataNodes | int) }}
|
||||
{{- range $index, $dbname := $.Values.postgresql.databases }}
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ printf "attachdn-%s-db%s-data%s" $.Release.Name ($index | toString) ($pod | toString) | trunc 63 }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" $ }}
|
||||
chart: {{ template "timescaledb.chart" $ }}
|
||||
release: {{ $.Release.Name }}
|
||||
heritage: {{ $.Release.Service }}
|
||||
annotations:
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 600
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" $ }}
|
||||
chart: {{ template "timescaledb.chart" $ }}
|
||||
release: {{ $.Release.Name }}
|
||||
heritage: {{ $.Release.Service }}
|
||||
dataNode: {{ template "timescaledb.dataname" $ }}-{{ $pod }}
|
||||
spec:
|
||||
containers:
|
||||
- name: attachdn-{{ $index }}
|
||||
image: postgres:14.5-alpine # A relatively small official image that can run psql
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
# We wait for the data node to allow connections
|
||||
# We wait for the access node to allow connections to DBNAME
|
||||
- >
|
||||
while ! pg_isready -U postgres -h "${DATA_NODE_DNS}"; do sleep 1; done;
|
||||
while ! psql -d "${ACCESS_SVC_CONNSTR}" --set dbname="${DBNAME}" --set ON_ERROR_STOP=1 --command '\c :"dbname"'; do sleep 1; done;
|
||||
echo "${SQLCOMMAND}" | psql -d "${ACCESS_SVC_CONNSTR}" --file=- --echo-queries --set ON_ERROR_STOP=1 \
|
||||
--set dbname="${DBNAME}" \
|
||||
--set data_node_name="${DATA_NODE_NAME}" \
|
||||
--set data_node_dns="${DATA_NODE_DNS}"
|
||||
env:
|
||||
{{- /*
|
||||
Some parameter juggling is required to ensure we don't have SQL injection;
|
||||
which is not necessarily a major security leak at this stage, but we want
|
||||
to be able to support database names like 'test db' or, 'CamelCase'.
|
||||
|
||||
The template quote function ensures bash will be able to interpret the variable.
|
||||
The --set dbname= and subsequent :'dbname' psql_variable ensures no SQL injection can occur.
|
||||
|
||||
https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-INTERPOLATION
|
||||
*/}}
|
||||
- name: DBNAME
|
||||
value: {{ $dbname | quote }}
|
||||
- name: ACCESS_SVC_CONNSTR
|
||||
value: host={{ template "timescaledb.fullname" $ }} user=postgres connect_timeout=3 sslmode=disable
|
||||
- name: DATA_NODE_DNS
|
||||
value: {{ template "timescaledb.dataname" $ }}-{{ $pod }}.{{ template "timescaledb.dataname" $ }}
|
||||
- name: DATA_NODE_NAME
|
||||
value: {{ template "timescaledb.dataname" $ }}-{{ $pod }}
|
||||
- name: SQLCOMMAND
|
||||
value: |
|
||||
\c :"dbname"
|
||||
SELECT *
|
||||
FROM add_data_node(:'data_node_name'::name, host => :'data_node_dns', if_not_exists => true)
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "timescaledb.accessname" $ }}
|
||||
key: password-superuser
|
||||
restartPolicy: OnFailure
|
||||
backoffLimit: 2
|
||||
...
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
72
charts/templates/job-create-databases.yaml
Normal file
72
charts/templates/job-create-databases.yaml
Normal file
@@ -0,0 +1,72 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
{{- range $index, $dbname := .Values.postgresql.databases }}
|
||||
---
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: {{ printf "createdb-%s-db%s" $.Release.Name ($index | toString) | trunc 63 }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" $ }}
|
||||
chart: {{ template "timescaledb.chart" $ }}
|
||||
release: {{ $.Release.Name }}
|
||||
heritage: {{ $.Release.Service }}
|
||||
annotations:
|
||||
"helm.sh/hook-delete-policy": hook-succeeded
|
||||
spec:
|
||||
ttlSecondsAfterFinished: 600
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" $ }}
|
||||
chart: {{ template "timescaledb.chart" $ }}
|
||||
release: {{ $.Release.Name }}
|
||||
heritage: {{ $.Release.Service }}
|
||||
spec:
|
||||
containers:
|
||||
- name: createdb-{{ $index }}
|
||||
image: postgres:14.5-alpine # A relatively small official image that can run psql
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- >
|
||||
while ! pg_isready -U postgres -h {{ template "timescaledb.fullname" $ }}; do sleep 1; done;
|
||||
echo "${SQLCOMMAND}" | psql --file=- --echo-queries -d "${ACCESS_SVC_CONNSTR}" \
|
||||
--set ON_ERROR_STOP=1 \
|
||||
--set dbname="${DBNAME}"
|
||||
env:
|
||||
{{- /*
|
||||
Some parameter juggling is required to ensure we don't have SQL injection;
|
||||
which is not necessarily a major security leak at this stage, but we want
|
||||
to be able to support database names like 'test db' or, 'CamelCase'.
|
||||
|
||||
The template quote function ensures bash will be able to interpret the variable.
|
||||
The --set dbname= and subsequent :'dbname' psql_variable ensures no SQL injection can occur.
|
||||
|
||||
https://www.postgresql.org/docs/current/app-psql.html#APP-PSQL-INTERPOLATION
|
||||
*/}}
|
||||
- name: DBNAME
|
||||
value: {{ $dbname | quote }}
|
||||
- name: ACCESS_SVC_CONNSTR
|
||||
value: host={{ template "timescaledb.fullname" $ }} user=postgres connect_timeout=3 sslmode=disable
|
||||
- name: SQLCOMMAND
|
||||
value: |
|
||||
SELECT format('CREATE DATABASE %I', :'dbname')
|
||||
WHERE NOT EXISTS (
|
||||
SELECT
|
||||
FROM pg_database
|
||||
WHERE datname=:'dbname'
|
||||
)
|
||||
\gexec
|
||||
\c :"dbname"
|
||||
CREATE EXTENSION IF NOT EXISTS timescaledb;
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "timescaledb.accessname" $ }}
|
||||
key: password-superuser
|
||||
restartPolicy: OnFailure
|
||||
backoffLimit: 2
|
||||
...
|
||||
{{ end }}
|
||||
31
charts/templates/sec-timescaledb.yaml
Normal file
31
charts/templates/sec-timescaledb.yaml
Normal file
@@ -0,0 +1,31 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "timescaledb.accessname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
chart: {{ template "timescaledb.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
type: Opaque
|
||||
data:
|
||||
password-superuser: {{ .Values.credentials.accessNode.superuser | b64enc }}
|
||||
...
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "timescaledb.dataname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
chart: {{ template "timescaledb.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
type: Opaque
|
||||
data:
|
||||
password-superuser: {{ .Values.credentials.dataNode.superuser | b64enc }}
|
||||
...
|
||||
14
charts/templates/serviceaccount-timescaledb.yaml
Normal file
14
charts/templates/serviceaccount-timescaledb.yaml
Normal file
@@ -0,0 +1,14 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
{{- if .Values.serviceAccount.create }}
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: {{ template "timescaledb.serviceAccountName" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
chart: {{ template "timescaledb.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
{{- end }}
|
||||
166
charts/templates/statefulset-timescaledb-accessnode.yaml
Normal file
166
charts/templates/statefulset-timescaledb-accessnode.yaml
Normal file
@@ -0,0 +1,166 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ template "timescaledb.accessname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
chart: {{ template "timescaledb.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
serviceName: {{ template "timescaledb.accessname" . }}
|
||||
replicas: 1
|
||||
podManagementPolicy: Parallel
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
release: {{ .Release.Name }}
|
||||
timescaleNodeType: access
|
||||
template:
|
||||
metadata:
|
||||
name: {{ template "timescaledb.accessname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
release: {{ .Release.Name }}
|
||||
timescaleNodeType: access
|
||||
spec:
|
||||
serviceAccountName: {{ template "timescaledb.serviceAccountName" . }}
|
||||
securityContext:
|
||||
# The postgres user inside the TimescaleDB image has uid=1000.
|
||||
# This configuration ensures the permissions of the mounts are suitable
|
||||
fsGroup: {{ template "postgres.uid" }}
|
||||
runAsGroup: {{ template "postgres.uid" }}
|
||||
runAsNonRoot: true
|
||||
runAsUser: {{ template "postgres.uid" }}
|
||||
initContainers:
|
||||
- name: initdb
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
env:
|
||||
- name: POSTGRESQL_CUSTOM_PARAMETERS
|
||||
value: |
|
||||
{{- range $key, $value := .Values.postgresql.parameters }}
|
||||
{{ printf "%s = '%s'" $key ($value | toString) }}
|
||||
{{- end }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "timescaledb.accessname" . }}
|
||||
key: password-superuser
|
||||
- name: POSTGRES_PASSWORD_DATA_NODE
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "timescaledb.dataname" . }}
|
||||
key: password-superuser
|
||||
{{- if .Values.env }}
|
||||
{{ .Values.env | default list | toYaml | indent 8 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- sh
|
||||
- '-c'
|
||||
# By calling the original entrypoint with the first argument being postgres
|
||||
# we ensure we do everything that is required to init a PostgreSQL instance.
|
||||
# By supplying --single however, we ensure the postmaster is running in the
|
||||
# foreground, allowing us to do some more initialization
|
||||
- |
|
||||
set -e
|
||||
install -o postgres -g postgres -m 0700 -d "${PGDATA}"
|
||||
/docker-entrypoint.sh postgres --single < /dev/null
|
||||
grep -qxF "include 'postgresql_helm_customizations.conf'" "${PGDATA}/postgresql.conf" \
|
||||
|| echo "include 'postgresql_helm_customizations.conf'" >> "${PGDATA}/postgresql.conf"
|
||||
echo "Writing custom PostgreSQL Parameters to ${PGDATA}/postgresql_helm_customizations.conf"
|
||||
echo "cluster_name = '$(hostname)'" > "${PGDATA}/postgresql_helm_customizations.conf"
|
||||
echo "${POSTGRESQL_CUSTOM_PARAMETERS}" | sort >> "${PGDATA}/postgresql_helm_customizations.conf"
|
||||
echo "*:*:*:postgres:${POSTGRES_PASSWORD_DATA_NODE}" > "${PGDATA}/../.pgpass"
|
||||
chown postgres:postgres "${PGDATA}/../.pgpass" "${PGDATA}/postgresql_helm_customizations.conf"
|
||||
chmod 0600 "${PGDATA}/../.pgpass"
|
||||
echo "Adding host all all all md5 in pg_hba.conf"
|
||||
grep -qxF "host all all all md5" "${PGDATA}/pg_hba.conf" \
|
||||
|| echo "host all all all md5" >> ${PGDATA}/pg_hba.conf
|
||||
volumeMounts:
|
||||
- name: storage-volume
|
||||
mountPath: "{{ .Values.persistentVolume.mountPath }}"
|
||||
subPath: "{{ .Values.persistentVolume.subPath }}"
|
||||
containers:
|
||||
- name: timescaledb
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
# We start postgres with a fully cleared environment
|
||||
command:
|
||||
- sh
|
||||
- '-c'
|
||||
- exec env -i PGDATA="${PGDATA}" PATH="${PATH}" /docker-entrypoint.sh postgres
|
||||
env:
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: metadata.namespace
|
||||
{{- if .Values.env }}
|
||||
{{ .Values.env | default list | toYaml | indent 8 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
volumeMounts:
|
||||
- name: storage-volume
|
||||
mountPath: "{{ .Values.persistentVolume.mountPath }}"
|
||||
subPath: "{{ .Values.persistentVolume.subPath }}"
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 10 }}
|
||||
# {{- with .Values.nodeSelector }}
|
||||
# nodeSelector:
|
||||
nodeSelector:
|
||||
kubernetes.io/hostname: an
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.schedulerName }}
|
||||
schedulerName: {{ .Values.schedulerName }}
|
||||
{{- end }}
|
||||
{{- if .Values.affinity }}
|
||||
affinity:
|
||||
{{ .Values.affinity | toYaml | indent 8 }}
|
||||
{{- else if .Values.affinityTemplate }}
|
||||
affinity:
|
||||
{{ tpl .Values.affinityTemplate . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if not .Values.persistentVolume.enabled }}
|
||||
- name: storage-volume
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if .Values.persistentVolume.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: storage-volume
|
||||
annotations:
|
||||
{{- if .Values.persistentVolume.annotations }}
|
||||
{{ toYaml .Values.persistentVolume.annotations | indent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{ toYaml .Values.persistentVolume.accessModes | indent 8 }}
|
||||
resources:
|
||||
requests:
|
||||
storage: "{{ .Values.persistentVolume.size }}"
|
||||
{{- if .Values.persistentVolume.storageClass }}
|
||||
{{- if (eq "-" .Values.persistentVolume.storageClass) }}
|
||||
storageClassName: ""
|
||||
{{- else }}
|
||||
storageClassName: "{{ .Values.persistentVolume.storageClass }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
159
charts/templates/statefulset-timescaledb-datanode.yaml
Normal file
159
charts/templates/statefulset-timescaledb-datanode.yaml
Normal file
@@ -0,0 +1,159 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
name: {{ template "timescaledb.dataname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
chart: {{ template "timescaledb.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
serviceName: {{ template "timescaledb.dataname" . }}
|
||||
replicas: {{ .Values.dataNodes }}
|
||||
podManagementPolicy: Parallel
|
||||
selector:
|
||||
matchLabels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
release: {{ .Release.Name }}
|
||||
timescaleNodeType: data
|
||||
template:
|
||||
metadata:
|
||||
name: {{ template "timescaledb.dataname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
release: {{ .Release.Name }}
|
||||
timescaleNodeType: data
|
||||
spec:
|
||||
serviceAccountName: {{ template "timescaledb.serviceAccountName" . }}
|
||||
securityContext:
|
||||
# The postgres user inside the TimescaleDB image has uid=1000.
|
||||
# This configuration ensures the permissions of the mounts are suitable
|
||||
fsGroup: {{ template "postgres.uid" }}
|
||||
runAsGroup: {{ template "postgres.uid" }}
|
||||
runAsNonRoot: true
|
||||
runAsUser: {{ template "postgres.uid" }}
|
||||
initContainers:
|
||||
- name: initdb
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
env:
|
||||
- name: POSTGRESQL_CUSTOM_PARAMETERS
|
||||
value: |
|
||||
{{- range $key, $value := .Values.postgresql.parameters }}
|
||||
{{ printf "%s = '%s'" $key ($value | toString) }}
|
||||
{{- end }}
|
||||
- name: POSTGRES_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "timescaledb.dataname" . }}
|
||||
key: password-superuser
|
||||
{{- if .Values.env }}
|
||||
{{ .Values.env | default list | toYaml | indent 8 }}
|
||||
{{- end }}
|
||||
command:
|
||||
- sh
|
||||
- '-c'
|
||||
# By calling the original entrypoint with the first argument being postgres
|
||||
# we ensure we do everything that is required to init a PostgreSQL instance.
|
||||
# By supplying --single however, we ensure the postmaster is running in the
|
||||
# foreground, allowing us to do some more initialization
|
||||
- |
|
||||
set -e
|
||||
install -o postgres -g postgres -m 0700 -d "${PGDATA}" "${PGDATA}/../conf.d"
|
||||
/docker-entrypoint.sh postgres --single < /dev/null
|
||||
grep -qxF "include 'postgresql_helm_customizations.conf'" "${PGDATA}/postgresql.conf" \
|
||||
|| echo "include 'postgresql_helm_customizations.conf'" >> "${PGDATA}/postgresql.conf"
|
||||
echo "Writing custom PostgreSQL Parameters to ${PGDATA}/postgresql_helm_customizations.conf"
|
||||
echo "cluster_name = '$(hostname)'" > "${PGDATA}/postgresql_helm_customizations.conf"
|
||||
echo "${POSTGRESQL_CUSTOM_PARAMETERS}" | sort >> "${PGDATA}/postgresql_helm_customizations.conf"
|
||||
echo "Adding host all all all md5 in pg_hba.conf"
|
||||
grep -qxF "host all all all md5" "${PGDATA}/pg_hba.conf" \
|
||||
|| echo "host all all all md5" >> ${PGDATA}/pg_hba.conf
|
||||
# The TimescaleDB extension should not be available by default, as this interferes with the bootstrapping
|
||||
# done by the access nodes. Therefore we drop the extensions from template1
|
||||
echo "DROP EXTENSION timescaledb" | /docker-entrypoint.sh postgres --single -D "${PGDATA}" template1
|
||||
volumeMounts:
|
||||
- name: storage-volume
|
||||
mountPath: "{{ .Values.persistentVolume.mountPath }}"
|
||||
subPath: "{{ .Values.persistentVolume.subPath }}"
|
||||
containers:
|
||||
- name: timescaledb
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: false
|
||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
|
||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||
# We start postgres with a fully cleared environment
|
||||
command:
|
||||
- sh
|
||||
- '-c'
|
||||
- exec env -i PGDATA="${PGDATA}" PATH="${PATH}" /docker-entrypoint.sh postgres
|
||||
env:
|
||||
- name: POD_NAMESPACE
|
||||
valueFrom:
|
||||
fieldRef:
|
||||
apiVersion: v1
|
||||
fieldPath: metadata.namespace
|
||||
{{- if .Values.env }}
|
||||
{{ .Values.env | default list | toYaml | indent 8 }}
|
||||
{{- end }}
|
||||
ports:
|
||||
- containerPort: 5432
|
||||
volumeMounts:
|
||||
- name: storage-volume
|
||||
mountPath: "{{ .Values.persistentVolume.mountPath }}"
|
||||
subPath: "{{ .Values.persistentVolume.subPath }}"
|
||||
resources:
|
||||
{{ toYaml .Values.resources | indent 10 }}
|
||||
{{- with .Values.nodeSelector }}
|
||||
nodeSelector:
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- with .Values.tolerations }}
|
||||
tolerations:
|
||||
{{ toYaml . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if .Values.schedulerName }}
|
||||
schedulerName: {{ .Values.schedulerName }}
|
||||
{{- end }}
|
||||
{{- if .Values.affinity }}
|
||||
affinity:
|
||||
{{ .Values.affinity | toYaml | indent 8 }}
|
||||
{{- else if .Values.affinityTemplate }}
|
||||
affinity:
|
||||
{{ tpl .Values.affinityTemplate . | indent 8 }}
|
||||
{{- end }}
|
||||
{{- if not .Values.persistentVolume.enabled }}
|
||||
- name: storage-volume
|
||||
emptyDir: {}
|
||||
{{- end }}
|
||||
{{- if .Values.persistentVolume.enabled }}
|
||||
volumeClaimTemplates:
|
||||
- metadata:
|
||||
name: storage-volume
|
||||
annotations:
|
||||
{{- if .Values.persistentVolume.annotations }}
|
||||
{{ toYaml .Values.persistentVolume.annotations | indent 8 }}
|
||||
{{- end }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
accessModes:
|
||||
{{ toYaml .Values.persistentVolume.accessModes | indent 8 }}
|
||||
resources:
|
||||
requests:
|
||||
storage: "{{ .Values.persistentVolume.size }}"
|
||||
{{- if .Values.persistentVolume.storageClass }}
|
||||
{{- if (eq "-" .Values.persistentVolume.storageClass) }}
|
||||
storageClassName: ""
|
||||
{{- else }}
|
||||
storageClassName: "{{ .Values.persistentVolume.storageClass }}"
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
25
charts/templates/svc-timescaledb-access.yaml
Normal file
25
charts/templates/svc-timescaledb-access.yaml
Normal file
@@ -0,0 +1,25 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "timescaledb.fullname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
chart: {{ template "timescaledb.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
annotations:
|
||||
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "4000"
|
||||
spec:
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- name: postgresql
|
||||
port: 5432
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
timescaleNodeType: access
|
||||
...
|
||||
23
charts/templates/svc-timescaledb-data.yaml
Normal file
23
charts/templates/svc-timescaledb-data.yaml
Normal file
@@ -0,0 +1,23 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: {{ template "timescaledb.dataname" . }}
|
||||
labels:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
chart: {{ template "timescaledb.chart" . }}
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
spec:
|
||||
clusterIP: None
|
||||
ports:
|
||||
- name: postgresql
|
||||
port: 5432
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: {{ template "timescaledb.fullname" . }}
|
||||
timescaleNodeType: data
|
||||
...
|
||||
114
charts/values.yaml
Normal file
114
charts/values.yaml
Normal file
@@ -0,0 +1,114 @@
|
||||
# This file and its contents are licensed under the Apache License 2.0.
|
||||
# Please see the included NOTICE for copyright information and LICENSE for a copy of the license.
|
||||
|
||||
dataNodes: 3
|
||||
|
||||
# To prevent very long names, we override the name, otherwise it would default to
|
||||
# timescaledb-multinode (the name of the chart)
|
||||
nameOverride: timescaledb
|
||||
|
||||
image:
|
||||
# Image was built from
|
||||
# https://github.com/timescale/timescaledb-docker-ha
|
||||
repository: timescale/timescaledb-ha
|
||||
tag: pg14.5-ts2.8.0-patroni-static-primary-latest
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
# Credentials used by PostgreSQL
|
||||
credentials:
|
||||
accessNode:
|
||||
superuser: big_dick
|
||||
dataNode:
|
||||
superuser: big_dick
|
||||
|
||||
# Extra custom environment variables.
|
||||
# These should be an EnvVar, as this allows you to inject secrets into the environment
|
||||
# https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/#envvar-v1-core
|
||||
env:
|
||||
- name: LC_ALL
|
||||
value: C.UTF-8
|
||||
- name: LANG
|
||||
value: C.UTF-8
|
||||
- name: PGDATA
|
||||
# This should be a subdirectory of the persistentVolume (if any), as PostgreSQL will need to
|
||||
# fully manage permissions. Also, using /var/lib/postgresql/data is discouraged, as this is
|
||||
# a Docker Volume in many Docker images, which means the data is not actually persisted.
|
||||
value: /var/lib/postgresql/pgdata
|
||||
|
||||
persistentVolume:
|
||||
enabled: true
|
||||
size: 100G
|
||||
## database 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: "-"
|
||||
subPath: ""
|
||||
mountPath: "/var/lib/postgresql"
|
||||
annotations: {}
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
|
||||
resources: {}
|
||||
|
||||
postgresql:
|
||||
databases:
|
||||
- postgres
|
||||
- example
|
||||
parameters:
|
||||
max_connections: 100
|
||||
max_prepared_transactions: 150
|
||||
# This is rather small, but as this Helm Chart may be used to spin up
|
||||
# 1 access node and 4 data nodes on a single minikube/microk8s this is set
|
||||
# to a conservative value
|
||||
shared_buffers: 300MB
|
||||
work_mem: 16MB
|
||||
log_connections: 'on'
|
||||
log_line_prefix: "%t [%p]: [%c-%l] %u@%d,app=%a [%e] "
|
||||
log_min_duration_statement: '1s'
|
||||
log_statement: ddl
|
||||
log_checkpoints: 'on'
|
||||
log_lock_waits: 'on'
|
||||
# These values are set as the default data volume size
|
||||
# is small as well.
|
||||
min_wal_size: 256MB
|
||||
max_wal_size: 512MB
|
||||
temp_file_limit: 1GB
|
||||
|
||||
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#nodeselector
|
||||
nodeSelector: {}
|
||||
|
||||
# https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
|
||||
tolerations: []
|
||||
|
||||
# https://kubernetes.io/docs/concepts/configuration/assign-pod-node/#affinity-and-anti-affinity
|
||||
affinityTemplate: |
|
||||
podAntiAffinity:
|
||||
preferredDuringSchedulingIgnoredDuringExecution:
|
||||
- weight: 100
|
||||
podAffinityTerm:
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
labelSelector:
|
||||
matchLabels:
|
||||
app: {{ template "timescaledb.name" . }}
|
||||
release: {{ .Release.Name | quote }}
|
||||
affinity: {}
|
||||
|
||||
## Use an alternate scheduler, e.g. "stork".
|
||||
## ref: https://kubernetes.io/docs/tasks/administer-cluster/configure-multiple-schedulers/
|
||||
##
|
||||
# schedulerName:
|
||||
|
||||
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:
|
||||
Reference in New Issue
Block a user