initial work on single-container postgresql app (#758)

* initial work on single-container postgresql app

* update

* some more polish

* use new common version for postgresql

* fix a mistake

* moar fixup

* whoops

* fixes

* more fixing

* add pre-upgrade backup hook

* also add backup storage to questions.yaml
This commit is contained in:
Kjeld Schouten-Lebbing
2021-08-12 13:55:45 +02:00
committed by GitHub
parent a0a77fa6a3
commit 9808021cbc
13 changed files with 860 additions and 0 deletions

View File

@@ -0,0 +1,24 @@
# 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
.project
.idea/
*.tmproj
.vscode/
# OWNERS file for Kubernetes
OWNERS

View File

@@ -0,0 +1,8 @@
# Configuration Options
##### Connecting to other apps
If you need to connect this App to other Apps on TrueNAS SCALE, please refer to our "Linking Apps Together" guide:
https://truecharts.org/manual/linking/
##### Available config options
In the future this page is going to contain an automated list of options available in the installation/edit UI.

View File

@@ -0,0 +1,29 @@
apiVersion: v2
kubeVersion: ">=1.16.0-0"
name: postgresql
version: 1.0.0
appVersion: "auto"
description: PostgresSQL
type: application
deprecated: false
home: https://github.com/truecharts/apps/tree/master/stable/postgres
icon: https://d1q6f0aelx0por.cloudfront.net/product-logos/library-postgres-logo.png
keywords:
- postgres
- postgressql
- dtabase
- sql
sources:
- https://www.postgresql.org/
dependencies:
- name: common
repository: https://truecharts.org/
version: 6.8.0
maintainers:
- email: info@truecharts.org
name: TrueCharts
url: truecharts.org
- email: kjeld@schouten-lebbing.nl
name: Ornias1993
url: truecharts.org
# annotations:

View File

@@ -0,0 +1,3 @@
# Introduction
![Version: 2.0.0](https://img.shields.io/badge/Version-2.0.0-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: auto](https://img.shields.io/badge/AppVersion-auto-informational?style=flat-square)

View File

@@ -0,0 +1,3 @@
categories:
- database
icon_url: https://d1q6f0aelx0por.cloudfront.net/product-logos/library-postgres-logo.png

View File

@@ -0,0 +1,30 @@
##
# This file contains Values.yaml content that gets added to the output of questions.yaml
# It's ONLY meant for content that the user is NOT expected to change.
# Example: Everything under "image" is not included in questions.yaml but is included here.
##
image:
repository: postgres
pullPolicy: IfNotPresent
tag: "13.3"
pgdatapath: "/data"
envValueFrom:
POSTGRES_PASSWORD:
secretKeyRef:
name: '{{ .Values.existingSecret | default ( include "common.names.fullname" . ) }}'
key: "postgresql-password"
envTpl:
PGDATA: "{{ .Values.pgdatapath }}"
POSTGRES_USER: "{{ .Values.postgresqlUsername }}"
POSTGRES_DB: "{{ .Values.postgresqlDatabase }}"
# POSTGRESQL_POSTGRES_PASSWORD: "{{ .Values.postgrespassword }}"
# POSTGRESQL_PASSWORD: "{{ .Values.password }}"
##
# Most other defaults are set in questions.yaml
# For other options please refer to the wiki, default_values.yaml or the common library chart
##

View File

@@ -0,0 +1,631 @@
groups:
- name: "Container Image"
description: "Image to be used for container"
- name: "Controller"
description: "Configure workload deployment"
- name: "Container Configuration"
description: "additional container configuration"
- name: "App Configuration"
description: "App specific config options"
- name: "Networking and Services"
description: "Configure Network and Services for container"
- name: "Storage and Persistence"
description: "Persist and share data that is separate from the container"
- name: "Ingress"
description: "Ingress Configuration"
- name: "Security and Permissions"
description: "Configure security context and permissions"
- name: "Resources and Devices"
description: "Specify resources/devices to be allocated to workload"
- name: "Advanced"
description: "Advanced Configuration"
questions:
- variable: portal
group: "Container Image"
label: "Configure Portal Button"
schema:
type: dict
hidden: true
attrs:
- variable: enabled
label: "Enable"
description: "enable the portal button"
schema:
hidden: true
editable: false
type: boolean
default: false
- variable: controller
group: "Controller"
label: ""
schema:
type: dict
attrs:
- variable: type
description: "Please specify type of workload to deploy"
label: "(Advanced) Controller Type"
schema:
type: string
default: "deployment"
required: true
enum:
- value: "deployment"
description: "Deployment"
- value: "statefulset"
description: "Statefulset"
- value: "daemonset"
description: "Daemonset"
- variable: replicas
description: "Number of desired pod replicas"
label: "Desired Replicas"
schema:
type: int
default: 1
required: true
- variable: strategy
description: "Please specify type of workload to deploy"
label: "(Advanced) Update Strategy"
schema:
type: string
default: "Recreate"
required: true
enum:
- value: "Recreate"
description: "Recreate: Kill existing pods before creating new ones"
- value: "RollingUpdate"
description: "RollingUpdate: Create new pods and then kill old ones"
- value: "OnDelete"
description: "(Legacy) OnDelete: ignore .spec.template changes"
- variable: env
group: "Container Configuration"
label: "Image Environment"
schema:
type: dict
attrs:
- variable: TZ
label: "Timezone"
schema:
type: string
default: "Etc/UTC"
$ref:
- "definitions/timezone"
# Configure Enviroment Variables
- variable: envList
label: "Image environment"
group: "Container Configuration"
schema:
type: list
default: []
items:
- variable: envItem
label: "Environment Variable"
schema:
type: dict
attrs:
- variable: name
label: "Name"
schema:
type: string
- variable: value
label: "Value"
schema:
type: string
- variable: postgresqlDatabase
group: "App Configuration"
label: "Database Name"
schema:
type: string
default: "mydatabase"
required: true
- variable: user
group: "App Configuration"
label: "Database User"
schema:
type: string
default: "mydatabaseuser"
required: true
- variable: postgresqlPassword
group: "App Configuration"
label: "Database Password"
schema:
type: string
default: ""
required: true
- variable: hostNetwork
group: "Networking and Services"
label: "Enable Host Networking"
schema:
type: boolean
default: false
- variable: service
group: "Networking and Services"
label: "Configure Service(s)"
schema:
type: dict
attrs:
- variable: main
label: "Main Service"
description: "The Primary service on which the healthcheck runs, often the webUI"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the service"
schema:
type: boolean
default: true
hidden: true
- variable: type
label: "Service Type"
description: "ClusterIP's are only internally available, nodePorts expose the container to the host node System, Loadbalancer exposes the service using the system loadbalancer"
schema:
type: string
default: "ClusterIP"
enum:
- value: "NodePort"
description: "NodePort"
- value: "ClusterIP"
description: "ClusterIP"
- value: "LoadBalancer"
description: "LoadBalancer"
- variable: loadBalancerIP
label: "LoadBalancer IP"
description: "LoadBalancerIP"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: string
default: ""
- variable: externalIPs
label: "External IP's"
description: "External IP's"
schema:
show_if: [["type", "=", "LoadBalancer"]]
type: list
default: []
items:
- variable: externalIP
label: "External IP"
schema:
type: string
- variable: ports
label: "Service's Port(s) Configuration"
schema:
type: dict
attrs:
- variable: main
label: "Main Service Port Configuration"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the port"
schema:
type: boolean
default: true
hidden: true
- variable: protocol
label: "Port Type"
schema:
type: string
default: "TCP"
enum:
- value: HTTP
description: "HTTP"
- value: "HTTPS"
description: "HTTPS"
- value: TCP
description: "TCP"
- value: "UDP"
description: "UDP"
- variable: port
label: "Container Port"
schema:
type: int
default: 5432
editable: false
hidden: true
- variable: targetport
label: "Target Port"
description: "This port exposes the container port on the service"
schema:
type: int
default: 5432
editable: true
required: true
- variable: nodePort
label: "Node Port (Optional)"
description: "This port gets exposed to the node. Only considered when service type is NodePort"
schema:
type: int
min: 9000
max: 65535
default: 36009
required: true
- variable: persistence
label: "Integrated Persistent Storage"
group: "Storage and Persistence"
schema:
type: dict
attrs:
- variable: data
label: "App data Storage"
description: "Stores the Application Database."
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the storage"
schema:
type: boolean
default: true
- variable: type
label: "(Advanced) Type of Storage"
description: "Sets the persistence type"
schema:
type: string
default: "pvc"
enum:
- value: "pvc"
description: "pvc"
- value: "emptyDir"
description: "emptyDir"
- value: "hostPath"
description: "hostPath"
- variable: storageClass
label: "(Advanced) storageClass"
description: " Warning: Anything other than SCALE-ZFS will break rollback!"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "SCALE-ZFS"
- variable: setPermissions
label: "Automatic Permissions"
description: "Automatically set permissions on install"
schema:
show_if: [["type", "=", "hostPath"]]
type: boolean
default: true
- variable: readOnly
label: "readOnly"
schema:
type: boolean
default: false
- variable: hostPath
label: "hostPath"
description: "Path inside the container the storage is mounted"
schema:
show_if: [["type", "=", "hostPath"]]
type: hostpath
- variable: hostPathType
label: "hostPath Type"
schema:
show_if: [["type", "=", "hostPath"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "DirectoryOrCreate"
description: "DirectoryOrCreate"
- value: "Directory"
description: "Directory"
- value: "FileOrCreate"
description: "FileOrCreate"
- value: "File"
description: "File"
- value: "Socket"
description: "Socket"
- value: "CharDevice"
description: "CharDevice"
- value: "BlockDevice"
description: "BlockDevice"
- variable: mountPath
label: "mountPath"
description: "Path inside the container the storage is mounted"
schema:
type: string
default: "/data"
hidden: true
- variable: medium
label: "EmptyDir Medium"
schema:
show_if: [["type", "=", "emptyDir"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "Memory"
description: "Memory"
- variable: accessMode
label: "Access Mode (Advanced)"
description: "Allow or disallow multiple PVC's writhing to the same PV"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "ReadWriteOnce"
enum:
- value: "ReadWriteOnce"
description: "ReadWriteOnce"
- value: "ReadOnlyMany"
description: "ReadOnlyMany"
- value: "ReadWriteMany"
description: "ReadWriteMany"
- variable: size
label: "Size quotum of storage"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "100Gi"
- variable: backups
label: "App backup Storage"
description: "Stores the Application backups."
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the storage"
schema:
type: boolean
default: true
- variable: type
label: "(Advanced) Type of Storage"
description: "Sets the persistence type"
schema:
type: string
default: "pvc"
enum:
- value: "pvc"
description: "pvc"
- value: "emptyDir"
description: "emptyDir"
- value: "hostPath"
description: "hostPath"
- variable: storageClass
label: "(Advanced) storageClass"
description: " Warning: Anything other than SCALE-ZFS will break rollback!"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "SCALE-ZFS"
- variable: setPermissions
label: "Automatic Permissions"
description: "Automatically set permissions on install"
schema:
show_if: [["type", "=", "hostPath"]]
type: boolean
default: true
- variable: readOnly
label: "readOnly"
schema:
type: boolean
default: false
- variable: hostPath
label: "hostPath"
description: "Path inside the container the storage is mounted"
schema:
show_if: [["type", "=", "hostPath"]]
type: hostpath
- variable: hostPathType
label: "hostPath Type"
schema:
show_if: [["type", "=", "hostPath"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "DirectoryOrCreate"
description: "DirectoryOrCreate"
- value: "Directory"
description: "Directory"
- value: "FileOrCreate"
description: "FileOrCreate"
- value: "File"
description: "File"
- value: "Socket"
description: "Socket"
- value: "CharDevice"
description: "CharDevice"
- value: "BlockDevice"
description: "BlockDevice"
- variable: mountPath
label: "mountPath"
description: "Path inside the container the storage is mounted"
schema:
type: string
default: "/backups"
hidden: true
- variable: medium
label: "EmptyDir Medium"
schema:
show_if: [["type", "=", "emptyDir"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "Memory"
description: "Memory"
- variable: accessMode
label: "Access Mode (Advanced)"
description: "Allow or disallow multiple PVC's writhing to the same PV"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "ReadWriteOnce"
enum:
- value: "ReadWriteOnce"
description: "ReadWriteOnce"
- value: "ReadOnlyMany"
description: "ReadOnlyMany"
- value: "ReadWriteMany"
description: "ReadWriteMany"
- variable: size
label: "Size quotum of storage"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "100Gi"
- variable: persistenceList
label: "Additional app storage"
group: "Storage and Persistence"
schema:
type: list
default: []
items:
- variable: persistenceListEntry
label: "Custom Storage"
schema:
type: dict
attrs:
- variable: enabled
label: "Enable the storage"
schema:
type: boolean
default: true
- variable: type
label: "(Advanced) Type of Storage"
description: "Sets the persistence type"
schema:
type: string
default: "hostPath"
enum:
- value: "pvc"
description: "pvc"
- value: "emptyDir"
description: "emptyDir"
- value: "hostPath"
description: "hostPath"
- variable: storageClass
label: "(Advanced) storageClass"
description: " Warning: Anything other than SCALE-ZFS will break rollback!"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "SCALE-ZFS"
- variable: setPermissions
label: "Automatic Permissions"
description: "Automatically set permissions on install"
schema:
show_if: [["type", "=", "hostPath"]]
type: boolean
default: true
- variable: readOnly
label: "readOnly"
schema:
type: boolean
default: false
- variable: hostPath
label: "hostPath"
description: "Path inside the container the storage is mounted"
schema:
show_if: [["type", "=", "hostPath"]]
type: hostpath
- variable: hostPathType
label: "hostPath Type"
schema:
show_if: [["type", "=", "hostPath"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "DirectoryOrCreate"
description: "DirectoryOrCreate"
- value: "Directory"
description: "Directory"
- value: "FileOrCreate"
description: "FileOrCreate"
- value: "File"
description: "File"
- value: "Socket"
description: "Socket"
- value: "CharDevice"
description: "CharDevice"
- value: "BlockDevice"
description: "BlockDevice"
- variable: mountPath
label: "mountPath"
description: "Path inside the container the storage is mounted"
schema:
type: string
required: true
default: ""
- variable: medium
label: "EmptyDir Medium"
schema:
show_if: [["type", "=", "emptyDir"]]
type: string
default: ""
enum:
- value: ""
description: "Default"
- value: "Memory"
description: "Memory"
- variable: accessMode
label: "Access Mode (Advanced)"
description: "Allow or disallow multiple PVC's writhing to the same PVC"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "ReadWriteOnce"
enum:
- value: "ReadWriteOnce"
description: "ReadWriteOnce"
- value: "ReadOnlyMany"
description: "ReadOnlyMany"
- value: "ReadWriteMany"
description: "ReadWriteMany"
- variable: size
label: "Size quotum of storage"
schema:
show_if: [["type", "=", "pvc"]]
type: string
default: "100Gi"
- variable: resources
group: "Resources and Devices"
label: ""
schema:
type: dict
attrs:
- variable: limits
label: "Advanced Limit Resource Consumption"
schema:
type: dict
attrs:
- variable: cpu
label: "CPU"
schema:
type: string
default: "2000m"
- variable: memory
label: "Memory RAM"
schema:
type: string
default: "2Gi"
- variable: requests
label: "Advanced Request minimum resources required"
schema:
type: dict
attrs:
- variable: cpu
label: "CPU"
schema:
type: string
default: "10m"
- variable: memory
label: "Memory RAM"
schema:
type: string
default: "50Mi"

View File

View File

@@ -0,0 +1,15 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: "postgres-backup-hook-config-map"
annotations:
rollme: {{ randAlphaNum 5 | quote }}
data:
entrypoint.sh: |-
#!/bin/sh
cmd="/docker-entrypoint.sh postgres"
eval "${cmd}" & disown;
until pg_isready; do
sleep 5;
done;
pg_dump -U $POSTGRES_USER -d {{ .Values.postgresqlDatabase }} > /backups/$BACKUP_NAME;

View File

@@ -0,0 +1,2 @@
{{ include "common.all" . }}

View File

@@ -0,0 +1,13 @@
apiVersion: v1
kind: Secret
metadata:
name: {{ include "common.names.fullname" . }}
labels:
{{- include "common.labels" . | nindent 4 }}
annotations:
{{- with .Values.annotations }}
{{- toYaml . | nindent 4 }}
{{- end }}
type: Opaque
data:
postgresql-password: {{ ( .Values.postgresqlPassword | default "empty" ) | b64enc | quote }}

View File

@@ -0,0 +1,58 @@
{{- if .Values.ixChartContext -}}
{{- if .Values.ixChartContext.isUpgrade -}}
{{- $upgradeDict := .Values.ixChartContext.upgradeMetadata -}}
{{ $values := (. | mustDeepCopy) }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: "pre-upgrade-hook2"
annotations:
"helm.sh/hook": pre-upgrade
"helm.sh/hook-weight": "1"
"helm.sh/hook-delete-policy": hook-succeeded
rollme: {{ randAlphaNum 5 | quote }}
spec:
template:
metadata:
name: "pre-upgrade-hook2"
spec:
restartPolicy: Never
containers:
- name: {{ .Chart.Name }}-postgres-backup
image: {{ printf "%v:%v" .Values.image.repository .Values.image.tag}}
imagePullPolicy: {{ .Values.image.pullPolicy }}
env:
- name: BACKUP_NAME
value: {{- printf "postgres-backup-from-%s-to-%s-revision-%d" $upgradeDict.oldChartVersion $upgradeDict.newChartVersion (int64 $upgradeDict.preUpgradeRevision) -}}
- name: PGDATA
value: {{ .Values.pgdatapath | quote }}
- name: POSTGRES_USER
value: {{ .Values.postgresqlUsername | quote }}
- name: POSTGRES_DB
value: {{ .Values.postgresqlDatabase | quote }}
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ ( .Values.existingSecret | default ( include "common.names.fullname" . ) ) | quote }}
key: "postgresql-password"
command:
- "/bin/backup_entrypoint.sh"
volumeMounts:
- name: backup-script-configmap
mountPath: /bin/backup_entrypoint.sh
readOnly: true
subPath: entrypoint.sh
{{- with (include "common.controller.volumeMounts" . | trim) }}
{{ nindent 4 . }}
{{- end }}
volumes:
- name: backup-script-configmap
configMap:
defaultMode: 0700
name: "postgres-backup-hook-config-map"
{{- with (include "common.controller.volumes" . | trim) }}
{{- nindent 2 . }}
{{- end }}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,44 @@
image:
repository: postgres
pullPolicy: IfNotPresent
tag: "13.3"
strategy:
type: Recreate
service:
main:
enabled: true
ports:
main:
port: 5432
persistence:
data:
enabled: true
type: emptyDir
backups:
enabled: true
type: emptyDir
pgdatapath: "/data"
postgresqlPassword: "testpass"
postgresqlUsername: "test"
postgresqlDatabase: "test"
# existingSecret: ""
envValueFrom:
POSTGRES_PASSWORD:
secretKeyRef:
name: '{{ .Values.existingSecret | default ( include "common.names.fullname" . ) }}'
key: "postgresql-password"
envTpl:
PGDATA: "{{ .Values.pgdatapath }}"
POSTGRES_USER: "{{ .Values.postgresqlUsername }}"
POSTGRES_DB: "{{ .Values.postgresqlDatabase }}"
# POSTGRESQL_POSTGRES_PASSWORD: "{{ .Values.postgrespassword }}"
# POSTGRESQL_PASSWORD: "{{ .Values.password }}"