Contour Development
VS Code Setup
Enable e2e for gopls buildFlags so that we can open e2e tests without errors and get proper code navigation and completion.
mkdir -p .vscode
cat <<EOF > .vscode/settings.json
{
"go.buildFlags": [
"-tags=e2e"
]
}
EOF
Testing (No Cluster Required)
make check # Unit tests only make lint # Linting make generate # Code generation (run after modifying CRDs) make checkall # All of the above (run before commits)
Testing (Requires Kind Cluster)
make run-e2e # End-to-end tests
To run specific e2e tests, set the CONTOUR_E2E_TEST_FOCUS environment variable to a regex matching the test name.
For example, to run only tests related to external name services over HTTPS:
CONTOUR_E2E_TEST_FOCUS="external name services work over https" make run-e2e
Kind Cluster Setup
Purpose: Create local Kubernetes cluster for Contour testing and development.
scripts/setup-cluster.sh # Start Kind cluster with Contour and echoserver deployed
Cleanup:
scripts/delete-cluster.sh
Run Contour from Source (Host) + Envoy (Cluster)
Purpose: Local Contour development with rapid iteration and debugging.
Step 1 is one-time setup done after setup-cluster.sh.
Step 2 is repeated after each code change.
1. Prepare Cluster for Local Development
scripts/prepare-for-contour-on-host.sh # Configures Service/EndpointSlice so Envoy can connect Contour running on host
2. Run Contour
CLI:
go run github.com/projectcontour/contour/cmd/contour serve \ --xds-address=0.0.0.0 \ --xds-port=8001 \ --envoy-service-http-port=8080 \ --envoy-service-https-port=8443 \ --contour-cafile=ca.crt \ --contour-cert-file=tls.crt \ --contour-key-file=tls.key \ --debug
VS Code Debugger:
mkdir -p .vscode
cat <<EOF > .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Run contour",
"type": "go",
"request": "launch",
"mode": "auto",
"cwd": "${workspaceRoot}",
"program": "cmd/contour",
"args": ["serve", "--xds-address=0.0.0.0", "--xds-port=8001", "--envoy-service-http-port=8080", "--envoy-service-https-port=8443", "--contour-cafile=ca.crt", "--contour-cert-file=tls.crt", "--contour-key-file=tls.key", "--debug"]
}
]
}
EOF
Start debug session using workbench.action.debug.start command.
Build and Deploy Custom Contour Image to Cluster
Purpose: Test Contour changes running fully in-cluster.
Step 1 is repeated for each code change. Steps 2 and 3 are one-time setup.
1. Build and Load Image
make container VERSION=latest kind load docker-image ghcr.io/projectcontour/contour:latest --name contour
2. Patch Deployments
kubectl -n projectcontour patch deployment contour --patch-file=assets/contour-deployment-patch.yaml kubectl -n projectcontour patch daemonset envoy --patch-file=assets/envoy-daemonset-patch.yaml
3. Verify
kubectl -n projectcontour rollout status deployment/contour kubectl -n projectcontour rollout status daemonset/envoy kubectl -n projectcontour get pods -o wide kubectl -n projectcontour describe pod -l app=contour | grep Image:
Test Traffic With Echoserver
Purpose: Test Contour routing and Envoy configuration with a real upstream service.
Use httpie http CLI tool instead of curl to send requests.
Echoserver is already deployed by setup-cluster.sh.
# Linux http http://echoserver.127-0-0-101.nip.io # macOS (requires port-forwarding) kubectl -n projectcontour port-forward daemonset/envoy 8080:8080 http localhost:8080 Host:echoserver.127-0-0-101.nip.io
For load testing and benchmarking, use echoclient:
If you need more advanced traffic profiles than the echoclient CLI supports, create custom Go code using the echoclient Go API.
go run github.com/tsaarni/echoclient/cmd/echoclient@latest get -url http://echoserver.127-0-0-101.nip.io -concurrency 10
Troubleshooting
Purpose: Diagnose Contour and Envoy runtime issues, inspect configuration, analyze metrics.
Logs
kubectl -n projectcontour logs -f deployment/contour # Contour logs (stream) kubectl -n projectcontour logs -f daemonset/envoy -c envoy # Envoy logs (stream) kubectl -n projectcontour logs -f daemonset/envoy -c shutdown-manager # Shutdown manager (stream) kubectl -n projectcontour logs -l app=contour --tail=100 # All Contour pods kubectl -n projectcontour logs deployment/contour --previous # Previous container (if crashed)
Contour Metrics and Debug
kubectl -n projectcontour port-forward deployment/contour 8000:8000 http localhost:8000/metrics # Prometheus metrics http localhost:8000/debug/pprof/ # Debug info http localhost:8000/debug/dag # Internal DAG state
Envoy Admin API
Purpose: Inspect Envoy runtime configuration, clusters, routes, and statistics.
kubectl -n projectcontour port-forward daemonset/envoy 9001:9001 http http://localhost:9001/config_dump?include_eds | jq -C . | less # Full config dump with EDS http http://localhost:9001/config_dump | jq '.configs[].dynamic_active_clusters' # Active clusters http http://localhost:9001/config_dump | jq '.configs[].dynamic_route_configs' # Route configs http http://localhost:9001/clusters # Cluster statistics http http://localhost:9001/listeners # Listener statistics http http://localhost:9001/server_info # Server info http http://localhost:9001/stats # All stats http http://localhost:9001/help # Available endpoints
Deploy Specific Contour Version
Purpose: Test compatibility, reproduce bugs, or regression testing against specific releases.
kubectl apply -f https://projectcontour.io/quickstart/v1.28.0/contour.yaml # Available versions: https://raw.githubusercontent.com/projectcontour/contour/refs/heads/main/versions.yaml
Custom Contour Configuration
Purpose: Modify global Contour behavior (timeouts, logging, etc).
Three methods: ConfigMap, ContourConfiguration CRD, or command-line flags.
Configuration File (ConfigMap)
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: contour
namespace: projectcontour
data:
contour.yaml: |
# Consult Contour configuration docs for available fields: https://projectcontour.io/docs/main/configuration/
<configure-as-needed>
EOF
kubectl -n projectcontour delete pod -l app=contour # Restart Contour to pick up changes
ContourConfiguration CRD
cat <<EOF | kubectl apply -f - apiVersion: projectcontour.io/v1alpha1 kind: ContourConfiguration metadata: name: contour namespace: projectcontour spec: # Consult ContourConfiguration API for available fields: https://projectcontour.io/docs/main/config/api/ <configure-as-needed> EOF kubectl -n projectcontour delete pod -l app=contour # Restart Contour to pick up changes
Command-Line Flags
kubectl -n projectcontour patch deployment contour --type=json -p='[
{
"op": "add",
"path": "/spec/template/spec/containers/0/args/-",
"value": "--debug"
}
]'
When running from source, add flags to go run command or launch configuration.
Update Website Documentation
cd site && hugo server --disableFastRender # Starts at http://localhost:1313
Development Guidelines
New configuration options - implement in both methods:
- •ConfigMap: pkg/config/parameters.go + document in site/content/docs/main/configuration.md
- •CRD: apis/projectcontour/v1alpha1/contourconfig.go
After dependency updates (client-go, controller-runtime): Run make generate to update CRDs.
Resources
- •Contour docs: https://projectcontour.io/docs/
- •Contour repo: https://github.com/projectcontour/contour
- •Contour helm chart: https://github.com/projectcontour/helm-charts
- •Contour CRDs: https://projectcontour.io/docs/main/config/api/
- •Contour config file and command-line flags: https://projectcontour.io/docs/main/configuration/
- •Envoy docs: https://www.envoyproxy.io/docs/envoy/latest/
- •Envoy XDS API: https://www.envoyproxy.io/docs/envoy/latest/api-v3/api
- •Envoy Admin REST API: https://www.envoyproxy.io/docs/envoy/latest/operations/admin.html
- •Envoy statistics: https://www.envoyproxy.io/docs/envoy/latest/configuration/http/http_conn_man/stats and https://www.envoyproxy.io/docs/envoy/latest/configuration/upstream/cluster_manager/cluster_stats
- •Kind docs: https://kind.sigs.k8s.io/
- •Echoserver docs: https://github.com/tsaarni/echoserver
- •HTTPie docs: https://httpie.io/docs
- •Echoclient docs: https://github.com/tsaarni/echoclient