Claude Skills Guide

Claude Code for OpenFaaS Kubernetes Workflow

Serverless functions have revolutionized how developers build and deploy applications. OpenFaaS (Functions as a Service) provides a powerful, Kubernetes-native platform for running functions at scale. When combined with Claude Code, you get an intelligent development partner that can help you design, implement, and manage OpenFaaS functions more efficiently than ever before.

This guide walks you through building a complete OpenFaaS Kubernetes workflow using Claude Code, with practical examples and actionable strategies you can apply to your projects immediately.

Understanding OpenFaaS on Kubernetes

OpenFaaS is an open-source framework that lets you package functions as containers and deploy them to Kubernetes. Unlike cloud-provider lock-in solutions, OpenFaaS gives you full control over your serverless infrastructure while maintaining simplicity.

When you use Claude Code alongside OpenFaaS, you gain several advantages:

Setting Up Your OpenFaaS Environment

Before building functions, ensure your Kubernetes cluster has OpenFaaS properly installed. Claude Code can help you verify the installation and configure your environment.

Installing OpenFaaS with Claude Code

First, ensure you have a working Kubernetes cluster. Then use the official OpenFaaS Helm chart for installation:

# Add the OpenFaaS helm repository
helm repo add openfaas https://openfaas.github.io/openfaas-kubernetes/
helm repo update

# Install OpenFaaS with basic authentication
helm upgrade --install openfaas openfaas/openfaas \
  --namespace openfaas \
  --set basicAuth=true \
  --set serviceType=LoadBalancer

After installation, retrieve your admin password:

# Get the admin password
kubectl get secret -n openfaas basic-auth -o jsonpath="{.data.basic-auth-admin-password}" | base64 -d

Claude Code can create a comprehensive setup script that handles all these steps plus configures your local environment for function deployment.

Creating Your First OpenFaaS Function

OpenFaaS supports multiple programming languages through templates. Let’s create a function using Python, which is a common choice for data processing and automation tasks.

Function Structure and Implementation

A typical OpenFaaS function follows this pattern:

import json

def handle(req):
    """
    Main entry point for the OpenFaaS function.
    The request body is passed as the `req` parameter.
    """
    # Parse incoming request
    if isinstance(req, str):
        try:
            data = json.loads(req)
        except json.JSONDecodeError:
            data = {"message": req}
    else:
        data = req
    
    # Process the request
    result = process_data(data)
    
    # Return the response
    return {
        "status": "success",
        "result": result
    }

def process_data(data):
    """Business logic for processing data."""
    # Your custom processing logic here
    return {"processed": True, "input": data}

When working with Claude Code, you can provide context about your function requirements, and it will generate optimized implementations with proper error handling, logging, and testing stubs.

Deploying the Function

Use the OpenFaaS CLI to deploy your function:

# Build the function container
faas-cli build -f function.yml

# Push to your registry
faas-cli push -f function.yml

# Deploy to Kubernetes
faas-cli deploy -f function.yml

Claude Code can generate the complete function.yml configuration:

version: 1.0
provider:
  name: openfaas
  gateway: http://openfaas.openfaas:8080

functions:
  data-processor:
    lang: python3
    handler: ./data-processor
    image: your-registry/data-processor:latest
    environment:
      write_timeout: 60
      read_timeout: 60
      exec_timeout: 60
    limits:
      memory: 128Mi
    requests:
      memory: 64Mi
    annotations:
      description: "Processes incoming data payloads"

Building Complex Workflows with Function Chaining

Real-world applications often require chaining multiple functions together. OpenFaaS supports this through its async invocation pattern and queueing system.

Designing a Data Processing Pipeline

Consider a typical data processing workflow:

  1. Ingest function - Receives raw data and validates format
  2. Transform function - Cleans and transforms data
  3. Enrich function - Adds additional data from external sources
  4. Store function - Saves processed data to database

Here’s how Claude Code helps design this workflow:

# ingest-function/main.py
import json
import requests

def handle(req):
    """Validates and queues data for processing."""
    data = json.loads(req) if isinstance(req, str) else req
    
    # Validate required fields
    required_fields = ["id", "timestamp", "payload"]
    missing = [f for f in required_fields if f not in data]
    
    if missing:
        return {
            "status": "error",
            "error": f"Missing required fields: {missing}"
        }
    
    # Queue for next stage
    invoke_next_function("transform-function", data)
    
    return {"status": "queued", "id": data["id"]}

def invoke_next_function(function_name, payload):
    """Invoke the next function in the pipeline."""
    gateway = "http://openfaas/openfaas:8080"
    response = requests.post(
        f"{gateway}/function/{function_name}",
        json=payload,
        headers={"Content-Type": "application/json"}
    )
    return response.json()

Managing Pipeline State

For more complex pipelines, consider using a state management approach:

# pipeline-orchestrator/main.py
import json
import time
from datetime import datetime

class PipelineState:
    """Manages state across function pipeline execution."""
    
    def __init__(self):
        self.stages = ["ingest", "transform", "enrich", "store"]
    
    def create_pipeline_run(self, initial_data):
        """Initialize a new pipeline run."""
        return {
            "run_id": f"run-{int(time.time())}",
            "status": "started",
            "current_stage": "ingest",
            "stages_completed": [],
            "data": initial_data,
            "started_at": datetime.utcnow().isoformat()
        }
    
    def advance_stage(self, state, stage_name, output):
        """Move to the next pipeline stage."""
        state["stages_completed"].append({
            "stage": stage_name,
            "output": output,
            "completed_at": datetime.utcnow().isoformat()
        })
        
        current_idx = self.stages.index(stage_name)
        if current_idx < len(self.stages) - 1:
            state["current_stage"] = self.stages[current_idx + 1]
        else:
            state["status"] = "completed"
        
        return state

def handle(req):
    """Orchestrates the multi-stage pipeline."""
    state = PipelineState()
    initial_data = json.loads(req) if isinstance(req, str) else req
    
    pipeline_state = state.create_pipeline_run(initial_data)
    
    # Execute each stage sequentially
    for stage in state.stages:
        result = execute_stage(stage, pipeline_state["data"])
        pipeline_state = state.advance_stage(pipeline_state, stage, result)
        
        if pipeline_state["status"] == "error":
            break
    
    return pipeline_state

def execute_stage(stage_name, data):
    """Execute a single pipeline stage."""
    # Implementation depends on your infrastructure
    # Could use function invocation, HTTP calls, etc.
    return {"executed": stage_name, "success": True}

Integrating Claude Code with CI/CD

Automating your OpenFaaS deployments through CI/CD ensures consistent, repeatable releases. Claude Code can help generate pipeline configurations and optimize your deployment workflow.

GitHub Actions Workflow

name: Deploy OpenFaaS Functions

on:
  push:
    branches: [main]
    paths:
      - 'functions/**'

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      
      - name: Set up OpenFaaS CLI
        run: |
          curl -sL https://cli.openfaas.com | sudo sh
      
      - name: Build functions
        run: faas-cli build -f function.yml
      
      - name: Push images
        run: faas-cli push -f function.yml
        env:
          DOCKER_REGISTRY: ${{ secrets.DOCKER_REGISTRY }}
      
      - name: Deploy to cluster
        run: faas-cli deploy -f function.yml
        env:
          OPENFAAS_URL: ${{ secrets.OPENFAAS_URL }}
          OPENFAAS_PASSWORD: ${{ secrets.OPENFAAS_PASSWORD }}

Automated Testing in CI

Add automated testing to ensure function quality:

# test_function.py
import pytest
import json
import sys
sys.path.insert(0, './function')

from handler import handle

def test_handle_valid_request():
    """Test function with valid input."""
    request = {
        "id": "test-123",
        "timestamp": "2026-03-15T10:00:00Z",
        "payload": {"key": "value"}
    }
    
    response = handle(json.dumps(request))
    result = json.loads(response)
    
    assert result["status"] == "success"
    assert "result" in result

def test_handle_missing_fields():
    """Test function with missing required fields."""
    request = {"id": "test-123"}  # Missing timestamp and payload
    
    response = handle(json.dumps(request))
    result = json.loads(response)
    
    assert result["status"] == "error"
    assert "Missing required fields" in result["error"]

def test_handle_string_input():
    """Test function with string input."""
    response = handle("simple string input")
    result = json.loads(response)
    
    assert result["status"] == "success"

Optimizing Function Performance

Claude Code can help you identify performance bottlenecks and optimize your functions for better throughput and resource utilization.

Resource Allocation Guidelines

Configure appropriate resource limits based on function requirements:

functions:
  data-processor:
    lang: python3
    handler: ./data-processor
    image: your-registry/data-processor:latest
    
    # Conservative limits for stateless functions
    limits:
      memory: 256Mi
      cpu: 500m
    
    # Request what you typically need
    requests:
      memory: 128Mi
      cpu: 100m
    
    # Health check configuration
    readinessProbe:
      initialDelaySeconds: 2
      periodSeconds: 2
    livenessProbe:
      initialDelaySeconds: 5
      periodSeconds: 5

Caching Strategies

For functions that process similar data, implement caching:

import json
import hashlib
from functools import lru_cache

# Simple in-memory cache (consider Redis for distributed caching)
_cache = {}

def get_cache_key(data):
    """Generate a cache key from input data."""
    json_str = json.dumps(data, sort_keys=True)
    return hashlib.md5(json_str.encode()).hexdigest()

def handle(req):
    """Function with caching support."""
    data = json.loads(req) if isinstance(req, str) else req
    
    cache_key = get_cache_key(data)
    
    # Check cache
    if cache_key in _cache:
        return {
            "status": "success",
            "result": _cache[cache_key],
            "cached": True
        }
    
    # Process data
    result = process_data(data)
    
    # Store in cache
    _cache[cache_key] = result
    
    return {
        "status": "success",
        "result": result,
        "cached": False
    }

def process_data(data):
    """Actual processing logic."""
    # Your implementation here
    return {"processed": True, "data": data}

Monitoring and Observability

Effective monitoring is crucial for production OpenFaaS deployments. Claude Code can help set up comprehensive observability.

Logging Best Practices

import json
import logging
import sys

# Configure structured logging
logging.basicConfig(
    level=logging.INFO,
    format='%(message)s',
    stream=sys.stdout
)

logger = logging.getLogger(__name__)

def handle(req):
    """Function with structured logging."""
    data = json.loads(req) if isinstance(req, str) else req
    
    logger.info("Function invoked", extra={
        "request_id": data.get("id"),
        "function": "data-processor"
    })
    
    try:
        result = process_data(data)
        
        logger.info("Function completed", extra={
            "request_id": data.get("id"),
            "status": "success"
        })
        
        return {"status": "success", "result": result}
        
    except Exception as e:
        logger.error("Function failed", extra={
            "request_id": data.get("id"),
            "error": str(e)
        })
        
        return {"status": "error", "error": str(e)}

def process_data(data):
    """Process the data."""
    # Your implementation
    return {"processed": True}

Prometheus Metrics Integration

For metrics collection, extend your function:

from prometheus_client import Counter, Histogram, generate_latest
import time

# Define metrics
REQUEST_COUNT = Counter(
    'function_requests_total',
    'Total function requests',
    ['status']
)

REQUEST_DURATION = Histogram(
    'function_duration_seconds',
    'Function execution duration'
)

def handle(req):
    """Function with Prometheus metrics."""
    start_time = time.time()
    
    try:
        result = process_data(req)
        REQUEST_COUNT.labels(status='success').inc()
        
        return {"status": "success", "result": result}
        
    except Exception as e:
        REQUEST_COUNT.labels(status='error').inc()
        raise
        
    finally:
        REQUEST_DURATION.observe(time.time() - start_time)

Best Practices and Actionable Tips

To get the most out of Claude Code with OpenFaaS, consider these proven strategies:

  1. Keep functions focused - Each function should do one thing well. This improves testability and allows easier scaling.

  2. Use environment variables for configuration - Avoid hardcoding values. Claude Code can help generate configuration templates that work across development, staging, and production.

  3. Implement proper error handling - Functions should return meaningful error messages and handle exceptions gracefully.

  4. Set appropriate timeouts - Configure read, write, and execution timeouts based on your function’s expected runtime.

  5. Use async invocation for long-running tasks - For functions that take more than a few seconds, use OpenFaaS’s async pattern with queueing.

  6. Leverage Claude Code for debugging - When functions fail, share logs and error messages with Claude Code for analysis and suggestions.

  7. Version your functions - Tag container images and maintain a changelog for function updates.

  8. Test locally before deployment - Use faas-cli up for local development and testing.

Conclusion

Building OpenFaaS functions on Kubernetes doesn’t have to be complicated. Claude Code serves as an intelligent development partner, helping you design efficient functions, generate configuration files, debug issues, and optimize performance.

Start with simple functions, establish good practices early, and gradually build more complex workflows as your needs evolve. The combination of OpenFaaS’s serverless capabilities and Claude Code’s AI-assisted development creates a powerful platform for building scalable, event-driven applications.

Remember to check the OpenFaaS documentation for the latest features and best practices, and use Claude Code’s understanding of both your application code and Kubernetes primitives to streamline your development workflow.

Built by theluckystrike — More at zovo.one