Terminal.skills
Use Cases/Implement Service Mesh for Microservices

Implement Service Mesh for Microservices

Add Istio service mesh to an existing Kubernetes cluster to gain traffic management, mutual TLS, circuit breaking, and observability for a microservices architecture.

#kubernetes#helm#containers#orchestration#docker-compose
Works with:claude-codeopenai-codexgemini-clicursor
$

You have an existing Kubernetes cluster running a microservices application — a frontend, an API gateway, several backend services, and a database. Services communicate over plain HTTP with no encryption, no retries, and no traffic control. This walkthrough adds Istio to give you mTLS everywhere, traffic management, and observability.

Step 1: Local Development Setup with Docker Compose

Before deploying to Kubernetes with Istio, verify the microservices work together locally.

yaml
# docker-compose.yml — Local development stack for the microservices
version: "3.8"
services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
    environment:
      - API_URL=http://api-gateway:8080

  api-gateway:
    build: ./api-gateway
    ports:
      - "8080:8080"
    environment:
      - USERS_SERVICE=http://users:8081
      - ORDERS_SERVICE=http://orders:8082
      - PAYMENTS_SERVICE=http://payments:8083

  users:
    build: ./users
    environment:
      - DATABASE_URL=postgresql://app:secret@postgres:5432/users

  orders:
    build: ./orders
    environment:
      - DATABASE_URL=postgresql://app:secret@postgres:5432/orders
      - PAYMENTS_SERVICE=http://payments:8083

  payments:
    build: ./payments
    environment:
      - DATABASE_URL=postgresql://app:secret@postgres:5432/payments

  postgres:
    image: postgres:15
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: secret
    volumes:
      - pgdata:/var/lib/postgresql/data

volumes:
  pgdata:
bash
# local-test.sh — Verify services work locally
docker compose up -d
curl http://localhost:8080/health
docker compose down

Step 2: Install Istio on the Cluster

Install Istio with the default profile and enable sidecar injection for your application namespace.

bash
# install-istio.sh — Install Istio and enable injection
istioctl install --set profile=default -y

kubectl create namespace microservices
kubectl label namespace microservices istio-injection=enabled

istioctl verify-install

Step 3: Deploy the Application with Helm

Use Helm to deploy the microservices into the mesh-enabled namespace. With sidecar injection enabled, each pod automatically gets an Envoy proxy.

bash
# deploy-app.sh — Deploy microservices via Helm
helm install microservices ./helm/microservices \
  --namespace microservices \
  --set global.image.tag=v1.0.0 \
  --wait

Verify all pods have 2 containers (app + istio-proxy sidecar):

bash
# verify-injection.sh — Confirm sidecar injection
kubectl get pods -n microservices
# Each pod should show 2/2 READY
istioctl analyze -n microservices

Step 4: Enable Strict mTLS

Enforce mutual TLS across the entire mesh so all service-to-service communication is encrypted and authenticated.

yaml
# security/peer-authentication.yaml — Enforce strict mTLS mesh-wide
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
  name: default
  namespace: istio-system
spec:
  mtls:
    mode: STRICT
bash
# apply-mtls.sh — Enable strict mTLS
kubectl apply -f security/peer-authentication.yaml

# Verify mTLS is active between services
istioctl proxy-config secret deploy/api-gateway -n microservices | head

Step 5: Configure Traffic Management

Set up destination rules for circuit breaking and virtual services for retries and timeouts.

yaml
# networking/destination-rules.yaml — Circuit breaking for backend services
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: users-service
  namespace: microservices
spec:
  host: users
  trafficPolicy:
    connectionPool:
      tcp:
        maxConnections: 50
      http:
        http1MaxPendingRequests: 50
        http2MaxRequests: 100
    outlierDetection:
      consecutive5xxErrors: 3
      interval: 10s
      baseEjectionTime: 30s
      maxEjectionPercent: 50
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: payments-service
  namespace: microservices
spec:
  host: payments
  trafficPolicy:
    connectionPool:
      http:
        http1MaxPendingRequests: 25
        http2MaxRequests: 50
    outlierDetection:
      consecutive5xxErrors: 2
      interval: 10s
      baseEjectionTime: 60s
yaml
# networking/virtual-services.yaml — Retries and timeouts for API gateway routes
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: api-gateway
  namespace: microservices
spec:
  hosts:
    - api-gateway
  http:
    - route:
        - destination:
            host: api-gateway
      timeout: 15s
      retries:
        attempts: 3
        perTryTimeout: 5s
        retryOn: 5xx,reset,connect-failure
bash
# apply-traffic.sh — Apply traffic management rules
kubectl apply -f networking/

Step 6: Set Up Ingress Gateway

Expose the application through Istio's ingress gateway with TLS.

yaml
# networking/gateway.yaml — Istio Gateway for external HTTPS access
apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: app-gateway
  namespace: microservices
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 443
        name: https
        protocol: HTTPS
      tls:
        mode: SIMPLE
        credentialName: app-tls-cert
      hosts:
        - "app.example.com"
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: app-ingress
  namespace: microservices
spec:
  hosts:
    - "app.example.com"
  gateways:
    - app-gateway
  http:
    - match:
        - uri:
            prefix: /api
      route:
        - destination:
            host: api-gateway
            port:
              number: 8080
    - route:
        - destination:
            host: frontend
            port:
              number: 3000

Step 7: Canary Deployment

Deploy a new version of the users service with traffic splitting to gradually roll out changes.

yaml
# canary/users-canary.yaml — Canary deployment with 10% traffic to v2
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: users-canary
  namespace: microservices
spec:
  hosts:
    - users
  http:
    - route:
        - destination:
            host: users
            subset: stable
          weight: 90
        - destination:
            host: users
            subset: canary
          weight: 10
---
apiVersion: networking.istio.io/v1beta1
kind: DestinationRule
metadata:
  name: users-versions
  namespace: microservices
spec:
  host: users
  subsets:
    - name: stable
      labels:
        version: v1
    - name: canary
      labels:
        version: v2

Step 8: Observability

Install Kiali, Grafana, and Jaeger to visualize the mesh traffic and trace requests across services.

bash
# install-observability.sh — Deploy Istio observability addons
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/prometheus.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/grafana.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/jaeger.yaml
kubectl apply -f https://raw.githubusercontent.com/istio/istio/release-1.20/samples/addons/kiali.yaml

# Access dashboards
istioctl dashboard kiali
istioctl dashboard grafana
istioctl dashboard jaeger

Verification

bash
# verify-mesh.sh — Confirm the service mesh is fully operational
istioctl proxy-status
istioctl analyze -n microservices
kubectl get virtualservices,destinationrules,gateways -n microservices
curl -k https://app.example.com/api/health

The microservices now communicate over encrypted mTLS connections, have automatic retries and circuit breaking, support canary deployments through traffic splitting, and provide full observability through Kiali, Grafana, and Jaeger dashboards.