Skip to content

Integrations: Kubernetes #3877

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 20 commits into from
Apr 7, 2025
Merged
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
5 changes: 5 additions & 0 deletions use-timescale/integrations/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ Some of the most in-demand integrations are listed below.
| [Pulumi][pulumi] | Define and manage cloud infrastructure using code in multiple languages. |
| [Render][render] | Deploy and scale web applications, databases, and services easily. |
| [Terraform][terraform] | Safely and predictably provision and manage infrastructure in any cloud. |
| [Kubernetes][kubernetes] | Deploy, scale, and manage containerized applications automatically. |


## Data engineering and extract, transform, load

Expand Down Expand Up @@ -172,6 +174,7 @@ Some of the most in-demand integrations are listed below.
| [Tooljet][tooljet] | Develop internal tools and business applications with a low-code builder. |
| [Zapier][zapier] | Automate workflows by connecting different applications and services. |


[ads]: /use-timescale/:currentVersion:/integrations/azure-data-studio/
[airbyte]: https://docs.airbyte.com/integrations/sources/postgres
[amazon-sagemaker]: /use-timescale/:currentVersion:/integrations/amazon-sagemaker
Expand Down Expand Up @@ -243,6 +246,7 @@ Some of the most in-demand integrations are listed below.
[power-bi]: /use-timescale/:currentVersion:/integrations/power-bi
[prisma]: https://www.prisma.io/docs/orm/overview/databases/postgresql
[prometheus]: /use-timescale/:currentVersion:/integrations/prometheus
[kubernetes]: /use-timescale/:currentVersion:/integrations/kubernetes
[psql]: /use-timescale/:currentVersion:/integrations/psql/
[pulumi]: https://www.pulumi.com/registry/packages/timescale/
[python]: /quick-start/:currentVersion:/python/
Expand Down Expand Up @@ -272,3 +276,4 @@ Some of the most in-demand integrations are listed below.
[tooljet]: https://docs.tooljet.ai/docs/data-sources/postgresql/
[typeorm]: https://typeorm.biunav.com/en/connection-options.html#postgres-cockroachdb-connection-options
[zapier]: https://zapier.com/apps/postgresql/integrations

312 changes: 312 additions & 0 deletions use-timescale/integrations/kubernetes.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,312 @@
---
title: Integrate Kubernetes with Timescale Cloud
excerpt: Learn how to integrate Kubernetes with Timescale Cloud to enable seamless deployment and scaling of your PostgreSQL workloads
products: [cloud, mst, self_hosted]
keywords: [Kubernetes, Timescale Cloud, PostgreSQL, container orchestration]
---

import IntegrationPrereqs from "versionContent/_partials/_integration-prereqs.mdx";

# Integrate Kubernetes with $CLOUD_LONG

[Kubernetes][kubernetes] is an open-source container orchestration system that automates the deployment, scaling, and management of containerized applications. You can deploy $CLOUD_LONG within your Kubernetes clusters.

This guide explains how to connect a Kubernetes cluster to $CLOUD_LONG, configure persistent storage, and manage deployments effectively.

## Prerequisites

<IntegrationPrereqs />

- Install [self-managed Kubernetes][kubernetes-install] or sign up for a Kubernetes [Turnkey Cloud Solution][kubernetes-managed].
- Install [kubectl][kubectl] for command-line interaction with your cluster.

## Integrate Timescale in a Kubernetes cluster

<Tabs>

<Tab title="Timescale Cloud">

To connect your Kubernetes cluster to your $SERVICE_LONG:

<Procedure>

1. **Create a default namespace for your $CLOUD_LONG components**

1. Create the Timescale namespace:

```shell
kubectl create namespace timescale
```

1. Set this namespace as the default for your session:

```shell
kubectl config set-context --current --namespace=timescale
```

For more information, see [Kubernetes Namespaces][kubernetes-namespace].

1. **Create a Kubernetes secret that stores your $SERVICE_LONG credentials**

Update the following command with your [connection details][connection-info], then run it:

```shell
kubectl create secret generic timescale-secret \
--from-literal=PGHOST=<host> \
--from-literal=PGPORT=<port> \
--from-literal=PGDATABASE=<dbname> \
--from-literal=PGUSER=<user> \
--from-literal=PGPASSWORD=<password>
```

1. **Configure network access to $CLOUD_LONG**

- **Managed Kubernetes**: outbound connections to external databases like $CLOUD_LONG work by default.
Make sure your cluster’s security group or firewall rules allow outbound traffic to $CLOUD_LONG IP.

- **Self-hosted Kubernetes**: If your cluster is behind a firewall or running on-premise, you may need to allow
egress traffic to $CLOUD_LONG. Test connectivity using your [connection details][connection-info]:

```shell
nc -zv <host> <port>
```

If the connection fails, check your firewall rules.

1. **Create a Kubernetes deployment that can access your $CLOUD_LONG**

Run the following command to apply the deployment:

```shell
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: timescale-app
spec:
replicas: 1
selector:
matchLabels:
app: timescale-app
template:
metadata:
labels:
app: timescale-app
spec:
containers:
- name: timescale-container
image: postgres:latest
envFrom:
- secretRef:
name: timescale-secret
EOF
```

1. **Test the connection**

1. Create and run a pod that uses the [connection details][connection-info] you added to `timescale-secret` in
the `timescale` namespace:

```shell
kubectl run test-pod --image=postgres --restart=Never \
--env="PGHOST=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGHOST}' | base64 --decode)" \
--env="PGPORT=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGPORT}' | base64 --decode)" \
--env="PGDATABASE=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGDATABASE}' | base64 --decode)" \
--env="PGUSER=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGUSER}' | base64 --decode)" \
--env="PGPASSWORD=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGPASSWORD}' | base64 --decode)" \
-- sleep infinity
```

2. Launch a psql shell in the `test-pod` you just created:

```shell
kubectl exec -it test-pod -- bash -c "psql -h \$PGHOST -U \$PGUSER -d \$PGDATABASE"
```

You start a `psql` session connected to your $SERVICE_LONG.

</Procedure>

</Tab>

<Tab title="Self-hosted TimescaleDB">

To connect your Kubernetes cluster to self-hosted $TIMESCALE_DB running in the cluster:

<Procedure>

1. **Create a default namespace for $COMPANY components**

1. Create the $COMPANY namespace:

```shell
kubectl create namespace timescale
```

1. Set this namespace as the default for your session:

```shell
kubectl config set-context --current --namespace=timescale
```

For more information, see [Kubernetes Namespaces][kubernetes-namespace].

1. **Set up a persistent volume claim (PVC) storage**

To manually set up a persistent volume and claim for self-hosted Kubernetes, run the following command:

```yaml
kubectl apply -f - <<EOF
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: timescale-pvc
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
EOF
```

1. **Deploy $TIMESCALE_DB as a StatefulSet**

By default, the [Timescale Docker image][timescale-docker-image] you are installing on Kubernetes uses the
default $PG database, user and password. To deploy $TIMESCALE_DB on Kubernetes, run the following command:

```yaml
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: timescaledb
spec:
serviceName: timescaledb
replicas: 1
selector:
matchLabels:
app: timescaledb
template:
metadata:
labels:
app: timescaledb
spec:
containers:
- name: timescaledb
image: 'timescale/timescaledb:latest-pg17'
env:
- name: POSTGRES_USER
value: postgres
- name: POSTGRES_PASSWORD
value: postgres
- name: POSTGRES_DB
value: postgres
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- containerPort: 5432
volumeMounts:
- mountPath: /var/lib/postgresql/data
name: timescale-storage
volumes:
- name: timescale-storage
persistentVolumeClaim:
claimName: timescale-pvc
EOF
```

1. **Allow applications to connect by exposing $TIMESCALE_DB within Kubernetes**

```yaml
kubectl apply -f - <<EOF
apiVersion: v1
kind: Service
metadata:
name: timescaledb
spec:
selector:
app: timescaledb
ports:
- protocol: TCP
port: 5432
targetPort: 5432
type: ClusterIP
EOF
```

1. **Create a Kubernetes secret to store the database credentials**

```shell
kubectl create secret generic timescale-secret \
--from-literal=PGHOST=timescaledb \
--from-literal=PGPORT=5432 \
--from-literal=PGDATABASE=postgres \
--from-literal=PGUSER=postgres \
--from-literal=PGPASSWORD=postgres
```

1. **Deploy an application that connects to $TIMESCALE_DB**

```shell
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: timescale-app
spec:
replicas: 1
selector:
matchLabels:
app: timescale-app
template:
metadata:
labels:
app: timescale-app
spec:
containers:
- name: timescale-container
image: postgres:latest
envFrom:
- secretRef:
name: timescale-secret
EOF
```

1. **Test the database connection**

1. Create and run a pod to verify database connectivity using your [connection details][connection-info] saved in `timescale-secret`:

```shell
kubectl run test-pod --image=postgres --restart=Never \
--env="PGHOST=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGHOST}' | base64 --decode)" \
--env="PGPORT=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGPORT}' | base64 --decode)" \
--env="PGDATABASE=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGDATABASE}' | base64 --decode)" \
--env="PGUSER=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGUSER}' | base64 --decode)" \
--env="PGPASSWORD=$(kubectl get secret timescale-secret -o=jsonpath='{.data.PGPASSWORD}' | base64 --decode)" \
-- sleep infinity
```

1. Launch the PostgreSQL interactive shell within the created `test-pod`:

```shell
kubectl exec -it test-pod -- bash -c "psql -h \$PGHOST -U \$PGUSER -d \$PGDATABASE"
```

You see the PostgreSQL interactive terminal.

</Procedure>

</Tab>

</Tabs>

You have successfully integrated Kubernetes with $CLOUD_LONG.

[connection-info]: /use-timescale/:currentVersion:/integrations/find-connection-details/
[kubernetes]: https://kubernetes.io/
[kubectl]: https://kubernetes.io/docs/tasks/tools/
[kubernetes-namespace]: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/
[kubernetes-install]: https://kubernetes.io/docs/setup/
[kubernetes-managed]: https://kubernetes.io/docs/setup/production-environment/turnkey-solutions/
[timescale-docker-image]: https://hub.docker.com/r/timescale/timescaledb
12 changes: 11 additions & 1 deletion use-timescale/page-index/page-index.js
Original file line number Diff line number Diff line change
Expand Up @@ -791,6 +791,11 @@ module.exports = [
href: "decodable",
excerpt: "Integrate Decodable with Timescale Cloud",
},
{
title: "Debezium",
href: "debezium",
excerpt: "Integrate Debezium with Timescale products",
},
{
title: "Fivetran",
href: "fivetran",
Expand All @@ -806,6 +811,11 @@ module.exports = [
href: "grafana",
excerpt: "Integrate Grafana with Timescale products",
},
{
title: "Kubernetes",
href: "kubernetes",
excerpt: "Integrate Kubernetes with Timescale products",
},
{
title: "Microsoft Azure",
href: "microsoft-azure",
Expand All @@ -819,7 +829,7 @@ module.exports = [
{
title: "PostgreSQL",
href: "postgresql",
excerpt: "Integrate PostgreSQL with Timescale Cloud",
excerpt: "Integrate PostgreSQL with Timescale products",
},
{
title: "Prometheus",
Expand Down