Contour in Cloud-Native Engineering
Category: ingress
Status: Active
Stars: 4,800
Last Updated: 2026-04-22
Primary Language: Go
Documentation: https://projectcontour.io/
Purpose and Use Cases
Contour is a CNCF incubating project that provides a Kubernetes ingress controller using Envoy proxy for load balancing and traffic routing.
What Problem Does It Solve?
Complex ingress management in Kubernetes. Before Contour, users had to use Kubernetes Ingress resources with limited functionality or deploy individual Envoy instances manually. Contour provides a native Kubernetes integration with advanced routing, TLS termination, and HTTP/2 support.
When to Use This Project
Use Contour when you need:
- Advanced HTTP routing beyond basic Kubernetes Ingress
- HTTP/2 and gRPC support out of the box
- Complex routing rules with weighted traffic splitting
- TLS termination with certificate management
- Integration with external services and upstream policies
Key Use Cases
- Kubernetes Ingress: Primary use case - route external traffic to services
- Traffic Management: Weighted traffic splitting, canary deployments
- TLS Termination: HTTPS termination with automatic certificate management
- API Gateway: Front door for microservices with advanced routing
- Multi-tenant Ingress: Isolated ingress for different teams/tenants
Architecture Design Patterns
Contour Components
1. Contour (Control Plane)
# Contour control plane components
contour server \
--incluster \
--xds-address=0.0.0.0 \
--xds-port=8001 \
--config-path=/config/contour.yaml
Responsibilities:
- Reads Kubernetes resources (Ingress, Gateway, HTTPProxy)
- Generates Envoy configuration
- Communicates with Envoy via XDS API
- Manages certificate secrets
2. Envoy (Data Plane)
# Envoy data plane
envoy -c /config/envoy.yaml --service-cluster contour
Responsibilities:
- Handles actual traffic routing
- TLS termination
- Load balancing
- Rate limiting
- Circuit breaking
XDS API Architecture
Contour uses Envoy's XDS (x Discovery Service) protocol:
# Contour generates XDS resources
resources:
- "@type": type.googleapis.com/envoy.config.listener.v3.Listener
name: ingress
address:
socket_address:
address: 0.0.0.0
port_value: 8080
- "@type": type.googleapis.com/envoy.config.route.v3.RouteConfiguration
name: ingress
virtual_hosts:
- name: ingress
domains: ["*"]
routes:
- match:
prefix: "/api"
route:
cluster: api-service
Resource Hierarchy
Contour uses a resource hierarchy:
# HTTPProxy - Contour's custom resource
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: example
namespace: default
spec:
virtualhost:
fqdn: example.com
tls:
secretName: example-tls
routes:
- conditions:
- prefix: "/"
services:
- name: frontend
port: 80
- conditions:
- prefix: "/api"
services:
- name: api
port: 8080
Certificate Management
1. Standard Kubernetes Secrets
# TLS certificate from Kubernetes Secret
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: secure
spec:
virtualhost:
fqdn: secure.example.com
tls:
secretName: secure-example-com-tls # Kubernetes Secret
2. ACME Certificate Management
# ACME certificate via cert-manager
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: acme
spec:
virtualhost:
fqdn: acme.example.com
tls:
secretName: acme-example-com-tls
minimumProtocolVersion: "1.2"
passthrough: false
Gateway API Integration
Contour supports the Gateway API for modern ingress management:
# Gateway API resource
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: contour
spec:
controllerName: projectcontour.io/contour-gateway-controller
parametersRef:
group: projectcontour.io
kind: GatewayParameters
name: contour-params
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: example
spec:
gatewayClassName: contour
listeners:
- name: http
port: 80
protocol: HTTP
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: example-tls
Upstream Policy
# Upstream policy for backend services
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: policy-example
spec:
routes:
- services:
- name: backend
port: 80
policy:
loadBalancer:
policy: RingHash
requestHashPolicies:
- header:
headerName: "x-request-id"
retryPolicy:
count: 3
perTryTimeout: 2s
connectionPool:
tcp:
maxConnections: 100
http:
h2ProtocolSettings:
maxConcurrentStreams: 100
Integration Approaches
Kubernetes Native Integration
1. Ingress Resource
# Standard Kubernetes Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: example
annotations:
kubernetes.io/ingress.class: contour
spec:
rules:
- host: example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 8080
2. HTTPProxy Resource
# Contour's HTTPProxy with advanced features
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: advanced
spec:
virtualhost:
fqdn: advanced.example.com
tls:
secretName: advanced-tls
minimumProtocolVersion: "1.2"
routes:
- conditions:
- prefix: "/v1"
services:
- name: api-v1
port: 8080
timeoutPolicy:
response: 30s
idle: 5m
retryPolicy:
count: 3
perTryTimeout: 2s
- conditions:
- prefix: "/v2"
services:
- name: api-v2
port: 8080
rewritePolicy:
prefix: "/api"
3. Gateway API Resource
# Gateway API with Contour
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
name: main-gateway
spec:
gatewayClassName: contour
listeners:
- name: http
port: 80
protocol: HTTP
- name: https
port: 443
protocol: HTTPS
tls:
mode: Terminate
certificateRefs:
- name: main-cert
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
name: main-route
spec:
parentRefs:
- name: main-gateway
hostnames:
- example.com
rules:
- matches:
- path:
type: Prefix
value: /
backendRefs:
- name: frontend
port: 80
- matches:
- path:
type: Prefix
value: /api
backendRefs:
- name: api
port: 8080
External Services Integration
1. External Service Reference
# Reference external service
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: external
spec:
routes:
- conditions:
- prefix: "/external"
services:
- name: external-service
port: 443
protocol: https
urlScheme: https
# External service load balancing
loadBalancer:
policy: RoundRobin
2. Weighted Services
# Traffic splitting between services
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: canary
spec:
routes:
- conditions:
- prefix: "/"
services:
- name: primary
port: 80
weight: 90
- name: canary
port: 80
weight: 10
# Percent-based traffic splitting
policy:
loadBalancer:
policy: RoundRobin
Load Balancer Integration
1. NLB Integration (AWS)
# AWS NLB with Contour
apiVersion: v1
kind: Service
metadata:
name: contour-envoy
namespace: projectcontour
annotations:
service.beta.kubernetes.io/aws-load-balancer-type: "external"
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: "instance"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
type: LoadBalancer
ports:
- name: http
port: 80
targetPort: 8080
- name: https
port: 443
targetPort: 8443
selector:
app: contour-envoy
2. Service Mesh Integration
# Istio integration with Contour
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: mesh-integration
spec:
routes:
- conditions:
- prefix: "/api"
services:
- name: api
port: 8080
# Service mesh integration
policy:
loadBalancer:
policy: Maglev
Monitoring Integration
1. Prometheus Metrics
# Enable Prometheus metrics
apiVersion: v1
kind: ConfigMap
metadata:
name: contour
namespace: projectcontour
data:
contour.yaml: |
xds-address: "0.0.0.0"
xds-port: 8001
debug: true
# Contour metrics
metrics:
address: "0.0.0.0"
port: 8002
2. Tracing Integration
# Jaeger/Zipkin tracing
apiVersion: v1
kind: ConfigMap
metadata:
name: contour
namespace: projectcontour
data:
contour.yaml: |
xds-address: "0.0.0.0"
xds-port: 8001
tracing:
type: zipkin
service-name: contour
sampling-rate: 0.0001
config:
collector-host: zipkin.observability.svc.cluster.local
collector-port: 9411
Common Pitfalls and How to Avoid Them
1. TLS Configuration
Pitfall: Missing TLS configuration for HTTPS traffic.
# ❌ Incorrect - no TLS configuration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: insecure
spec:
routes:
- services:
- name: backend
port: 8080
# ✅ Correct - with TLS configuration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: secure
spec:
virtualhost:
fqdn: secure.example.com
tls:
secretName: secure-tls
minimumProtocolVersion: "1.2"
routes:
- services:
- name: backend
port: 8080
2. Route Conditions
Pitfall: Incorrect route condition matching.
# ❌ Incorrect - conflicting routes
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: conflicting
spec:
routes:
- conditions:
- prefix: "/"
services:
- name: default
port: 80
- conditions:
- prefix: "/" # Conflicts with first!
services:
- name: other
port: 80
# ✅ Correct - specific routes
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: correct
spec:
routes:
- conditions:
- prefix: "/api"
services:
- name: api
port: 80
- conditions:
- prefix: "/web"
services:
- name: web
port: 80
3. Service Discovery
Pitfall: Backend service not in same namespace.
# ❌ Incorrect - cross-namespace service reference
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: cross-namespace
namespace: ingress
spec:
routes:
- services:
- name: backend
namespace: production # Must specify namespace
port: 8080
# ✅ Correct - explicit namespace
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: same-namespace
namespace: default
spec:
routes:
- services:
- name: backend
port: 8080 # Same namespace as HTTPProxy
4. HTTP/2 Configuration
Pitfall: HTTP/2 not properly configured.
# ❌ Incorrect - HTTP/2 misconfiguration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: http2-missing
spec:
routes:
- services:
- name: backend
port: 8080
# Missing HTTP/2 configuration
# ✅ Correct - HTTP/2 enabled
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: http2-enabled
spec:
routes:
- services:
- name: backend
port: 8080
# HTTP/2 automatically enabled for gRPC
policy:
loadBalancer:
policy: Maglev
5. Certificate Expiration
Pitfall: TLS certificates not rotated.
# ❌ Incorrect - manual certificate management
# Certificates expire and cause outages
# ✅ Correct - automatic rotation
# Use cert-manager with ACME
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
spec:
secretName: example-com-tls
duration: 2160h # 90 days
renewBefore: 360h # 15 days before expiration
commonName: example.com
dnsNames:
- example.com
- "*.example.com"
issuerRef:
name: letsencrypt
kind: ClusterIssuer
6. Timeout Configuration
Pitfall: Missing timeout configuration.
# ❌ Incorrect - no timeouts
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: no-timeouts
spec:
routes:
- services:
- name: slow-backend
port: 8080
# ✅ Correct - with timeouts
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: with-timeouts
spec:
routes:
- services:
- name: slow-backend
port: 8080
timeoutPolicy:
response: 30s
idle: 5m
Coding Practices
HTTPProxy Templates
// HTTPProxy template generation
package ingress
import (
projectcontouriov1 "github.com/projectcontour/contour/api/projectcontour/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
// GenerateHTTPProxy creates a standard HTTPProxy
func GenerateHTTPProxy(name, namespace, fqdn string, routes []Route) *projectcontouriov1.HTTPProxy {
proxy := &projectcontouriov1.HTTPProxy{
TypeMeta: metav1.TypeMeta{
APIVersion: "projectcontour.io/v1",
Kind: "HTTPProxy",
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Labels: map[string]string{
"app": name,
},
},
Spec: projectcontouriov1.HTTPProxySpec{
VirtualHost: &projectcontouriov1.VirtualHost{
Fqdn: fqdn,
TLS: &projectcontouriov1.TLS{
SecretName: fqdnToSecretName(fqdn),
},
},
Routes: convertRoutes(routes),
},
}
return proxy
}
// Route represents an HTTP route
type Route struct {
Path string
Service string
Port int32
Timeout string
Retries int
Weight int32
}
func convertRoutes(routes []Route) []projectcontouriov1.Route {
var result []projectcontouriov1.Route
for _, r := range routes {
route := projectcontouriov1.Route{
Conditions: []projectcontouriov1.Condition{
{
Prefix: r.Path,
},
},
Services: []projectcontouriov1.Service{
{
Name: r.Service,
Port: r.Port,
},
},
}
if r.Timeout != "" {
route.TimeoutPolicy = &projectcontouriov1.TimeoutPolicy{
Response: r.Timeout,
}
}
if r.Retries > 0 {
route.RetryPolicy = &projectcontouriov1.RetryPolicy{
Count: uint32(r.Retries),
}
}
if r.Weight > 0 {
route.Services[0].Weight = r.Weight
}
result = append(result, route)
}
return result
}
func fqdnToSecretName(fqdn string) string {
// Convert FQDN to secret name
// example.com -> example-com-tls
return fqdn + "-tls"
}
Ingress Controller Integration
// Contour Ingress Controller
package controller
import (
"context"
"fmt"
projectcontouriov1 "github.com/projectcontour/contour/api/projectcontour/v1"
networkingv1 "k8s.io/api/networking/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/tools/cache"
)
// IngressHandler handles Kubernetes Ingress resources
type IngressHandler struct {
client clientset.Interface
proxyInformer cache.SharedIndexInformer
}
// HandleIngress converts Ingress to HTTPProxy
func (h *IngressHandler) HandleIngress(ing *networkingv1.Ingress) error {
// Convert Ingress to HTTPProxy
proxy := h.convertIngressToHTTPProxy(ing)
// Create or update HTTPProxy
_, err := h.client.ProjectcontourV1().HTTPProxies(ing.Namespace).Create(
context.Background(),
proxy,
metav1.CreateOptions{},
)
if apierrors.IsAlreadyExists(err) {
// Update existing HTTPProxy
_, err = h.client.ProjectcontourV1().HTTPProxies(ing.Namespace).Update(
context.Background(),
proxy,
metav1.UpdateOptions{},
)
}
return err
}
func (h *IngressHandler) convertIngressToHTTPProxy(ing *networkingv1.Ingress) *projectcontouriov1.HTTPProxy {
routes := make([]projectcontouriov1.Route, 0)
for _, rule := range ing.Spec.Rules {
if rule.IngressRuleValue.HTTP == nil {
continue
}
for _, path := range rule.IngressRuleValue.HTTP.Paths {
route := projectcontouriov1.Route{
Conditions: []projectcontouriov1.Condition{
{
Prefix: path.Path,
},
},
Services: []projectcontouriov1.Service{
{
Name: path.Backend.Service.Name,
Port: path.Backend.Service.Port.Number,
},
},
}
routes = append(routes, route)
}
}
return &projectcontouriov1.HTTPProxy{
TypeMeta: metav1.TypeMeta{
APIVersion: "projectcontour.io/v1",
Kind: "HTTPProxy",
},
ObjectMeta: metav1.ObjectMeta{
Name: ing.Name + "-proxy",
Namespace: ing.Namespace,
Labels: ing.Labels,
},
Spec: projectcontouriov1.HTTPProxySpec{
Routes: routes,
},
}
}
Testing
// HTTPProxy testing
package ingress
import (
"testing"
projectcontouriov1 "github.com/projectcontour/contour/api/projectcontour/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestGenerateHTTPProxy(t *testing.T) {
routes := []Route{
{
Path: "/api",
Service: "api-service",
Port: 8080,
Timeout: "30s",
},
{
Path: "/",
Service: "web-service",
Port: 80,
},
}
proxy := GenerateHTTPProxy("test", "default", "example.com", routes)
// Validate HTTPProxy
if proxy.Name != "test" {
t.Errorf("expected name 'test', got '%s'", proxy.Name)
}
if proxy.Namespace != "default" {
t.Errorf("expected namespace 'default', got '%s'", proxy.Namespace)
}
if proxy.Spec.VirtualHost.Fqdn != "example.com" {
t.Errorf("expected FQDN 'example.com', got '%s'", proxy.Spec.VirtualHost.Fqdn)
}
if proxy.Spec.VirtualHost.TLS.SecretName != "example.com-tls" {
t.Errorf("expected TLS secret 'example.com-tls', got '%s'", proxy.Spec.VirtualHost.TLS.SecretName)
}
if len(proxy.Spec.Routes) != 2 {
t.Errorf("expected 2 routes, got %d", len(proxy.Spec.Routes))
}
// Validate routes
if proxy.Spec.Routes[0].Conditions[0].Prefix != "/api" {
t.Errorf("expected prefix '/api', got '%s'", proxy.Spec.Routes[0].Conditions[0].Prefix)
}
if proxy.Spec.Routes[0].Services[0].Name != "api-service" {
t.Errorf("expected service 'api-service', got '%s'", proxy.Spec.Routes[0].Services[0].Name)
}
}
Fundamentals
Contour Architecture
1. Control Plane
- Contour: Reads Kubernetes resources and generates Envoy config
- XDS API: Communicates with Envoy data plane
- Certificate Manager: Manages TLS certificates
2. Data Plane
- Envoy: Handles traffic routing and load balancing
- XDS Client: Connects to Contour control plane
- Listeners: HTTP/HTTPS listeners on configured ports
Contour Deployment
# Contour deployment
kubectl apply -f https://projectcontour.io/quickstart/contour.yaml
# Verify deployment
kubectl -n projectcontour get pods
# Check Envoy pods
kubectl -n projectcontour get pods -l app=contour-envoy
Resource Types
1. HTTPProxy
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: example
spec:
virtualhost:
fqdn: example.com
routes:
- services:
- name: service
port: 80
2. TLSService
apiVersion: projectcontour.io/v1
kind: TLSService
metadata:
name: tls-service
spec:
secretName: tls-secret
minProtocolVersion: "1.2"
3. GatewayClass
apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
name: contour
spec:
controllerName: projectcontour.io/contour-gateway-controller
Configuration Options
1. Contour Config
# contour.yaml
xds-address: "0.0.0.0"
xds-port: 8001
debug: true
metrics:
address: "0.0.0.0"
port: 8002
tracing:
type: zipkin
service-name: contour
sampling-rate: 0.0001
2. Envoy Config
# Envoy bootstrap config
static_resources:
listeners:
- name: ingress
address:
socket_address:
address: 0.0.0.0
port_value: 8080
clusters:
- name: xds_cluster
connect_timeout: 30s
type: STRICT_DNS
lb_policy: ROUND_ROBIN
load_assignment:
cluster_name: xds_cluster
endpoints:
- lb_endpoints:
- endpoint:
address:
socket_address:
address: contour
port_value: 8001
Scaling and Deployment Patterns
High Availability
# HA Contour deployment
# Multiple Contour instances with leader election
kubectl apply -f https://projectcontour.io/quickstart/contour-ha.yaml
# Scale Envoy pods
kubectl -n projectcontour scale deployment contour-envoy --replicas=3
Auto-scaling
# Horizontal Pod Autoscaler for Envoy
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: contour-envoy
namespace: projectcontour
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: contour-envoy
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
Load Balancing Strategies
# Load balancing in HTTPProxy
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: lb-example
spec:
routes:
- services:
- name: backend
port: 8080
policy:
loadBalancer:
policy: RoundRobin # Random, RingHash,Maglev, WeightedLeastRequest
Rate Limiting
# Rate limiting configuration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: rate-limit
spec:
routes:
- services:
- name: api
port: 8080
policy:
ratelimit:
local:
requests: 100
period: 1s
Circuit Breaking
# Circuit breaking configuration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: circuit-breaker
spec:
routes:
- services:
- name: backend
port: 8080
policy:
connectionPool:
tcp:
maxConnections: 100
http:
h2ProtocolSettings:
maxConcurrentStreams: 100
requestTimeout: 30s
idleTimeout: 5m
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
Additional Resources
Official Documentation
- Project Contour - Project website
- Contour Documentation - Complete documentation
- Contour GitHub - Source code
- Contour API Reference - API documentation
Implementations
- Kubernetes Ingress Contour - Kubernetes integration
- Contour Operator - Operator for Contour
- Contour Helm Chart - Helm installation
Community Resources
- CNCF Contour - CNCF project page
- Contour Slack - Community discussion
- Contour Mailing List - Announcements
Learning Resources
- Contour Getting Started - Tutorial
- Contour Examples - Example configurations
- Contour Webinars - Video content
This SKILL.md file was verified and last updated on 2026-04-22. Content based on CNCF Contour project and production usage patterns.
Tutorial
This tutorial covers installation, configuration, and basic usage of Contour for Kubernetes ingress management.
Prerequisites
Before starting with Contour, ensure you have:
- A running Kubernetes cluster (1.23+)
kubectlconfigured with cluster admin access- Basic understanding of Kubernetes services and ingress concepts
- Helm 3.x (if using Helm installation)
Installation
Method 1: Using kubectl apply (Quick Start)
# Download and apply the latest Contour manifest
curl -sL https://projectcontour.io/quickstart/contour.yaml > contour.yaml
# Apply the manifest
kubectl apply -f contour.yaml
# Verify the installation
kubectl -n projectcontour get pods
# Expected output:
# NAME READY STATUS RESTARTS AGE
# contour-7d8f9c6b9-abc12 1/1 Running 0 2m
# contour-7d8f9c6b9-def34 1/1 Running 0 2m
# contour-envoy-xyz56 1/1 Running 0 2m
Method 2: Using Helm (Production Recommended)
# Add the Contour Helm repository
helm repo add projectcontour https://projectcontour.github.io/charts
helm repo update
# Install Contour
helm install contour projectcontour/contour \
--create-namespace \
--namespace projectcontour \
--set contour.config.filePath=/config/contour.yaml
# Verify installation
helm -n projectcontour list
Method 3: Custom Configuration
# Create namespace
kubectl create namespace projectcontour
# Apply Contour with custom config
kubectl apply -f contour.yaml
# Create custom ConfigMap for Contour
kubectl create configmap contour-config \
--from-file=contour.yaml=./my-contour-config.yaml \
-n projectcontour
# Patch deployment to use custom config
kubectl patch deployment contour \
--namespace projectcontour \
--type='json' \
-p='[{"op": "add", "path": "/spec/template/spec/volumes/-", "value": {"name": "config", "configMap": {"name": "contour-config"}}}]'
Basic Configuration
Contour is configured via a YAML file and Kubernetes ConfigMap.
Contour Config File
Create contour.yaml:
# contour.yaml - Contour main configuration
xds-address: "0.0.0.0"
xds-port: 8001
debug:
address: "0.0.0.0"
port: 8000
metrics:
address: "0.0.0.0"
port: 8002
tracing:
type: zipkin
service-name: contour
sampling-rate: 0.0001
config:
collector-host: zipkin.observability.svc.cluster.local
collector-port: 9411
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
Enable Gateway API Support
# contour.yaml - Enable Gateway API
gateway:
apiVersion: gateway.networking.k8s.io/v1beta1
enabled: true
Configure TLS Settings
# contour.yaml - TLS configuration
tls:
minimumProtocolVersion: "1.2"
cipherSuites:
- TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
Usage Examples
Creating Your First HTTPProxy
# hello-world.yaml
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: hello-world
namespace: default
spec:
virtualhost:
fqdn: hello-world.example.com
tls:
secretName: hello-world-tls
minimumProtocolVersion: "1.2"
routes:
- conditions:
- prefix: "/"
services:
- name: hello
port: 80
Apply the configuration:
# Create a simple hello service first
kubectl create deployment hello --image=nginx --port=80
kubectl expose deployment hello --port=80 --target-port=80 --type=ClusterIP
# Apply HTTPProxy
kubectl apply -f hello-world.yaml
# Check status
kubectl get httpproxy hello-world -o yaml
Configure Path-Based Routing
# multi-path.yaml
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: multi-path
namespace: default
spec:
virtualhost:
fqdn: app.example.com
tls:
secretName: app-tls
routes:
- conditions:
- prefix: "/api"
services:
- name: api-service
port: 8080
timeoutPolicy:
response: 30s
idle: 5m
- conditions:
- prefix: "/web"
services:
- name: web-service
port: 80
- conditions:
- prefix: "/admin"
services:
- name: admin-service
port: 8080
Enable gRPC Support
# grpc-service.yaml
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: grpc-service
namespace: default
spec:
virtualhost:
fqdn: grpc.example.com
tls:
secretName: grpc-tls
routes:
- conditions:
- prefix: "/"
services:
- name: grpc-backend
port: 50051
# gRPC is automatically enabled when using HTTP/2
Common Operations
Checking Contour Status
# Check Contour pod status
kubectl -n projectcontour get pods -l app=contour
# Check Envoy pod status
kubectl -n projectcontour get pods -l app=contour-envoy
# View Contour logs
kubectl -n projectcontour logs -l app=contour -f
# View Envoy logs
kubectl -n projectcontour logs -l app=contour-envoy -f
Debugging Configuration Issues
# Validate HTTPProxy syntax
kubectl apply -f my-proxy.yaml --dry-run=client
# Check Contour XDS status
kubectl -n projectcontour exec -l app=contour -- contour status
# Check Envoy configuration
kubectl -n projectcontour exec -l app=contour-envoy -- envoy config dump
Monitoring with Prometheus
# Enable Prometheus scraping
apiVersion: v1
kind: ConfigMap
metadata:
name: contour
namespace: projectcontour
data:
contour.yaml: |
xds-address: "0.0.0.0"
xds-port: 8001
debug: true
metrics:
address: "0.0.0.0"
port: 8002
---
# Prometheus scrape configuration
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: contour
namespace: projectcontour
labels:
release: prometheus
spec:
selector:
matchLabels:
app: contour
endpoints:
- port: metrics
path: /metrics
interval: 30s
Viewing TLS Certificate Status
# List certificates in secret
kubectl get secret -n projectcontour contour-envoy -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -text -noout
# Check certificate expiration
kubectl get secret -n projectcontour contour-envoy -o jsonpath='{.data.tls\.crt}' | base64 -d | openssl x509 -enddate -noout
# View Contour TLS configuration
kubectl -n projectcontour get secret contour-envoy -o yaml
Traffic Management Examples
# Canary deployment with weighted routing
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: canary
namespace: default
spec:
virtualhost:
fqdn: myapp.example.com
tls:
secretName: myapp-tls
routes:
- conditions:
- prefix: "/"
services:
- name: myapp-primary
port: 80
weight: 90
- name: myapp-canary
port: 80
weight: 10
# Retry configuration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: with-retries
namespace: default
spec:
routes:
- conditions:
- prefix: "/api"
services:
- name: api
port: 8080
retryPolicy:
count: 3
perTryTimeout: 2s
retryOn:
- 5xx
- reset
- connect-failure
Best Practices for Contour
1. Use Namespace Isolation
# HTTPProxy in different namespaces
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: frontend
namespace: web
spec:
virtualhost:
fqdn: frontend.example.com
tls:
secretName: frontend-tls
routes:
- services:
- name: frontend
port: 80
---
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: backend
namespace: api
spec:
virtualhost:
fqdn: api.example.com
tls:
secretName: api-tls
routes:
- services:
- name: backend
port: 8080
2. Implement Timeout and Retry Policies
# Production-ready timeout and retry configuration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: production
namespace: default
spec:
routes:
- conditions:
- prefix: "/"
services:
- name: backend
port: 8080
timeoutPolicy:
response: 30s # Response timeout
idle: 5m # Idle timeout
reconnect: 3 # Number of retries
perTryTimeout: 5s # Per-try timeout
retryPolicy:
count: 3 # Retry count
perTryTimeout: 2s # Per-try timeout
retryOn:
- 5xx # Retry on 5xx errors
- reset # Retry on connection reset
- connect-failure # Retry on connection failures
3. Use Resource Limits
# Contour deployment with resource limits
apiVersion: apps/v1
kind: Deployment
metadata:
name: contour
namespace: projectcontour
spec:
template:
spec:
containers:
- name: contour
resources:
requests:
memory: "256Mi"
cpu: "100m"
limits:
memory: "512Mi"
cpu: "500m"
4. Enable Access Logging
# Enable Envoy access logging
apiVersion: v1
kind: ConfigMap
metadata:
name: contour
namespace: projectcontour
data:
contour.yaml: |
xds-address: "0.0.0.0"
xds-port: 8001
debug: true
accessLog:
- type: file
path: /var/log/contour/envoy.log
format: "%LOCAL_PORT% %PROTOCOL% %STATUS% %STATUS_CODE% %RESPONSE_FLAGS% %UPSTREAM_HOST% %UPSTREAM_CLUSTER% %UPSTREAM_SERVICE_TIME% %REQUEST_SIZE% %RESPONSE_SIZE% %DOWNSTREAM_REMOTE_ADDRESS% %DOWNSTREAM_LOCAL_ADDRESS% %REQUEST_METHOD% %REQUEST_PATH% %REQUEST_HEADERS% %RESPONSE_HEADERS% %UPSTREAM_STREAM_RESPONSE_FLAGS%"
5. Certificate Management with cert-manager
# Certificate from cert-manager
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: example-com
namespace: default
spec:
secretName: example-com-tls
duration: 2160h # 90 days
renewBefore: 360h # 15 days before expiration
commonName: example.com
dnsNames:
- example.com
- "*.example.com"
issuerRef:
name: letsencrypt-prod
kind: ClusterIssuer
---
# Reference in HTTPProxy
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: secure
namespace: default
spec:
virtualhost:
fqdn: example.com
tls:
secretName: example-com-tls
minimumProtocolVersion: "1.2"
6. Health Check Endpoints
# Contour health endpoint
curl http://localhost:8000/healthz
# Contour metrics endpoint
curl http://localhost:8002/metrics
# Check Contour status
kubectl -n projectcontour exec -l app=contour -- contour status
7. Circuit Breaking Configuration
# Circuit breaker for backend services
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: circuit-breaker
namespace: default
spec:
routes:
- conditions:
- prefix: "/api"
services:
- name: api
port: 8080
policy:
loadBalancer:
policy: RingHash
requestHashPolicies:
- header:
headerName: "x-request-id"
connectionPool:
tcp:
maxConnections: 100
http:
h2ProtocolSettings:
maxConcurrentStreams: 100
requestTimeout: 30s
idleTimeout: 5m
outlierDetection:
consecutive5xxErrors: 5
interval: 30s
baseEjectionTime: 30s
maxEjectionPercent: 50
This SKILL.md file was verified and last updated on 2026-04-22. Content based on CNCF Contour project and production usage patterns.
Examples
Basic HTTPProxy Configuration
# Basic HTTPProxy for a single service
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: simple
namespace: default
spec:
virtualhost:
fqdn: simple.example.com
tls:
secretName: simple-tls
minimumProtocolVersion: "1.2"
routes:
- conditions:
- prefix: "/"
services:
- name: my-service
port: 80
TLS Passthrough
# TLS passthrough configuration
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: tls-passthrough
namespace: default
spec:
virtualhost:
fqdn: secure.example.com
tls:
passthrough: true
routes:
- conditions:
- prefix: "/"
services:
- name: my-service
port: 443
Weighted Traffic Splitting
# Traffic splitting between versions
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: canary
namespace: default
spec:
virtualhost:
fqdn: app.example.com
tls:
secretName: app-tls
routes:
- conditions:
- prefix: "/"
services:
- name: app-v1
port: 80
weight: 95
- name: app-v2
port: 80
weight: 5
External Service
# Route to external service
apiVersion: projectcontour.io/v1
kind: HTTPProxy
metadata:
name: external
namespace: default
spec:
routes:
- conditions:
- prefix: "/external"
services:
- name: external-service
port: 443
protocol: https
urlScheme: https
policy:
loadBalancer:
policy: RoundRobin
When to Use
Use this skill when:
- Integrating a CNCF project into Kubernetes infrastructure — You need to configure, deploy, or troubleshoot a cloud-native tool within a cluster
- **Designing cloud-native archite
…(truncated)