fix(postgresql): init

This commit is contained in:
WrenIX 2023-09-26 00:12:53 +02:00
parent 1aaf27397d
commit 352e65e513
Signed by: wrenix
GPG key ID: 7AFDB012974B1BB5
12 changed files with 486 additions and 0 deletions

23
postgresql/.helmignore Normal file
View file

@ -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
*.orig
*~
# Various IDEs
.project
.idea/
*.tmproj
.vscode/

16
postgresql/Chart.yaml Normal file
View file

@ -0,0 +1,16 @@
---
apiVersion: "v2"
name: "postgresql"
description: "A Helm chart for running PostgreSQL (Postgres) database"
type: "application"
version: "0.1.0"
appVersion: "16.0-alpine3.18"
keywords:
- "postgresql"
- "postgres"
- "database"
- "sql"
annotations:
category: "Database"

View file

@ -0,0 +1,10 @@
{{- range $username, $password := .Values.job.users }}
echo 'user "{{ $username }}":'
psql -tc "SELECT 1 FROM pg_user WHERE usename = '{{ $username }}'" | grep -q 1;
if [ $? -ne 0 ]; then
psql -c "CREATE USER {{ $username }} WITH ENCRYPTED PASSWORD '{{ $password }}'";
else
psql -c "ALTER USER {{ $username }} WITH ENCRYPTED PASSWORD '{{ $password }}'";
fi
echo ""
{{- end }}

View file

@ -0,0 +1,10 @@
{{- range $name, $config := .Values.job.databases }}
echo 'database "{{ $name }}":'
psql -tc "SELECT 1 FROM pg_database WHERE datname = '{{ $name }}'" | grep -q 1
if [ $? -ne 0 ]; then
psql -c "CREATE DATABASE {{ $name }} {{ with $config.additionalParams }}{{ . }} {{ end }}";
fi
psql -c "ALTER DATABASE {{ $name }} OWNER TO {{ $config.owner }}";
psql -c "GRANT ALL PRIVILEGES ON DATABASE {{ $name }} TO {{ $config.owner }}";
echo ""
{{- end }}

17
postgresql/files/_run Normal file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env bash
RETRIES={{ .Values.job.retries }}
until psql -c "select 1" > /dev/null 2>&1 || [ $RETRIES -eq "0" ]; do
echo "Waiting {{ .Values.job.wait }}s for postgres server, $((RETRIES--)) remaining attempts..."
sleep {{ .Values.job.wait }}
done
if [ ${RETRIES} -eq "0" ]; then
echo "Maximum wait attempts exceeded, aborting".
exit 1;
fi
set -e
for script in *.sh; do
echo "**** execute script ${script}"
./${script}
done

View file

@ -0,0 +1,62 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "postgresql.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 "postgresql.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 "postgresql.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "postgresql.labels" -}}
helm.sh/chart: {{ include "postgresql.chart" . }}
{{ include "postgresql.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "postgresql.selectorLabels" -}}
app.kubernetes.io/name: {{ include "postgresql.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
Create the name of the service account to use
*/}}
{{- define "postgresql.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "postgresql.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,74 @@
{{- if .Values.job.enabled }}
---
apiVersion: "batch/v1"
kind: "Job"
metadata:
name: "{{ include "postgresql.fullname" . }}-bootstrap"
labels:
{{- include "postgresql.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": "post-install,post-upgrade"
"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
spec:
backoffLimit: 4
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "postgresql.selectorLabels" . | nindent 8 }}
spec:
restartPolicy: Never
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "postgresql.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: "psql"
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: "PGHOST"
value: {{ include "postgresql.fullname" . | quote }}
- name: "PGPORT"
value: {{ .Values.service.port | quote }}
- name: "PGUSER"
value: {{ .Values.postgres.user | quote }}
- name: "PGPASSWORD"
value: {{ .Values.postgres.password | quote }}
command:
- "/bin/sh"
- "-c"
- "cd /bootstrap/ && ./_run"
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- mountPath: "/bootstrap/"
name: "bootstrap"
readOnly: true
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: "bootstrap"
secret:
secretName: {{ include "postgresql.fullname" . }}-job
defaultMode: 0550
{{- end }}

View file

@ -0,0 +1,16 @@
{{- if .Values.job.enabled }}
---
apiVersion: "v1"
kind: "Secret"
metadata:
name: {{ include "postgresql.fullname" . }}-job
labels:
{{- include "postgresql.labels" . | nindent 4 }}
stringData:
_run: |-
{{- tpl (.Files.Get "files/_run") . | nindent 4 }}
10-init-user.sh: |-
{{- tpl (.Files.Get "files/10-init-user.sh") . | nindent 4 }}
20-init-db.sh: |-
{{- tpl (.Files.Get "files/20-init-db.sh") . | nindent 4 }}
{{- end }}

View file

@ -0,0 +1,15 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "postgresql.fullname" . }}
labels:
{{- include "postgresql.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: postgresql
protocol: TCP
name: postgresql
selector:
{{- include "postgresql.selectorLabels" . | nindent 4 }}

View file

@ -0,0 +1,12 @@
{{- if .Values.serviceAccount.create -}}
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "postgresql.serviceAccountName" . }}
labels:
{{- include "postgresql.labels" . | nindent 4 }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}

View file

@ -0,0 +1,116 @@
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ include "postgresql.fullname" . }}
labels:
{{- include "postgresql.labels" . | nindent 4 }}
spec:
replicas: 1
serviceName: {{ include "postgresql.fullname" . }}-headless
selector:
matchLabels:
{{- include "postgresql.selectorLabels" . | nindent 6 }}
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "postgresql.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "postgresql.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: "POSTGRES_PASSWORD"
value: {{ .Values.postgres.password | quote }}
- name: "POSTGRES_USER"
value: {{ .Values.postgres.user | quote }}
- name: "PGPORT"
value: {{ .Values.service.port | quote }}
- name: "PGDATA"
value: "/var/lib/postgresql/data"
ports:
- name: postgresql
containerPort: {{ .Values.service.port }}
protocol: TCP
livenessProbe:
exec:
command:
- /bin/sh
- -c
- exec pg_isready -U {{ .Values.postgres.user | quote }} -h 127.0.0.1 -p {{ .Values.service.port }}
readinessProbe:
exec:
command:
- /bin/sh
- -c
- exec pg_isready -U {{ .Values.postgres.user | quote }} -h 127.0.0.1 -p {{ .Values.service.port }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
volumeMounts:
- name: "data"
mountPath: "/var/lib/postgresql/data"
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
volumes:
- name: "data"
{{- if .Values.persistence.hostPath }}
hostPath:
type: Directory
path: {{ .Values.persistence.hostPath | quote }}
{{- else if .Values.persistence.enabled }}
persistentVolumeClaim:
{{ if .Values.persistence.existingClaim }}
claimName: {{ .Values.persistence.existingClaim }}
{{- else }}
claimName: {{ include "postgresql.fullname" . }}-data
{{- end }}
{{- else }}
emptyDir: {}
{{- end }}
{{- if and .Values.persistence.enabled (not .Values.persistence.hostPath) (not .Values.persistence.existingClaim) }}
volumeClaimTemplates:
- metadata:
name: data
labels:
{{- include "postgresql.labels" . | nindent 8 }}
{{- with .Values.persistence.annotations }}
annotations:
{{ toYaml . | indent 8 }}
{{- end }}
spec:
accessModes:
- {{ .Values.persistence.accessMode | quote }}
resources:
requests:
storage: {{ .Values.persistence.size | quote }}
{{- with .Values.persistence.storageClass }}
{{- if (eq "-" .) }}
storageClassName: ""
{{- else }}
storageClassName: {{ . | quote }}
{{- end }}
{{- end }}
{{- end }}

115
postgresql/values.yaml Normal file
View file

@ -0,0 +1,115 @@
# Default values for postgresql.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
image:
registry: docker.io
repository: postgres
pullPolicy: IfNotPresent
# Overrides the image tag whose default is the chart appVersion.
tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
# Specifies whether a service account should be created
create: false
# Annotations to add to the service account
annotations: {}
# The name of the service account to use.
# If not set and create is true, a name is generated using the fullname template
name: ""
podAnnotations: {}
podSecurityContext: {}
# fsGroup: 2000
securityContext: {}
# capabilities:
# drop:
# - ALL
# readOnlyRootFilesystem: true
# runAsNonRoot: true
# runAsUser: 1000
service:
type: ClusterIP
port: 5432
resources: {}
# We usually recommend not to specify default resources and to leave this as a conscious
# choice for the user. This also increases chances charts run on environments with little
# resources, such as Minikube. If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
nodeSelector: {}
tolerations: []
affinity: {}
## Enable persistence using Persistent Volume Claims
## ref: http://kubernetes.io/docs/user-guide/persistent-volumes/
##
persistence:
enabled: true
annotations: {}
## 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: "-"
## A manually managed Persistent Volume and Claim
## Requires persistence.enabled: true
## If defined, PVC must be created manually before volume will be bound
# existingClaim:
## Do not create an PVC, direct use hostPath in Pod
# hostPath:
accessMode: ReadWriteOnce
size: 1Gi
# PostgreSQL configuration.
postgres:
# -- Database user.
user: "postgres"
# -- Database password.
password: "SUPERSTRONGPW"
# This job bootstrap the database server with databases and users.
job:
# -- Enable database bootstrapping.
enabled: true
# -- Amount of retries while waiting for postgresql server is available.
retries: 60
# -- Time to wait in each wait in each iteration until postgresql server is available.
wait: 5
# -- Bootstrap users into postgresql server. When users already exists, they will stay untouched.
#
# users:
# username: RandomPassword0#"
users: {}
# -- Bootstrap databases into postgresql server. When databases already exists, they will stay untouched.
#
# databases:
# "name_of_database":
# owner: "existing_user_which_will_get_grant"
# additionalParams: "" # Optional
databases: {}