Skip to content

konkarah/istio

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Microservices Demo — Service Registration, Discovery & Observability

A complete microservices learning project built with Node.js/Express. Runs in two modes from the same codebase:

  • Docker Compose — DIY registry, manual discovery, Jaeger + Prometheus + Grafana
  • Kubernetes + Istio — K8s DNS, Envoy sidecars, Kiali + Jaeger + Prometheus + Grafana

Architecture

Client
  │
  ▼
api-gateway          ← single entry point (port 3004 / Istio IngressGateway)
  │
  ├── user-service    ← returns user data
  ├── product-service ← returns product catalogue
  └── order-service   ← calls user + product, returns enriched orders
       ├── user-service
       └── product-service

In Docker Compose, a DIY registry service acts as the phonebook. In Kubernetes, CoreDNS replaces the registry entirely.


Project Structure

.
├── shared/
│   ├── logger.js           structured JSON logging
│   ├── middleware.js        request logging, tracing headers, /metrics
│   └── service-client.js   register/discover/heartbeat (Docker mode only)
├── registry/               DIY phonebook — Docker Compose only
├── user-service/
├── product-service/
├── order-service/
├── api-gateway/
├── k8s-istio/
│   ├── 00-namespace.yaml       enables Istio sidecar injection
│   ├── 01-services.yaml        Deployments + Services (port name: http required)
│   ├── 02-istio-gateway.yaml   IngressGateway + routing rules
│   ├── 03-istio-traffic-policy.yaml  mTLS, retries, circuit breaking
│   ├── 04-telemetry.yaml       100% trace sampling to Jaeger
│   └── 05-mesh-config.yaml     points Envoy sidecars at Jaeger collector
├── observability/
│   ├── prometheus.yml          scrape config for all services
│   └── grafana-datasource.yml  auto-wires Prometheus into Grafana
└── docker-compose.yml

Option A — Docker Compose (local, no Kubernetes needed)

Run

docker compose up --build

URLs

URL What
http://localhost:3004 API Gateway
http://localhost:3000/services Registry — see all registered services
http://localhost:16686 Jaeger — distributed traces
http://localhost:9090 Prometheus — raw metrics
http://localhost:3100 Grafana — dashboards (login: admin / admin)

Generate traffic

while true; do
  curl -s http://localhost:3004/users > /dev/null
  curl -s http://localhost:3004/products > /dev/null
  curl -s http://localhost:3004/orders/ORD-001 > /dev/null
  curl -s http://localhost:3004/orders/ORD-002 > /dev/null
  curl -s -X POST http://localhost:3004/orders \
    -H "Content-Type: application/json" \
    -d '{"userId":1,"productId":102,"quantity":1}' > /dev/null
  echo "tick $(date +%H:%M:%S)"
  sleep 1
done

What to look for

Jaeger → Service: api-gateway → Find Traces → click any trace

Prometheus → query request_total → Graph tab

Grafana → Dashboards → add panel → Prometheus datasource → query request_total


Option B — Kubernetes + Istio (full production setup)

One-time prerequisites

# Install tools
brew install minikube istioctl

# Start cluster
minikube start --memory=4096 --cpus=4

# Install Istio
istioctl install --set profile=demo -y

# Install observability addons
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.21/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.21/samples/addons/jaeger.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.21/samples/addons/grafana.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.21/samples/addons/kiali.yaml

# Wait for all addons to be ready
kubectl rollout status deployment/prometheus -n istio-system
kubectl rollout status deployment/jaeger -n istio-system
kubectl rollout status deployment/grafana -n istio-system
kubectl rollout status deployment/kiali -n istio-system

Every time you deploy (fresh or after code changes)

# Step 1 — point Docker at minikube's daemon
eval $(minikube docker-env)

# Step 2 — build images (must use ms- prefix to match 01-services.yaml)
docker build -t ms-user-service:latest     -f user-service/Dockerfile .
docker build -t ms-product-service:latest  -f product-service/Dockerfile .
docker build -t ms-order-service:latest    -f order-service/Dockerfile .
docker build -t ms-api-gateway:latest      -f api-gateway/Dockerfile .

# Step 3 — apply K8s manifests
kubectl apply -f k8s-istio/00-namespace.yaml
kubectl apply -f k8s-istio/01-services.yaml
kubectl apply -f k8s-istio/02-istio-gateway.yaml
kubectl apply -f k8s-istio/03-istio-traffic-policy.yaml
kubectl apply -f k8s-istio/04-telemetry.yaml
kubectl apply -f k8s-istio/05-mesh-config.yaml

# Step 4 — wait for all 8 pods to be 2/2 Running
kubectl get pods -n microservices -w
# Press Ctrl+C once all show 2/2 Running with 0 restarts

# Step 5 — restart pods to pick up mesh config (only needed after 05-mesh-config changes)
kubectl rollout restart deployment -n microservices
kubectl rollout status deployment -n microservices

Get the gateway URL

# Terminal 1 — KEEP THIS OPEN (minikube tunnel)
minikube service istio-ingressgateway -n istio-system --url
# You'll see 5 URLs. The SECOND one (port 80) is your gateway.
# Example output:
#   http://127.0.0.1:59042  ← port 15021 (health check) — NOT this one
#   http://127.0.0.1:59043  ← port 80 (HTTP) — USE THIS ONE
#   http://127.0.0.1:59044  ← port 443
#   ...

To confirm which port is correct:

kubectl get service istio-ingressgateway -n istio-system
# Look for 80:XXXXX/TCP in the PORT(S) column
# The minikube URL mapping to port 80 is your gateway

Generate traffic (Terminal 2)

export GW=http://127.0.0.1:59043   # replace with your port 80 URL

while true; do
  curl -s $GW/users > /dev/null
  curl -s $GW/products > /dev/null
  curl -s $GW/orders > /dev/null
  curl -s $GW/orders/ORD-001 > /dev/null
  curl -s $GW/orders/ORD-002 > /dev/null
  curl -s -X POST $GW/orders \
    -H "Content-Type: application/json" \
    -d '{"userId":1,"productId":102,"quantity":1}' > /dev/null
  echo "tick $(date +%H:%M:%S)"
  sleep 1
done

Open dashboards (one per terminal)

istioctl dashboard kiali       # service graph, live traffic, health
istioctl dashboard jaeger      # distributed traces
istioctl dashboard grafana     # metric dashboards
istioctl dashboard prometheus  # raw metric queries

What to look for in each dashboard

Kiali

  1. Left sidebar → Graph
  2. Namespace dropdown → select microservices
  3. Top right → change Last 1m to Last 5m
  4. You'll see: istio-ingressgateway → order-service → user-service + product-service
  5. Click any arrow to see request rate, error %, and latency on that edge
  6. Left sidebar → Distributed Tracing → links directly to Jaeger

Jaeger

  1. Service dropdown → select istio-ingressgateway
  2. Click Find Traces
  3. Click any trace to see the full timeline across all services
  4. Each coloured bar = one service's processing time

Prometheus

  1. Query box → type istio_requests_total → Execute → Graph tab
  2. Try: rate(istio_requests_total[1m]) for requests per second
  3. Try: istio_request_duration_milliseconds_bucket for latency

Grafana

  1. Left sidebar → Dashboards → Browse → Istio folder
  2. Open Istio Service Dashboard
  3. Service dropdown → select order-service.microservices.svc.cluster.local
  4. See: request rate, error rate, p50/p99 latency as live graphs

Stopping and resuming

# Stop (preserves everything)
minikube stop

# Resume next time
minikube start
eval $(minikube docker-env)
# Re-run the minikube service tunnel command to get fresh ports
minikube service istio-ingressgateway -n istio-system --url

Teardown

kubectl delete namespace microservices
minikube stop

How K8S_MODE works

Every service checks process.env.K8S_MODE at startup:

Docker Compose (K8S_MODE=false) Kubernetes (K8S_MODE=true)
Registration register() on startup skipped
Heartbeat sent every 10s skipped
Discovery discover("user-service") env var URL direct
Deregister on SIGTERM skipped
Who handles discovery your registry service K8s CoreDNS
Who handles health nothing (Docker restarts) liveness + readiness probes
Who handles encryption nothing (plain HTTP) Istio mTLS (automatic)
Who handles retries you'd write it Istio VirtualService YAML

Common issues

Pods CrashLoopBackOff

kubectl logs -n microservices deployment/user-service -c user-service
kubectl logs -n microservices deployment/user-service -c istio-proxy | tail -20

404 from gateway

# Confirm you're using the port 80 URL, not port 15021
kubectl get service istio-ingressgateway -n istio-system
istioctl analyze -n microservices

No traces in Jaeger

# Confirm telemetry config is applied
kubectl get telemetry -n istio-system
# Restart pods to pick up config
kubectl rollout restart deployment -n microservices

Kiali graph empty

  • Wait 2 minutes after starting traffic loop
  • Change time range from Last 1m to Last 5m
  • Click the refresh button top right

alt text alt text alt text alt textalt text

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors