logo
Kubernetes
Kubernetes

Kubernetes

Deploy Colanode on Kubernetes for production environments requiring high availability, scalability, and professional operations. This guide uses Helm charts to simplify deployment and management.

Architecture Overview

The Helm chart deploys a complete Colanode stack:

  • Colanode Server: Main application server (scalable)
  • PostgreSQL: Database with pgvector extension
  • Redis/Valkey: Message queue and caching
  • MinIO: S3-compatible object storage
  • Ingress: HTTPS termination and routing (optional)

Quick Installation

  1. Add the Helm Repository
# Add the official Colanode Helm repository
helm repo add colanode https://static.colanode.com/hosting/kubernetes/chart

# Update repository
helm repo update

# Search for available charts
helm search repo colanode
  1. Install with Default Values
# Install Colanode with default configuration
helm install my-colanode colanode/colanode

# Monitor deployment
kubectl get pods -w
  1. Access Your Deployment
# Get service information
kubectl get services

# Port forward for local access (temporary)
kubectl port-forward svc/my-colanode 3000:3000

# Access via browser: http://localhost:3000

Custom Installation

  1. Create values.yaml with your customizations:
# values.yaml
colanode:
  replicaCount: 2

  image:
    repository: ghcr.io/colanode/server
    tag: "latest"
    pullPolicy: IfNotPresent

  # Enable config file override
  configFile:
    enabled: true
    # We will pass the content via --set-file or you can inline it here if it's small
    # data: |
    #   { ... }

  ingress:
    enabled: true
    className: "nginx"
    hosts:
      - host: colanode.company.com
        paths:
          - path: /
            pathType: Prefix
    tls:
      - secretName: colanode-tls
        hosts:
          - colanode.company.com

# Dependencies
postgresql:
  enabled: true
  auth:
    username: colanode_user
    password: secure_postgres_password
    database: colanode_db
  primary:
    persistence:
      size: 20Gi

redis:
  enabled: true
  auth:
    password: secure_redis_password
  master:
    persistence:
      size: 8Gi

minio:
  enabled: true
  auth:
    rootUser: admin
    rootPassword: secure_minio_password
  persistence:
    size: 50Gi
  1. Install with Custom Values and Config File
# Install with custom configuration and config.json
helm install my-colanode colanode/colanode -f values.yaml \
  --set-file colanode.configFile.data=./config.json

# Upgrade existing installation
helm upgrade my-colanode colanode/colanode -f values.yaml \
  --set-file colanode.configFile.data=./config.json

Configuration model

  • The Colanode server image already contains a full config.json, so the chart works out of the box without extra values. Only secrets referenced via env:// (for example POSTGRES_URL, REDIS_URL) must remain in environment variables.

  • To supply your own configuration file, enable the helper values:

    colanode:
      configFile:
        enabled: true
        # Recommended: pass the file at install time instead of inlining

    Then install with:

    helm install my-colanode ./hosting/kubernetes/chart \
      --set colanode.configFile.enabled=true \
      --set-file colanode.configFile.data=./config.json
  • If you already manage a ConfigMap, set colanode.configFile.existingConfigMap=<name> and the chart will mount it at /app/apps/server/config.json.

  • Keep secrets as environment variables referenced from JSON via env://SECRET_NAME.

Environment variables do not override JSON values unless explicitly referenced.

Configuration Options

Core Colanode Settings

ParameterDescriptionDefault
colanode.replicaCountNumber of Colanode server replicas1
colanode.image.repositoryColanode server image repositoryghcr.io/colanode/server
colanode.image.tagImage taglatest
colanode.nodeEnvNode environment (NODE_ENV)production
colanode.additionalEnvExtra env vars (for secrets)[]

Resource Configuration

colanode:
  resources:
    limits:
      cpu: 2000m
      memory: 4Gi
    requests:
      cpu: 1000m
      memory: 2Gi

  nodeSelector:
    kubernetes.io/os: linux

  tolerations: []

  affinity:
    podAntiAffinity:
      preferredDuringSchedulingIgnoredDuringExecution:
        - weight: 100
          podAffinityTerm:
            labelSelector:
              matchExpressions:
                - key: app.kubernetes.io/name
                  operator: In
                  values:
                    - colanode
            topologyKey: kubernetes.io/hostname

Ingress Configuration

colanode:
  ingress:
    enabled: true
    className: "nginx" # or "traefik", "alb", etc.
    annotations:
      cert-manager.io/cluster-issuer: "letsencrypt-prod"
      nginx.ingress.kubernetes.io/ssl-redirect: "true"
      nginx.ingress.kubernetes.io/proxy-read-timeout: "3600"
      nginx.ingress.kubernetes.io/proxy-send-timeout: "3600"
    hosts:
      - host: colanode.example.com
        paths:
          - path: /
            pathType: Prefix
    tls:
      - secretName: colanode-tls
        hosts:
          - colanode.example.com

Database Configuration

The chart uses a custom PostgreSQL image with pgvector extension:

postgresql:
  enabled: true
  image:
    repository: pgvector/pgvector
    tag: "pg17"

  auth:
    username: colanode_user
    password: your_secure_password
    database: colanode_db

  primary:
    persistence:
      enabled: true
      size: 50Gi
      storageClass: "fast-ssd"

    resources:
      limits:
        cpu: 2000m
        memory: 4Gi
      requests:
        cpu: 1000m
        memory: 2Gi

    configuration: |
      max_connections = 200
      shared_buffers = 256MB
      effective_cache_size = 1GB
      maintenance_work_mem = 64MB
      wal_buffers = 16MB

To use an external PostgreSQL database:

postgresql:
  enabled: false

colanode:
  # Pass connection string via env var (referenced by default config.json)
  additionalEnv:
    - name: POSTGRES_URL
      value: "postgres://user:password@external-db:5432/colanode_db"

Storage Configuration

The Helm chart supports four storage backends: File System, S3, Google Cloud Storage, and Azure Blob Storage. Configure using the colanode.storage values.

File System Storage

Uses Kubernetes Persistent Volume Claims to store files.

Basic Configuration:

colanode:
  storage:
    type: file
    file:
      directory: /var/lib/colanode/storage
      persistence:
        enabled: true
        size: 20Gi
        storageClass: "" # Use cluster default
        accessModes:
          - ReadWriteOnce

Using an Existing PVC:

colanode:
  storage:
    type: file
    file:
      directory: /var/lib/colanode/storage
      persistence:
        enabled: true
        existingClaim: "my-existing-pvc"

Using emptyDir (ephemeral):

colanode:
  storage:
    type: file
    file:
      directory: /var/lib/colanode/storage
      persistence:
        enabled: false

S3-Compatible Storage

Option 1: Using Bundled MinIO (Default)

Enable MinIO in the Helm chart:

minio:
  enabled: true
  persistence:
    enabled: true
    size: 100Gi
    storageClass: "fast-ssd"

colanode:
  storage:
    type: s3
    s3:
      bucket: colanode
      region: us-east-1
      # endpoint, accessKey, and secretKey auto-configured from MinIO

Option 2: Using External S3

Disable MinIO and configure external S3:

minio:
  enabled: false

colanode:
  storage:
    type: s3
    s3:
      endpoint: "https://s3.amazonaws.com"
      bucket: my-colanode-bucket
      region: us-west-2
      forcePathStyle: false
      accessKey:
        value: "AKIA..."
      secretKey:
        value: "..."

Option 3: Using Existing Secrets

Reference existing Kubernetes secrets:

colanode:
  storage:
    type: s3
    s3:
      endpoint: "https://s3.amazonaws.com"
      bucket: my-bucket
      region: us-west-2
      accessKey:
        existingSecret: "aws-credentials"
        secretKey: "access-key-id"
      secretKey:
        existingSecret: "aws-credentials"
        secretKey: "secret-access-key"

Google Cloud Storage

Configure GCS with a service account secret:

Step 1: Create a Kubernetes secret with your GCP service account key:

kubectl create secret generic gcs-credentials \
  --from-file=key.json=/path/to/service-account.json

Step 2: Configure Helm values:

colanode:
  storage:
    type: gcs
    gcs:
      bucket: my-colanode-bucket
      projectId: my-gcp-project-123
      credentialsSecret:
        name: gcs-credentials
        key: key.json
        mountPath: /var/secrets/gcp
        fileName: service-account.json

Alternative: Use a credentials path (if managing the file separately):

colanode:
  storage:
    type: gcs
    gcs:
      bucket: my-colanode-bucket
      projectId: my-gcp-project-123
      credentialsPath: /etc/gcp/credentials.json

Azure Blob Storage

Configure Azure storage with account credentials:

Basic Configuration:

colanode:
  storage:
    type: azure
    azure:
      account: mystorageaccount
      containerName: colanode
      accountKey:
        value: "base64encodedkey=="

Using an Existing Secret:

colanode:
  storage:
    type: azure
    azure:
      account: mystorageaccount
      containerName: colanode
      accountKey:
        existingSecret: "azure-storage-credentials"
        secretKey: "account-key"

High Availability Setup

Multi-Replica Deployment

colanode:
  replicaCount: 3

  podDisruptionBudget:
    enabled: true
    minAvailable: 2

  autoscaling:
    enabled: true
    minReplicas: 2
    maxReplicas: 10
    targetCPUUtilizationPercentage: 80
    targetMemoryUtilizationPercentage: 80

postgresql:
  architecture: replication
  readReplicas:
    replicaCount: 2

redis:
  architecture: replication
  replica:
    replicaCount: 2

minio:
  mode: distributed
  statefulset:
    replicaCount: 4

Load Balancing

colanode:
  service:
    type: ClusterIP
    port: 3000
    annotations:
      service.beta.kubernetes.io/aws-load-balancer-type: "nlb"

  ingress:
    annotations:
      nginx.ingress.kubernetes.io/upstream-hash-by: "$remote_addr"
      nginx.ingress.kubernetes.io/session-cookie-name: "colanode-affinity"
      nginx.ingress.kubernetes.io/session-cookie-expires: "86400"

Monitoring and Observability

Prometheus Metrics

colanode:
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true
      namespace: monitoring
      interval: 30s
      path: /metrics

  podAnnotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "3000"
    prometheus.io/path: "/metrics"

Logging Configuration

colanode:
  logging:
    level: "info"
    format: "json"

  podAnnotations:
    fluentbit.io/parser: "json"

Security Configuration

Network Policies

networkPolicies:
  enabled: true
  ingress:
    - from:
        - namespaceSelector:
            matchLabels:
              name: ingress-nginx
      ports:
        - protocol: TCP
          port: 3000

Pod Security Standards

colanode:
  podSecurityContext:
    runAsNonRoot: true
    runAsUser: 1000
    fsGroup: 1000

  securityContext:
    allowPrivilegeEscalation: false
    capabilities:
      drop:
        - ALL
    readOnlyRootFilesystem: true

Secrets Management

colanode:
  # existingSecret: "colanode-secrets" # Not used by default chart logic anymore, use additionalEnv or specific secret keys

  # Example of injecting secrets via additionalEnv
  additionalEnv:
    - name: POSTGRES_PASSWORD
      valueFrom:
        secretKeyRef:
          name: colanode-secrets
          key: postgres-password

Create the secret:

kubectl create secret generic colanode-secrets \
  --from-literal=postgres-password=your_postgres_password \
  --from-literal=redis-password=your_redis_password \
  --from-literal=minio-password=your_minio_password

Example: Configuring Cloudflare R2 as ‘s3’ storage

Here is a complete example of configuring Cloudflare R2 storage using additionalEnv to inject secrets into a custom configuration.

1. Prepare custom config (config.json) with env:// references:

{
  "storage": {
    "provider": {
      "type": "s3",
      "endpoint": "env://R2_ENDPOINT",
      "accessKey": "env://R2_ACCESS_KEY",
      "secretKey": "env://R2_SECRET_KEY",
      "bucket": "env://R2_BUCKET",
      "region": "auto"
    }
  }
}

2. Create the secret:

kubectl create secret generic r2-creds \
  --from-literal=access-key="YOUR_R2_ACCESS_KEY_ID" \
  --from-literal=secret-key="YOUR_R2_SECRET_ACCESS_KEY"

3. Configure values (r2-values.yaml) to map the secret:

colanode:
  configFile:
    enabled: true

  additionalEnv:
    - name: R2_ENDPOINT
      value: "https://<ACCOUNT_ID>.r2.cloudflarestorage.com"
    - name: R2_BUCKET
      value: "my-bucket-name"
    - name: R2_ACCESS_KEY
      valueFrom:
        secretKeyRef:
          name: r2-creds
          key: access-key
    - name: R2_SECRET_KEY
      valueFrom:
        secretKeyRef:
          name: r2-creds
          key: secret-key

4. Deploy:

helm upgrade --install my-colanode colanode/colanode \
  -f r2-values.yaml \
  --set-file colanode.configFile.data=custom-config.json

Management Commands

Installation Management

# List Helm releases
helm list

# Get release status
helm status my-colanode

# View release history
helm history my-colanode

# Rollback to previous version
helm rollback my-colanode 1

Scaling Operations

# Scale Colanode replicas
kubectl scale deployment my-colanode --replicas=5

# Scale via Helm
helm upgrade my-colanode colanode/colanode --set colanode.replicaCount=5

Monitoring and Debugging

# Check pod status
kubectl get pods -l app.kubernetes.io/name=colanode

# View pod logs
kubectl logs -f deployment/my-colanode

# Execute into pod
kubectl exec -it deployment/my-colanode -- /bin/sh

# Port forward for debugging
kubectl port-forward svc/my-colanode 3000:3000

Backup and Recovery

Database Backup

# Add to values.yaml
postgresql:
  backup:
    enabled: true
    schedule: "0 2 * * *" # Daily at 2 AM
    storage:
      size: 20Gi
      storageClass: "standard"

Manual backup:

# Create database backup
kubectl exec -it my-colanode-postgresql-0 -- pg_dump -U colanode_user colanode_db > backup.sql

# Restore from backup
kubectl exec -i my-colanode-postgresql-0 -- psql -U colanode_user colanode_db < backup.sql

MinIO Backup

# Backup MinIO data
kubectl exec -it my-colanode-minio-0 -- mc mirror local/colanode-files /backup/files/

# Restore MinIO data
kubectl exec -it my-colanode-minio-0 -- mc mirror /backup/files/ local/colanode-files

Upgrading

Upgrade Process

# Update Helm repository
helm repo update

# Check available versions
helm search repo colanode -l

# Upgrade to latest version
helm upgrade my-colanode colanode/colanode

# Upgrade to specific version
helm upgrade my-colanode colanode/colanode --version 1.2.3

Rolling Updates

colanode:
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1