# Installing PostgreSQL in Kubernetes with Bitnami's Helm Chart

PostgreSQL is one of the most popular and reliable open-source relational database systems available today.

When running it in a Kubernetes environment, the [Bitnami Helm chart](https://github.com/bitnami/charts/tree/main/bitnami/postgresql) is a top choice.

This guide will walk you through the setup process and how I have deployed Postgres in my Homelab Kubernetes cluster.

## HomeLab Course

If you have further questions on this deployment or want to check out my Homelab course in the Travis Media Community, then head over to our [community page](https://www.skool.com/travis-media-community) and JOIN!

## Step 1: Create Kubernetes Secrets for Database Credentials

First, we need to securely store our database passwords as Kubernetes secrets. This prevents passwords from being exposed in configuration files or deployment manifests.

```bash
kubectl create secret generic postgres-credentials -n database \
  --from-literal=POSTGRES_PASSWORD='AdminPassword' \
  --from-literal=APP_DB_PASSWORD='AUserPassword'
```

> **Note:** Replace 'AdminPassword' and 'AUserPassword' with secure passwords of your own.

## Step 2: Prepare Storage on Worker Node

PostgreSQL requires persistent storage to maintain your data across pod restarts and redeployments.

I have one master node and one worker node, so for this guide, I'll use host path volumes on our worker node.

#### Create the Required Directories

```bash
sudo mkdir -p /data/postgres-data /data/postgres-dump
```

#### Set Correct Ownership for the Bitnami PostgreSQL User (UID 1001)

```bash
sudo chown -R 1001:1001 /data/postgres-data
sudo chown -R 1001:1001 /data/postgres-dump
```

#### Configure Appropriate Permissions

```bash
sudo chmod -R 750 /data/postgres-data
sudo chmod -R 750 /data/postgres-dump
```

## Step 3: Create Persistent Volumes

Create a file named `postgres-pv.yaml` with the following persistent volume definitions.

```yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-data-pv
spec:
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  claimRef:
    namespace: database
    name: data-postgres-postgresql-0
  hostPath:
    path: /data/postgres-data
    type: DirectoryOrCreate
---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-dump-pv
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  storageClassName: local-storage
  claimRef:
    namespace: database
    name: postgres-postgresql-pgdumpall
  hostPath:
    path: /data/postgres-dump
    type: DirectoryOrCreate
```

then apply it to your cluster:

```bash
kubectl create -f postgres-pv.yaml
```

> **Important:** Your `postgres-pv.yaml` should define appropriate persistent volumes that point to the directories created in step 2, with the correct storage class and access modes. Be sure to tweak as needed.

## Step 4: Deploy PostgreSQL with Helm

Now we're ready to install PostgreSQL using the Bitnami Helm chart. Create a custom `postgres-values.yaml` file with the following configuration preferences (again tweak as necessary).

```yaml
auth:
  existingSecret: postgres-credentials
  secretKeys:
    adminPasswordKey: POSTGRES_PASSWORD
    userPasswordKey: APP_DB_PASSWORD

primary:
  persistence:
    storageClass: 'local-storage'
    size: 10Gi
    accessModes:
      - ReadWriteOnce
    annotations: {}

service:
  type: ClusterIP
  ports:
    postgresql: 5432

# Backup and monitoring options
backup:
  enabled: true
  cronjob:
    schedule: '0 2 * * *' # Daily backup at 2 AM
```

Then run:

```bash
helm install postgres oci://registry-1.docker.io/bitnamicharts/postgresql -n database --values postgres-values.yaml
```

The Helm chart will create all necessary resources.

## Step 5: Database Administration and Configuration

Once PostgreSQL is running, you can connect to it for administrative tasks.

### Access the PostgreSQL Pod

```bash
kubectl exec -it -n database postgres-postgresql-0 -- /opt/bitnami/scripts/postgresql/entrypoint.sh /bin/bash
```

### Log in to PostgreSQL

```bash
psql -U postgres
```

When prompted, enter the admin password you specified in step 1.

### Common Database Administration Tasks

Here are some typicsl administrative tasks you may want to perform at this point:

#### Create a New Database

```sql
CREATE DATABASE homelabdb;
```

#### Create a Database User

```sql
CREATE USER myuser WITH PASSWORD 'your-password';
```

#### Grant Privileges

```sql
GRANT ALL PRIVILEGES ON DATABASE homelabdb TO myuser;
GRANT ALL PRIVILEGES ON SCHEMA public TO myuser;
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO myuser;
```

#### Create a Table

```sql
CREATE TABLE daily_steps (
    id SERIAL PRIMARY KEY,
    date DATE UNIQUE NOT NULL,
    steps INTEGER NOT NULL,
    created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
);
```

#### Change Object Ownership

```sql
-- Connect to the specific database
\c homelabdb postgres

-- Change table ownership
ALTER TABLE daily_steps OWNER TO travis;

-- Grant all privileges explicitly
GRANT ALL PRIVILEGES ON TABLE daily_steps TO travis;
GRANT ALL PRIVILEGES ON SCHEMA public TO travis;
```

#### Verify Permissions

```sql
\z daily_steps
```

## Conclusion

You now have a fully functional PostgreSQL database running in your Kubernetes cluster. This setup provides the foundation for deploying stateful applications that require relational database storage.

For production environments, consider implementing:

- Regular database backups
- High availability configurations
- Monitoring and alerting
- Resource limits and requests tuning

The Bitnami PostgreSQL Helm chart offers many additional configuration options through its values file, allowing you to customize the deployment to your specific needs.