A Helm chart for TimescaleDB - The Open Source Time-Series Database for PostgreSQL. TimescaleDB is built on PostgreSQL and provides advanced time-series capabilities including automatic partitioning, columnar compression, continuous aggregates, and more.
- Kubernetes 1.24+
- Helm 3.2.0+
- PV provisioner support in the underlying infrastructure (if persistence is enabled)
To install the chart with the release name my-timescaledb:
helm install my-timescaledb oci://registry-1.docker.io/cloudpirates/timescaledbTo install with custom values:
helm install my-timescaledb oci://registry-1.docker.io/cloudpirates/timescaledb -f my-values.yamlOr install directly from the local chart:
helm install my-timescaledb ./charts/timescaledbThe command deploys TimescaleDB on the Kubernetes cluster in the default configuration. The Configuration section lists the parameters that can be configured during installation.
To uninstall/delete the my-timescaledb deployment:
helm uninstall my-timescaledbThe command removes all the Kubernetes components associated with the chart and deletes the release.
This Helm chart is cryptographically signed with Cosign to ensure authenticity and prevent tampering.
Public Key:
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE5U+rM2d3hDjgP5T3cLShuuQIU9vR
Z4/G+Nug6q5vRa+C3qUA1wXjbaJFAfcIrv5VjmYAYOj13shnPpp3Zh4fnQ==
-----END PUBLIC KEY-----
To verify the helm chart before installation, copy the public key to the file cosign.pub and run cosign:
cosign verify --key cosign.pub registry-1.docker.io/cloudpirates/timescaledb:<version>The following table lists the configurable parameters of the TimescaleDB chart and their default values.
| Parameter | Description | Default |
|---|---|---|
global.imageRegistry |
Global Docker image registry | "" |
global.imagePullSecrets |
Global Docker registry secret names as an array | [] |
| Parameter | Description | Default |
|---|---|---|
image.registry |
TimescaleDB image registry | docker.io |
image.repository |
TimescaleDB image repository | timescale/timescaledb |
image.tag |
TimescaleDB image tag (immutable tags are recommended) | "2.23.1-pg17@sha256:a6581100f2f1cd1e03a29a94a49c488a174de65e57301c04de255804645e5a31" |
image.pullPolicy |
TimescaleDB image pull policy | Always |
| Parameter | Description | Default |
|---|---|---|
replicaCount |
Number of TimescaleDB replicas to deploy (Note: TimescaleDB doesn't support multi-master replication by default) | 1 |
nameOverride |
String to partially override timescaledb.fullname | "" |
fullnameOverride |
String to fully override timescaledb.fullname | "" |
namespaceOverride |
String to override the namespace for all resources | "" |
commonLabels |
Labels to add to all deployed objects | {} |
commonAnnotations |
Annotations to add to all deployed objects | {} |
| Parameter | Description | Default |
|---|---|---|
podLabels |
Pod labels | {} |
| Parameter | Description | Default |
|---|---|---|
podSecurityContext.fsGroup |
Group ID for the volumes of the pod | 999 |
containerSecurityContext.allowPrivilegeEscalation |
Enable container privilege escalation | false |
containerSecurityContext.runAsNonRoot |
Configure the container to run as a non-root user | true |
containerSecurityContext.runAsUser |
User ID for the TimescaleDB container | 999 |
containerSecurityContext.runAsGroup |
Group ID for the TimescaleDB container | 999 |
containerSecurityContext.readOnlyRootFilesystem |
Mount container root filesystem as read-only | false |
containerSecurityContext.capabilities.drop |
Linux capabilities to be dropped | ["ALL"] |
priorityClassName |
Priority class for the timescaledb instance | "" |
| Parameter | Description | Default |
|---|---|---|
auth.postgresPassword |
Password for the postgres admin user. If not set, a random password will be generated | "" |
auth.existingSecret |
Name of existing secret to use for TimescaleDB credentials | "" |
auth.secretKeys.adminPasswordKey |
Name of key in existing secret to use for TimescaleDB credentials | "postgres-password" |
| Parameter | Description | Default |
|---|---|---|
config.postgresqlSharedPreloadLibraries |
Shared preload libraries (comma-separated list) | "timescaledb" |
config.postgresqlMaxConnections |
Maximum number of connections | 100 |
config.postgresqlSharedBuffers |
Amount of memory the database server uses for shared memory buffers | "" |
config.postgresqlEffectiveCacheSize |
Effective cache size | "" |
config.postgresqlWorkMem |
Amount of memory to be used by internal sort operations and hash tables | "" |
config.postgresqlMaintenanceWorkMem |
Maximum amount of memory to be used by maintenance operations | "" |
config.postgresqlWalBuffers |
Amount of memory used in shared memory for WAL data | "" |
config.postgresqlCheckpointCompletionTarget |
Time spent flushing dirty buffers during checkpoint, as fraction of checkpoint interval | "" |
config.postgresqlRandomPageCost |
Sets the planner's estimate of the cost of a non-sequentially-fetched disk page | "" |
config.postgresqlLogStatement |
Sets the type of statements logged | "" |
config.postgresqlLogMinDurationStatement |
Sets the minimum execution time above which statements will be logged | "" |
config.timescaledbTelemetry |
Enable/disable TimescaleDB telemetry | "off" |
config.timescaledbMaxBackgroundWorkers |
Maximum number of TimescaleDB background workers | 8 |
config.extraConfig |
Additional TimescaleDB configuration parameters | [] |
config.existingConfigmap |
Name of existing ConfigMap with TimescaleDB configuration | "" |
| Parameter | Description | Default |
|---|---|---|
service.type |
TimescaleDB service type | ClusterIP |
service.port |
TimescaleDB service port | 5432 |
service.targetPort |
TimescaleDB container port | 5432 |
service.annotations |
Service annotations | {} |
| Parameter | Description | Default |
|---|---|---|
ingress.enabled |
Enable ingress record generation for TimescaleDB | false |
ingress.className |
IngressClass that will be used to implement the Ingress | "" |
ingress.annotations |
Additional annotations for the Ingress resource | {} |
ingress.hosts[0].host |
Hostname for TimescaleDB ingress | timescaledb.local |
ingress.hosts[0].paths[0].path |
Path for TimescaleDB ingress | / |
ingress.hosts[0].paths[0].pathType |
Path type for TimescaleDB ingress | Prefix |
ingress.tls |
TLS configuration for TimescaleDB ingress | [] |
| Parameter | Description | Default |
|---|---|---|
resources |
The resources to allocate for the container | {} |
| Parameter | Description | Default |
|---|---|---|
persistence.enabled |
Enable persistence using Persistent Volume Claims | true |
persistence.storageClass |
Persistent Volume storage class | "" |
persistence.annotations |
Persistent Volume Claim annotations | {} |
persistence.labels |
Labels for persistent volume claims | {} |
persistence.size |
Persistent Volume size | 8Gi |
persistence.accessModes |
Persistent Volume access modes | ["ReadWriteOnce"] |
persistence.existingClaim |
The name of an existing PVC to use for persistence | "" |
| Parameter | Description | Default |
|---|---|---|
livenessProbe.enabled |
Enable livenessProbe on TimescaleDB containers | true |
livenessProbe.initialDelaySeconds |
Initial delay seconds for livenessProbe | 30 |
livenessProbe.periodSeconds |
Period seconds for livenessProbe | 10 |
livenessProbe.timeoutSeconds |
Timeout seconds for livenessProbe | 5 |
livenessProbe.failureThreshold |
Failure threshold for livenessProbe | 3 |
livenessProbe.successThreshold |
Success threshold for livenessProbe | 1 |
readinessProbe.enabled |
Enable readinessProbe on TimescaleDB containers | true |
readinessProbe.initialDelaySeconds |
Initial delay seconds for readinessProbe | 5 |
readinessProbe.periodSeconds |
Period seconds for readinessProbe | 5 |
readinessProbe.timeoutSeconds |
Timeout seconds for readinessProbe | 5 |
readinessProbe.failureThreshold |
Failure threshold for readinessProbe | 3 |
readinessProbe.successThreshold |
Success threshold for readinessProbe | 1 |
startupProbe.enabled |
Enable startupProbe on TimescaleDB containers | true |
startupProbe.initialDelaySeconds |
Initial delay seconds for startupProbe | 30 |
startupProbe.periodSeconds |
Period seconds for startupProbe | 10 |
startupProbe.timeoutSeconds |
Timeout seconds for startupProbe | 5 |
startupProbe.failureThreshold |
Failure threshold for startupProbe | 30 |
startupProbe.successThreshold |
Success threshold for startupProbe | 1 |
| Parameter | Description | Default |
|---|---|---|
nodeSelector |
Node labels for pod assignment | {} |
tolerations |
Toleration labels for pod assignment | [] |
affinity |
Affinity settings for pod assignment | {} |
| Parameter | Description | Default |
|---|---|---|
extraEnvVars |
Additional environment variables to set | [] |
extraObjects |
A list of additional Kubernetes objects to deploy alongside the release | [] |
You can use the extraObjects array to deploy additional Kubernetes resources (such as NetworkPolicies, ConfigMaps, etc.) alongside the release. This is useful for customizing your deployment with extra manifests that are not covered by the default chart options.
Helm templating is supported in any field, but all template expressions must be quoted. For example, to use the release namespace, write namespace: "{{ .Release.Namespace }}".
Example: Deploy a NetworkPolicy with templating
extraObjects:
- apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: "{{ .Release.Namespace }}"
spec:
podSelector: {}
policyTypes:
- Egress
egress:
- to:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: kube-system
podSelector:
matchLabels:
k8s-app: kube-dns
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCPAll objects in extraObjects will be rendered and deployed with the release. You can use any valid Kubernetes manifest, and reference Helm values or built-in objects as needed (just remember to quote template expressions).
Deploy TimescaleDB with default configuration:
helm install my-timescaledb ./charts/timescaledb# values-production.yaml
persistence:
enabled: true
storageClass: "fast-ssd"
size: 100Gi
resources:
requests:
memory: "1Gi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "1000m"
auth:
postgresPassword: "your-secure-admin-password"
config:
postgresqlMaxConnections: 200
postgresqlSharedBuffers: "256MB"
postgresqlEffectiveCacheSize: "1GB"
postgresqlWorkMem: "8MB"
postgresqlMaintenanceWorkMem: "128MB"
timescaledbMaxBackgroundWorkers: 16
timescaledbTelemetry: "off"
ingress:
enabled: true
className: "nginx"
hosts:
- host: timescaledb.yourdomain.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: timescaledb-tls
hosts:
- timescaledb.yourdomain.comDeploy with production values:
helm install my-timescaledb ./charts/timescaledb -f values-production.yaml# values-timeseries.yaml
resources:
requests:
memory: "4Gi"
cpu: "2000m"
limits:
memory: "8Gi"
cpu: "4000m"
config:
postgresqlMaxConnections: 500
postgresqlSharedBuffers: "2GB"
postgresqlEffectiveCacheSize: "6GB"
postgresqlWorkMem: "16MB"
postgresqlMaintenanceWorkMem: "512MB"
postgresqlWalBuffers: "32MB"
postgresqlCheckpointCompletionTarget: "0.9"
postgresqlRandomPageCost: "1.0"
timescaledbMaxBackgroundWorkers: 32
timescaledbTelemetry: "off"
extraConfig:
- "timescaledb.max_background_workers = 32"
- "effective_io_concurrency = 200"
- "random_page_cost = 1.0"
- "seq_page_cost = 1.0"
persistence:
enabled: true
storageClass: "fast-ssd"
size: 500Gi
affinity:
podAntiAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app.kubernetes.io/name
operator: In
values:
- timescaledb
topologyKey: kubernetes.io/hostname# values-external-secret.yaml
auth:
existingSecret: "timescaledb-credentials"
secretKeys:
adminPasswordKey: "postgres-password"Create the secret first:
kubectl create secret generic timescaledb-credentials \
--from-literal=postgres-password=your-admin-password# values-custom-config.yaml
config:
existingConfigmap: "timescaledb-custom-config"Create the ConfigMap first:
apiVersion: v1
kind: ConfigMap
metadata:
name: timescaledb-custom-config
data:
postgresql.conf: |
# Custom TimescaleDB configuration
max_connections = 300
shared_buffers = 512MB
effective_cache_size = 2GB
work_mem = 16MB
maintenance_work_mem = 256MB
# TimescaleDB specific settings
shared_preload_libraries = 'timescaledb'
timescaledb.telemetry_level = OFF
timescaledb.max_background_workers = 16
# Time-series optimizations
effective_io_concurrency = 200
random_page_cost = 1.0
seq_page_cost = 1.0kubectl port-forward service/my-timescaledb 5432:5432# Connect as postgres user
psql -h localhost -U postgres -d postgres -W- Admin User:
postgres - Admin Password: Auto-generated (check secret) or configured value
Get the auto-generated password:
# Admin password
kubectl get secret my-timescaledb -o jsonpath="{.data.postgres-password}" | base64 --decode-
Pod fails to start with permission errors
- Ensure your storage class supports the required access modes
- Check if security contexts are compatible with your cluster policies
- Verify the TimescaleDB data directory permissions
-
Cannot connect to TimescaleDB
- Verify the service is running:
kubectl get svc - Check if authentication is properly configured
- Ensure firewall rules allow access to port 5432
- Check TimescaleDB logs:
kubectl logs <pod-name>
- Verify the service is running:
-
TimescaleDB extension not loaded
- Verify
shared_preload_librariesincludestimescaledb - Check if the database initialization completed successfully
- Review pod logs for TimescaleDB-specific errors
- Verify
-
Performance issues with time-series queries
- Check if tables are properly converted to hypertables
- Review chunk intervals and partitioning strategy
- Monitor resource usage with
kubectl top pod - Consider adjusting TimescaleDB background workers
-
Memory Configuration for Time-Series
config: postgresqlSharedBuffers: "512MB" # 25-30% of RAM for time-series postgresqlEffectiveCacheSize: "2GB" # 75% of RAM postgresqlWorkMem: "16MB" # Higher for analytical queries postgresqlMaintenanceWorkMem: "256MB" timescaledbMaxBackgroundWorkers: 16 # More workers for compression
-
Connection Settings
config: postgresqlMaxConnections: 200
-
I/O Optimization
config: postgresqlRandomPageCost: "1.0" # Lower for SSD storage extraConfig: - "effective_io_concurrency = 200" - "maintenance_io_concurrency = 10"
-
TimescaleDB Specific Settings
config: timescaledbTelemetry: "off" timescaledbMaxBackgroundWorkers: 32 extraConfig: - "timescaledb.max_background_workers = 32" - "timescaledb.bgw_launcher_poll_time = 5s"
Manual Backup with pg_dump
kubectl exec -it <pod-name> -- pg_dump -U postgres -d mydb > backup.sqlTimescaleDB-specific Backup
kubectl exec -it <pod-name> -- pg_dump -U postgres -d mydb --schema-only > schema.sql
kubectl exec -it <pod-name> -- pg_dump -U postgres -d mydb --data-only > data.sqlFor issues related to this Helm chart, please check: