A hands-on lab that recreates the moving parts of a small content delivery network end-to-end: edge nodes, anycast-style request steering, tiered caching, origin shielding, and observability. Built to mirror the kind of work a Senior Network Engineer does at a CDN — but small enough to run on a single laptop with Docker Compose.
Think of it as a "CDN in a box" you can break, profile, and tune.
┌────────────┐ anycast-ish ┌────────────┐
client ─► │ geo-LB │ ──────────────────────► │ edge PoP │ ──► cache hit ─► client
└────────────┘ (lowest-latency map) │ (nginx) │
│ └─────┬──────┘
│ │ miss
▼ ▼
metrics + logs ◄──── Prometheus ◄──── origin shield ──► origin
│
▼
Grafana
- Edges: Nginx with
proxy_cache,stale-while-revalidate, conditional GETs - Steering: weighted/geo map → nearest PoP (simulated RTT via
tc netem) - Shield: single mid-tier cache collapsing requests before they hit origin
- Provisioning: Ansible roles for repeatable PoP rollout
- Observability: Prometheus + Grafana dashboards (cache-hit %, TTFB p50/p95, origin RPS)
git clone https://github.com/1994-munk/edge-cdn-lab.git cd edge-cdn-lab docker compose up -d ./scripts/seed-traffic.sh # synthetic load across PoPs open http://localhost:3000 # Grafana (admin/admin)
Provision a fresh PoP:
ansible-playbook -i inventories/lab ansible/site.yml --limit pop-fra
| Signal | Why it matters | Where |
|---|---|---|
| Cache-hit ratio | Direct lever on origin cost & TTFB | Grafana → CDN / Edge |
| TTFB p50 / p95 | User-perceived latency | Grafana → CDN / Latency |
| Origin RPS | Validates shield + collapsing | Grafana → Origin |
| 5xx rate | Health under stress | Grafana → SLO |
docs/runbooks/cache-poisoning.md— invalidation & purge workflowdocs/runbooks/pop-failover.md— pulling a PoP out of rotationdocs/runbooks/origin-overload.md— shield tuning + request collapsing
- Multi-PoP Nginx with tiered cache
- Prometheus + Grafana dashboards
- Ansible provisioning
- QUIC / HTTP3 edge listener
- eBPF-based connection accounting
- Synthetic RUM beacon