Skip to content

Service-Mesh vs Ingress/API GatewayΒΆ

TasksΒΆ

They handle different traffic:

  • Service Mesh = Pod-to-Pod (EAST-WEST) inside cluster
  • Ingress = External-to-Pod (NORTH-SOUTH) into cluster

Visual ExplanationΒΆ

═══════════════════════════════════════════════════════════════════════════
                    NORTH-SOUTH vs EAST-WEST TRAFFIC
═══════════════════════════════════════════════════════════════════════════

                         External Users
                         (Internet/Corp Network)
                                 β”‚
                                 β”‚ NORTH-SOUTH
                                 β”‚ (Ingress handles this)
                                 β”‚
                    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
                    β”‚    KUBERNETES CLUSTER   β”‚
                    β”‚                         β”‚
                    β”‚    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”     β”‚
                    β”‚    β”‚   Ingress    β”‚     β”‚
                    β”‚    β”‚  Controller  β”‚     β”‚
                    β”‚    β””β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”˜     β”‚
                    β”‚           β”‚             β”‚
                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
                    β”‚  β”‚  Frontend Pod   β”‚    β”‚
                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
                    β”‚           β”‚             β”‚
                    β”‚           β”‚ EAST-WEST   β”‚
                    β”‚           β”‚ (Service Mesh handles this)
                    β”‚           β”‚             β”‚
                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
                    β”‚  β”‚   API Pod       │────┼─► Database Pod
                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
                    β”‚           β”‚             β”‚
                    β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”€β”€β”    β”‚
                    β”‚  β”‚   Auth Pod      │────┼─► Cache Pod
                    β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜    β”‚
                    β”‚                         β”‚
                    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

What Each DoesΒΆ

Ingress/API Gateway (NORTH-SOUTH)ΒΆ

Purpose: Get traffic INTO the cluster

Handles:

βœ… External β†’ Cluster routing
βœ… TLS termination (HTTPS)
βœ… Hostname routing (api.mci.local)
βœ… Path routing (/users, /orders)
βœ… External load balancing
βœ… Public IP exposure

Example Flow:

User Browser (Internet)
    ↓
http://api.mci.local/users
    ↓
LoadBalancer IP (192.168.228.200)
    ↓
Ingress Controller
    ↓
Routes to "api-service"
    ↓
API Pod receives request

Service Mesh (EAST-WEST)ΒΆ

Purpose: Manage traffic BETWEEN pods inside cluster

Handles:

βœ… Pod β†’ Pod communication
βœ… mTLS (encrypted pod-to-pod)
βœ… Service-to-service policies
βœ… Retries, timeouts, circuit breakers
βœ… Traffic splitting (A/B testing)
βœ… Observability between services
βœ… Service discovery

Example Flow:

API Pod wants to call Auth Service
    ↓
Service Mesh intercepts
    ↓
Checks: Is API pod allowed to call Auth?
    ↓
Encrypts with mTLS
    ↓
Load balances across Auth pods
    ↓
Tracks latency, errors
    ↓
Auth Pod receives request

Complete ArchitectureΒΆ

═══════════════════════════════════════════════════════════════════════════
              BOTH INGRESS AND SERVICE MESH TOGETHER
═══════════════════════════════════════════════════════════════════════════

External User
    β”‚
    β”‚ 1. NORTH-SOUTH (Ingress)
    β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Ingress Controller (Cilium Envoy)                             β”‚
β”‚  β€’ TLS termination                                             β”‚
β”‚  β€’ Hostname routing                                            β”‚
β”‚  β€’ External authentication                                     β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
                 β–Ό
            Frontend Pod
                 β”‚
                 β”‚ 2. EAST-WEST (Service Mesh)
                 β”‚    β€’ mTLS encryption
                 β”‚    β€’ L7 policies
                 β”‚    β€’ Retry logic
                 β”‚    β€’ Circuit breaker
                 β–Ό
            API Pod ──────► Auth Pod
                 β”‚              β”‚
                 β”‚              β”‚ 3. EAST-WEST
                 β”‚              β–Ό
                 β”‚         Database Pod
                 β”‚
                 β”‚ 4. EAST-WEST
                 β–Ό
            Payment Pod ───► Kafka Pod
                 β”‚
                 β”‚ 5. EAST-WEST
                 β–Ό
            Notification Pod

Why You Need BothΒΆ

Scenario Without Service Mesh (Only Ingress)ΒΆ

βœ… External traffic reaches cluster
❌ No encryption between pods
❌ No pod-to-pod policies
❌ No retry logic between services
❌ No circuit breakers
❌ Limited observability of internal traffic
❌ No canary deployments

Scenario Without Ingress (Only Service Mesh)ΒΆ

❌ External traffic can't reach cluster
❌ No TLS termination for external clients
❌ No hostname-based routing from outside
βœ… Internal pod-to-pod works great

Cilium's Unique PositionΒΆ

Cilium does BOTH Ingress AND Service Mesh!

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚               CILIUM STACK                 β”‚
β”‚                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Ingress Controller (Cilium Envoy)   β”‚  β”‚
β”‚  β”‚  Handles: NORTH-SOUTH                β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Service Mesh (Cilium + Envoy)       β”‚  β”‚
β”‚  β”‚  Handles: EAST-WEST                  β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Kube-proxy Replacement (eBPF)       β”‚  β”‚
β”‚  β”‚  Handles: Load balancing             β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Network Policies (eBPF + Envoy)     β”‚  β”‚
β”‚  β”‚  Handles: L3/L4/L7 security          β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β”‚                                            β”‚
β”‚  β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”  β”‚
β”‚  β”‚  Observability (Hubble)              β”‚  β”‚
β”‚  β”‚  Handles: All traffic visibility     β”‚  β”‚
β”‚  β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

This is why Cilium is powerful - it's an all-in-one solution.

Feature ComparisonΒΆ

Feature Ingress Only Service Mesh Only Both (Cilium)
External access βœ… ❌ βœ…
TLS termination βœ… ❌ βœ…
Hostname routing βœ… ❌ βœ…
Pod-to-pod mTLS ❌ βœ… βœ…
Retries/timeouts ❌ βœ… βœ…
Circuit breakers ❌ βœ… βœ…
Traffic splitting ❌ βœ… βœ…
L7 observability ⚠️ (edge only) βœ… (internal) βœ… (everywhere)
Network policies ⚠️ (limited) βœ… βœ…

Real-World ExampleΒΆ

E-commerce ApplicationΒΆ

User Request: https://shop.mci.local/checkout
    β”‚
    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ β”‚ INGRESS NEEDED                          β”‚
    β”‚ β”‚ β€’ Accept HTTPS from internet            β”‚
    β”‚ β”‚ β€’ Route /checkout to frontend           β”‚
    β”‚ β”‚ β€’ TLS termination                       β”‚
    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β–Ό
Frontend Pod
    β”‚
    β”‚ Makes API call: POST /api/payment
    β”‚
    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ β”‚ SERVICE MESH NEEDED                     β”‚
    β”‚ β”‚ β€’ Encrypt traffic (mTLS)                β”‚
    β”‚ β”‚ β€’ Retry if payment service down         β”‚
    β”‚ β”‚ β€’ Circuit breaker if failing            β”‚
    β”‚ β”‚ β€’ L7 policy: only POST allowed          β”‚
    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β–Ό
Payment Service Pod
    β”‚
    β”‚ Calls: GET /api/inventory
    β”‚
    β”‚ β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚ β”‚ SERVICE MESH NEEDED                     β”‚
    β”‚ β”‚ β€’ Check authorization                   β”‚
    β”‚ β”‚ β€’ Track latency                         β”‚
    β”‚ β”‚ β€’ Load balance across inventory pods    β”‚
    β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    β–Ό
Inventory Service Pod

You need both:

  • Ingress to get the user's request into the cluster
  • Service Mesh to manage the internal service calls

When You DON'T Need Service MeshΒΆ

Simple applications:

User β†’ Ingress β†’ Single Monolith Pod β†’ Database

If you have:

  • Only 1-3 services
  • No pod-to-pod communication
  • No need for mTLS
  • No complex retry logic
  • Simple architecture

Then skip Service Mesh, just use Ingress.

When You DON'T Need IngressΒΆ

Internal-only cluster:

No external access needed
Pods only talk to each other
All traffic is EAST-WEST

Examples:

  • Data processing cluster (Kafka, Spark)
  • Batch job cluster
  • ML training cluster

Then skip Ingress, just use Service Mesh.

Summary TableΒΆ

Traffic Type Component Purpose Do You Need It?
External β†’ Cluster Ingress Get traffic in βœ… YES (always)
Pod β†’ Pod Service Mesh Manage internal traffic ⚠️ Only if microservices
External APIs API Gateway Advanced API features ❌ Not for internal tools

Bottom LineΒΆ

Service Mesh β‰  Replacement for Ingress

They're complementary:

  • Ingress = Front door to your cluster
  • Service Mesh = Internal traffic management

For MCI:

  • βœ… Use Cilium Ingress (you need external access)
  • ⚠️ Service Mesh features later (if you build microservices)
  • ❌ Skip API Gateway (internal tools don't need it)