This is a simple demo application for Kubernetes showcasing a microservices architecture built entirely with NGINX. The application simulates an online ordering system with a gateway that routes traffic to internal microservices (payment and user) and external APIs (SpaceX, GitHub).
nginx/
├── base/ # Base Kubernetes resources (deployments, services, configmaps)
├── patch/ # Kustomize patches (e.g., Speedscale sidecar injection)
├── jobs/ # Traffic generation CronJob and scripts
├── replays/ # TrafficReplay custom resources
├── kustomization.yaml
└── ns.yaml # Namespace definition
- Gateway: NGINX reverse proxy that routes requests to:
/payment→ Payment service/user→ User service/login→ Returns authentication response/spacex→ SpaceX API (external backend)
- Payment: NGINX service that proxies to GitHub API (demonstrates external API integration)
- User: NGINX service that returns user profile information
- Traffic Generator: CronJob that runs every 5 minutes, simulating 10 users with realistic behavior patterns
- Kubernetes cluster (minikube, kind, or cloud provider)
- kubectl configured to access your cluster
- Speedscale operator installed (for traffic capture and replay)
Deploy all three services (gateway, payment, user) to the demo namespace:
kubectl apply -k ./This will create:
- Namespace:
demo - Deployments: gateway, payment, user
- Services: gateway, payment, user
- ConfigMaps with NGINX configurations and traffic generation script
- CronJob that generates traffic every 5 minutes automatically
Verify the deployment:
kubectl get pods -n demo
kubectl get services -n demo
kubectl get cronjobs -n demoThe demo includes a CronJob that automatically generates exciting simulated user traffic every 5 minutes. This creates:
- 10 named users (Alice, Bob, Charlie, Diana, Eve, Frank, Grace, Henry, Ivy, Jack)
- User personas: Space enthusiasts, shoppers, browsers, and power users
- Realistic behavior: Login flows, profile views, varied actions based on user type
- Randomized timing: Variable delays between requests to simulate real users
- Live stats: Color-coded output showing success/failure rates
- Background activity: Simulated API health checks and background jobs
The script hits all gateway endpoints with realistic patterns:
- Authentication flows via
/login - User profile management via
/userand/user/profile/{id} - Payment processing via
/paymentand/payment/lookup/{id} - External SpaceX API calls via
/spacex/*(launches, rockets, company info)
Watch the continuous traffic generation:
# Check CronJob schedule
kubectl get cronjobs -n demo
# See recent jobs
kubectl get jobs -n demo
# Watch logs from the most recent run
kubectl logs -f $(kubectl get pods -n demo -l job-name --sort-by=.metadata.creationTimestamp -o name | tail -1)To generate traffic immediately without waiting for the schedule:
kubectl create job traffic-manual --from=cronjob/traffic-generator -n demo
# Watch it run
kubectl logs -f job/traffic-manual -n demoTo change how often traffic is generated, edit the CronJob:
# Every 2 minutes: "*/2 * * * *"
# Every 10 minutes: "*/10 * * * *"
# Every hour: "0 * * * *"
kubectl edit cronjob traffic-generator -n demoTo temporarily stop automatic traffic generation:
kubectl patch cronjob traffic-generator -n demo -p '{"spec":{"suspend":true}}'To resume:
kubectl patch cronjob traffic-generator -n demo -p '{"spec":{"suspend":false}}'To generate custom traffic, you can also use the curl script:
./run_curl.shEnable sidecar injection by uncommenting the patch in kustomization.yaml:
patchesStrategicMerge:
- patch/inject.yamlThen redeploy:
kubectl apply -k ./Generate traffic and Speedscale will automatically capture all inbound and outbound requests.
The gateway and payment services automatically detect when Speedscale is injected:
- With Speedscale: Uses the injected CA certificate at
/etc/ssl/speedscale/ca-certificates.crtfor TLS verification. This allows replay to work correctly with mocked external APIs. - Without Speedscale: Uses system default TLS verification for direct connections to external APIs.
The containers check for the SSL_CERT_FILE environment variable at startup and configure nginx accordingly. This means replay traffic works seamlessly without 502 errors on external API calls.
Once you have captured traffic, you can replay it against your services.
Edit replays/replay.yaml and update the snapshotID field with your captured snapshot ID:
spec:
snapshotID: "your-snapshot-id-here"kubectl apply -f replays/replay.yamlThis will:
- Create a temporary workload with the gateway deployment
- Replay the captured traffic against it
- Validate responses match expected behavior
- Clean up temporary resources when complete
Check the status of the replay:
kubectl get trafficreplay -n demo
kubectl describe trafficreplay nginx-demo-replay -n demoView replay results in the Speedscale dashboard or via CLI:
speedctl replay get nginx-demo-replayThe gateway now includes a proxy to the SpaceX API. You can test it by:
# Get latest launch info
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -n demo -- \
curl http://gateway/spacex/launches/latest
# Get all rockets
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -n demo -- \
curl http://gateway/spacex/rockets
# Get company info
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -n demo -- \
curl http://gateway/spacex/companyThese requests proxy through the gateway to https://api.spacexdata.com/v4/*.
Remove all resources (this will also stop the CronJob):
kubectl delete -k ./
kubectl delete -f replays/replay.yamlOr delete the entire namespace (quickest way):
kubectl delete namespace demoTo stop just the traffic generation without removing the services:
kubectl delete cronjob traffic-generator -n demo