Sign inSign up

bwalia/wslproxy-ingress-controller

By bwalia

β€’Updated 19 days ago

Kubernetes Ingress Controller with zero-downtime updates built on OpenResty

Image
0

4.2K

bwalia/wslproxy-ingress-controller repository overview

⁠WSLProxy Ingress Controller

Cloud-Native Kubernetes Ingress Controller built on OpenResty with Zero-Downtime Updates

⁠Overview

WSLProxy Ingress Controller is a high-performance, production-ready Kubernetes Ingress Controller built on OpenResty (NGINX + Lua). It provides dynamic L7 load balancing with zero-restart backend updates, advanced routing capabilities, and comprehensive observability.

⁠Key Features

β πŸš€ Zero-Downtime Updates
  • Dynamic upstream management via Lua (no OpenResty reloads required)
  • Real-time configuration updates driven by Kubernetes API watches
  • Seamless backend changes without dropping connections
⁠🎯 Advanced Load Balancing
  • Multiple algorithms: Round-Robin, Weighted Round-Robin, Least Connections, IP Hash
  • Active and passive health checks
  • Circuit breaking for fault tolerance
  • Automatic failover and recovery
β πŸ“Š Cloud-Native Observability
  • Prometheus metrics (request count, latency, upstream health, config sync status)
  • Structured JSON logging
  • OpenTelemetry tracing support (optional)
  • Real-time health status tracking
β πŸ”’ Production-Ready Security
  • Native cert-manager integration for automatic TLS provisioning
  • Support for Let's Encrypt, internal PKI, and wildcard certificates
  • Hot reload of certificates without pod restarts
  • Configurable TLS versions and cipher suites
⁠🎨 Custom Resource Definitions
  • WSLProxyBackend: Advanced backend configuration with load balancing policies
  • WSLProxyRoute: Sophisticated routing with header-based routing, canary deployments, and traffic splitting
  • Full validation and status reporting
β βš™οΈ CNCF Compliance
  • Standard Kubernetes Ingress API support
  • IngressClass compatibility
  • Controller-runtime based implementation
  • Leader election for high availability

⁠Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                     Kubernetes Cluster                       β”‚
β”‚                                                               β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”   β”‚
β”‚  β”‚  WSLProxy        β”‚        β”‚   OpenResty Pods        β”‚   β”‚
β”‚  β”‚  Controller      │───────▢│   (Dynamic Proxy)       β”‚   β”‚
β”‚  β”‚  (Go)            β”‚  HTTP  β”‚                         β”‚   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  API   β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚
β”‚         β”‚                     β”‚  β”‚ Lua Dynamic       β”‚  β”‚   β”‚
β”‚         β”‚ Watches             β”‚  β”‚ Upstream Manager  β”‚  β”‚   β”‚
β”‚         β–Ό                     β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”        β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚   β”‚
β”‚  β”‚  CRDs:           β”‚        β”‚  β”‚ OpenResty/NGINX   β”‚  β”‚   β”‚
β”‚  β”‚  - WSLProxyBackendβ”‚        β”‚  β”‚ (High Perf Proxy) β”‚  β”‚   β”‚
β”‚  β”‚  - WSLProxyRoute β”‚        β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚   β”‚
β”‚  β”‚  - Ingress       β”‚        β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜   β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                    β”‚                  β”‚
β”‚         β”‚                                 β”‚                  β”‚
β”‚         β”‚                                 β–Ό                  β”‚
β”‚         β–Ό                         β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”          β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”            β”‚   Backend    β”‚          β”‚
β”‚  β”‚  Services &      β”‚            β”‚   Services   β”‚          β”‚
β”‚  β”‚  Endpoints       β”‚            β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜          β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜                                       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
⁠Why Two Docker Images?

The WSLProxy Ingress Controller uses a two-component architecture that separates the control plane from the data plane:

⁠1. Controller Image: bwalia/wslproxy-ingress-controller

Role: Kubernetes Control Plane (Brain)

This is a Go-based Kubernetes controller that:

  • Watches Kubernetes API for changes to CRDs (WSLProxyBackend, WSLProxyRoute, Ingress)
  • Reconciles desired state with actual state
  • Translates Kubernetes resources into OpenResty configuration
  • Pushes configuration updates to OpenResty pods via HTTP API
  • Manages leader election for high availability
  • Reports status back to Kubernetes

When it runs: Continuously as a Kubernetes Deployment Handles: Configuration management and Kubernetes integration Does NOT handle: Actual HTTP traffic

⁠2. OpenResty Image: bwalia/wslproxy-openresty-ingress

Role: Data Plane (Traffic Handler)

This is an OpenResty (NGINX + Lua) proxy that:

  • Handles all incoming HTTP/HTTPS traffic
  • Implements dynamic load balancing with Lua scripts
  • Performs health checks on upstream servers
  • Routes requests based on configuration from the Controller
  • Exposes HTTP API for dynamic configuration updates (no restarts needed)
  • Collects and exports Prometheus metrics

When it runs: As a DaemonSet or Deployment with LoadBalancer/NodePort Service Handles: All production traffic Does NOT handle: Kubernetes API interaction

⁠Benefits of This Architecture

βœ… Separation of Concerns

  • Controller can be updated without affecting traffic handling
  • OpenResty can be scaled independently based on traffic load
  • Different resource requirements (Controller: CPU for reconciliation, OpenResty: Memory for connections)

βœ… Zero-Downtime Updates

  • Configuration changes don't require OpenResty restarts
  • Controller updates don't impact traffic
  • Lua-based dynamic upstream management keeps connections alive

βœ… Production Best Practices

  • Follows Kubernetes operator pattern
  • Matches industry-standard ingress controller design (similar to NGINX Ingress, Kong, etc.)
  • Clear failure domains and troubleshooting boundaries

βœ… Scalability

  • Run 1 Controller replica (or 3 for HA)
  • Scale OpenResty replicas to 10+ based on traffic
  • Efficient resource utilization
⁠Deployment Model
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Controller Pod (1-3 replicas)                          β”‚
β”‚  Image: bwalia/wslproxy-ingress-controller:1.0.0        β”‚
β”‚  Resources: ~200Mi memory, ~100m CPU                    β”‚
β”‚  Role: Configuration Management                         β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                     β”‚ HTTP API
                     β”‚ (config updates)
                     β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  OpenResty Pods (N replicas)                            β”‚
β”‚  Image: bwalia/wslproxy-openresty-ingress:1.0.0         β”‚
β”‚  Resources: ~512Mi memory, ~500m CPU per replica        β”‚
β”‚  Role: Traffic Handling                                 β”‚
β”‚  Service: LoadBalancer (receives external traffic)      β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
⁠Quick Image Summary
ImagePurposeContainsTypical Replicas
bwalia/wslproxy-ingress-controllerControl PlaneGo binary, Kubernetes client libraries1-3 (HA)
bwalia/wslproxy-openresty-ingressData PlaneOpenResty, Lua scripts, HTTP API2-10+ (traffic-based)

Both images are required for a functioning ingress controller setup.

⁠Quick Start

⁠Prerequisites
  • Kubernetes 1.20+
  • Helm 3+
  • cert-manager (optional, for TLS automation)
⁠Installation
# Add Helm repository (once available)
helm repo add wslproxy https://charts.wslproxy.org
helm repo update

# Install the controller
helm install wslproxy-ingress wslproxy/wslproxy-ingress-controller \
  --namespace wslproxy-system \
  --create-namespace \
  --set ingressClass.isDefaultClass=true

# Verify installation
kubectl -n wslproxy-system get pods
kubectl -n wslproxy-system get svc
⁠Basic Usage
⁠1. Create a Backend
apiVersion: wslproxy.io/v1alpha1
kind: WSLProxyBackend
metadata:
  name: my-api-backend
spec:
  upstreams:
    - host: api-server-1.default.svc.cluster.local
      port: 8080
      weight: 2
    - host: api-server-2.default.svc.cluster.local
      port: 8080
      weight: 1
  loadBalancing: weighted-round-robin
  healthCheck:
    enabled: true
    path: /health
    interval: 5
⁠2. Create a Route
apiVersion: wslproxy.io/v1alpha1
kind: WSLProxyRoute
metadata:
  name: my-api-route
spec:
  host: api.example.com
  paths:
    - path: /api/v1
      pathType: Prefix
      backend:
        name: my-api-backend
  tls:
    secretName: api-tls-cert
    minVersion: "1.2"
  rateLimit:
    requestsPerSecond: 100
    burst: 20
⁠3. Use Standard Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    wslproxy.io/load-balancing: "weighted-round-robin"
    wslproxy.io/rate-limit: "100"
spec:
  ingressClassName: wslproxy
  rules:
    - host: app.example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80
  tls:
    - hosts:
        - app.example.com
      secretName: app-tls

⁠Configuration

⁠Controller Options
controller:
  replicas: 2
  leaderElection:
    enabled: true
  metrics:
    enabled: true
    port: 8080
  logging:
    level: info
    format: json
⁠OpenResty Options
openresty:
  replicas: 3
  autoscaling:
    enabled: true
    minReplicas: 3
    maxReplicas: 10
  resources:
    limits:
      cpu: "2"
      memory: 2Gi
  sharedDicts:
    upstreams: "10m"
    upstream_health: "10m"
    cache: "50m"
⁠cert-manager Integration
certManager:
  enabled: true
  issuerRef:
    name: letsencrypt-prod
    kind: ClusterIssuer

⁠Advanced Features

⁠Canary Deployments
apiVersion: wslproxy.io/v1alpha1
kind: WSLProxyRoute
metadata:
  name: canary-route
spec:
  host: api.example.com
  paths:
    - path: /api
      backend:
        name: stable-backend
  trafficSplit:
    primary:
      backend:
        name: stable-backend
      weight: 90
    canary:
      backend:
        name: canary-backend
      weight: 10
⁠Header-Based Routing
apiVersion: wslproxy.io/v1alpha1
kind: WSLProxyRoute
metadata:
  name: header-route
spec:
  host: api.example.com
  headers:
    X-API-Version: "v2"
  paths:
    - path: /api
      backend:
        name: api-v2-backend
⁠CORS Configuration
apiVersion: wslproxy.io/v1alpha1
kind: WSLProxyRoute
metadata:
  name: cors-route
spec:
  host: api.example.com
  cors:
    allowOrigins:
      - "https://app.example.com"
    allowMethods:
      - GET
      - POST
      - PUT
    allowHeaders:
      - Content-Type
      - Authorization
    maxAge: 3600

⁠Monitoring

⁠Prometheus Metrics

The controller exposes Prometheus metrics on port 8080:

# Controller metrics
wslproxy_controller_reconcile_duration_seconds
wslproxy_controller_reconcile_total
wslproxy_controller_errors_total

# OpenResty metrics
wslproxy_upstream_health_status
wslproxy_upstream_requests_total
wslproxy_upstream_response_duration_seconds
wslproxy_backend_config_updates_total
⁠ServiceMonitor
observability:
  prometheus:
    enabled: true
    serviceMonitor:
      enabled: true
      interval: 30s

⁠Migration from nginx-ingress

WSLProxy Ingress Controller is compatible with standard Kubernetes Ingress resources. To migrate from nginx-ingress:

  1. Install WSLProxy Ingress Controller alongside nginx-ingress
  2. Update IngressClass on your Ingress resources
  3. Gradually migrate traffic by adjusting DNS/load balancer
  4. Leverage WSLProxy CRDs for advanced features

See MIGRATION.md⁠ for detailed migration guide.

⁠Performance

Benchmarks show WSLProxy can handle:

  • 100,000+ requests/second on modest hardware (4 CPU, 8GB RAM)
  • Sub-millisecond latency for dynamic upstream updates
  • Zero packet loss during configuration updates
  • 10,000+ upstreams with active health checks

⁠Contributing

Contributions welcome! Please see CONTRIBUTING.md⁠ for guidelines.

⁠License

Apache License 2.0 - See LICENSE⁠

⁠Support


Built with ❀️ by the WSLProxy Team

Tag summary

Content type

Image

Digest

sha256:02846b14d…

Size

11.8 MB

Last updated

19 days ago

docker pull bwalia/wslproxy-ingress-controller