Files

Kubernetes Deployment Guide for YouMusic

This guide explains how to deploy YouMusic to your k3s cluster.

Prerequisites

  • k3s cluster running
  • kubectl configured to access your cluster
  • cert-manager installed (for TLS certificates)
  • nginx ingress controller installed
  • Optional: Private container registry credentials

Quick Start

0. Database Migrations

YouMusic now uses Alembic for database migrations. An init container will automatically run migrations before the app starts.

How it works:

  • Init container runs /app/backend/run-migrations.sh
  • Executes alembic upgrade head
  • Must complete successfully before app starts
  • Shares the same data volume with the app

1. Build and Push Docker Image

# Build the image
docker build -t youmusic:latest .

# Tag for your registry (example with GitHub Container Registry)
docker tag youmusic:latest ghcr.io/wahyd4/youmusic:latest

# Push to registry
docker push ghcr.io/wahyd4/youmusic:latest

2. Update Manifest

Edit k8s/manifest.yaml and update:

# Line 47: Update image name
image: "ghcr.io/wahyd4/youmusic:latest"

# Line 125-126: Update domain name
- host: music.junv.cc  # Your domain
  secretName: youmusic-tls

3. Create Secret for Private Registry (Optional)

If using private registry:

kubectl create secret docker-registry github-image-pull-secret \
  --docker-server=ghcr.io \
  --docker-username=your-github-username \
  --docker-password=your-github-token \
  --docker-email=your-email@example.com

Then uncomment in manifest:

imagePullSecrets:
  - name: github-image-pull-secret

4. Deploy to Kubernetes

# Apply the manifest
kubectl apply -f k8s/manifest.yaml

# Check deployment status
kubectl get pods -l app=youmusic
kubectl get svc youmusic
kubectl get ingress youmusic-ingress

5. Verify Deployment

# Check pod logs
kubectl logs -f deployment/youmusic

# Check migration init container logs
kubectl logs -l app=youmusic -c youmusic-migrations

# Check if pod is running
kubectl get pods

# Describe pod for details
kubectl describe pod -l app=youmusic

Manifest Structure

PersistentVolumeClaim (PVC)

- Name: youmusic-data-pvc
- Size: 50Gi
- Access: ReadWriteOnce (single node)
- Storage Class: local-path (default in k3s)

Stores:

  • SQLite database (/app/data/youmusic.db)
  • Music files (/app/data/music/)
  • Uploaded files (/app/data/uploads/)
  • Thumbnails (/app/data/music/thumbnails/)
  • Artist cache (/app/data/cache/artists/)
  • Artist images (/app/data/cache/artist_images/)

Deployment

- Replicas: 1 (SQLite limitation)
- Strategy: Recreate (prevent multiple pods)
- Image: Your registry image
- Resources:
  - Requests: 200m CPU, 512Mi RAM
  - Limits: 2000m CPU, 2048Mi RAM

Environment Variables:

  • DATABASE_URL: SQLite connection string
  • MUSIC_DIR: Music files directory
  • UPLOAD_DIR: Upload directory
  • TEMP_DIR: Temporary files
  • BASE_DIR: Application base directory

Health Checks:

  • Liveness: HTTP GET / every 10s
  • Readiness: HTTP GET / every 5s

Service

- Type: ClusterIP
- Port: 80 → 8000 (container)

Ingress

- Class: nginx
- TLS: Enabled (Let's Encrypt)
- Max Upload: 500MB
- Timeouts: 600s

Annotations:

  • proxy-body-size: 500m - Large file uploads
  • proxy-read-timeout: 600 - Long downloads
  • proxy-send-timeout: 600 - Long uploads

Configuration Options

Storage Class

Update if using different storage:

storageClassName: nfs-client  # Or your storage class

Domain Configuration

Update your domain in:

spec:
  tls:
    - hosts:
        - your-domain.com
      secretName: youmusic-tls
  rules:
    - host: your-domain.com

Enable Authentication (Optional)

Uncomment in ingress annotations:

nginx.ingress.kubernetes.io/auth-url: "https://pass.junv.cc/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://pass.junv.cc/?redirect=https%3A%2F%2F$host$request_uri"

Resource Limits

Adjust based on your needs:

resources:
  requests:
    cpu: 200m      # Increase for better performance
    memory: 512Mi  # Increase if many downloads
  limits:
    cpu: 2000m     # Max CPU
    memory: 2048Mi # Max memory

Persistent Data

All data is stored in the PVC:

/app/data/
├── youmusic.db              # SQLite database
├── music/                   # Downloaded music files
│   ├── song1.mp3
│   ├── song2.mp3
│   └── thumbnails/          # Song thumbnails
│       ├── song1.jpg
│       └── song2.jpg
├── uploads/                 # User uploaded files
├── temp/                    # Temporary download files
└── cache/                   # Cache directory
    ├── artists/             # Artist metadata JSON
    │   └── Westlife.json
    └── artist_images/       # Artist avatars
        └── Westlife.jpg

Backup Data

# Get pod name
POD=$(kubectl get pod -l app=youmusic -o jsonpath='{.items[0].metadata.name}')

# Copy data from pod
kubectl cp $POD:/app/data ./youmusic-backup

# Or use exec to tar
kubectl exec $POD -- tar czf - /app/data > youmusic-backup.tar.gz

Restore Data

# Copy backup to pod
kubectl cp ./youmusic-backup $POD:/app/data-restore

# Or restore from tar
kubectl exec -i $POD -- tar xzf - -C /app < youmusic-backup.tar.gz

Monitoring

View Logs

# Follow logs
kubectl logs -f deployment/youmusic

# Last 100 lines
kubectl logs --tail=100 deployment/youmusic

# All containers (if multiple)
kubectl logs -f -l app=youmusic --all-containers

Pod Status

# Get pod details
kubectl describe pod -l app=youmusic

# Get events
kubectl get events --sort-by=.metadata.creationTimestamp

Resource Usage

# CPU and memory usage
kubectl top pod -l app=youmusic

# Node resources
kubectl top nodes

Troubleshooting

Pod Not Starting

# Check pod status
kubectl get pods -l app=youmusic

# Check events
kubectl describe pod -l app=youmusic

# Check logs
kubectl logs deployment/youmusic

Common Issues:

  • Image pull errors → Check imagePullSecrets
  • Permission denied → Check volume permissions
  • Database locked → Ensure single replica only

Database Issues

# Check migration init container logs
kubectl logs -l app=youmusic -c youmusic-migrations

# Exec into pod
kubectl exec -it deployment/youmusic -- bash

# Check database
cd /app/data
ls -la youmusic.db

# Check SQLite
sqlite3 youmusic.db "SELECT COUNT(*) FROM music;"

# Manually run migrations if needed
cd /app/backend
./migrate.sh current
./migrate.sh history
./migrate.sh upgrade

Storage Full

# Check disk usage
kubectl exec deployment/youmusic -- df -h /app/data

# Check directory sizes
kubectl exec deployment/youmusic -- du -sh /app/data/*

Solution: Increase PVC size:

resources:
  requests:
    storage: 100Gi  # Increase from 50Gi

Then:

kubectl patch pvc youmusic-data-pvc -p '{"spec":{"resources":{"requests":{"storage":"100Gi"}}}}'

Ingress Not Working

# Check ingress
kubectl get ingress youmusic-ingress
kubectl describe ingress youmusic-ingress

# Check cert-manager
kubectl get certificate
kubectl describe certificate youmusic-tls

Scaling Limitations

⚠️ Important: YouMusic uses SQLite, which does NOT support multiple concurrent writers.

Limitations:

  • Can handle multiple readers
  • Cannot scale replicas > 1
  • ReadWriteOnce PVC (single node only)

For Production at Scale:

  • Consider migrating to PostgreSQL/MySQL
  • Update DATABASE_URL environment variable
  • Enable multi-replica deployment

Updates

Update Image

# Build new version
docker build -t ghcr.io/wahyd4/youmusic:v2 .
docker push ghcr.io/wahyd4/youmusic:v2

# Update deployment
kubectl set image deployment/youmusic youmusic=ghcr.io/wahyd4/youmusic:v2

# Or edit manifest and reapply
kubectl apply -f k8s/manifest.yaml

# Check rollout status
kubectl rollout status deployment/youmusic

Rollback

# View rollout history
kubectl rollout history deployment/youmusic

# Rollback to previous version
kubectl rollout undo deployment/youmusic

# Rollback to specific revision
kubectl rollout undo deployment/youmusic --to-revision=2

Clean Up

# Delete all resources
kubectl delete -f k8s/manifest.yaml

# Delete PVC (will delete all data!)
kubectl delete pvc youmusic-data-pvc

⚠️ Warning: Deleting the PVC will permanently delete all music, database, and cache!

Advanced Configuration

Using NFS Storage

apiVersion: v1
kind: PersistentVolume
metadata:
  name: youmusic-nfs-pv
spec:
  capacity:
    storage: 100Gi
  accessModes:
    - ReadWriteMany
  nfs:
    server: 192.168.1.5
    path: "/nfs/youmusic"

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: youmusic-data-pvc
spec:
  storageClassName: ""
  volumeName: youmusic-nfs-pv
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 100Gi

Multiple Environments

# Create namespace
kubectl create namespace youmusic-prod
kubectl create namespace youmusic-dev

# Deploy to specific namespace
kubectl apply -f k8s/manifest.yaml -n youmusic-prod
kubectl apply -f k8s/manifest-dev.yaml -n youmusic-dev

Security Considerations

  1. Enable Authentication (Recommended)

    • Use nginx ingress auth
    • Integrate with OAuth2 proxy
    • Restrict access to trusted users
  2. Network Policies

    • Restrict pod-to-pod communication
    • Limit egress for downloads
  3. Resource Limits

    • Set CPU/memory limits
    • Prevent resource exhaustion
  4. Secrets Management

    • Use Kubernetes secrets for sensitive data
    • Consider using sealed-secrets or external-secrets

Support

For issues or questions:

  • Check logs: kubectl logs deployment/youmusic
  • Review events: kubectl get events
  • Check documentation: See main README.md
  • GitHub Issues: [Your repo URL]

Deployment Version: 1.0.0 Last Updated: 2024-10-30