1056 lines
34 KiB
Markdown
1056 lines
34 KiB
Markdown
# 🐘 PostgreSQL & Gitea Integration Guide
|
||
|
||
> **Complete Guide to PostgreSQL Database Support for Gitea in Your FreeLeaps Kubernetes Environment**
|
||
> *From configuration to data access to troubleshooting*
|
||
|
||
---
|
||
|
||
## 📋 **Table of Contents**
|
||
|
||
1. [🎯 **Overview**](#-overview)
|
||
2. [🏗️ **Your Current Setup**](#️-your-current-setup)
|
||
3. [🔧 **Database Configuration**](#-database-configuration)
|
||
4. [📊 **Data Access Methods**](#-data-access-methods)
|
||
5. [🔍 **Database Monitoring**](#-database-monitoring)
|
||
6. [🚨 **Troubleshooting**](#-troubleshooting)
|
||
7. [💾 **Backup & Recovery**](#-backup--recovery)
|
||
8. [🔒 **Security Best Practices**](#-security-best-practices)
|
||
9. [📈 **Performance Optimization**](#-performance-optimization)
|
||
10. [🛠️ **Maintenance Procedures**](#️-maintenance-procedures)
|
||
|
||
---
|
||
|
||
## 🎯 **Overview**
|
||
|
||
### **What is PostgreSQL in Your Gitea Setup?**
|
||
|
||
PostgreSQL serves as the **primary database backend** for your Gitea installation, storing all critical data including:
|
||
|
||
- **User accounts** and authentication information
|
||
- **Repository metadata** and settings
|
||
- **Issues, pull requests, and comments**
|
||
- **Wiki pages** and documentation
|
||
- **Activity logs** and audit trails
|
||
- **Organization and team data**
|
||
- **Webhook configurations** and integrations
|
||
|
||
### **Why PostgreSQL Instead of SQLite?**
|
||
|
||
Your setup uses PostgreSQL for several important reasons:
|
||
|
||
1. **Production Reliability** - Better for concurrent access and high availability
|
||
2. **Data Integrity** - ACID compliance and transaction support
|
||
3. **Scalability** - Can handle larger datasets and more users
|
||
4. **Backup & Recovery** - Better tools for data protection
|
||
5. **Performance** - Optimized for complex queries and indexing
|
||
|
||
---
|
||
|
||
## 🏗️ **Your Current Setup**
|
||
|
||
### **🌐 Environment-Specific Configurations**
|
||
|
||
#### **Alpha Environment** (`freeleaps-alpha`)
|
||
```yaml
|
||
# Location: freeleaps-ops/freeleaps/helm-pkg/3rd/gitea/values.alpha.yaml
|
||
postgresql-ha:
|
||
enabled: false # ❌ High Availability disabled
|
||
|
||
postgresql:
|
||
enabled: true # ✅ Standard PostgreSQL enabled
|
||
global:
|
||
postgresql:
|
||
auth:
|
||
password: r8sA8CPHD9!bt6d
|
||
database: gitea
|
||
username: gitea
|
||
service:
|
||
ports:
|
||
postgresql: 5432
|
||
primary:
|
||
persistence:
|
||
size: 5Gi # 5GB storage for alpha
|
||
volumePermissions:
|
||
enabled: true
|
||
```
|
||
|
||
#### **Production Environment** (`freeleaps-prod`)
|
||
```yaml
|
||
# Location: freeleaps-ops/freeleaps/helm-pkg/3rd/gitea/values.prod.yaml
|
||
postgresql-ha:
|
||
enabled: true # ✅ High Availability enabled
|
||
global:
|
||
postgresql:
|
||
database: gitea
|
||
password: HFf#Xo4QtfK^CW?@
|
||
username: gitea
|
||
clusterDomain: freeleaps.cluster
|
||
postgresql:
|
||
image:
|
||
repository: freeleaps/postgresql-repmgr
|
||
tag: 16.3.0-debian-12-r20
|
||
repmgrPassword: WGZ47gbUTLvo
|
||
postgresPassword: X9H2*9M2ZWYmuZ
|
||
password: bhYmZ3ivfD@udWc@8jrB4@
|
||
pgpool:
|
||
adminPassword: Rk(*4vc%wFVu5>C|
|
||
persistence:
|
||
size: 25Gi # 25GB storage for production
|
||
|
||
postgresql:
|
||
enabled: false # ❌ Standard PostgreSQL disabled
|
||
```
|
||
|
||
### **🔧 Architecture Comparison**
|
||
|
||
#### **Alpha Environment (Standard PostgreSQL)**
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ ALPHA ENVIRONMENT │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
||
│ │ Gitea Pod │ │ PostgreSQL │ │ Redis │ │
|
||
│ │ (Web UI) │ │ (Database) │ │ (Cache) │ │
|
||
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
||
│ │ │ │ │
|
||
│ │ TCP 5432 │ │ │
|
||
│ └────────────────────┘ │ │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ Single PostgreSQL Instance │ │
|
||
│ │ - Database: gitea │ │
|
||
│ │ - User: gitea │ │
|
||
│ │ - Storage: 5Gi │ │
|
||
│ │ - No replication │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
#### **Production Environment (PostgreSQL HA)**
|
||
```
|
||
┌─────────────────────────────────────────────────────────────┐
|
||
│ PRODUCTION ENVIRONMENT │
|
||
├─────────────────────────────────────────────────────────────┤
|
||
│ ┌─────────────────┐ ┌─────────────────┐ ┌──────────────┐ │
|
||
│ │ Gitea Pod │ │ PostgreSQL │ │ Redis │ │
|
||
│ │ (Web UI) │ │ HA Cluster │ │ (Cache) │ │
|
||
│ └─────────────────┘ └─────────────────┘ └──────────────┘ │
|
||
│ │ │ │ │
|
||
│ │ TCP 5432 │ │ │
|
||
│ └────────────────────┘ │ │
|
||
│ ┌─────────────────────────────────────────────────────────┐ │
|
||
│ │ PostgreSQL HA Cluster │ │
|
||
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
|
||
│ │ │ Primary │ │ Replica │ │ PgPool │ │ │
|
||
│ │ │ Node │ │ Node │ │ (Proxy) │ │ │
|
||
│ │ └─────────────┘ └─────────────┘ └─────────────┘ │ │
|
||
│ │ - Database: gitea │ │
|
||
│ │ - User: gitea │ │
|
||
│ │ - Storage: 25Gi │ │
|
||
│ │ - Automatic failover │ │
|
||
│ └─────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────┘
|
||
```
|
||
|
||
---
|
||
|
||
## 🔧 **Database Configuration**
|
||
|
||
### **📋 How Gitea Connects to PostgreSQL**
|
||
|
||
#### **Connection Configuration**
|
||
Gitea automatically configures its database connection based on your Helm values:
|
||
|
||
```yaml
|
||
# Gitea database configuration (auto-generated)
|
||
database:
|
||
DB_TYPE: postgres
|
||
HOST: <postgresql-service-name>.<namespace>.svc.cluster.local
|
||
NAME: gitea
|
||
USER: gitea
|
||
PASSWD: <password-from-values>
|
||
PORT: 5432
|
||
```
|
||
|
||
#### **Service Discovery**
|
||
```bash
|
||
# Alpha Environment
|
||
HOST: gitea-postgresql.freeleaps-alpha.svc.cluster.local
|
||
|
||
# Production Environment
|
||
HOST: gitea-postgresql-ha-pgpool.freeleaps-prod.svc.cluster.local
|
||
```
|
||
|
||
### **🔍 Database Schema**
|
||
|
||
#### **Key Gitea Tables**
|
||
```sql
|
||
-- User management
|
||
user -- User accounts and profiles
|
||
public_key -- SSH public keys
|
||
access_token -- API access tokens
|
||
|
||
-- Repository management
|
||
repository -- Repository metadata
|
||
mirror -- Repository mirrors
|
||
repo_unit -- Repository permissions
|
||
repo_watch -- Repository watching
|
||
|
||
-- Issue tracking
|
||
issue -- Issues and pull requests
|
||
comment -- Comments on issues/PRs
|
||
label -- Issue labels
|
||
milestone -- Project milestones
|
||
|
||
-- Activity and logs
|
||
action -- User activity logs
|
||
webhook -- Webhook configurations
|
||
hook_task -- Webhook execution history
|
||
|
||
-- Wiki and documentation
|
||
wiki_page -- Wiki pages
|
||
wiki_revision -- Wiki page revisions
|
||
```
|
||
|
||
---
|
||
|
||
## 📊 **Data Access Methods**
|
||
|
||
### **🔑 Direct Database Access**
|
||
|
||
#### **Method 1: Port Forward (Recommended)**
|
||
```bash
|
||
# Alpha Environment
|
||
kubectl port-forward svc/gitea-postgresql -n freeleaps-alpha 5432:5432
|
||
|
||
# Production Environment
|
||
kubectl port-forward svc/gitea-postgresql-ha-pgpool -n freeleaps-prod 5432:5432
|
||
|
||
# Connect with psql
|
||
psql -h localhost -p 5432 -U gitea -d gitea
|
||
# Password: r8sA8CPHD9!bt6d (alpha) or HFf#Xo4QtfK^CW?@ (prod)
|
||
```
|
||
|
||
#### **Method 2: Direct Pod Access**
|
||
```bash
|
||
# Alpha Environment
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea
|
||
|
||
# Production Environment
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- psql -U gitea -d gitea
|
||
```
|
||
|
||
#### **Method 3: Using kubectl exec with psql**
|
||
```bash
|
||
# Alpha Environment
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "SELECT * FROM user LIMIT 5;"
|
||
|
||
# Production Environment
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- psql -U gitea -d gitea -c "SELECT * FROM user LIMIT 5;"
|
||
```
|
||
|
||
### **🔍 Useful Database Queries**
|
||
|
||
#### **User Management**
|
||
```sql
|
||
-- List all users
|
||
SELECT id, name, email, created_unix, is_admin FROM user;
|
||
|
||
-- Find admin users
|
||
SELECT id, name, email FROM user WHERE is_admin = true;
|
||
|
||
-- Count total users
|
||
SELECT COUNT(*) as total_users FROM user;
|
||
|
||
-- Find recently created users
|
||
SELECT name, email, created_unix
|
||
FROM user
|
||
WHERE created_unix > extract(epoch from now() - interval '30 days')
|
||
ORDER BY created_unix DESC;
|
||
```
|
||
|
||
#### **Repository Management**
|
||
```sql
|
||
-- List all repositories
|
||
SELECT id, owner_id, name, description, created_unix
|
||
FROM repository
|
||
ORDER BY created_unix DESC;
|
||
|
||
-- Find repositories by owner
|
||
SELECT r.id, r.name, r.description, u.name as owner_name
|
||
FROM repository r
|
||
JOIN user u ON r.owner_id = u.id
|
||
WHERE u.name = 'your-username';
|
||
|
||
-- Count repositories per user
|
||
SELECT u.name, COUNT(r.id) as repo_count
|
||
FROM user u
|
||
LEFT JOIN repository r ON u.id = r.owner_id
|
||
GROUP BY u.id, u.name
|
||
ORDER BY repo_count DESC;
|
||
```
|
||
|
||
#### **Issue Tracking**
|
||
```sql
|
||
-- List recent issues
|
||
SELECT i.id, i.title, i.created_unix, u.name as creator
|
||
FROM issue i
|
||
JOIN user u ON i.poster_id = u.id
|
||
WHERE i.is_closed = false
|
||
ORDER BY i.created_unix DESC
|
||
LIMIT 10;
|
||
|
||
-- Count issues by status
|
||
SELECT
|
||
CASE WHEN is_closed = true THEN 'Closed' ELSE 'Open' END as status,
|
||
COUNT(*) as count
|
||
FROM issue
|
||
GROUP BY is_closed;
|
||
|
||
-- Find issues with most comments
|
||
SELECT i.id, i.title, COUNT(c.id) as comment_count
|
||
FROM issue i
|
||
LEFT JOIN comment c ON i.id = c.issue_id
|
||
GROUP BY i.id, i.title
|
||
ORDER BY comment_count DESC
|
||
LIMIT 10;
|
||
```
|
||
|
||
#### **Activity Monitoring**
|
||
```sql
|
||
-- Recent user activity
|
||
SELECT a.id, a.user_id, a.op_type, a.repo_id, a.created_unix, u.name as user_name
|
||
FROM action a
|
||
JOIN user u ON a.user_id = u.id
|
||
ORDER BY a.created_unix DESC
|
||
LIMIT 20;
|
||
|
||
-- Most active users
|
||
SELECT u.name, COUNT(a.id) as activity_count
|
||
FROM user u
|
||
JOIN action a ON u.id = a.user_id
|
||
WHERE a.created_unix > extract(epoch from now() - interval '7 days')
|
||
GROUP BY u.id, u.name
|
||
ORDER BY activity_count DESC
|
||
LIMIT 10;
|
||
```
|
||
|
||
### **📊 Database Monitoring Queries**
|
||
|
||
#### **Performance Metrics**
|
||
```sql
|
||
-- Database size
|
||
SELECT
|
||
pg_size_pretty(pg_database_size('gitea')) as database_size;
|
||
|
||
-- Table sizes
|
||
SELECT
|
||
schemaname,
|
||
tablename,
|
||
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as size
|
||
FROM pg_tables
|
||
WHERE schemaname = 'public'
|
||
ORDER BY pg_total_relation_size(schemaname||'.'||tablename) DESC;
|
||
|
||
-- Connection count
|
||
SELECT count(*) as active_connections
|
||
FROM pg_stat_activity
|
||
WHERE state = 'active';
|
||
```
|
||
|
||
---
|
||
|
||
## 🔍 **Database Monitoring**
|
||
|
||
### **📊 Key Metrics to Monitor**
|
||
|
||
#### **1. Connection Health**
|
||
```bash
|
||
# Check if Gitea can connect to PostgreSQL
|
||
kubectl logs -f deployment/gitea -n freeleaps-alpha | grep -i "database\|postgres"
|
||
|
||
# Check PostgreSQL service status
|
||
kubectl get svc -n freeleaps-alpha | grep postgresql
|
||
kubectl get pods -n freeleaps-alpha | grep postgresql
|
||
```
|
||
|
||
#### **2. Performance Metrics**
|
||
```bash
|
||
# Check PostgreSQL resource usage
|
||
kubectl top pods -n freeleaps-alpha | grep postgresql
|
||
|
||
# Check storage usage
|
||
kubectl get pvc -n freeleaps-alpha | grep postgresql
|
||
```
|
||
|
||
#### **3. Production HA Monitoring**
|
||
```bash
|
||
# Check HA cluster status (Production only)
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr cluster show
|
||
|
||
# Check PgPool status (Production only)
|
||
kubectl exec -it deployment/gitea-postgresql-ha-pgpool -n freeleaps-prod -- pgpool -c "SHOW pool_status;"
|
||
```
|
||
|
||
### **🚨 Monitoring Alerts**
|
||
|
||
#### **Critical Alerts**
|
||
```yaml
|
||
# Database connection failures
|
||
- Alert: GiteaDatabaseConnectionFailed
|
||
Condition: Gitea cannot connect to PostgreSQL
|
||
Action: Check PostgreSQL pod status and logs
|
||
|
||
# High connection count
|
||
- Alert: PostgreSQLHighConnections
|
||
Condition: Active connections > 80% of max_connections
|
||
Action: Investigate connection leaks or scaling needs
|
||
|
||
# Storage warnings
|
||
- Alert: PostgreSQLStorageWarning
|
||
Condition: Storage usage > 80%
|
||
Action: Plan storage expansion
|
||
```
|
||
|
||
---
|
||
|
||
## 🚨 **Troubleshooting**
|
||
|
||
### **🔍 Common Issues & Solutions**
|
||
|
||
#### **1. Gitea Cannot Connect to Database**
|
||
|
||
##### **Problem**: Gitea fails to start due to database connection issues
|
||
```bash
|
||
# Symptoms:
|
||
# - Gitea pod stuck in CrashLoopBackOff
|
||
# - Logs show "database connection failed"
|
||
# - Gitea web UI shows database error
|
||
|
||
# Diagnosis:
|
||
kubectl logs -f deployment/gitea -n freeleaps-alpha
|
||
kubectl describe pod -l app=gitea -n freeleaps-alpha
|
||
|
||
# Solutions:
|
||
# 1. Check PostgreSQL pod status
|
||
kubectl get pods -n freeleaps-alpha | grep postgresql
|
||
|
||
# 2. Check PostgreSQL logs
|
||
kubectl logs -f deployment/gitea-postgresql -n freeleaps-alpha
|
||
|
||
# 3. Test database connectivity
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "SELECT 1;"
|
||
|
||
# 4. Verify credentials
|
||
kubectl get secret gitea-postgresql -n freeleaps-alpha -o yaml
|
||
```
|
||
|
||
#### **2. Database Performance Issues**
|
||
|
||
##### **Problem**: Slow database queries or high resource usage
|
||
```bash
|
||
# Symptoms:
|
||
# - Slow Gitea web interface
|
||
# - High CPU/memory usage on PostgreSQL pod
|
||
# - Timeout errors in logs
|
||
|
||
# Diagnosis:
|
||
# 1. Check resource usage
|
||
kubectl top pods -n freeleaps-alpha | grep postgresql
|
||
|
||
# 2. Check slow queries
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT query, mean_time, calls
|
||
FROM pg_stat_statements
|
||
ORDER BY mean_time DESC
|
||
LIMIT 10;"
|
||
|
||
# 3. Check table statistics
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT schemaname, tablename, n_tup_ins, n_tup_upd, n_tup_del, n_live_tup, n_dead_tup
|
||
FROM pg_stat_user_tables
|
||
ORDER BY n_dead_tup DESC;"
|
||
|
||
# Solutions:
|
||
# 1. Optimize slow queries
|
||
# 2. Add database indexes
|
||
# 3. Increase resource limits
|
||
# 4. Consider read replicas (Production)
|
||
```
|
||
|
||
#### **3. Storage Issues**
|
||
|
||
##### **Problem**: Database running out of storage space
|
||
```bash
|
||
# Symptoms:
|
||
# - PostgreSQL pod shows storage errors
|
||
# - PVC shows high usage
|
||
# - Database operations fail
|
||
|
||
# Diagnosis:
|
||
# 1. Check PVC usage
|
||
kubectl get pvc -n freeleaps-alpha | grep postgresql
|
||
|
||
# 2. Check database size
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT pg_size_pretty(pg_database_size('gitea'));"
|
||
|
||
# 3. Check table sizes
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT tablename, pg_size_pretty(pg_total_relation_size(tablename)) as size
|
||
FROM pg_tables
|
||
WHERE schemaname = 'public'
|
||
ORDER BY pg_total_relation_size(tablename) DESC;"
|
||
|
||
# Solutions:
|
||
# 1. Increase PVC size
|
||
kubectl patch pvc gitea-postgresql -n freeleaps-alpha -p '{"spec":{"resources":{"requests":{"storage":"10Gi"}}}}'
|
||
|
||
# 2. Clean up old data
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "VACUUM FULL;"
|
||
|
||
# 3. Archive old repositories/issues
|
||
```
|
||
|
||
#### **4. Production HA Issues**
|
||
|
||
##### **Problem**: PostgreSQL HA cluster not healthy
|
||
```bash
|
||
# Symptoms:
|
||
# - Primary node down
|
||
# - Replication lag
|
||
# - PgPool connection errors
|
||
|
||
# Diagnosis:
|
||
# 1. Check cluster status
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr cluster show
|
||
|
||
# 2. Check node status
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr node status
|
||
|
||
# 3. Check PgPool status
|
||
kubectl exec -it deployment/gitea-postgresql-ha-pgpool -n freeleaps-prod -- pgpool -c "SHOW pool_status;"
|
||
|
||
# Solutions:
|
||
# 1. Restart problematic nodes
|
||
kubectl delete pod gitea-postgresql-ha-postgresql-1 -n freeleaps-prod
|
||
|
||
# 2. Rejoin cluster if needed
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-1 -n freeleaps-prod -- repmgr node rejoin
|
||
|
||
# 3. Check replication lag
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- repmgr cluster show
|
||
```
|
||
|
||
### **🛠️ Debugging Commands**
|
||
|
||
#### **Essential Debugging Commands**
|
||
```bash
|
||
# Check PostgreSQL status
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_isready -U gitea -d gitea
|
||
|
||
# Check database connections
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT count(*) as active_connections
|
||
FROM pg_stat_activity
|
||
WHERE state = 'active';"
|
||
|
||
# Check database locks
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT * FROM pg_locks WHERE NOT granted;"
|
||
|
||
# Check slow queries
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT query, mean_time, calls
|
||
FROM pg_stat_statements
|
||
ORDER BY mean_time DESC
|
||
LIMIT 5;"
|
||
|
||
# Check table bloat
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT schemaname, tablename, n_dead_tup, n_live_tup,
|
||
CASE WHEN n_live_tup > 0 THEN round(100.0 * n_dead_tup / n_live_tup, 2) ELSE 0 END as bloat_ratio
|
||
FROM pg_stat_user_tables
|
||
WHERE n_dead_tup > 0
|
||
ORDER BY bloat_ratio DESC;"
|
||
```
|
||
|
||
---
|
||
|
||
## 💾 **Backup & Recovery**
|
||
|
||
### **📦 Backup Strategies**
|
||
|
||
#### **1. Automated Backups**
|
||
```bash
|
||
# Create backup script
|
||
#!/bin/bash
|
||
# scripts/backup-gitea-database.sh
|
||
|
||
NAMESPACE="freeleaps-alpha"
|
||
BACKUP_DIR="/tmp/gitea-backups"
|
||
DATE=$(date +%Y%m%d_%H%M%S)
|
||
|
||
mkdir -p $BACKUP_DIR
|
||
|
||
echo "📦 Creating Gitea database backup..."
|
||
|
||
# Create database backup
|
||
kubectl exec -it deployment/gitea-postgresql -n $NAMESPACE -- pg_dump -U gitea -d gitea --format=custom --file=/tmp/gitea-backup-$DATE.dump
|
||
|
||
# Copy backup file
|
||
kubectl cp $NAMESPACE/deployment/gitea-postgresql:/tmp/gitea-backup-$DATE.dump $BACKUP_DIR/
|
||
|
||
echo "✅ Backup created: $BACKUP_DIR/gitea-backup-$DATE.dump"
|
||
```
|
||
|
||
#### **2. Manual Backups**
|
||
```bash
|
||
# Alpha Environment
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_dump -U gitea -d gitea > gitea-backup-$(date +%Y%m%d).sql
|
||
|
||
# Production Environment
|
||
kubectl exec -it statefulset/gitea-postgresql-ha-postgresql-0 -n freeleaps-prod -- pg_dump -U gitea -d gitea > gitea-prod-backup-$(date +%Y%m%d).sql
|
||
```
|
||
|
||
#### **3. Backup Verification**
|
||
```bash
|
||
# Verify backup integrity
|
||
pg_restore --list gitea-backup-20241201.dump
|
||
|
||
# Test restore to temporary database
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "CREATE DATABASE gitea_test;"
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_restore -U gitea -d gitea_test gitea-backup-20241201.dump
|
||
```
|
||
|
||
### **🔄 Recovery Procedures**
|
||
|
||
#### **1. Full Database Restore**
|
||
```bash
|
||
# Stop Gitea
|
||
kubectl scale deployment gitea -n freeleaps-alpha --replicas=0
|
||
|
||
# Restore database
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_restore -U gitea -d gitea --clean --if-exists gitea-backup-20241201.dump
|
||
|
||
# Restart Gitea
|
||
kubectl scale deployment gitea -n freeleaps-alpha --replicas=1
|
||
```
|
||
|
||
#### **2. Selective Data Recovery**
|
||
```bash
|
||
# Restore specific tables
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
-- Restore only user table
|
||
\copy user FROM '/tmp/user_backup.csv' WITH CSV HEADER;
|
||
|
||
-- Restore only repository table
|
||
\copy repository FROM '/tmp/repository_backup.csv' WITH CSV HEADER;"
|
||
```
|
||
|
||
#### **3. Point-in-Time Recovery**
|
||
```bash
|
||
# Enable WAL archiving for point-in-time recovery
|
||
# This requires additional PostgreSQL configuration
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
-- Restore to specific timestamp
|
||
SELECT pg_wal_replay_resume();
|
||
SELECT pg_wal_replay_pause();"
|
||
```
|
||
|
||
---
|
||
|
||
## 🔒 **Security Best Practices**
|
||
|
||
### **🛡️ Current Security Analysis**
|
||
|
||
#### **✅ Security Strengths**
|
||
1. **Network isolation** - PostgreSQL runs in Kubernetes namespace
|
||
2. **Resource limits** - CPU and memory limits set
|
||
3. **Non-root user** - Runs as postgres user in container
|
||
4. **TLS support** - SSL/TLS configuration available (Production)
|
||
|
||
#### **⚠️ Security Weaknesses**
|
||
1. **Hardcoded passwords** - Passwords in values files
|
||
2. **Default permissions** - Overly permissive user access
|
||
3. **No audit logging** - Limited security event tracking
|
||
4. **No network policies** - No ingress/egress restrictions
|
||
|
||
### **🔧 Security Improvements**
|
||
|
||
#### **1. Secret Management**
|
||
```yaml
|
||
# Use Kubernetes secrets instead of hardcoded values
|
||
apiVersion: v1
|
||
kind: Secret
|
||
metadata:
|
||
name: gitea-postgresql-credentials
|
||
namespace: freeleaps-alpha
|
||
type: Opaque
|
||
data:
|
||
username: Z2l0ZWE= # base64 encoded
|
||
password: <base64-encoded-password>
|
||
---
|
||
# Reference in Helm values
|
||
postgresql:
|
||
global:
|
||
postgresql:
|
||
auth:
|
||
existingSecret: gitea-postgresql-credentials
|
||
secretKeys:
|
||
usernameKey: username
|
||
passwordKey: password
|
||
```
|
||
|
||
#### **2. Network Policies**
|
||
```yaml
|
||
# Restrict network access to PostgreSQL
|
||
apiVersion: networking.k8s.io/v1
|
||
kind: NetworkPolicy
|
||
metadata:
|
||
name: gitea-postgresql-network-policy
|
||
namespace: freeleaps-alpha
|
||
spec:
|
||
podSelector:
|
||
matchLabels:
|
||
app: postgresql
|
||
policyTypes:
|
||
- Ingress
|
||
ingress:
|
||
- from:
|
||
- namespaceSelector:
|
||
matchLabels:
|
||
name: freeleaps-alpha
|
||
ports:
|
||
- protocol: TCP
|
||
port: 5432
|
||
```
|
||
|
||
#### **3. Database Hardening**
|
||
```sql
|
||
-- Limit database connections
|
||
ALTER SYSTEM SET max_connections = 100;
|
||
|
||
-- Enable SSL (Production)
|
||
ALTER SYSTEM SET ssl = on;
|
||
ALTER SYSTEM SET ssl_cert_file = '/etc/ssl/certs/server.crt';
|
||
ALTER SYSTEM SET ssl_key_file = '/etc/ssl/private/server.key';
|
||
|
||
-- Enable audit logging
|
||
CREATE EXTENSION pgaudit;
|
||
ALTER SYSTEM SET pgaudit.log = 'all';
|
||
ALTER SYSTEM SET pgaudit.log_level = 'log';
|
||
```
|
||
|
||
---
|
||
|
||
## 📈 **Performance Optimization**
|
||
|
||
### **🎯 Performance Tuning**
|
||
|
||
#### **1. Database Configuration**
|
||
```yaml
|
||
# Optimize PostgreSQL settings
|
||
postgresql:
|
||
primary:
|
||
extendedConfiguration: |-
|
||
# Memory settings
|
||
shared_buffers = 256MB
|
||
effective_cache_size = 1GB
|
||
work_mem = 4MB
|
||
maintenance_work_mem = 64MB
|
||
|
||
# Checkpoint settings
|
||
checkpoint_completion_target = 0.9
|
||
wal_buffers = 16MB
|
||
|
||
# Query optimization
|
||
random_page_cost = 1.1
|
||
effective_io_concurrency = 200
|
||
|
||
# Logging
|
||
log_min_duration_statement = 1000
|
||
log_checkpoints = on
|
||
log_connections = on
|
||
log_disconnections = on
|
||
```
|
||
|
||
#### **2. Index Optimization**
|
||
```sql
|
||
-- Create indexes for common queries
|
||
CREATE INDEX CONCURRENTLY idx_user_email ON user(email);
|
||
CREATE INDEX CONCURRENTLY idx_repository_owner ON repository(owner_id);
|
||
CREATE INDEX CONCURRENTLY idx_issue_repo ON issue(repo_id);
|
||
CREATE INDEX CONCURRENTLY idx_action_user_time ON action(user_id, created_unix);
|
||
|
||
-- Analyze table statistics
|
||
ANALYZE user;
|
||
ANALYZE repository;
|
||
ANALYZE issue;
|
||
ANALYZE action;
|
||
```
|
||
|
||
#### **3. Query Optimization**
|
||
```sql
|
||
-- Monitor slow queries
|
||
SELECT query, mean_time, calls, total_time
|
||
FROM pg_stat_statements
|
||
WHERE mean_time > 1000
|
||
ORDER BY mean_time DESC;
|
||
|
||
-- Optimize specific queries
|
||
-- Example: Optimize user search query
|
||
EXPLAIN ANALYZE SELECT * FROM user WHERE name ILIKE '%search%';
|
||
```
|
||
|
||
### **📊 Performance Monitoring**
|
||
|
||
#### **Key Performance Indicators**
|
||
1. **Query Response Time** - Average query execution time
|
||
2. **Connection Count** - Active database connections
|
||
3. **Cache Hit Ratio** - Buffer cache efficiency
|
||
4. **I/O Wait Time** - Disk I/O performance
|
||
5. **Lock Wait Time** - Database contention
|
||
|
||
#### **Performance Benchmarks**
|
||
```bash
|
||
# Your expected performance:
|
||
# - Query response time: < 100ms for simple queries
|
||
# - Connection count: < 80% of max_connections
|
||
# - Cache hit ratio: > 90%
|
||
# - I/O wait: < 5% of total time
|
||
# - Lock wait: < 1% of total time
|
||
```
|
||
|
||
---
|
||
|
||
## 🛠️ **Maintenance Procedures**
|
||
|
||
### **📅 Regular Maintenance Tasks**
|
||
|
||
#### **Daily Tasks**
|
||
```bash
|
||
# 1. Check database health
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_isready -U gitea -d gitea
|
||
|
||
# 2. Monitor connection count
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT count(*) as active_connections
|
||
FROM pg_stat_activity
|
||
WHERE state = 'active';"
|
||
|
||
# 3. Check for long-running queries
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
|
||
FROM pg_stat_activity
|
||
WHERE state = 'active'
|
||
AND now() - pg_stat_activity.query_start > interval '5 minutes';"
|
||
```
|
||
|
||
#### **Weekly Tasks**
|
||
```bash
|
||
# 1. Analyze table statistics
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
ANALYZE user;
|
||
ANALYZE repository;
|
||
ANALYZE issue;
|
||
ANALYZE action;"
|
||
|
||
# 2. Check table bloat
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT schemaname, tablename, n_dead_tup, n_live_tup,
|
||
CASE WHEN n_live_tup > 0 THEN round(100.0 * n_dead_tup / n_live_tup, 2) ELSE 0 END as bloat_ratio
|
||
FROM pg_stat_user_tables
|
||
WHERE n_dead_tup > 0
|
||
ORDER BY bloat_ratio DESC;"
|
||
|
||
# 3. Review slow queries
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT query, mean_time, calls
|
||
FROM pg_stat_statements
|
||
ORDER BY mean_time DESC
|
||
LIMIT 10;"
|
||
```
|
||
|
||
#### **Monthly Tasks**
|
||
```bash
|
||
# 1. Full database backup
|
||
./scripts/backup-gitea-database.sh
|
||
|
||
# 2. Vacuum and reindex
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
VACUUM FULL;
|
||
REINDEX DATABASE gitea;"
|
||
|
||
# 3. Review and optimize indexes
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT schemaname, tablename, indexname, idx_scan, idx_tup_read, idx_tup_fetch
|
||
FROM pg_stat_user_indexes
|
||
ORDER BY idx_scan DESC;"
|
||
```
|
||
|
||
### **🔧 Maintenance Scripts**
|
||
|
||
#### **Health Check Script**
|
||
```bash
|
||
#!/bin/bash
|
||
# scripts/gitea-database-health-check.sh
|
||
|
||
NAMESPACE="freeleaps-alpha"
|
||
POD_NAME=$(kubectl get pods -n $NAMESPACE -l app=postgresql -o jsonpath='{.items[0].metadata.name}')
|
||
|
||
echo "🐘 Gitea Database Health Check - $(date)"
|
||
echo "=================================="
|
||
|
||
# Check database connectivity
|
||
echo "📊 Database Connectivity:"
|
||
kubectl exec -it $POD_NAME -n $NAMESPACE -- pg_isready -U gitea -d gitea
|
||
|
||
# Check active connections
|
||
echo "🔗 Active Connections:"
|
||
kubectl exec -it $POD_NAME -n $NAMESPACE -- psql -U gitea -d gitea -c "
|
||
SELECT count(*) as active_connections
|
||
FROM pg_stat_activity
|
||
WHERE state = 'active';"
|
||
|
||
# Check database size
|
||
echo "💾 Database Size:"
|
||
kubectl exec -it $POD_NAME -n $NAMESPACE -- psql -U gitea -d gitea -c "
|
||
SELECT pg_size_pretty(pg_database_size('gitea'));"
|
||
|
||
# Check table statistics
|
||
echo "📋 Table Statistics:"
|
||
kubectl exec -it $POD_NAME -n $NAMESPACE -- psql -U gitea -d gitea -c "
|
||
SELECT schemaname, tablename, n_tup_ins, n_tup_upd, n_tup_del, n_live_tup, n_dead_tup
|
||
FROM pg_stat_user_tables
|
||
ORDER BY n_dead_tup DESC
|
||
LIMIT 5;"
|
||
```
|
||
|
||
#### **Backup Script**
|
||
```bash
|
||
#!/bin/bash
|
||
# scripts/gitea-database-backup.sh
|
||
|
||
NAMESPACE="freeleaps-alpha"
|
||
BACKUP_DIR="/tmp/gitea-backups"
|
||
DATE=$(date +%Y%m%d_%H%M%S)
|
||
|
||
mkdir -p $BACKUP_DIR
|
||
|
||
echo "📦 Creating Gitea database backup..."
|
||
|
||
# Create database backup
|
||
kubectl exec -it deployment/gitea-postgresql -n $NAMESPACE -- pg_dump -U gitea -d gitea --format=custom --file=/tmp/gitea-backup-$DATE.dump
|
||
|
||
# Copy backup file
|
||
kubectl cp $NAMESPACE/deployment/gitea-postgresql:/tmp/gitea-backup-$DATE.dump $BACKUP_DIR/
|
||
|
||
# Verify backup
|
||
kubectl exec -it deployment/gitea-postgresql -n $NAMESPACE -- pg_restore --list /tmp/gitea-backup-$DATE.dump > /dev/null
|
||
|
||
if [ $? -eq 0 ]; then
|
||
echo "✅ Backup created successfully: $BACKUP_DIR/gitea-backup-$DATE.dump"
|
||
else
|
||
echo "❌ Backup verification failed"
|
||
exit 1
|
||
fi
|
||
```
|
||
|
||
### **🚨 Emergency Procedures**
|
||
|
||
#### **1. Database Corruption Recovery**
|
||
```bash
|
||
# If database corruption is detected:
|
||
# 1. Stop Gitea
|
||
kubectl scale deployment gitea -n freeleaps-alpha --replicas=0
|
||
|
||
# 2. Restore from latest backup
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- pg_restore -U gitea -d gitea --clean --if-exists /tmp/gitea-backup-latest.dump
|
||
|
||
# 3. Restart Gitea
|
||
kubectl scale deployment gitea -n freeleaps-alpha --replicas=1
|
||
```
|
||
|
||
#### **2. Performance Emergency**
|
||
```bash
|
||
# If database performance is severely degraded:
|
||
# 1. Check for long-running queries
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "
|
||
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
|
||
FROM pg_stat_activity
|
||
WHERE state = 'active'
|
||
AND now() - pg_stat_activity.query_start > interval '5 minutes';"
|
||
|
||
# 2. Kill problematic queries
|
||
kubectl exec -it deployment/gitea-postgresql -n freeleaps-alpha -- psql -U gitea -d gitea -c "SELECT pg_terminate_backend(pid);"
|
||
|
||
# 3. Restart PostgreSQL if needed
|
||
kubectl rollout restart deployment/gitea-postgresql -n freeleaps-alpha
|
||
```
|
||
|
||
---
|
||
|
||
## 🎯 **Summary & Next Steps**
|
||
|
||
### **📊 Current State Assessment**
|
||
|
||
#### **✅ Strengths**
|
||
1. **Production-ready setup** - HA clustering in production
|
||
2. **Helm-based deployment** - Consistent and repeatable
|
||
3. **Environment separation** - Alpha vs Production configurations
|
||
4. **Integration working** - Gitea successfully using PostgreSQL
|
||
5. **Monitoring available** - Basic health checks and metrics
|
||
|
||
#### **⚠️ Areas for Improvement**
|
||
1. **Security hardening** - Remove hardcoded passwords, implement secrets
|
||
2. **Backup automation** - Implement automated backup procedures
|
||
3. **Performance tuning** - Optimize database settings for your workload
|
||
4. **Monitoring enhancement** - Add comprehensive monitoring and alerting
|
||
5. **Documentation** - Create runbooks for common operations
|
||
|
||
### **🚀 Recommended Actions**
|
||
|
||
#### **Immediate (This Week)**
|
||
1. **Implement secret management** - Move passwords to Kubernetes secrets
|
||
2. **Set up automated backups** - Create daily backup scripts
|
||
3. **Add basic monitoring** - Set up database health checks
|
||
4. **Document procedures** - Create runbooks for common operations
|
||
|
||
#### **Short Term (Next Month)**
|
||
1. **Security audit** - Review and improve security posture
|
||
2. **Performance tuning** - Optimize settings based on usage patterns
|
||
3. **Monitoring enhancement** - Add comprehensive metrics and alerting
|
||
4. **Training** - Train team on database management and troubleshooting
|
||
|
||
#### **Long Term (Next Quarter)**
|
||
1. **Advanced monitoring** - Implement predictive analytics and alerting
|
||
2. **Disaster recovery** - Set up automated backup and recovery procedures
|
||
3. **Performance optimization** - Implement query optimization and indexing
|
||
4. **Capacity planning** - Plan for growth and scaling
|
||
|
||
### **📚 Additional Resources**
|
||
|
||
#### **Official Documentation**
|
||
- **[PostgreSQL Documentation](https://www.postgresql.org/docs/)** - Official PostgreSQL guides
|
||
- **[Gitea Database Documentation](https://docs.gitea.com/installation/database-prep)** - Database setup guide
|
||
- **[Bitnami PostgreSQL Helm Chart](https://github.com/bitnami/charts/tree/main/bitnami/postgresql)** - Helm chart documentation
|
||
|
||
#### **Community Resources**
|
||
- **[PostgreSQL Slack](https://postgresql-slack.herokuapp.com/)** - Community support (Note: May require invitation)
|
||
- **[Gitea Community](https://gitea.com/gitea/helm-gitea)** - Gitea Helm chart community
|
||
- **[PostgreSQL Wiki](https://wiki.postgresql.org/wiki/)** - Community wiki
|
||
|
||
#### **Books & Courses**
|
||
- **"PostgreSQL: Up and Running"** by Regina Obe and Leo Hsu
|
||
- **"Gitea Documentation"** - Official Gitea guides
|
||
- **PostgreSQL Tutorials** - Official tutorial series
|
||
|
||
---
|
||
|
||
**🎉 You now have a comprehensive understanding of how PostgreSQL supports Gitea in your Kubernetes environment! Use this guide to maintain, monitor, and optimize your database infrastructure.**
|
||
|
||
---
|
||
|
||
*Last updated: $(date)*
|
||
*Maintained by: FreeLeaps DevOps Team*
|