Skip to content

Commit bf98880

Browse files
committed
Merge branch 'main' of https://github.com/boettiger-lab/k8s
2 parents 4eba22f + 861e73c commit bf98880

File tree

10 files changed

+422
-0
lines changed

10 files changed

+422
-0
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,20 @@ Nvidia container toolkit setup
1515
<https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html>
1616

1717

18+
# Tricks
19+
20+
RAM use (etc) of active container (cgroup)
21+
22+
```
23+
cat /sys/fs/cgroup/memory.max | awk '{printf "%.2f GB\n", $1/1024/1024/1024}'
24+
cat /sys/fs/cgroup/memory.current | awk '{printf "%.2f GB\n", $1/1024/1024/1024}'
25+
```
26+
1827

1928
## With external Caddy
2029

30+
(Deprecating)
31+
2132
- Run `K3s` with `--disabled=traefik` (as Caddy will be handling the external network; otherwise this creates conflicts over the http/https ports, 80 & 443).
2233
- For `jupyterhub`, config needs:
2334

postgres/.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
# Ignore actual secrets file
2+
secrets.sh
3+
4+
# Ignore any other local secret files
5+
*.local
6+
*.secret
7+
.env

postgres/README.md

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
# PostgreSQL on Kubernetes
2+
3+
This directory contains the Kubernetes manifests and scripts to deploy PostgreSQL on your cluster.
4+
5+
## Quick Start
6+
7+
1. **Set up secrets:**
8+
```bash
9+
cp secrets.sh.example secrets.sh
10+
# Edit secrets.sh with your actual password
11+
```
12+
13+
2. **Deploy PostgreSQL:**
14+
```bash
15+
chmod +x deploy.sh
16+
./deploy.sh
17+
```
18+
19+
3. **Connect to PostgreSQL:**
20+
- From within the cluster: `psql -h postgres-service.postgres.svc.cluster.local -U postgres -d postgres`
21+
- From outside (port-forward): `kubectl port-forward service/postgres-service 5432:5432 -n postgres`
22+
23+
4. **Clean up:**
24+
```bash
25+
chmod +x cleanup.sh
26+
./cleanup.sh
27+
```
28+
29+
## Files
30+
31+
- `secrets.sh.example` - Template for secrets configuration (copy to `secrets.sh`)
32+
- `secrets.sh` - Your actual secrets (gitignored, create from example)
33+
- `.gitignore` - Ensures secrets don't get committed
34+
- `postgres-pvc.yaml` - Persistent Volume Claim for data storage (10Gi)
35+
- `postgres-deployment.yaml` - PostgreSQL deployment with health checks
36+
- `postgres-service.yaml` - Service to expose PostgreSQL within the cluster
37+
- `deploy.sh` - Script to deploy all resources
38+
- `cleanup.sh` - Script to remove all resources
39+
40+
## Configuration
41+
42+
### Default Credentials
43+
44+
Credentials are set in your local `secrets.sh` file:
45+
- **Host:** postgres-service.postgres.svc.cluster.local
46+
- **Port:** 5432
47+
- **Database:** Set in `secrets.sh` (default: postgres)
48+
- **Username:** Set in `secrets.sh` (default: postgres)
49+
- **Password:** Set in `secrets.sh`
50+
51+
⚠️ **Security Note:** Never commit `secrets.sh` to version control!
52+
53+
### Storage
54+
- Default storage request: 10Gi
55+
- Access mode: ReadWriteOnce
56+
- You may need to specify a `storageClassName` in `postgres-pvc.yaml` depending on your cluster setup
57+
58+
### Resource Limits
59+
- Memory: 256Mi request, 512Mi limit
60+
- CPU: 250m request, 500m limit
61+
62+
## Customization
63+
64+
### Changing Credentials
65+
Edit your local `secrets.sh` file:
66+
```bash
67+
export POSTGRES_PASSWORD="your-new-secure-password"
68+
export POSTGRES_DB="your-database-name"
69+
export POSTGRES_USER="your-username"
70+
```
71+
72+
### Storage Class
73+
If your cluster uses a specific storage class, uncomment and modify the `storageClassName` in `postgres-pvc.yaml`.
74+
75+
### PostgreSQL Version
76+
To use a different PostgreSQL version, modify the `image` field in `postgres-deployment.yaml`:
77+
```yaml
78+
image: postgres:14 # or postgres:13, postgres:16, etc.
79+
```
80+
81+
## Connection Examples
82+
83+
### From a Pod in the Cluster
84+
```yaml
85+
apiVersion: v1
86+
kind: Pod
87+
metadata:
88+
name: postgres-client
89+
namespace: postgres
90+
spec:
91+
containers:
92+
- name: postgres-client
93+
image: postgres:17
94+
command: ['sh', '-c', 'sleep 3600']
95+
env:
96+
- name: PGPASSWORD
97+
value: "postgres123"
98+
```
99+
100+
Then exec into the pod:
101+
```bash
102+
kubectl exec -it postgres-client -n postgres -- psql -h postgres-service.postgres.svc.cluster.local -U postgres -d postgres
103+
```
104+
105+
### Environment Variables for Applications
106+
```yaml
107+
env:
108+
- name: DATABASE_URL
109+
value: "postgresql://postgres:postgres123@postgres-service.postgres.svc.cluster.local:5432/postgres"
110+
- name: POSTGRES_HOST
111+
value: "postgres-service.postgres.svc.cluster.local"
112+
- name: POSTGRES_PORT
113+
value: "5432"
114+
- name: POSTGRES_DB
115+
value: "postgres"
116+
- name: POSTGRES_USER
117+
value: "postgres"
118+
- name: POSTGRES_PASSWORD
119+
valueFrom:
120+
secretKeyRef:
121+
name: postgres-secret
122+
key: postgres-password
123+
```
124+
125+
## Troubleshooting
126+
127+
### Check Pod Status
128+
```bash
129+
kubectl get pods -l app=postgres -n postgres
130+
kubectl describe pod -l app=postgres -n postgres
131+
```
132+
133+
### Check Logs
134+
```bash
135+
kubectl logs -l app=postgres -n postgres
136+
```
137+
138+
### Check PVC Status
139+
```bash
140+
kubectl get pvc postgres-pvc -n postgres
141+
```
142+
143+
### Test Connection
144+
```bash
145+
kubectl run postgres-client --rm -i --tty --image postgres:17 -n postgres -- psql -h postgres-service.postgres.svc.cluster.local -U postgres -d postgres
146+
```
147+
148+
## High Availability Notes
149+
150+
This setup deploys a single PostgreSQL instance. For production environments, consider:
151+
152+
1. **PostgreSQL Operator** - Use operators like Zalando's PostgreSQL Operator or Crunchy Data PostgreSQL Operator
153+
2. **Backup Strategy** - Implement automated backups using tools like pgBackRest or Barman
154+
3. **Monitoring** - Add monitoring with tools like pg_stat_statements and exporters for Prometheus
155+
4. **Resource Tuning** - Adjust memory and CPU limits based on your workload
156+
157+
## Security Considerations
158+
159+
1. **Change Default Password** - Always change the default password in production
160+
2. **Network Policies** - Consider implementing Kubernetes Network Policies to restrict access
161+
3. **TLS** - Configure SSL/TLS for encrypted connections
162+
4. **RBAC** - Use Kubernetes RBAC to control access to PostgreSQL resources

postgres/cleanup.sh

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#!/bin/bash
2+
3+
# PostgreSQL Kubernetes Cleanup Script
4+
# This script removes PostgreSQL from your Kubernetes cluster
5+
6+
set -e
7+
8+
echo "🗑️ Removing PostgreSQL from Kubernetes..."
9+
10+
# Remove all PostgreSQL resources
11+
echo "🗄️ Removing PostgreSQL deployment..."
12+
kubectl delete -f postgres-deployment.yaml --ignore-not-found=true
13+
14+
echo "🌐 Removing PostgreSQL service..."
15+
kubectl delete -f postgres-service.yaml --ignore-not-found=true
16+
17+
echo "💾 Removing persistent volume claim..."
18+
kubectl delete -f postgres-pvc.yaml --ignore-not-found=true
19+
20+
echo "📝 Removing PostgreSQL secret..."
21+
kubectl delete -f postgres-secret.yaml --ignore-not-found=true
22+
23+
echo "📦 Removing postgres namespace..."
24+
kubectl delete namespace postgres --ignore-not-found=true
25+
26+
echo "✅ PostgreSQL cleanup completed!"

postgres/deploy.sh

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
#!/bin/bash
2+
3+
# PostgreSQL Kubernetes Deployment Script
4+
# This script deploys PostgreSQL to your Kubernetes cluster
5+
6+
set -e
7+
8+
echo "🚀 Deploying PostgreSQL to Kubernetes..."
9+
10+
# Load secrets from local file
11+
if [ -f "./secrets.sh" ]; then
12+
echo "📝 Loading secrets from secrets.sh..."
13+
source ./secrets.sh
14+
else
15+
echo "❌ secrets.sh not found!"
16+
echo "Please copy secrets.sh.example to secrets.sh and set your password:"
17+
echo " cp secrets.sh.example secrets.sh"
18+
echo " # Edit secrets.sh with your actual password"
19+
exit 1
20+
fi
21+
22+
# Validate required environment variables
23+
if [ -z "$POSTGRES_PASSWORD" ]; then
24+
echo "❌ POSTGRES_PASSWORD not set in secrets.sh"
25+
exit 1
26+
fi
27+
28+
# Set defaults for optional variables
29+
POSTGRES_DB=${POSTGRES_DB:-"postgres"}
30+
POSTGRES_USER=${POSTGRES_USER:-"postgres"}
31+
32+
echo "🔐 Creating PostgreSQL secret with your password..."
33+
34+
# Create namespace if it doesn't exist
35+
echo "📦 Creating postgres namespace..."
36+
kubectl create namespace postgres --dry-run=client -o yaml | kubectl apply -f -
37+
38+
# Create secret from environment variables
39+
echo "� Creating PostgreSQL secret..."
40+
kubectl create secret generic postgres-secret \
41+
--from-literal=postgres-password="$POSTGRES_PASSWORD" \
42+
--from-literal=postgres-user="$POSTGRES_USER" \
43+
--from-literal=postgres-db="$POSTGRES_DB" \
44+
--namespace=postgres \
45+
--dry-run=client -o yaml | kubectl apply -f -
46+
47+
# Apply all PostgreSQL manifests
48+
49+
echo " Creating persistent volume claim..."
50+
kubectl apply -f postgres-pvc.yaml
51+
52+
echo "🗄️ Creating PostgreSQL deployment..."
53+
kubectl apply -f postgres-deployment.yaml
54+
55+
echo "🌐 Creating PostgreSQL service..."
56+
kubectl apply -f postgres-service.yaml
57+
58+
echo "⏳ Waiting for PostgreSQL to be ready..."
59+
kubectl wait --for=condition=available --timeout=300s deployment/postgres -n postgres
60+
61+
echo "✅ PostgreSQL deployment completed!"
62+
echo ""
63+
echo "Connection details:"
64+
echo " PostgreSQL Host: postgres-service.postgres.svc.cluster.local"
65+
echo " PostgreSQL Port: 5432"
66+
echo " Database: $POSTGRES_DB"
67+
echo " Username: $POSTGRES_USER"
68+
echo " Password: [from secrets.sh]"
69+
echo ""
70+
echo "To connect from within the cluster:"
71+
echo " psql -h postgres-service.postgres.svc.cluster.local -U $POSTGRES_USER -d $POSTGRES_DB"
72+
echo ""
73+
echo "To port-forward PostgreSQL for external access:"
74+
echo " kubectl port-forward service/postgres-service 5432:5432 -n postgres"
75+
echo " Then connect to localhost:5432"

postgres/postgres-deployment.yaml

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: postgres
5+
namespace: postgres
6+
spec:
7+
replicas: 1
8+
selector:
9+
matchLabels:
10+
app: postgres
11+
template:
12+
metadata:
13+
labels:
14+
app: postgres
15+
spec:
16+
containers:
17+
- name: postgres
18+
image: postgres:17
19+
imagePullPolicy: IfNotPresent
20+
ports:
21+
- containerPort: 5432
22+
env:
23+
- name: POSTGRES_PASSWORD
24+
valueFrom:
25+
secretKeyRef:
26+
name: postgres-secret
27+
key: postgres-password
28+
- name: POSTGRES_USER
29+
valueFrom:
30+
secretKeyRef:
31+
name: postgres-secret
32+
key: postgres-user
33+
- name: POSTGRES_DB
34+
valueFrom:
35+
secretKeyRef:
36+
name: postgres-secret
37+
key: postgres-db
38+
volumeMounts:
39+
- mountPath: /var/lib/postgresql/data
40+
name: postgres-storage
41+
resources:
42+
requests:
43+
memory: "256Mi"
44+
cpu: "250m"
45+
limits:
46+
memory: "512Mi"
47+
cpu: "500m"
48+
livenessProbe:
49+
exec:
50+
command:
51+
- /bin/sh
52+
- -c
53+
- exec pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" -h 127.0.0.1 -p 5432
54+
initialDelaySeconds: 30
55+
periodSeconds: 10
56+
timeoutSeconds: 5
57+
successThreshold: 1
58+
failureThreshold: 6
59+
readinessProbe:
60+
exec:
61+
command:
62+
- /bin/sh
63+
- -c
64+
- -e
65+
- |
66+
exec pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB" -h 127.0.0.1 -p 5432
67+
[ -f /opt/bitnami/postgresql/tmp/.initialized ] || [ -f /bitnami/postgresql/.initialized ]
68+
initialDelaySeconds: 5
69+
periodSeconds: 10
70+
timeoutSeconds: 5
71+
successThreshold: 1
72+
failureThreshold: 6
73+
volumes:
74+
- name: postgres-storage
75+
persistentVolumeClaim:
76+
claimName: postgres-pvc

postgres/postgres-ingress.yaml

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## NOTE: Assumes cert-manager and external-dns have been set up.
2+
## Ensure A record exists first if external-dns is not setup
3+
## cloudflare-proxied specific option to cloudflare, subdomains only, does not support sub.sub domains.
4+
##
5+
## This uses Traefik's TCP routing to expose PostgreSQL directly
6+
## Clients can connect using: psql -h postgres-cirrus.carlboettiger.info -p 5432 -U postgres
7+
8+
apiVersion: traefik.containo.us/v1alpha1
9+
kind: IngressRouteTCP
10+
metadata:
11+
name: postgres-tcp-ingress
12+
annotations:
13+
external-dns.alpha.kubernetes.io/cloudflare-proxied: "false" # TCP traffic cannot be proxied through Cloudflare
14+
labels:
15+
app: postgres
16+
spec:
17+
entryPoints:
18+
- postgres-tcp # You'll need to configure this entrypoint in Traefik
19+
routes:
20+
- match: HostSNI(`postgres-cirrus.carlboettiger.info`)
21+
services:
22+
- name: postgres-service
23+
port: 5432
24+
tls:
25+
secretName: postgres-tls

0 commit comments

Comments
 (0)