Skip to main content

Kubernetes Deployment

Deploy Imagor Studio on Kubernetes for production-scale deployments.

Prerequisites

  • Kubernetes cluster (1.19+)
  • kubectl configured
  • PostgreSQL database (recommended)
  • S3-compatible storage (optional)

Basic Deployment

Namespace

apiVersion: v1
kind: Namespace
metadata:
name: imagor-studio

Database Secret

apiVersion: v1
kind: Secret
metadata:
name: database-secret
namespace: imagor-studio
type: Opaque
stringData:
url: postgres://user:password@postgres:5432/imagor_studio

Migration Job

apiVersion: batch/v1
kind: Job
metadata:
name: imagor-studio-migrate
namespace: imagor-studio
spec:
template:
spec:
containers:
- name: migrate
image: shumc/imagor-studio:latest
command: ["imagor-studio-migrate", "--migrate-command=up"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secret
key: url
restartPolicy: OnFailure

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: imagor-studio
namespace: imagor-studio
spec:
replicas: 3
selector:
matchLabels:
app: imagor-studio
template:
metadata:
labels:
app: imagor-studio
spec:
containers:
- name: imagor-studio
image: shumc/imagor-studio:latest
ports:
- containerPort: 8000
name: http
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: database-secret
key: url
- name: PORT
value: "8000"
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 5
periodSeconds: 5

Service

apiVersion: v1
kind: Service
metadata:
name: imagor-studio
namespace: imagor-studio
spec:
selector:
app: imagor-studio
ports:
- port: 80
targetPort: 8000
name: http
type: ClusterIP

Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: imagor-studio
namespace: imagor-studio
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- imagor.example.com
secretName: imagor-studio-tls
rules:
- host: imagor.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: imagor-studio
port:
number: 80

Deploy

# Create namespace
kubectl apply -f namespace.yaml

# Create secrets
kubectl apply -f secrets.yaml

# Run migrations
kubectl apply -f migration-job.yaml
kubectl wait --for=condition=complete job/imagor-studio-migrate -n imagor-studio

# Deploy application
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
kubectl apply -f ingress.yaml

With PostgreSQL

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: imagor-studio
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:15
ports:
- containerPort: 5432
env:
- name: POSTGRES_DB
value: imagor_studio
- name: POSTGRES_USER
value: imagor
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: postgres-secret
key: password
volumeMounts:
- name: postgres-data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: postgres-data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10Gi

Scaling

Horizontal Pod Autoscaler

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: imagor-studio
namespace: imagor-studio
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: imagor-studio
minReplicas: 3
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80

Monitoring

ServiceMonitor (Prometheus)

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: imagor-studio
namespace: imagor-studio
spec:
selector:
matchLabels:
app: imagor-studio
endpoints:
- port: http
path: /metrics
interval: 30s

Best Practices

  1. Use StatefulSets for databases
  2. Configure resource limits
  3. Set up health checks
  4. Use secrets for sensitive data
  5. Enable autoscaling
  6. Configure ingress with TLS
  7. Set up monitoring and logging
  8. Use persistent volumes for data

Next Steps