Skip to main content

Kubernetes Deployment

This guide covers deploying Terragnos Core on Kubernetes, including configuration, scaling, and operational considerations.

Prerequisites

  • Kubernetes cluster (1.24+)
  • kubectl configured to access your cluster
  • Container registry access (for pulling Terragnos images)
  • PostgreSQL database (in-cluster or external)

Basic Deployment

Namespace

Create a namespace for Terragnos Core:

apiVersion: v1
kind: Namespace
metadata:
name: terragnos-core

Secrets

Create secrets for sensitive configuration:

apiVersion: v1
kind: Secret
metadata:
name: terragnos-secrets
namespace: terragnos-core
type: Opaque
stringData:
DATABASE_URL: postgres://user:password@db:5432/terragnos
AUTH_JWT_SECRET: your-jwt-secret-minimum-32-characters
LICENSE_KEY: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
LICENSE_PUBLIC_KEY: |
-----BEGIN PUBLIC KEY-----
...
-----END PUBLIC KEY-----

ConfigMap

Create a ConfigMap for non-sensitive configuration:

apiVersion: v1
kind: ConfigMap
metadata:
name: terragnos-config
namespace: terragnos-core
data:
PORT: "3000"
NODE_ENV: "production"
LOG_LEVEL: "info"
AUTH_DEFAULT_TENANT: "default"
RATE_LIMIT_TTL: "60"
RATE_LIMIT_LIMIT: "120"
LAYER_CACHE_TTL_SECONDS: "3600"

API Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: terragnos-api
namespace: terragnos-core
spec:
replicas: 3
selector:
matchLabels:
app: terragnos-api
template:
metadata:
labels:
app: terragnos-api
spec:
containers:
- name: api
image: terragnos/core-api:latest
ports:
- containerPort: 3000
envFrom:
- secretRef:
name: terragnos-secrets
- configMapRef:
name: terragnos-config
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"
livenessProbe:
httpGet:
path: /v1/health/live
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /v1/health/ready
port: 3000
initialDelaySeconds: 10
periodSeconds: 5

Worker Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
name: terragnos-worker
namespace: terragnos-core
spec:
replicas: 2
selector:
matchLabels:
app: terragnos-worker
template:
metadata:
labels:
app: terragnos-worker
spec:
containers:
- name: worker
image: terragnos/core-worker:latest
envFrom:
- secretRef:
name: terragnos-secrets
- configMapRef:
name: terragnos-config
resources:
requests:
memory: "512Mi"
cpu: "500m"
limits:
memory: "2Gi"
cpu: "2000m"

Service

Expose the API service:

apiVersion: v1
kind: Service
metadata:
name: terragnos-api
namespace: terragnos-core
spec:
selector:
app: terragnos-api
ports:
- port: 80
targetPort: 3000
type: ClusterIP

Ingress

Expose the API externally:

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

Database Setup

Option 1: External Database

Use an external managed database (recommended for production):

# Update DATABASE_URL in secrets to point to external database
DATABASE_URL: postgres://user:password@external-db.example.com:5432/terragnos

Option 2: In-Cluster Database

Deploy PostgreSQL with PostGIS in the cluster:

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
namespace: terragnos-core
spec:
serviceName: postgres
replicas: 1
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgis/postgis:16-3.4
env:
- name: POSTGRES_DB
value: terragnos
- name: POSTGRES_USER
value: terragnos
- 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: 100Gi

Database Migrations

Run migrations using a Job:

apiVersion: batch/v1
kind: Job
metadata:
name: terragnos-migrations
namespace: terragnos-core
spec:
template:
spec:
containers:
- name: db-setup
image: terragnos/core-db-setup:latest
envFrom:
- secretRef:
name: terragnos-secrets
restartPolicy: Never
backoffLimit: 3

Scaling

Horizontal Pod Autoscaling

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: terragnos-api-hpa
namespace: terragnos-core
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: terragnos-api
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

Manual Scaling

kubectl scale deployment terragnos-api --replicas=5 -n terragnos-core

Networking

Service Mesh

Terragnos Core works with service meshes (Istio, Linkerd):

  • mTLS: Enable mutual TLS for service-to-service communication
  • Traffic management: Use service mesh for advanced routing
  • Observability: Leverage mesh telemetry

Network Policies

Restrict network access:

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: terragnos-api-policy
namespace: terragnos-core
spec:
podSelector:
matchLabels:
app: terragnos-api
policyTypes:
- Ingress
- Egress
ingress:
- from:
- namespaceSelector:
matchLabels:
name: ingress-nginx
ports:
- protocol: TCP
port: 3000
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432

Monitoring

ServiceMonitor (Prometheus)

apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: terragnos-api
namespace: terragnos-core
spec:
selector:
matchLabels:
app: terragnos-api
endpoints:
- port: http
path: /metrics
interval: 15s

Best Practices

  1. Use StatefulSets for databases – Ensures stable network identities
  2. Set resource limits – Prevent resource exhaustion
  3. Use health checks – Configure liveness and readiness probes
  4. Enable autoscaling – Scale based on CPU/memory usage
  5. Use secrets management – Store sensitive data in Kubernetes secrets
  6. Enable TLS – Use TLS for all external traffic
  7. Monitor everything – Set up Prometheus and Grafana
  8. Backup regularly – Automate database backups
  9. Use namespaces – Isolate Terragnos Core in its own namespace
  10. Update regularly – Keep container images updated