Resumen

Instala y ejecuta n8n en Kubernetes con KubeMode, conectándolo a PostgreSQL y Redis para un entorno listo para escalar. Aquí verás cómo crear el clúster con K3D, definir recursos clave como ConfigMap, PVC, Service, Deployment e Ingress, y validar con kubectl que todo queda operativo.

¿Cómo preparar Kubernetes y servicios base?

Primero se valida el entorno local con K3D y kubectl y se crea un clúster mapeando un puerto público al load balancer. Después se despliegan Postgres y Redis con Helm (chart de “Bitnami” en el ejemplo) y se comprueba que los pods están en estado “Running”.

¿Qué comandos iniciales necesitas?

  • Verificar versiones con comandos: k3d version y kubectl version.

  • Crear clúster y exponer puerto: k3d cluster create demo --port 8080@loadbalancer.

  • Ver información del clúster: kubectl cluster-info.

    Instalar PostgreSQL con Helm

    helm install postgres vitnami/postgres
    --set postgresqlUsername=n8n
    --set postgresqlPassword="mi clave"
    --set postgresqlDatabase=n8n

    Verificar estado de pods

    a) kubectl get pods b) kubectl logs -f

¿Qué datos y puertos son críticos?

  • PostgreSQL: puerto 5432, base de datos y usuario: n8n, contraseña: “mi clave”.
  • Redis: puerto 6379, listo cuando muestra “ready to accept connections”.
  • Mapear 8080 al load balancer del clúster para acceder desde el host.

¿Qué recursos de Kubernetes definen n8n en KubeMode?

La configuración se centraliza en un ConfigMap que expone variables para DB (host, puerto, base y credenciales), Redis y KubeMode. Se añade un PersistentVolumeClaim (PVC) para persistir /home/node/.n8n. El Service expone solo el pod main en el puerto 5678 usando ClusterIP.

¿Cómo configurar variables con ConfigMap?

  • Tipo y conexión de base: host del servicio de Postgres (formato servicio.namespace.svc.cluster.local), puerto 5432, base n8n, usuario n8n, contraseña “mi clave”.

  • Conexión a Redis: host del servicio y puerto 6379.

  • Modo de ejecución: KubeMode activo para usar worker y main.

  • Red en local: N8N_TRUST_PROXY y N8N_PROXY_HOPS habilitados.

  • Seguridad: autenticación básica del editor con usuario admin y contraseña admin.

  • Rutas de webhooks: URL base para “test” y “producción”.

    configmap-n8n.yaml (fragmento)

    apiVersion: v1 kind: ConfigMap metadata: name: n8nconfig data:

    DB: host/puerto/base/usuario/clave

    Redis: host/puerto

    KubeMode y ajustes de proxy local

    Auth básica y webhooks

¿Cómo persistir datos con PVC y exponer el servicio?

  • PVC: solicita almacenamiento y modo de acceso para el directorio de trabajo de n8n.

  • Service (main): selecciona app: n8n y expone el puerto 5678 como ClusterIP.

    pvc-n8n-data.yaml (fragmento)

    apiVersion: v1 kind: PersistentVolumeClaim metadata: name: n8n-data spec: accessModes: ["ReadWriteOnce"] resources: requests: storage: 5Gi

    service-n8n-main.yaml (fragmento)

    apiVersion: v1 kind: Service metadata: name: n8n-main spec: selector: app: n8n ports: - port: 5678 type: ClusterIP

¿Cómo desplegar y verificar con deployments e ingress?

Se crean dos Deployments: uno para worker y otro para main. El worker corre con concurrency=1, lee entorno desde el ConfigMap, define requests/limits (memoria 512Mi/1Gi, CPU 250m/500m) y monta el PVC. Usa liveness y readiness probes por exec. El main arranca con start, expone 5678 y define probes HTTP GET a /healthz con delays mayores porque depende de Redis y Postgres.

¿Qué especificaciones clave usa cada deployment?

  • Imagen: n8n:latest para worker y main.

  • Worker: argumento worker y --concurrency=1.

  • Main: endpoint de salud /healthz en 5678 con httpGet.

  • Recursos: requests y limits para memoria y CPU.

  • Almacenamiento: montar PVC en /home/node/.n8n.

    deployment-n8n-worker.yaml (fragmento)

    apiVersion: apps/v1 kind: Deployment metadata: name: n8n-worker spec: replicas: 1 selector: matchLabels: app: n8n role: worker template: metadata: labels: app: n8n role: worker spec: containers: - name: n8n-worker image: n8n:latest args: ["worker", "--concurrency=1"] envFrom: - configMapRef: name: n8nconfig resources: requests: { memory: "512Mi", cpu: "250m" } limits: { memory: "1Gi", cpu: "500m" } volumeMounts: - name: n8n-data mountPath: /home/node/.n8n volumes: - name: n8n-data persistentVolumeClaim: claimName: n8n-data

    deployment-n8n-main.yaml (fragmento)

    apiVersion: apps/v1 kind: Deployment metadata: name: n8n-main spec: replicas: 1 selector: matchLabels: app: n8n role: main template: metadata: labels: app: n8n role: main spec: containers: - name: n8n-main image: n8n:latest args: ["start"] ports: - containerPort: 5678 readinessProbe: httpGet: { path: "/healthz", port: 5678 } initialDelaySeconds: 30 livenessProbe: httpGet: { path: "/healthz", port: 5678 } initialDelaySeconds: 30 volumeMounts: - name: n8n-data mountPath: /home/node/.n8n volumes: - name: n8n-data persistentVolumeClaim: claimName: n8n-data

¿Cómo publicar con ingress y aplicar en orden?

  • Ingress con Traefik (por defecto en K3D), host localhost, path: /, backend n8n-main:5678.

    ingress-n8n-localhost.yaml (fragmento)

    apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: n8n spec: rules: - host: localhost http: paths: - path: / pathType: Prefix backend: service: name: n8n-main port: number: 5678

  • Aplicar recursos en orden: ConfigMap, PVC, Service, Deployments (primero main, luego worker) e Ingress.

    kubectl apply -f configmap-n8n.yaml kubectl apply -f pvc-n8n-data.yaml kubectl apply -f service-n8n-main.yaml kubectl apply -f deployment-n8n-main.yaml kubectl apply -f deployment-n8n-worker.yaml kubectl apply -f ingress-n8n-localhost.yaml

  • Validar con kubectl get pods hasta ver disponibles. Revisar con kubectl logs el main. Abrir el navegador y completar el registro con correo y contraseña fuerte.

¿Quieres que profundicemos en el autoescalado horizontal en Kubernetes para n8n y sus workers? Cuéntame tu escenario y lo vemos paso a paso.