Deploy with Kubernetes

Deploy NFYio on Kubernetes using Helm. Configure values.yaml, scaling, rolling updates, Prometheus monitoring, and secrets management.

This guide covers deploying NFYio on Kubernetes using the official Helm chart. You’ll configure values, scale workloads, manage rolling updates, set up Prometheus monitoring, and handle persistent volumes and secrets.

Prerequisites

  • Kubernetes cluster 1.24+ (EKS, GKE, AKS, or self-managed)
  • kubectl configured for your cluster
  • Helm 3.8+
  • Basic understanding of Kubernetes concepts (Pods, Services, PVCs, Secrets)

Verify your setup:

kubectl cluster-info
helm version

Helm Chart Installation

Add the NFYio Helm Repository

helm repo add nfyio https://charts.nfyio.io
helm repo update

Install with Default Values

helm install nfyio nfyio/nfyio --namespace nfyio --create-namespace

Install with Custom Values

helm install nfyio nfyio/nfyio -f values.yaml --namespace nfyio --create-namespace

values.yaml Configuration

Create a values.yaml to override defaults. Key sections:

# values.yaml - NFYio Helm Chart Configuration

# ── Global ─────────────────────────────────────────
global:
  imageRegistry: ""  # Use default; set for private registry
  imagePullSecrets: []

# ── Gateway (API, Auth, Dashboard) ───────────────────
gateway:
  replicaCount: 2
  image:
    repository: nfyio/gateway
    tag: "0.9.0"
    pullPolicy: IfNotPresent
  resources:
    requests:
      cpu: 250m
      memory: 512Mi
    limits:
      cpu: 1000m
      memory: 1Gi
  env:
    - name: SESSION_SECRET
      valueFrom:
        secretKeyRef:
          name: nfyio-secrets
          key: session-secret
    - name: PUBLIC_URL
      value: "https://nfyio.yourdomain.com"
    - name: ALLOWED_ORIGINS
      value: "https://app.yourdomain.com"

# ── Storage Proxy (S3-compatible) ───────────────────
storage:
  replicaCount: 2
  resources:
    requests:
      cpu: 100m
      memory: 256Mi
    limits:
      cpu: 500m
      memory: 512Mi

# ── Agent Service (RAG, LLM) ───────────────────────
agent:
  replicaCount: 1
  resources:
    requests:
      cpu: 500m
      memory: 1Gi
    limits:
      cpu: 2000m
      memory: 4Gi

# ── PostgreSQL ──────────────────────────────────────
postgresql:
  enabled: true
  auth:
    username: nfyio
    password: ""  # Set via --set or secret
    database: nfyio
  primary:
    persistence:
      enabled: true
      size: 20Gi
      storageClass: ""  # Use default StorageClass

# ── Redis ───────────────────────────────────────────
redis:
  enabled: true
  auth:
    enabled: true
    existingSecret: nfyio-secrets
    existingSecretPasswordKey: redis-password
  master:
    persistence:
      enabled: true
      size: 8Gi

# ── SeaweedFS ───────────────────────────────────────
seaweedfs:
  master:
    persistence:
      enabled: true
      size: 10Gi
  volume:
    replicaCount: 1
    persistence:
      enabled: true
      size: 100Gi  # Adjust for object storage capacity

# ── Ingress ──────────────────────────────────────────
ingress:
  enabled: true
  className: nginx
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
    nginx.ingress.kubernetes.io/proxy-body-size: "100m"
  hosts:
    - host: nfyio.yourdomain.com
      paths:
        - path: /
          pathType: Prefix
  tls:
    - secretName: nfyio-tls
      hosts:
        - nfyio.yourdomain.com

# ── Service Monitor (Prometheus) ───────────────────
serviceMonitor:
  enabled: true
  interval: 30s

Secrets Management

Create Secrets Manually

kubectl create namespace nfyio

kubectl create secret generic nfyio-secrets \
  --namespace nfyio \
  --from-literal=session-secret=$(openssl rand -hex 64) \
  --from-literal=postgres-password=$(openssl rand -base64 24) \
  --from-literal=redis-password=$(openssl rand -base64 24) \
  --from-literal=keycloak-admin-password=$(openssl rand -base64 24) \
  --from-literal=openai-api-key=sk-your-key-here

Use External Secrets Operator (Optional)

If using External Secrets Operator with AWS Secrets Manager or Vault:

# external-secret.yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: nfyio-secrets
  namespace: nfyio
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: aws-secrets-manager
    kind: ClusterSecretStore
  target:
    name: nfyio-secrets
  data:
    - secretKey: session-secret
      remoteRef:
        key: nfyio/production
        property: session_secret
    - secretKey: postgres-password
      remoteRef:
        key: nfyio/production
        property: postgres_password

Install with Secrets

helm install nfyio nfyio/nfyio -f values.yaml \
  --set postgresql.auth.existingSecret=nfyio-secrets \
  --set postgresql.auth.secretKeys.userPasswordKey=postgres-password \
  --namespace nfyio \
  --create-namespace

Scaling

Horizontal Pod Autoscaler (HPA)

Add HPA for the gateway and storage proxy:

# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nfyio-gateway
  namespace: nfyio
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nfyio-gateway
  minReplicas: 2
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70
    - type: Resource
      resource:
        name: memory
        target:
          type: Utilization
          averageUtilization: 80
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: nfyio-storage
  namespace: nfyio
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: nfyio-storage
  minReplicas: 2
  maxReplicas: 6
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 70

Apply:

kubectl apply -f hpa.yaml

Manual Scaling

kubectl scale deployment nfyio-gateway -n nfyio --replicas=4
kubectl scale deployment nfyio-storage -n nfyio --replicas=3

Rolling Updates

Update Image Version

# Update to new version
helm upgrade nfyio nfyio/nfyio -f values.yaml \
  --set gateway.image.tag=0.10.0 \
  --set storage.image.tag=0.10.0 \
  --set agent.image.tag=0.10.0 \
  --namespace nfyio

Configure Rolling Update Strategy

In values.yaml:

gateway:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0

Monitor Rollout

kubectl rollout status deployment/nfyio-gateway -n nfyio
kubectl rollout history deployment/nfyio-gateway -n nfyio

# Rollback if needed
kubectl rollout undo deployment/nfyio-gateway -n nfyio

Persistent Volumes

Storage Classes

Ensure your cluster has a default StorageClass or specify one:

postgresql:
  primary:
    persistence:
      storageClass: gp3  # AWS EBS gp3
      size: 50Gi

redis:
  master:
    persistence:
      storageClass: gp3
      size: 20Gi

seaweedfs:
  volume:
    persistence:
      storageClass: gp3
      size: 500Gi  # For object storage

Backup PVCs with Velero

# Install Velero (example for AWS)
velero install \
  --provider aws \
  --bucket nfyio-backups \
  --backup-location-config region=us-east-1 \
  --snapshot-location-config region=us-east-1

# Create backup
velero backup create nfyio-backup --include-namespaces nfyio

Monitoring with Prometheus

Enable ServiceMonitor

Ensure the chart has serviceMonitor.enabled: true and Prometheus Operator is installed.

PrometheusRule for Alerts

# prometheus-rules.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
  name: nfyio-alerts
  namespace: nfyio
  labels:
    prometheus: kube-prometheus
spec:
  groups:
    - name: nfyio
      rules:
        - alert: NfyioGatewayDown
          expr: up{job="nfyio-gateway"} == 0
          for: 2m
          labels:
            severity: critical
          annotations:
            summary: "NFYio Gateway is down"
        - alert: NfyioStorageHighLatency
          expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket{job="nfyio-storage"}[5m])) > 1
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Storage proxy P95 latency > 1s"
        - alert: NfyioAgentHighMemory
          expr: container_memory_usage_bytes{container="nfyio-agent"} / container_spec_memory_limit_bytes{container="nfyio-agent"} > 0.9
          for: 5m
          labels:
            severity: warning
          annotations:
            summary: "Agent service memory usage > 90%"

Apply:

kubectl apply -f prometheus-rules.yaml

Grafana Dashboard

Import the NFYio dashboard (JSON) from the chart or create panels for:

  • Request rate (gateway, storage, agent)
  • Error rate (4xx, 5xx)
  • Latency percentiles (P50, P95, P99)
  • Resource usage (CPU, memory per pod)

Full Installation Example

# 1. Create namespace and secrets
kubectl create namespace nfyio
kubectl create secret generic nfyio-secrets -n nfyio \
  --from-literal=session-secret=$(openssl rand -hex 64) \
  --from-literal=postgres-password=$(openssl rand -base64 24) \
  --from-literal=redis-password=$(openssl rand -base64 24) \
  --from-literal=keycloak-admin-password=$(openssl rand -base64 24) \
  --from-literal=openai-api-key=sk-your-key

# 2. Install Helm chart
helm install nfyio nfyio/nfyio -f values.yaml \
  --namespace nfyio \
  --wait \
  --timeout 10m

# 3. Verify
kubectl get pods -n nfyio
kubectl get svc -n nfyio

# 4. Run migrations
kubectl exec -it deployment/nfyio-gateway -n nfyio -- deno task migrate

Troubleshooting

IssueSolution
ImagePullBackOffCheck image name, registry, and imagePullSecrets
CrashLoopBackOffCheck logs: kubectl logs -f deployment/nfyio-gateway -n nfyio
PVC pendingVerify StorageClass exists and has provisioner
Secret not foundEnsure secret exists and keys match chart expectations
Ingress 502Check backend service and pod readiness

What’s Next