Mike Barkas

Software Technologies

Mike Barkas

Mike Barkas

Software Technologies

Postgres Kubernetes Deployment

December 11, 2024

This is an overview of setting up a Postgres server in my Kubernetes homelab. I wanted a database server (I like postgres) running in my cluster that multiple apps could use.

Setting up a Postgres server in my Kubernetes homelab was very informative and I learned a lot about k8s in the process. Using a deployment for a database in Kubernetes is only for development and testing.

Design Decision

In order to have persistent data storage and backup and restore capabilities for a database in Kubernetes you should use a StatefulSet. For learning and experimenting with a single node cluster, I am currently using k3s, I decided to use a deployment for postgres.

The requirements I had for postgres:

  • Custom config file for starting the postgres server
  • Persistent data directory
  • init files for the postgres container, to create tables and seed data
  • A postgres server available to other pods and services

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: postgres
  labels:
    app: postgres
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      name: postgres
      labels:
        app: postgres
    spec:
      containers:
        - name: postgres
          image: postgres:16
          imagePullPolicy: IfNotPresent
          args: ["-c", "config_file=/config/postgresql.conf"]
          ports:
            - containerPort: 5432
          envFrom:
            - secretRef:
                name: db-credentials
          volumeMounts:
            - name: data
              mountPath: /var/lib/postgresql/data
            - name: config
              mountPath: /config
            - name: init
              mountPath: /docker-entrypoint-initdb.d
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pg-data-pvc
        - name: config
          persistentVolumeClaim:
            claimName: pg-config-pvc
        - name: init
          persistentVolumeClaim:
            claimName: pg-init-pvc
      restartPolicy: Always
      

Problem-solving Approaches

Since I am currently using a single node cluster for development, I created PVs on the node with local-path for data, config, and the init directories. This would allow for the files to exist so I could mount the init files for the postgres container. k3s provides a local-path StorageClass.

For the database credentials I am using a k8s secret that sets environment variables for the container. For development this is adequate. There are better options for production.

Other apps in the cluster need to access the postgres server, so I exposed the database with a service in a separate k8s namespace using ClusterIP.

Future Improvements

Next steps for Postgres in my homelab is to create a StatefulSet in k8s and persistent data storage and implement backups.

Lessons Learned

I learned about how pods and PVs behave using deployments, especially with multinode clusters. Deployments are not used for applications that have state. I have a better understanding of DNS in pods and services.

The yaml files are available in my homelab github repo