Skip to content

Service Mesh

Problem Statement

"I need to secure service-to-service communication with mTLS and enforce authorization policies, but I do not want the resource overhead and operational complexity of Istio or Linkerd sidecars."

Traditional service mesh solutions inject a sidecar proxy container into every pod. This doubles memory and CPU consumption per pod, complicates debugging, and introduces latency from the extra network hop. NovaEdge replaces sidecars with a transparent proxy (TPROXY) running on the node agent DaemonSet, so there is zero per-pod overhead.


Architecture

graph LR
    subgraph Node_A["Node A"]
        direction TB
        SA["Service A Pod"]
        IPTABLES_A["iptables<br/>NOVAEDGE_MESH chain"]
        AGENT_A["NovaEdge Agent<br/>TPROXY :15001<br/>mTLS Tunnel :15002"]
        style SA fill:#FFE4B5,stroke:#333
        style IPTABLES_A fill:#fff,stroke:#999,stroke-dasharray: 5 5
        style AGENT_A fill:#90EE90,stroke:#333
    end

    subgraph Node_B["Node B"]
        direction TB
        AGENT_B["NovaEdge Agent<br/>TPROXY :15001<br/>mTLS Tunnel :15002"]
        IPTABLES_B["iptables<br/>NOVAEDGE_MESH chain"]
        SB["Service B Pod"]
        style SB fill:#FFE4B5,stroke:#333
        style IPTABLES_B fill:#fff,stroke:#999,stroke-dasharray: 5 5
        style AGENT_B fill:#90EE90,stroke:#333
    end

    subgraph Mesh_CA["Mesh CA (Controller)"]
        CA["Embedded CA<br/>ECDSA P-256<br/>SPIFFE Identity"]
        style CA fill:#90EE90,stroke:#333
    end

    SA -- "ClusterIP traffic" --> IPTABLES_A
    IPTABLES_A -- "redirect :15001" --> AGENT_A
    AGENT_A -- "HTTP/2 mTLS tunnel<br/>:15002" --> AGENT_B
    AGENT_B --> IPTABLES_B
    IPTABLES_B --> SB

    CA -. "issue/rotate certs<br/>24h lifetime" .-> AGENT_A
    CA -. "issue/rotate certs<br/>24h lifetime" .-> AGENT_B

How It Works

  1. TPROXY Interception -- The NovaEdge agent on each node creates an iptables chain called NOVAEDGE_MESH. This chain intercepts outbound ClusterIP traffic from mesh-enabled pods and redirects it to the agent's transparent proxy listener on port 15001.

  2. mTLS Tunnel -- The agent on the source node establishes an HTTP/2 mTLS tunnel (port 15002) to the agent on the destination node. Both endpoints authenticate using SPIFFE-format X.509 certificates.

  3. SPIFFE Identity -- Every agent receives a SPIFFE identity in the format spiffe://cluster.local/agent/<node-name>. The embedded mesh CA in the controller issues ECDSA P-256 certificates with a 24-hour lifetime. Certificates are automatically renewed at 80% of their lifetime (roughly every 19 hours).

  4. Authorization Engine -- The MeshAuthorization policy type lets you define which source identities (by namespace, service account, or SPIFFE ID) are allowed to reach which destinations (by HTTP method and path).


Step 1: Enable Mesh on a Service

Add the novaedge.io/mesh: "enabled" annotation to your Service or Deployment. The NovaEdge agent will automatically set up TPROXY interception for pods backing this service.

apiVersion: v1
kind: Service
metadata:
  name: backend-api
  namespace: production
  annotations:
    novaedge.io/mesh: "enabled"
spec:
  selector:
    app: backend-api
  ports:
    - name: http
      port: 8080
      targetPort: 8080
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend-api
  namespace: production
  annotations:
    novaedge.io/mesh: "enabled"
spec:
  replicas: 3
  selector:
    matchLabels:
      app: backend-api
  template:
    metadata:
      labels:
        app: backend-api
      annotations:
        novaedge.io/mesh: "enabled"
    spec:
      containers:
        - name: backend-api
          image: myregistry/backend-api:v2.1.0
          ports:
            - containerPort: 8080

No sidecar injection occurs. The NovaEdge agent DaemonSet (already running on every node) detects the annotation and configures TPROXY rules for matching pods.


Step 2: Verify TPROXY Interception

Once the annotation is applied, the agent creates iptables rules in the NOVAEDGE_MESH chain. You can verify this on any node where a mesh-enabled pod is scheduled:

# Check iptables rules on a specific node (requires privileged access)
kubectl debug node/<node-name> -it --image=busybox -- \
  nsenter -t 1 -m -u -i -n -p -- iptables -t mangle -L NOVAEDGE_MESH -v -n

Expected output shows rules redirecting ClusterIP-destined traffic to port 15001:

Chain NOVAEDGE_MESH (1 references)
 pkts bytes target     prot opt in     out     source       destination
  142  8520 TPROXY     tcp  --  *      *       0.0.0.0/0    10.96.0.0/12      TPROXY redirect 0.0.0.0:15001 mark 0x1/0x1

Step 3: Verify Certificate Issuance

The controller's embedded mesh CA automatically issues SPIFFE certificates to every agent. Verify that certificates are active:

# Check agent logs for certificate issuance
kubectl logs -n novaedge-system daemonset/novaedge-agent | grep -i "mesh cert"

Expected log entries:

{"level":"info","msg":"mesh certificate issued","spiffe_id":"spiffe://cluster.local/agent/node-1","not_after":"2026-02-16T14:30:00Z","key_type":"ECDSA P-256"}
{"level":"info","msg":"mesh certificate renewal scheduled","renew_at":"2026-02-16T09:42:00Z"}
# Verify the SPIFFE identity on a specific agent
kubectl exec -n novaedge-system daemonset/novaedge-agent -- \
  novaedge-agent mesh status

Step 4: Define Mesh Authorization Policies

Use the MeshAuthorization policy type to control which services can communicate.

Allow Specific Namespaces

Allow only pods in the frontend namespace to reach the backend-api service:

apiVersion: novaedge.io/v1alpha1
kind: ProxyPolicy
metadata:
  name: backend-api-allow-frontend
  namespace: production
spec:
  type: MeshAuthorization
  targetRef:
    kind: Service
    name: backend-api
  meshAuthorization:
    action: ALLOW
    rules:
      - from:
          - namespaces:
              - frontend

Allow by Service Account

Allow only pods running under the order-processor service account to call the payment-service:

apiVersion: novaedge.io/v1alpha1
kind: ProxyPolicy
metadata:
  name: payment-allow-orders
  namespace: production
spec:
  type: MeshAuthorization
  targetRef:
    kind: Service
    name: payment-service
  meshAuthorization:
    action: ALLOW
    rules:
      - from:
          - serviceAccounts:
              - order-processor
        to:
          - methods:
              - POST
            paths:
              - /api/v1/charges
              - /api/v1/refunds

Deny by SPIFFE ID Pattern

Block a specific agent node from reaching a sensitive service:

apiVersion: novaedge.io/v1alpha1
kind: ProxyPolicy
metadata:
  name: deny-untrusted-node
  namespace: production
spec:
  type: MeshAuthorization
  targetRef:
    kind: Service
    name: secrets-vault
  meshAuthorization:
    action: DENY
    rules:
      - from:
          - spiffeIds:
              - "spiffe://cluster.local/agent/untrusted-*"

Combined Authorization: Namespace + Path Restriction

Allow the monitoring namespace to access only the /healthz and /metrics endpoints:

apiVersion: novaedge.io/v1alpha1
kind: ProxyPolicy
metadata:
  name: backend-api-monitoring-readonly
  namespace: production
spec:
  type: MeshAuthorization
  targetRef:
    kind: Service
    name: backend-api
  meshAuthorization:
    action: ALLOW
    rules:
      - from:
          - namespaces:
              - monitoring
        to:
          - methods:
              - GET
            paths:
              - /healthz
              - /metrics

Step 5: Verify Mesh Communication

Check mTLS Tunnel Status

# List active mesh tunnels on an agent
kubectl exec -n novaedge-system daemonset/novaedge-agent -- \
  novaedge-agent mesh tunnels

Verify End-to-End Connectivity

Deploy a test pod and confirm that traffic flows through the mesh:

# From a mesh-enabled pod, curl a mesh-enabled service
kubectl exec -n frontend deploy/web-frontend -- \
  curl -s -o /dev/null -w "%{http_code}" http://backend-api.production.svc.cluster.local:8080/healthz

Expected output: 200

Check Authorization Policy Enforcement

Attempt an unauthorized call and verify it is denied:

# From a non-allowed namespace, try to reach the backend
kubectl exec -n unauthorized-ns deploy/rogue-client -- \
  curl -s -o /dev/null -w "%{http_code}" http://backend-api.production.svc.cluster.local:8080/api

Expected output: 403

Inspect Mesh Metrics

# Check mesh-specific Prometheus metrics
kubectl exec -n novaedge-system daemonset/novaedge-agent -- \
  curl -s localhost:9090/metrics | grep novaedge_mesh

Key metrics:

Metric Description
novaedge_mesh_connections_active Active mTLS tunnel connections
novaedge_mesh_requests_total Total mesh-intercepted requests
novaedge_mesh_auth_denied_total Requests denied by MeshAuthorization
novaedge_mesh_cert_expiry_seconds Seconds until mesh certificate expiry
novaedge_mesh_cert_renewals_total Certificate renewal count

How NovaEdge Mesh Compares to Sidecars

Aspect Sidecar Mesh (Istio/Linkerd) NovaEdge TPROXY Mesh
Per-pod overhead ~50-100 MB RAM per sidecar Zero (runs on DaemonSet)
Injection mechanism Mutating webhook adds container iptables TPROXY on node
Certificate management Per-pod identity certs Per-node SPIFFE certs
Network hops Pod -> Sidecar -> Network -> Sidecar -> Pod Pod -> Agent (TPROXY) -> Agent -> Pod
Deployment complexity CRDs + webhook + control plane Already part of NovaEdge agent
mTLS protocol HTTP/2 (Envoy) HTTP/2 mTLS tunnel (:15002)