Platforms

Kubernetes

Quick Start

Deploy Rivet Engine to Kubernetes with PostgreSQL storage.

1. Create Namespace

Save as namespace.yaml:

apiVersion: v1
kind: Namespace
metadata:
  name: rivet-engine
YAML

Apply:

kubectl apply -f namespace.yaml
Command Line

2. Deploy PostgreSQL

Save as postgres.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-config
  namespace: rivet-engine
data:
  POSTGRES_DB: rivet
  POSTGRES_USER: postgres
---
apiVersion: v1
kind: Secret
metadata:
  name: postgres-secret
  namespace: rivet-engine
type: Opaque
stringData:
  # IMPORTANT: Change this password in production!
  POSTGRES_PASSWORD: "postgres"
---
apiVersion: v1
kind: Service
metadata:
  name: postgres
  namespace: rivet-engine
spec:
  type: ClusterIP
  ports:
  - port: 5432
    targetPort: 5432
    protocol: TCP
    name: postgres
  selector:
    app: postgres
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: postgres
  namespace: rivet-engine
spec:
  serviceName: postgres
  replicas: 1
  selector:
    matchLabels:
      app: postgres
  template:
    metadata:
      labels:
        app: postgres
    spec:
      containers:
      - name: postgres
        image: postgres:17
        ports:
        - containerPort: 5432
          name: postgres
        envFrom:
        - configMapRef:
            name: postgres-config
        - secretRef:
            name: postgres-secret
        volumeMounts:
        - name: postgres-data
          mountPath: /var/lib/postgresql/data
          subPath: pgdata
        resources:
          requests:
            cpu: 250m
            memory: 512Mi
          limits:
            cpu: 1000m
            memory: 2Gi
        livenessProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - pg_isready -U postgres
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          exec:
            command:
            - /bin/sh
            - -c
            - pg_isready -U postgres
          initialDelaySeconds: 5
          periodSeconds: 5
  volumeClaimTemplates:
  - metadata:
      name: postgres-data
    spec:
      accessModes: ["ReadWriteOnce"]
      resources:
        requests:
          storage: 10Gi
YAML

Apply and wait for PostgreSQL to be ready:

kubectl apply -f postgres.yaml
kubectl -n rivet-engine wait --for=condition=ready pod -l app=postgres --timeout=300s
Command Line

3. Deploy Rivet Engine

The Rivet Engine deployment consists of two components:

  • Main Engine Deployment: Runs all services except singleton services. Configured with Horizontal Pod Autoscaling (HPA) to automatically scale between 2-10 replicas based on CPU and memory utilization.
  • Singleton Engine Deployment: Runs singleton services that must have exactly 1 replica (e.g., schedulers, coordinators).

Save as rivet-engine.yaml:

apiVersion: v1
kind: ConfigMap
metadata:
  name: engine-config
  namespace: rivet-engine
data:
  config.jsonc: |
    {
      "postgres": {
        "url": "postgresql://postgres:postgres@postgres:5432/rivet"
      },
      "topology": {
        "datacenter_label": 1,
        "datacenters": [
          {
            "name": "local",
            "datacenter_label": 1,
            "is_leader": true,
            "public_url": "http://localhost:6420",
            "peer_url": "http://rivet-engine.rivet-engine.svc.cluster.local:6421",
            "proxy_url": "http://rivet-engine.rivet-engine.svc.cluster.local:6420"
          }
        ]
      }
    }
---
apiVersion: v1
kind: Service
metadata:
  name: rivet-engine
  namespace: rivet-engine
spec:
  type: LoadBalancer
  ports:
  - name: guard
    port: 6420
    targetPort: 6420
    protocol: TCP
  - name: api-peer
    port: 6421
    targetPort: 6421
    protocol: TCP
  selector:
    app: rivet-engine
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rivet-engine
  namespace: rivet-engine
spec:
  replicas: 2
  selector:
    matchLabels:
      app: rivet-engine
  template:
    metadata:
      labels:
        app: rivet-engine
    spec:
      containers:
      - name: rivet-engine
        image: rivetkit/engine:latest
        args:
        - start
        - --except-services
        - singleton
        env:
        - name: RIVET_CONFIG_PATH
          value: /etc/rivet/config.jsonc
        ports:
        - containerPort: 6420
          name: guard
        - containerPort: 6421
          name: api-peer
        volumeMounts:
        - name: config
          mountPath: /etc/rivet
          readOnly: true
        resources:
          requests:
            cpu: 2000m
            memory: 4Gi
          limits:
            cpu: 4000m
            memory: 8Gi
        startupProbe:
          httpGet:
            path: /health
            port: 6421
          initialDelaySeconds: 30
          periodSeconds: 10
          failureThreshold: 30
        readinessProbe:
          httpGet:
            path: /health
            port: 6421
          periodSeconds: 5
          failureThreshold: 2
        livenessProbe:
          httpGet:
            path: /health
            port: 6421
          periodSeconds: 10
          failureThreshold: 3
      volumes:
      - name: config
        configMap:
          name: engine-config
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: rivet-engine
  namespace: rivet-engine
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: rivet-engine
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 60
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: rivet-engine-singleton
  namespace: rivet-engine
spec:
  replicas: 1
  selector:
    matchLabels:
      app: rivet-engine-singleton
  template:
    metadata:
      labels:
        app: rivet-engine-singleton
    spec:
      containers:
      - name: rivet-engine
        image: rivetkit/engine:latest
        args:
        - start
        - --services
        - singleton
        - --services
        - api-peer
        env:
        - name: RIVET_CONFIG_PATH
          value: /etc/rivet/config.jsonc
        ports:
        - containerPort: 6421
          name: api-peer
        volumeMounts:
        - name: config
          mountPath: /etc/rivet
          readOnly: true
        resources:
          requests:
            cpu: 2000m
            memory: 4Gi
          limits:
            cpu: 4000m
            memory: 8Gi
        startupProbe:
          httpGet:
            path: /health
            port: 6421
          initialDelaySeconds: 30
          periodSeconds: 10
          failureThreshold: 30
        readinessProbe:
          httpGet:
            path: /health
            port: 6421
          periodSeconds: 5
          failureThreshold: 2
        livenessProbe:
          httpGet:
            path: /health
            port: 6421
          periodSeconds: 10
          failureThreshold: 3
      volumes:
      - name: config
        configMap:
          name: engine-config
YAML

Apply and wait for the engine to be ready:

kubectl apply -f rivet-engine.yaml
kubectl -n rivet-engine wait --for=condition=ready pod -l app=rivet-engine --timeout=300s
kubectl -n rivet-engine wait --for=condition=ready pod -l app=rivet-engine-singleton --timeout=300s
Command Line

Note: The HPA requires a metrics server to be running in your cluster. Most Kubernetes distributions (including k3d, GKE, EKS, AKS) include this by default.

4. Verify Deployment

Check that all pods are running (you should see 2+ engine pods and 1 singleton pod):

kubectl -n rivet-engine get pods
kubectl -n rivet-engine get hpa
Command Line

5. Access the Engine

Get the service URL:

# For LoadBalancer
kubectl -n rivet-engine get service rivet-engine

# For port forwarding (local development)
kubectl -n rivet-engine port-forward service/rivet-engine 6420:6420 6421:6421
Command Line

Test the health endpoint:

curl http://localhost:6420/health
Command Line

Expected response:

{"runtime":"engine","status":"ok","version":"..."}
JSON

Local Development with k3d

For local Kubernetes testing with k3d:

# Create k3d cluster
k3d cluster create rivet \
  --api-port 6550 \
  -p "6420:30420@loadbalancer" \
  -p "6421:30421@loadbalancer" \
  --agents 2

# Apply manifests (use NodePort service type for k3d)
kubectl apply -f namespace.yaml
kubectl apply -f postgres.yaml
kubectl -n rivet-engine wait --for=condition=ready pod -l app=postgres --timeout=300s

# Modify rivet-engine.yaml service to use NodePort before applying:
# Change `type: LoadBalancer` to `type: NodePort`
# Add nodePort fields:
#   - name: guard
#     port: 6420
#     targetPort: 6420
#     nodePort: 30420
#   - name: api-peer
#     port: 6421
#     targetPort: 6421
#     nodePort: 30421

kubectl apply -f rivet-engine.yaml
kubectl -n rivet-engine wait --for=condition=ready pod -l app=rivet-engine --timeout=300s

# Access at http://localhost:6420 and http://localhost:6421
Command Line

Cleanup:

k3d cluster delete rivet
Command Line

Production Setup

Security

  1. Change PostgreSQL password in postgres-secret
  2. Use TLS for external access (configure ingress controller)
  3. Set admin token via environment variable:
    env:
    - name: RIVET__AUTH__ADMIN_TOKEN
      valueFrom:
        secretKeyRef:
          name: rivet-secrets
          key: admin-token
    
    YAML

Scaling

The engine is configured with Horizontal Pod Autoscaling (HPA) by default, automatically scaling between 2-10 replicas based on CPU (60%) and memory (80%) utilization.

To adjust the scaling parameters, modify the HPA configuration:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: rivet-engine
  namespace: rivet-engine
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: rivet-engine
  minReplicas: 2  # Adjust minimum replicas
  maxReplicas: 20 # Adjust maximum replicas
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 70  # Adjust CPU threshold
  - type: Resource
    resource:
      name: memory
      target:
        type: Utilization
        averageUtilization: 80  # Adjust memory threshold
YAML

Monitor HPA status:

kubectl -n rivet-engine get hpa
kubectl -n rivet-engine describe hpa rivet-engine
Command Line

Next Steps

Suggest changes to this page