Skip to content

Room 54

SERVICE MESH


The Traffic Conductor

  • A service mesh provides observability, traffic management, and security for microservice communication.
  • You’ll deploy a mesh sidecar architecture and control traffic between services.

📜 Mission Briefing

  1. Deploy a microservices application with 3 services: web, api, db.
  2. Inject sidecar proxies into each service using manual sidecar injection.
  3. Configure traffic routing: send 80% of traffic to api-v1 and 20% to api-v2.
  4. Set up mutual TLS (mTLS) between all services.
  5. Apply a retry policy for failed requests to the api service.
  6. Observe traffic flow using proxy access logs.
  7. The password is in the traffic split annotation: mesh54go.

Key Commands
Command Purpose
kubectl get pods -o jsonpath='{.items[*].spec.containers[*].name}' List all containers (check for sidecars)
kubectl logs <pod> -c envoy-proxy Sidecar proxy logs
kubectl get virtualservices Traffic routing rules
kubectl get destinationrules Load balancing and TLS config
kubectl get peerauthentication mTLS policies

Microservices Deployment
# web-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  labels:
    app: web
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
        - name: web
          image: nginx:1.25
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config
              mountPath: /etc/nginx/conf.d
      volumes:
        - name: config
          configMap:
            name: web-nginx-config
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: web-nginx-config
data:
  default.conf: |
    upstream api_backend {
      server api-service:8080;
    }
    server {
      listen 80;
      location / {
        root /usr/share/nginx/html;
      }
      location /api {
        proxy_pass http://api_backend;
      }
    }
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
    - port: 80
      targetPort: 80

Canary Deployment - Traffic Splitting
# api-v1-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-v1
  labels:
    app: api
    version: v1
spec:
  replicas: 3
  selector:
    matchLabels:
      app: api
      version: v1
  template:
    metadata:
      labels:
        app: api
        version: v1
    spec:
      containers:
        - name: api
          image: nginx:1.25
          ports:
            - containerPort: 8080
---
# api-v2-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-v2
  labels:
    app: api
    version: v2
  annotations:
    traffic-password: "mesh54go"
spec:
  replicas: 1
  selector:
    matchLabels:
      app: api
      version: v2
  template:
    metadata:
      labels:
        app: api
        version: v2
    spec:
      containers:
        - name: api
          image: nginx:1.26
          ports:
            - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  selector:
    app: api
  ports:
    - port: 8080
      targetPort: 8080

Manual Sidecar Injection
# sidecar-patch.yaml - Add Envoy sidecar to any deployment
# Apply with: kubectl patch deploy web --patch-file sidecar-patch.yaml
spec:
  template:
    spec:
      initContainers:
        - name: proxy-init
          image: envoyproxy/envoy:v1.28-latest
          command: ["sh", "-c", "echo 'Sidecar init complete'"]
          securityContext:
            capabilities:
              add: ["NET_ADMIN"]
      containers:
        - name: envoy-proxy
          image: envoyproxy/envoy:v1.28-latest
          ports:
            - containerPort: 15001
          command: ["envoy"]
          args:
            - "-c"
            - "/etc/envoy/envoy.yaml"
            - "--service-cluster"
            - "$(POD_NAME)"
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
          volumeMounts:
            - name: envoy-config
              mountPath: /etc/envoy
      volumes:
        - name: envoy-config
          configMap:
            name: envoy-sidecar-config

Traffic Splitting with Weighted Services
# Without a full service mesh, simulate traffic splitting with multiple deployments
# and weighted endpoints

# Scale to achieve 80/20 split
kubectl scale deploy api-v1 --replicas=4    # 4 out of 5 = 80%
kubectl scale deploy api-v2 --replicas=1    # 1 out of 5 = 20%

# Both share the same Service selector (app: api)
# Kubernetes will round-robin across all matching pods

# Verify the split
for i in $(seq 1 20); do
  kubectl exec deploy/web -- curl -s api-service:8080 2>/dev/null
done | sort | uniq -c | sort -rn

# Check the password annotation on api-v2
kubectl get deploy api-v2 -o jsonpath='{.metadata.annotations.traffic-password}'
# Output: mesh54go

mTLS Between Services
# mtls-policy.yaml - Require mTLS for all traffic
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: default
spec:
  mtls:
    mode: STRICT
# Without Istio, you can configure mTLS manually with certificates
# Generate self-signed certs for service communication

# Create CA
openssl req -x509 -newkey rsa:2048 -keyout ca-key.pem -out ca-cert.pem \
  -days 365 -nodes -subj "/CN=mesh-ca"

# Create service cert signed by CA
openssl req -newkey rsa:2048 -keyout svc-key.pem -out svc-csr.pem \
  -nodes -subj "/CN=api-service.default.svc.cluster.local"

openssl x509 -req -in svc-csr.pem -CA ca-cert.pem -CAkey ca-key.pem \
  -CAcreateserial -out svc-cert.pem -days 365

# Store as Kubernetes Secret
kubectl create secret tls api-tls \
  --cert=svc-cert.pem \
  --key=svc-key.pem

Retry Policy
# retry-configmap.yaml - Envoy retry configuration
apiVersion: v1
kind: ConfigMap
metadata:
  name: envoy-retry-config
data:
  retry.yaml: |
    retry_policy:
      retry_on: "5xx,reset,connect-failure"
      num_retries: 3
      per_try_timeout: 2s
      retry_back_off:
        base_interval: 0.5s
        max_interval: 5s

💡 Hints

  • A service mesh sidecar intercepts all inbound and outbound traffic from a pod.
  • Without Istio/Linkerd, you can simulate traffic splitting by controlling replica ratios.
  • mTLS ensures service-to-service encryption - the mesh CA issues and rotates certificates.
  • The password is in the api-v2 deployment annotation - use kubectl get deploy api-v2 -o yaml.

🔑 Password

Check the api-v2 deployment annotation: kubectl get deploy api-v2 -o jsonpath='{.metadata.annotations.traffic-password}'