DEV Community

Cover image for Load Testing PostgreSQL on Kubernetes: A YAML-Only Approach
Dmitry Romanoff
Dmitry Romanoff

Posted on

Load Testing PostgreSQL on Kubernetes: A YAML-Only Approach

In today’s cloud-native landscape, simulating database operations effectively is essential for testing and performance evaluation. This article guides you through deploying a PostgreSQL database on Kubernetes (K8s) and setting up multiple pods to simulate operations on the database, all using YAML files.

Load Testing PostgreSQL on Kubernetes: A YAML-Only Approach

Prerequisites

Before diving into the setup, ensure you have:

  • A Kubernetes cluster up and running (Minikube, GKE, EKS, etc.)
  • kubectl installed and configured to communicate with your cluster

Step 1: Create a Namespace

First, we’ll create a dedicated namespace for our PostgreSQL deployment.

# namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
  name: postgres-sim
Enter fullscreen mode Exit fullscreen mode

Run the following command to apply the namespace:

kubectl apply -f namespace.yaml
Enter fullscreen mode Exit fullscreen mode

Step 2: Set Up Persistent Storage

Next, we need to set up persistent storage for our PostgreSQL database. This involves creating a Persistent Volume (PV) and a Persistent Volume Claim (PVC).

# postgres-storage.yaml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: postgres-pv
  namespace: postgres-sim
spec:
  capacity:
    storage: 1Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    path: /data/postgres
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: postgres-pvc
  namespace: postgres-sim
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
Enter fullscreen mode Exit fullscreen mode

Apply the storage configuration:

kubectl apply -f postgres-storage.yaml
Enter fullscreen mode Exit fullscreen mode

Step 3: Deploy PostgreSQL

Now we’ll deploy the PostgreSQL database using a Deployment and expose it via a Service.

# postgres-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgres
  namespace: postgres-sim
spec:
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:14
        env:
        - name: POSTGRES_DB
          value: mydb
        - name: POSTGRES_USER
          value: user
        - name: POSTGRES_PASSWORD
          value: password
        ports:
        - containerPort: 5432
        volumeMounts:
        - mountPath: /var/lib/postgresql/data
          name: postgres-storage
      volumes:
      - name: postgres-storage
        persistentVolumeClaim:
          claimName: postgres-pvc
---
apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: postgres-sim
spec:
  selector:
    app: postgres
  ports:
    - protocol: TCP
      port: 5432
      targetPort: 5432
Enter fullscreen mode Exit fullscreen mode

Apply the PostgreSQL deployment:

kubectl apply -f postgres-deployment.yaml
Enter fullscreen mode Exit fullscreen mode

Step 4: Simulate Database Operations

To simulate operations on the PostgreSQL database, we’ll create a ConfigMap to store a simulation script and deploy it across three pods.

# db-simulation-script.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: db-simulation-script
  namespace: postgres-sim
data:
  simulate.py: |
    import psycopg2
    import random
    import time

    conn = psycopg2.connect(
        dbname="mydb",
        user="user",
        password="password",
        host="postgres",
        port="5432"
    )
    cur = conn.cursor()

    cur.execute("""
    CREATE TABLE IF NOT EXISTS test_table (
        id SERIAL PRIMARY KEY,
        data INTEGER NOT NULL
    );
    """)
    conn.commit()

    operations = ["insert", "update", "delete", "select"]

    for _ in range(1000000):
        operation = random.choice(operations)
        if operation == "insert":
            cur.execute("INSERT INTO test_table (data) VALUES (%s)", (random.randint(1, 100),))
        elif operation == "update":
            cur.execute("UPDATE test_table SET data = %s WHERE id = %s", (random.randint(1, 100), random.randint(1, 10)))
        elif operation == "delete":
            cur.execute("DELETE FROM test_table WHERE id = %s", (random.randint(1, 10),))
        elif operation == "select":
            cur.execute("SELECT * FROM test_table LIMIT 1")
            print(cur.fetchone())

        conn.commit()
        time.sleep(1)

    cur.close()
    conn.close()
Enter fullscreen mode Exit fullscreen mode

Now deploy the simulation pods:

# simulation-script.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: simulation-script-deployment
  namespace: postgres-sim
spec:
  replicas: 3
  selector:
    matchLabels:
      app: simulation-script
  template:
    metadata:
      labels:
        app: simulation-script
    spec:
      containers:
      - name: simulation-script
        image: python:3.9
        command: ["sh", "-c", "pip install psycopg2-binary && python /scripts/simulate.py"]
        volumeMounts:
        - name: script-volume
          mountPath: /scripts
        env:
        - name: PYTHONUNBUFFERED
          value: "1"
      volumes:
      - name: script-volume
        configMap:
          name: db-simulation-script
Enter fullscreen mode Exit fullscreen mode

Apply the simulation deployment:

kubectl apply -f db-simulation-script.yaml
kubectl apply -f simulation-script.yaml
Enter fullscreen mode Exit fullscreen mode

Step 5: Monitor the Operations

You can check the PostgreSQL database to see how the simulated operations have affected the data:

kubectl exec -it postgres-<pod-name> -n postgres-sim -- psql -U user -d mydb
Enter fullscreen mode Exit fullscreen mode

Replace with the actual name of the PostgreSQL pod. You can query the table to see the number of records:

SELECT count(1) FROM test_table;
Enter fullscreen mode Exit fullscreen mode

Conclusion

This setup can be useful for testing, load evaluation, and performance analysis. You can extend this further by introducing different workloads or modifying the simulation script to suit your needs.

Top comments (0)