A service mesh can secure inter-service communication without injecting sidecar proxies into every pod.

Let’s see this in action. Imagine two services, frontend and backend, running in Kubernetes. We want frontend to securely call backend using mutual TLS (mTLS), and backend to only accept connections from frontend.

Here’s the setup. We’ll use Cilium, a powerful CNI plugin that leverages eBPF, to manage this.

First, we need a Kubernetes cluster with Cilium installed. Ensure Cilium is configured to manage network policies and has mTLS enabled. This usually involves a Helm chart installation with specific values.

# values.yaml for Cilium Helm installation
enable-cilium- தள-cert-manager: "true"
enable-mtls: "true"
# other standard Cilium configurations...

Next, we deploy our services.

# frontend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: frontend
  template:
    metadata:
      labels:
        app: frontend
    spec:
      containers:
      - name: frontend
        image: your-frontend-image # Replace with your actual frontend image
        ports:
        - containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  selector:
    app: frontend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
---
# backend.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 1
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
      - name: backend
        image: your-backend-image # Replace with your actual backend image
        ports:
        - containerPort: 8081
---
apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  selector:
    app: backend
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8081

Now, the crucial part: configuring the mTLS policy. We’ll use CiliumNetworkPolicy to define this.

# mtlspolicy.yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: backend-mtls-policy
spec:
  endpointSelector:
    matchLabels:
      app: backend # This policy applies to pods labeled 'app: backend'
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend # Allow ingress only from pods labeled 'app: frontend'
    toPorts:
    - ports:
      - port: "80" # The service port for backend
        protocol: TCP
      # This section enables mTLS for the ingress traffic
      tls:
        mutual:
          internal: true # Use internal CA managed by Cilium

When Cilium is enabled for mTLS and the தள-cert-manager (Cilium’s certificate manager) is active, it automatically provisions certificates for your services. For frontend to call backend securely, frontend will automatically be given a client certificate signed by the internal CA. backend, when it receives a connection, will present its server certificate. The mutual: true in the policy tells Cilium to enforce that the incoming connection must present a valid client certificate signed by the same internal CA.

The magic happens at the eBPF level on each node. Cilium injects eBPF programs that intercept network traffic. For mTLS, these programs handle TLS handshake, certificate validation, and encryption/decryption without any application-level changes or separate proxy processes. The frontend application simply makes a standard HTTP request to the backend service’s ClusterIP. Cilium intercepts this request, performs the mTLS handshake with the backend (which is also managed by Cilium’s eBPF), and then forwards the decrypted, authenticated traffic to the backend pod. For outbound traffic from frontend, if it’s destined for backend and mTLS is required, Cilium also handles the client certificate presentation.

The most surprising thing is that your application code doesn’t need to know anything about certificates or TLS. It just makes a regular TCP connection to the Kubernetes Service IP. Cilium’s eBPF programs on the node intercept this, perform the TLS handshake using automatically generated certificates, validate the client certificate, and then forward the plaintext traffic to the application container. For outbound requests from frontend to backend, Cilium intercepts the outgoing connection, establishes a TLS connection with backend using frontend’s automatically provisioned client certificate, and then passes the decrypted data to the frontend application.

This means you can secure your entire cluster with mTLS by simply applying CiliumNetworkPolicies, without modifying your application code or deploying sidecar containers. The overhead is significantly lower than traditional sidecar-based service meshes because the logic is embedded directly into the kernel via eBPF.

The next step is to explore how to integrate external CAs or manage certificate rotation beyond the internal CA.

Want structured learning?

Take the full Cilium course →