Skip to content
This repository has been archived by the owner on Jan 18, 2024. It is now read-only.

charts/timescaledb-single: allow to override pod security context (e. g. run as different user) #590

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion charts/timescaledb-single/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
apiVersion: v1
name: timescaledb-single
description: 'TimescaleDB HA Deployment.'
version: 0.33.2
version: 0.34.0
icon: https://cdn.iconscout.com/icon/free/png-256/timescaledb-1958407-1651618.png

# appVersion specifies the version of the software, which can vary wildly,
Expand Down
1 change: 1 addition & 0 deletions charts/timescaledb-single/docs/admin-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ The following table lists the configurable parameters of the TimescaleDB Helm ch
| `pgBouncer.pg_hba` | The `pg_hba` to be used by pgBouncer | A `pg_hba` allowing non-superuser ssl-only connections |
| `pgBouncer.userListSecretName` | If set, a [user authentication file](https://www.pgbouncer.org/config.html#authentication-file-format) to be used by pgBouncer. | `nil` |
| `podManagementPolicy` | Either [`OrderedReady` or `Parallel`](https://kubernetes.io/docs/concepts/workloads/controllers/statefulset/#pod-management-policies) | `OrderedReady` |
| `podSecurityContext` | Security Context of the timescaledb pod. | `{ fsGroup: 1000, runAsGroup: 1000, runAsNonRoot: true, runAsUser: 1000 }` |
| `podMonitor.enabled` | Enable deployment of podMonitor used with prometheus-operator. | `false` |
| `podMonitor.path` | Path on which prometheus metrics are exposed. | `/metrics` |
| `podMonitor.interval` | Prometheus scrape interval. Lower values increase resolution, higher values reduce prometheus memory consumption. Do not set over 2m. | `10s` |
Expand Down
5 changes: 3 additions & 2 deletions charts/timescaledb-single/scripts/pgbackrest_restore.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ fi
# A missing PGDATA points to Patroni removing a botched PGDATA, or manual
# intervention. In this scenario, we need to recreate the DATA and WALDIRs
# to keep pgBackRest happy
[ -d "${PGDATA}" ] || install -o postgres -g postgres -d -m 0700 "${PGDATA}"
[ -d "${WALDIR}" ] || install -o postgres -g postgres -d -m 0700 "${WALDIR}"
uid="$(id -u)"; gid="$(id -g)"
[ -d "${PGDATA}" ] || install -o "$uid" -g "$gid" -d -m 0700 "${PGDATA}"
[ -d "${WALDIR}" ] || install -o "$uid" -g "$gid" -d -m 0700 "${WALDIR}"

exec pgbackrest --force --delta --log-level-console=detail restore
11 changes: 8 additions & 3 deletions charts/timescaledb-single/scripts/restore_or_initdb.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,9 @@ log() {
# A missing PGDATA points to Patroni removing a botched PGDATA, or manual
# intervention. In this scenario, we need to recreate the DATA and WALDIRs
# to keep pgBackRest happy
[ -d "${PGDATA}" ] || install -o postgres -g postgres -d -m 0700 "${PGDATA}"
[ -d "${WALDIR}" ] || install -o postgres -g postgres -d -m 0700 "${WALDIR}"
uid="$(id -u)"; gid="$(id -g)"
[ -d "${PGDATA}" ] || install -o "$uid" -g "$gid" -d -m 0700 "${PGDATA}"
[ -d "${WALDIR}" ] || install -o "$uid" -g "$gid" -d -m 0700 "${WALDIR}"

if [ "${BOOTSTRAP_FROM_BACKUP}" = "1" ]; then
log "Attempting restore from backup"
Expand Down Expand Up @@ -104,7 +105,11 @@ else

log "Invoking initdb"
# shellcheck disable=SC2086
initdb --auth-local=peer --auth-host=md5 --pgdata="${PGDATA}" --waldir="${WALDIR}" ${initdb_args}
initdb --username="$POSTGRES_USER" --auth-local=peer --auth-host=md5 --pgdata="${PGDATA}" --waldir="${WALDIR}" ${initdb_args}
EXITCODE=$?
if [ ${EXITCODE} -ne 0 ]; then
exit $EXITCODE
fi
fi

echo "include_if_exists = '${TSTUNE_FILE}'" >> "${PGDATA}/postgresql.conf"
4 changes: 0 additions & 4 deletions charts/timescaledb-single/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,6 @@ Create the name of the service account to use.
{{- end -}}
{{- end -}}

{{- define "postgres.uid" -}}
{{- default .Values.uid "1000" -}}
{{- end -}}

{{- define "data_directory" -}}
{{ printf "%s/data" .Values.persistentVolumes.data.mountPath }}
{{- end -}}
Expand Down
36 changes: 25 additions & 11 deletions charts/timescaledb-single/templates/statefulset-timescaledb.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,7 @@ spec:
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" }}
{{- toYaml .Values.podSecurityContext | nindent 8 }}
initContainers:
{{- if .Values.timescaledbTune.enabled }}
- name: tstune
Expand Down Expand Up @@ -133,10 +128,12 @@ spec:
- "-c"
- |
{{ .Values.debug.execStartPre }}
install -o postgres -g postgres -d -m 0700 {{ include "data_directory" . | quote }} {{ include "wal_directory" . | quote }} || exit 1
TABLESPACES={{ $.Values.persistentVolumes.tablespaces | default dict | keys | join " " | quote }}
for tablespace in {{ $.Values.persistentVolumes.tablespaces | default dict | keys | join " " }}; do
install -o postgres -g postgres -d -m 0700 "{{ include "tablespaces_dir" . }}/${tablespace}/data"
uid="$(id -u)"; gid="$(id -g)"
install -o "$uid" -g "$gid" -d -m 0700 {{ include "data_directory" . | quote }} {{ include "wal_directory" . | quote }} || exit 1

: "${POSTGRES_TABLESPACES:=""}"
for tablespace in $POSTGRES_TABLESPACES; do
install -o "$uid" -g "$gid" -d -m 0700 "{{ include "tablespaces_dir" . }}/${tablespace}/data"
done

# Environment variables can be read by regular users of PostgreSQL. Especially in a Kubernetes
Expand All @@ -154,7 +151,7 @@ spec:
export -p > "${HOME}/.pod_environment"
export -p | grep PGBACKREST > "${HOME}/.pgbackrest_environment"

for UNKNOWNVAR in $(env | awk -F '=' '!/^(PATRONI_.*|HOME|PGDATA|PGHOST|LC_.*|LANG|PATH|KUBERNETES_SERVICE_.*|AWS_ROLE_ARN|AWS_WEB_IDENTITY_TOKEN_FILE)=/ {print $1}')
for UNKNOWNVAR in $(env | awk -F '=' '!/^(PATRONI_.*|HOME|PGDATA|PGHOST|PGUSER|LC_.*|LANG|PATH|KUBERNETES_SERVICE_.*|AWS_ROLE_ARN|AWS_WEB_IDENTITY_TOKEN_FILE)=/ {print $1}')
do
unset "${UNKNOWNVAR}"
done
Expand All @@ -167,6 +164,11 @@ spec:

export PATRONI_POSTGRESQL_PGPASS="${HOME}/.pgpass.patroni"

# "patroni" does not set the user correctly on connect to postgres and authentication will be rejected
# "initdb" is particular about the current user existing in "/etc/passwd"
# so we use "nss_wrapper" to fake that
. docker-entrypoint.sh && setup_nss_wrapper

exec patroni /etc/timescaledb/patroni.yaml
env:
# We use mixed case environment variables for Patroni User management,
Expand All @@ -178,6 +180,8 @@ spec:
value: "/etc/timescaledb/patroni.yaml"
- name: PATRONI_admin_OPTIONS
value: createrole,createdb
- name: PATRONI_SUPERUSER_USERNAME
value: postgres
- name: PATRONI_REPLICATION_USERNAME
value: standby
# To specify the PostgreSQL and Rest API connect addresses we need
Expand Down Expand Up @@ -223,6 +227,10 @@ spec:
value: "/var/run/postgresql"
- name: WALDIR
value: {{ include "wal_directory" . | quote }}
- name: PGUSER
value: postgres
- name: POSTGRES_USER
value: postgres
- name: BOOTSTRAP_FROM_BACKUP
value: {{ .Values.bootstrapFromBackup.enabled | int | quote }}
{{- if .Values.bootstrapFromBackup.enabled }}
Expand All @@ -233,6 +241,8 @@ spec:
value: {{ .Values.backup.enabled | quote }}
- name: TSTUNE_FILE
value: {{ template "tstune_config" . }}
- name: HOME
value: /home/postgres
{{- if .Values.env }}{{ .Values.env | default list | toYaml | nindent 8 }}{{- end }}
# pgBackRest is also called using the archive_command if the backup is enabled.
# this script will also need access to the environment variables specified for
Expand Down Expand Up @@ -304,6 +314,8 @@ spec:
- mountPath: /etc/certificate
name: certificate
readOnly: true
- name: home
mountPath: /home/postgres
- name: socket-directory
mountPath: /var/run/postgresql
{{ if .Values.callbacks.configMap -}}
Expand Down Expand Up @@ -473,6 +485,8 @@ spec:
{{- .Values.affinity | toYaml | nindent 8 }}
{{- end }}
volumes:
- name: home
emptyDir: {}
- name: socket-directory
emptyDir: {}
- name: patroni-config
Expand Down
19 changes: 19 additions & 0 deletions charts/timescaledb-single/values.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,24 @@
"podMonitor": {
"type": "object"
},
"podSecurityContext": {
"additionalProperties": true,
"properties": {
"fsGroup": {
"type": "integer"
},
"runAsGroup": {
"type": "integer"
},
"runAsNonRoot": {
"type": "boolean"
},
"runAsUser": {
"type": "integer"
}
},
"type": "object"
},
"postInit": {
"description": "postInit allows you to configure additional scripts that will be run once\ndirectly after initialization of the database. It takes a list of VolumeProjection,\nevery .sh, .sql, and .sql.gz script will be executed in sorted order and they should\nreturn exitcode 0 on success.\n",
"items": {
Expand Down Expand Up @@ -826,6 +844,7 @@
"podAnnotations",
"podLabels",
"podManagementPolicy",
"podSecurityContext",
"prometheus",
"rbac",
"readinessProbe",
Expand Down
13 changes: 13 additions & 0 deletions charts/timescaledb-single/values.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ required:
- podAnnotations
- podLabels
- podManagementPolicy
- podSecurityContext
- prometheus
- rbac
- readinessProbe
Expand All @@ -45,6 +46,18 @@ properties:
podManagementPolicy:
type:
- string
podSecurityContext:
type: object
additionalProperties: true
properties:
fsGroup:
type: integer
runAsGroup:
type: integer
runAsNonRoot:
type: boolean
runAsUser:
type: integer
postInit:
description: |
postInit allows you to configure additional scripts that will be run once
Expand Down
8 changes: 8 additions & 0 deletions charts/timescaledb-single/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -405,6 +405,14 @@ persistentVolumes:
# size: 5Gi
# storageClass: gp2

podSecurityContext:
# The postgres user inside the TimescaleDB image has uid=1000.
# This configuration ensures the permissions of the mounts are suitable
fsGroup: 1000
runAsGroup: 1000
runAsNonRoot: true
runAsUser: 1000

resources: {}
# If you do want to specify resources, uncomment the following
# lines, adjust them as necessary, and remove the curly braces after 'resources:'.
Expand Down