pgblame

Running the agent on Kubernetes

One Deployment (single replica) plus a small PersistentVolumeClaim for the buffer. It's the same image everywhere — EKS, GKE, AKS, k3s, or any conformant cluster.

1. Create the secret

Keep the connection string and project token out of the manifest:

kubectl create namespace pgblame

kubectl -n pgblame create secret generic pgblame \
  --from-literal=db-url='postgresql://...' \
  --from-literal=token='pgb_...'

2. Apply the manifest

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pgblame-agent
  namespace: pgblame
spec:
  accessModes: ["ReadWriteOnce"]
  resources:
    requests:
      storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: pgblame-agent
  namespace: pgblame
spec:
  replicas: 1            # single writer — never scale this above 1
  strategy:
    type: Recreate       # stop the old pod before starting the new one
  selector:
    matchLabels:
      app: pgblame-agent
  template:
    metadata:
      labels:
        app: pgblame-agent
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 65532
        fsGroup: 65532   # lets the nonroot user write the volume
      containers:
        - name: agent
          image: ghcr.io/liberzon/pgblame-agent:latest
          env:
            - name: PGBLAME_DATABASE_URL
              valueFrom:
                secretKeyRef: { name: pgblame, key: db-url }
            - name: PGBLAME_TOKEN
              valueFrom:
                secretKeyRef: { name: pgblame, key: token }
            - name: PGBLAME_DATA_DIR
              value: /var/lib/pgblame
          volumeMounts:
            - name: data
              mountPath: /var/lib/pgblame
          resources:
            requests: { cpu: 10m, memory: 32Mi }
            limits:   { memory: 64Mi }
      volumes:
        - name: data
          persistentVolumeClaim:
            claimName: pgblame-agent
kubectl apply -f pgblame-agent.yaml

Notes

  • Single replica, Recreate strategy. Two agents on one database double-count deltas. Recreate guarantees the old pod is gone before the new one starts during a rollout.
  • fsGroup: 65532 is load-bearing. The image runs as UID 65532; without the fsGroup it can't write a root-owned volume and the buffer fails to open.
  • Persistence is optional. The PVC keeps the delta baseline + retry queue across restarts and rescheduling (recommended). To run ephemeral, drop the volumes / volumeMounts blocks and the PGBLAME_DATA_DIR env — you'll lose one delta window on each restart.ReadWriteOnce is fine; only one pod ever mounts it.

Helm

There isn't an official pgblame Helm chart yet. For most clusters the manifest above (one Deployment + one PVC) is simpler than a chart. If you template everything through Helm or Argo, use a generic app chart such as bjw-s app-template: map the image, the two secret env vars, PGBLAME_DATA_DIR, and a persistence mount at /var/lib/pgblame, and keep replicas: 1 with the Recreate strategy.

Tell pgblame about deploys

Run the agent on Kubernetes — pgblame