Stage 3 · Build
Databases in Kubernetes
Sidecar Patterns
Metrics exporters, connection proxies, and certificate rotation sidecars.
What Are Sidecars?
Sidecars are companion containers that run alongside the main database container in a pod. They share the network namespace and can access the same volumes. Sidecars handle cross-cutting concerns: monitoring, proxying, backup, and certificate management.
apiVersion: v1
kind: Pod
metadata:
name: postgres-with-sidecars
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
- name: metrics-exporter
image: prometheuscommunity/postgres-exporter
ports:
- containerPort: 9187
env:
- name: DATA_SOURCE_NAME
value: "postgresql://exporter:password@localhost:5432/mydb?sslmode=disable"
- name: pgbouncer
image: bitnami/pgbouncer
ports:
- containerPort: 6432
volumeMounts:
- name: pgbouncer-config
mountPath: /bitnami/pgbouncer
- name: backup-sidecar
image: backup-script:latest
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
readOnly: trueAll containers in the pod share the same network namespace. The metrics exporter connects to PostgreSQL via localhost. The proxy sidecar connects to PostgreSQL via localhost. They communicate through shared volumes or localhost.
Metrics Exporter Sidecar
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
template:
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
- name: exporter
image: prometheuscommunity/postgres-exporter:0.15.0
ports:
- containerPort: 9187
name: metrics
env:
- name: DATA_SOURCE_NAME
value: "postgresql://exporter:$(PASSWORD)@localhost:5432/postgres?sslmode=disable"
- name: PASSWORD
valueFrom:
secretKeyRef:
name: postgres-exporter
key: password
resources:
requests:
cpu: 10m
memory: 32Mi
limits:
cpu: 50m
memory: 64Mi
---
apiVersion: v1
kind: Service
metadata:
name: postgres-metrics
labels:
app: postgres
spec:
ports:
- port: 9187
name: metrics
selector:
app: postgresThe exporter sidecar runs alongside PostgreSQL and exposes metrics on port 9187. Prometheus scrapes this endpoint. The exporter queries pg_stat_activity, pg_stat_replication, and other system views to provide comprehensive metrics.
If using Prometheus Operator, create a ServiceMonitor instead of manually configuring scraping. The ServiceMonitor automatically discovers the exporter endpoint and configures Prometheus scraping.
Connection Proxy Sidecar
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
template:
spec:
containers:
- name: postgres
image: postgres:16
ports:
- containerPort: 5432
- name: pgbouncer
image: bitnami/pgbouncer:1.21.0
ports:
- containerPort: 6432
env:
- name: PGBOUNCER_DATABASE
value: "mydb"
- name: PGBOUNCER_POOL_MODE
value: "transaction"
- name: PGBOUNCER_DEFAULT_POOL_SIZE
value: "25"
- name: PGBOUNCER_MAX_CLIENT_CONN
value: "1000"
- name: PGBOUNCER_AUTH_TYPE
value: "scram-sha-256"
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
readOnly: true
volumes:
- name: pgbouncer-config
secret:
secretName: pgbouncer-configPgBouncer as a sidecar manages connection pooling for that specific pod. Applications connect to PgBouncer on port 6432, which multiplexes connections to PostgreSQL on port 5432. This reduces connection overhead.
Backup Sidecar
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
template:
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
- name: backup
image: backup-script:latest
command: ["/bin/bash", "/scripts/backup.sh"]
env:
- name: BACKUP_SCHEDULE
value: "0 2 * * *"
- name: BACKUP_RETENTION_DAYS
value: "7"
- name: S3_BUCKET
value: "s3://my-backups/postgres"
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
readOnly: true
- name: backup-scripts
mountPath: /scripts
readOnly: true
volumes:
- name: backup-scripts
configMap:
name: backup-scripts
defaultMode: 0755The backup sidecar shares the data volume (read-only) and runs pg_dump on a schedule. This keeps backup logic co-located with the database and independent of Kubernetes CronJobs, which may have scheduling limitations.
Certificate Rotation Sidecar
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
template:
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts:
- name: tls-certs
mountPath: /etc/postgresql/certs
readOnly: true
- name: cert-rotator
image: cert-manager/cert-manager-webhook
command: ["/bin/sh", "-c"]
args:
- |
while true; do
# Check certificate expiry
EXPIRY=$(openssl x509 -enddate -noout -in /etc/postgresql/certs/tls.crt | cut -d= -f2)
EXPIRY_EPOCH=$(date -d "$EXPIRY" +%s)
NOW_EPOCH=$(date +%s)
DAYS_LEFT=$(( (EXPIRY_EPOCH - NOW_EPOCH) / 86400 ))
if [ "$DAYS_LEFT" -lt 30 ]; then
echo "Certificate expires in $DAYS_LEFT days, rotating..."
# Trigger cert-manager renewal
kubectl annotate certificate postgres-tls cert-manager.io/issue-temporary-certificate=true
fi
sleep 86400 # Check daily
done
volumeMounts:
- name: tls-certs
mountPath: /etc/postgresql/certs
readOnly: true
volumes:
- name: tls-certs
secret:
secretName: postgres-tlsThe certificate rotator monitors TLS certificate expiry and triggers renewal before expiration. This prevents outages caused by expired certificates, which are a common cause of production incidents.
Sidecar Tradeoffs
| Pros | Cons |
|---|---|
| Separation of concerns | Increased pod resource usage |
| Independent scaling | More complex pod spec |
| Shared network namespace | Harder to debug |
| Easy to add/remove | Sidecar failures affect the pod |
| Co-located with data | Shared volumes create coupling |
Use sidecars for: monitoring (exporter), connection management (proxy), and certificate management. Avoid sidecars for: backup (use CronJobs for isolation), logging (use DaemonSet), and service mesh (use Istio/Linkerd).
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.