Kubernetes Gateway API implementation using Varnish.
Pre-built images are available on GitHub Container Registry:
ghcr.io/varnish/gateway-operator
ghcr.io/varnish/gateway-chaperone
Images are public and require no authentication to pull.
┌─────────────────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌─────────────┐ watches ┌──────────────────┐ │
│ │ Operator │ ◄────────────────────────│ Gateway API │ │
│ │ │ │ Resources │ │
│ └──────┬──────┘ │ - Gateway │ │
│ │ │ - HTTPRoute │ │
│ │ creates/updates │ - GatewayClass │ │
│ ▼ └──────────────────┘ │
│ ┌─────────────────────────────────────────────────────────┐ │
│ │ Varnish Pod │ │
│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ │
│ │ │ Varnish │ │ Chaperone │ │ ConfigMaps │ │ │
│ │ │ + ghost │◄───│ │◄───│ - main.vcl │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ └──────┬──────┘ └──────┬──────┘ └─────────────┘ │ │
│ │ ▼ │ │ │
│ │ varnishlog-json │ watches │ │
│ │ ▼ │ │
│ │ EndpointSlices │ │
│ └─────────────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘
Operator - Cluster-wide deployment. Watches Gateway API resources and:
- Creates Varnish pods with ghost VMOD + chaperone
- Generates VCL preamble + user VCL (concatenated)
- Writes routing rules to
routing.json(via ConfigMap)
Chaperone - Runs alongside each Varnish instance:
- Watches EndpointSlices, writes backend IPs to
ghost.json - Triggers ghost reload via HTTP (
/.varnish-ghost/reload) - Hot-reloads VCL via varnishadm when main.vcl changes
Ghost VMOD - Rust-based routing inside Varnish:
- Reads
ghost.jsonat init and on reload - Matches requests by hostname (exact + wildcard)
- Weighted backend selection
- Async HTTP client with connection pooling
All changes in HTTPRoutes will be
Two separate reload paths:
- VCL changes (user VCL updates): varnishadm hot-reload
- Backend/routing changes: ghost HTTP reload
routing.json (operator → ConfigMap):
{
"version": 2,
"vhosts": {
"api.example.com": {
"routes": [
{
"path_match": {"type": "PathPrefix", "value": "/v2"},
"service": "api-v2",
"namespace": "default",
"port": 8080,
"weight": 100,
"priority": 10300,
"rule_index": 0
}
]
}
}
}ghost.json (chaperone → ghost VMOD):
{
"version": 2,
"vhosts": {
"api.example.com": {
"routes": [
{
"path_match": {"type": "PathPrefix", "value": "/v2"},
"backends": [
{"address": "10.0.0.1", "port": 8080, "weight": 100},
{"address": "10.0.0.2", "port": 8080, "weight": 100}
],
"priority": 10300,
"rule_index": 0
}
]
}
}
}Helm (Recommended):
helm install varnish-gateway \
oci://ghcr.io/varnish/charts/varnish-gateway \
--namespace varnish-gateway-system \
--create-namespacekubectl (Alternative):
# Install Gateway API CRDs
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.2.0/standard-install.yaml
# Deploy the operator
kubectl apply -f deploy/See INSTALL.md for detailed installation instructions and configuration options.
To load custom Varnish VMODs (or any other files) into the gateway pods, use extraVolumes, extraVolumeMounts, and extraInitContainers in GatewayClassParameters. This follows the standard Kubernetes pattern of using an init container to populate a shared volume before the main container starts.
apiVersion: gateway.varnish-software.com/v1alpha1
kind: GatewayClassParameters
metadata:
name: varnish-params
spec:
varnishdExtraArgs:
- "-p"
- "vmod_path=/usr/lib/varnish/vmods:/extra-vmods"
extraVolumes:
- name: extra-vmods
emptyDir: {}
extraVolumeMounts:
- name: extra-vmods
mountPath: /extra-vmods
extraInitContainers:
- name: install-vmods
image: my-registry/my-vmods:latest
command: ["cp", "/vmods/libvmod_custom.so", "/dst/"]
volumeMounts:
- name: extra-vmods
mountPath: /dstThe init container copies the .so files into a shared emptyDir volume, the main container mounts that volume, and varnishdExtraArgs extends the VMOD search path so Varnish finds them. The same mechanism works for any file you need inside the pod (config files, TLS certs from external sources, etc.).
See CLAUDE.md for development setup and detailed documentation.