Instalación de OpenFaaS para Funciones Serverless

OpenFaaS (Functions as a Service) es una plataforma de código abierto que permite desplegar funciones serverless en Docker Swarm o Kubernetes sin depender de proveedores de nube específicos. Con OpenFaaS puedes empaquetar cualquier proceso en un contenedor y exponerlo como función HTTP, con escalado automático, invocación asíncrona y soporte para múltiples lenguajes. Esta guía cubre la instalación de OpenFaaS en Docker Swarm y Kubernetes, la creación de funciones con plantillas oficiales y la configuración de autoescalado.

Requisitos Previos

  • Ubuntu 20.04+ o Rocky Linux 8+ con acceso root
  • Docker instalado (para Docker Swarm) o cluster Kubernetes
  • Al menos 4 GB de RAM y 2 CPUs
  • Acceso a internet para descargar imágenes
# Instalar Docker
curl -fsSL https://get.docker.com | bash
systemctl enable --now docker

# Verificar Docker
docker --version
docker info | grep "Server Version"

Instalación en Docker Swarm

# Inicializar Docker Swarm (si no está inicializado)
docker swarm init --advertise-addr $(hostname -I | awk '{print $1}')

# Verificar que el Swarm está activo
docker info | grep "Swarm"
docker node ls

# Crear redes para OpenFaaS
docker network create -d overlay --attachable func_functions
docker network create -d overlay --attachable func_backend

# Descargar el archivo de stack de OpenFaaS
# Opción 1: Con faas-cli
curl -sL https://cli.openfaas.com | sudo sh
faas-cli deploy -f https://raw.githubusercontent.com/openfaas/faas/master/docker-compose.yml

# Opción 2: Descarga manual y despliegue
curl -sSL https://raw.githubusercontent.com/openfaas/faas/master/docker-compose.yml \
    -o /opt/openfaas-stack.yml

# Configurar contraseña básica de autenticación
ADMIN_PASSWORD=$(head -c 12 /dev/urandom | sha256sum | head -c 32)
echo "Contraseña de admin: $ADMIN_PASSWORD"

# Crear secret para la contraseña
echo -n "$ADMIN_PASSWORD" | docker secret create basic-auth-password -
echo -n "admin" | docker secret create basic-auth-user -

# Desplegar el stack
docker stack deploy --compose-file /opt/openfaas-stack.yml func

# Verificar que los servicios están ejecutando
docker stack ps func --no-trunc
docker service ls | grep func

Verificar la Instalación

# El gateway de OpenFaaS escucha en el puerto 8080
curl http://localhost:8080/healthz

# Autenticarse con faas-cli
export OPENFAAS_URL=http://localhost:8080
echo -n "$ADMIN_PASSWORD" | faas-cli login --username admin --password-stdin

# Listar funciones instaladas
faas-cli list

Instalación en Kubernetes

# Prerequisito: cluster Kubernetes con kubectl configurado
kubectl version --client

# Instalar OpenFaaS con arkade (gestor de herramientas para Kubernetes)
curl -sLS https://get.arkade.dev | sudo sh
arkade install openfaas

# O instalar manualmente con helm
helm repo add openfaas https://openfaas.github.io/faas-netes/
helm repo update

# Crear namespaces
kubectl create namespace openfaas
kubectl create namespace openfaas-fn  # Namespace para funciones

# Instalar OpenFaaS
helm upgrade openfaas --install openfaas/openfaas \
    --namespace openfaas \
    --set functionNamespace=openfaas-fn \
    --set generateBasicAuth=true \
    --set ingress.enabled=true

# Obtener la contraseña generada
kubectl -n openfaas get secret basic-auth -o jsonpath="{.data.basic-auth-password}" | \
    base64 --decode > openfaas-password.txt
echo "Contraseña guardada en openfaas-password.txt"

# Verificar despliegue
kubectl -n openfaas get pods
kubectl -n openfaas rollout status deploy/gateway

# Port-forward para acceder al gateway
kubectl -n openfaas port-forward svc/gateway 8080:8080 &
export OPENFAAS_URL=http://localhost:8080
cat openfaas-password.txt | faas-cli login --username admin --password-stdin

CLI faas-cli

# Instalar faas-cli
curl -sL https://cli.openfaas.com | sudo sh
faas-cli version

# Comandos principales de faas-cli
faas-cli list                           # Listar funciones
faas-cli list --verbose                 # Con más detalles
faas-cli describe FUNCION               # Descripción de una función
faas-cli invoke FUNCION                 # Invocar función (stdin -> stdout)
echo "hola mundo" | faas-cli invoke FUNCION  # Con entrada
faas-cli logs FUNCION                   # Ver logs de la función
faas-cli remove FUNCION                 # Eliminar función

# Gestión del registry de funciones
faas-cli store list                     # Ver funciones disponibles en el store
faas-cli store deploy figlet            # Desplegar función desde el store
echo "OpenFaaS" | faas-cli invoke figlet  # Invocar la función de texto ASCII

Crear y Desplegar Funciones

Función Node.js

# Crear nueva función usando plantilla Node.js
faas-cli new mi-funcion --lang node18
cd mi-funcion

# El archivo generado: mi-funcion/handler.js
cat > mi-funcion/handler.js << 'EOF'
'use strict'

// Función principal - recibe request y devuelve respuesta
module.exports = async (event, context) => {
    const body = event.body;
    const nombre = body?.nombre || 'mundo';

    // Procesamiento de la función
    const resultado = {
        mensaje: `Hola, ${nombre}! desde OpenFaaS`,
        timestamp: new Date().toISOString(),
        pid: process.pid
    };

    return context
        .status(200)
        .headers({ 'Content-Type': 'application/json' })
        .succeed(resultado);
}
EOF

# Añadir dependencias si son necesarias
cat > mi-funcion/package.json << 'EOF'
{
    "name": "mi-funcion",
    "version": "1.0.0",
    "description": "Mi función serverless",
    "main": "handler.js",
    "dependencies": {
        "axios": "^1.4.0"
    }
}
EOF

Función Python

# Crear función Python
faas-cli new mi-funcion-python --lang python3-http
cd mi-funcion-python

cat > mi-funcion-python/handler.py << 'EOF'
import json
import os

def handle(event, context):
    """Función serverless en Python"""
    
    # Parsear el cuerpo de la solicitud
    body = {}
    if event.body:
        body = json.loads(event.body)
    
    nombre = body.get('nombre', 'mundo')
    
    resultado = {
        'mensaje': f'Hola, {nombre}! desde OpenFaaS Python',
        'metodo': event.method,
        'funcion': os.getenv('HOSTNAME', 'desconocido')
    }
    
    return {
        "statusCode": 200,
        "body": json.dumps(resultado, ensure_ascii=False)
    }
EOF

Archivo de Configuración stack.yml

# stack.yml - Configuración de despliegue de funciones
version: 1.0
provider:
  name: openfaas
  gateway: http://127.0.0.1:8080

functions:
  mi-funcion:
    lang: node18
    handler: ./mi-funcion
    image: registry.miempresa.com/funciones/mi-funcion:latest
    # Variables de entorno
    environment:
      NODE_ENV: production
      DB_URL: "postgresql://user:pass@db:5432/funciones"
    # Límites de recursos
    limits:
      memory: 128Mi
      cpu: 0.1
    requests:
      memory: 64Mi
      cpu: 0.05
    # Etiquetas para autoescalado
    labels:
      com.openfaas.scale.min: "1"
      com.openfaas.scale.max: "10"
      com.openfaas.scale.factor: "20"
    # Anotaciones
    annotations:
      topic: pedidos-nuevos  # Suscribirse a este topic NATS
    # Secrets de Kubernetes/Docker Swarm
    secrets:
      - db-password
      - api-key
# Construir, enviar al registry y desplegar
faas-cli build -f stack.yml
faas-cli push -f stack.yml
faas-cli deploy -f stack.yml

# O todo en un comando
faas-cli up -f stack.yml

# Probar la función
curl -X POST http://localhost:8080/function/mi-funcion \
    -H "Content-Type: application/json" \
    -d '{"nombre": "OpenFaaS"}'

Funciones Asíncronas con NATS

# Invocar función de forma asíncrona (no espera respuesta)
curl -X POST http://localhost:8080/async-function/mi-funcion \
    -H "Content-Type: application/json" \
    -H "X-Callback-Url: https://mi-api.com/webhook" \
    -d '{"datos": "para procesar"}'

# La función se ejecuta en segundo plano
# El resultado se enviará al X-Callback-Url cuando termine

# Verificar el queue de NATS
# (El broker NATS se despliega automáticamente con OpenFaaS)
docker service logs func_queue-worker --follow

# Verificar que la cola está procesando
faas-cli list --verbose | grep "Invocation count"

Autoescalado de Funciones

# OpenFaaS escala automáticamente basándose en alertas de Prometheus
# Configurar etiquetas de escala en stack.yml:
# com.openfaas.scale.min: "1"    - Mínimo de réplicas
# com.openfaas.scale.max: "10"   - Máximo de réplicas
# com.openfaas.scale.factor: "20" - % de solicitudes en cola para escalar

# Para Kubernetes, configurar HPA
cat > /tmp/openfaas-hpa.yaml << 'EOF'
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: mi-funcion-hpa
  namespace: openfaas-fn
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: mi-funcion
  minReplicas: 1
  maxReplicas: 10
  metrics:
    - type: Resource
      resource:
        name: cpu
        target:
          type: Utilization
          averageUtilization: 50
EOF
kubectl apply -f /tmp/openfaas-hpa.yaml

# Verificar el autoescalado
kubectl -n openfaas-fn get hpa

# Escalar manualmente una función
kubectl -n openfaas-fn scale deployment mi-funcion --replicas=3

Monitoreo con Prometheus

# OpenFaaS expone métricas en el puerto 9090
curl http://localhost:9090/metrics | grep "gateway_"

# Métricas importantes de OpenFaaS
# gateway_function_invocation_total - Total de invocaciones por función
# gateway_function_invocation_started - Invocaciones en curso
# gateway_service_count - Número de réplicas por función

# Configurar Grafana para visualizar métricas
# El dashboard de OpenFaaS está disponible en grafana.com/dashboards/3526

# Ver métricas desde la CLI
faas-cli list --verbose
# Muestra: invocations, replicas, image para cada función

# Historial de invocaciones
faas-cli describe mi-funcion

Solución de Problemas

El stack de Docker Swarm no despliega:

docker stack ps func --no-trunc
# Ver servicios con errores
docker service ps func_gateway --no-trunc
# Ver logs del servicio
docker service logs func_gateway --tail 50

Error de autenticación al invocar funciones:

# Verificar que está autenticado
faas-cli list  # Si falla, re-autenticarse
echo "$ADMIN_PASSWORD" | faas-cli login -u admin --password-stdin --gateway http://localhost:8080

Las funciones no escalan automáticamente:

# Verificar que el AlertManager de Prometheus está configurado
# En Docker Swarm
docker service logs func_alertmanager | tail -20

# Verificar las etiquetas de escalado
faas-cli describe mi-funcion | grep -i label

La función tarda demasiado en responder (cold start):

# Configurar escala mínima de 1 para evitar cold starts
# En stack.yml:
# labels:
#   com.openfaas.scale.min: "1"

# Verificar que hay siempre al menos 1 réplica activa
faas-cli list --verbose | grep mi-funcion

Conclusión

OpenFaaS democratiza el modelo serverless al permitir ejecutarlo sobre cualquier infraestructura Linux existente—desde un servidor VPS hasta un cluster Kubernetes en producción—sin depender de AWS Lambda u otros servicios de nube. La portabilidad de las funciones como contenedores Docker, el soporte para múltiples lenguajes mediante plantillas y el autoescalado basado en Prometheus hacen de OpenFaaS una plataforma robusta para cargas de trabajo variables. Para producción, combina OpenFaaS con un registry de contenedores privado, un pipeline CI/CD automatizado y alertas de Prometheus para gestionar el ciclo de vida completo de tus funciones serverless.