Skip to content

Latest commit

 

History

History
207 lines (163 loc) · 6.94 KB

File metadata and controls

207 lines (163 loc) · 6.94 KB

Pingress Controller

A Kubernetes Ingress Controller built on Cloudflare's Pingora high-performance reverse proxy framework.

Overview

Pingress Controller consists of two components:

  • Controller — watches Kubernetes Ingress resources and generates proxy configuration
  • Proxy Server — a Pingora-based HTTP/HTTPS reverse proxy that routes traffic to backends

The controller runs as a Kubernetes Deployment and manages a DaemonSet of proxy server pods on every node, binding directly to host ports 80 and 443.

┌─────────────────────────────────────┐
│  Pingress Controller (Deployment)   │
│  Watches Ingress resources          │
│  Generates ConfigMap & Secret       │
│  Manages DaemonSet lifecycle        │
└──────────────┬──────────────────────┘
               │
   ┌───────────┴──────────────┐
   ▼                          ▼
ConfigMap                  Secret
(proxy.json)           (TLS certs/keys)
   │                          │
   └───────────┬──────────────┘
               ▼
┌──────────────────────────────────────┐
│  DaemonSet (on every node)           │
│  pingress-proxy-server               │
│  HTTP  → 0.0.0.0:8080 → host:80     │
│  HTTPS → 0.0.0.0:8443 → host:443    │
└──────────────────────────────────────┘

Features

  • HTTP and HTTPS routing with prefix and exact path matching
  • Wildcard domain support (e.g., *.example.com)
  • SNI-based TLS — per-host certificate selection with no restart required for cert updates
  • Dynamic configuration reload — file system watcher detects ConfigMap changes and reloads TLS certificates automatically
  • DaemonSet deployment — proxy runs on every node and binds to host ports for low-latency edge routing
  • Minimal container images — scratch-based Docker images with no OS layer

How It Works

Controller

  1. Watches all Ingress resources across the cluster for ingressClassName: pingress
  2. Converts Ingress rules into a PingressConfiguration JSON structure
  3. Extracts TLS certificates from referenced Kubernetes Secrets
  4. Creates or updates a ConfigMap and Secret in the pingress-system namespace
  5. Creates or updates a DaemonSet to deploy proxy pods
  6. Deletes the DaemonSet, ConfigMap, and Secret if no Ingresses remain

Proxy Server

  1. Loads routing configuration from a JSON file on startup
  2. Binds HTTP (:80) and HTTPS (:443) listeners
  3. Builds an in-memory TLS map keyed by hostname
  4. Routes each request by matching Host header and path against the rule table
  5. Watches the configuration directory; on change, reloads TLS certificates and sends SIGTERM to restart gracefully

Routing Algorithm

  • Exact hostnames are resolved via HashMap lookup (O(1))
  • Wildcard hostnames are matched using compiled regex patterns
  • Path matching supports Prefix and Exact types
  • The resolved backend is <service>.<namespace>:<port>, resolved via DNS at request time

Deployment

Prerequisites

  • Kubernetes 1.19+ cluster
  • kubectl configured with cluster admin access
  • Container registry accessible from the cluster

Install

# Apply RBAC and namespace
kubectl apply -f controller/manifests/hostport.yaml

# Create the IngressClass
kubectl apply -f controller/manifests/ingress-class.yaml

# Deploy the controller
kubectl apply -f controller/manifests/pingress-controller.yaml

Controller Arguments

Flag Description Default
--backend Deployment backend mode (HostPort) required
--namespace Namespace for proxy resources pingress-system
--proxy-server-image Proxy server container image required
--image-pull-secret Image pull secret name
--node-selector Node selector labels (key=value,...)

Proxy Server Arguments

Flag Description Default
--config Path to proxy.json configuration file required
--watch Directory to watch for configuration changes required
--listen-http HTTP listen address 0.0.0.0:80
--listen-https HTTPS listen address 0.0.0.0:443

Example Ingress

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  namespace: default
spec:
  ingressClassName: pingress
  tls:
    - hosts:
        - example.com
      secretName: example-tls
  rules:
    - host: example.com
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: my-service
                port:
                  number: 80

See controller/manifests/sample/sample.yaml for a complete example with a Deployment and Service.

Proxy Configuration Format

The controller generates a JSON configuration file consumed by the proxy server:

{
  "rules": [
    {
      "host": "example.com",
      "path": {
        "type": "Prefix",
        "path": "/"
      },
      "backend": {
        "type": "Service",
        "name": "my-service",
        "namespace": "default",
        "port": 80
      },
      "tls": {
        "key": "/etc/pingress/keys/example.com.key",
        "cert": "/etc/pingress/keys/example.com.cert"
      }
    }
  ]
}

Building

Building requires protobuf and a working Rust toolchain.

# Build all crates
cargo build --release

# Build controller image
docker build -f dockerfiles/controller.Dockerfile -t pingress-controller .

# Build proxy server image
docker build -f dockerfiles/server.Dockerfile -t pingress-proxy-server .

The proxy server image requires alpine-sdk, perl, and cmake for compiling Pingora's BoringSSL dependency. These are handled automatically in the multi-stage Dockerfile.

Workspace Structure

pingress-controller/
├── controller/          # Kubernetes reconciliation logic
│   └── manifests/       # Kubernetes YAML manifests
├── proxy/               # Pingora-based proxy server
├── pingress-config/     # Shared configuration types
├── src/                 # Workspace root binary
└── dockerfiles/         # Dockerfiles for controller and proxy

Limitations

  • LoadBalancer backend mode is not yet implemented
  • Backend Service endpoints are resolved via DNS at request time, not tracked dynamically
  • Configuration reload is performed by sending SIGTERM to the proxy process (no graceful connection draining)
  • The controller does not support multiple replicas with leader election

License

Apache License 2.0. See LICENSE for details.