Service Mesh Integration

Sentinel integrates with service mesh environments through dynamic service discovery and mTLS support. While not a service mesh itself, Sentinel can serve as an ingress gateway or edge proxy in mesh deployments.

Integration Patterns

┌─────────────────────────────────────────────────────────────────────┐
│                    SERVICE MESH INTEGRATION                          │
├─────────────────────────────────────────────────────────────────────┤
│                                                                      │
│  Pattern 1: Ingress Gateway                                          │
│  ┌──────────┐      ┌──────────┐      ┌──────────┐                   │
│  │ Internet │─────▶│ Sentinel │─────▶│ Mesh     │                   │
│  │          │      │ (edge)   │      │ Services │                   │
│  └──────────┘      └──────────┘      └──────────┘                   │
│                          │                                           │
│                    Service Discovery                                 │
│                    (DNS/Consul/K8s)                                  │
│                                                                      │
│  Pattern 2: Sidecar-Adjacent                                         │
│  ┌──────────┐      ┌──────────────────────────┐                     │
│  │ Internet │─────▶│ Pod                       │                     │
│  │          │      │ ┌────────┐  ┌──────────┐ │                     │
│  └──────────┘      │ │Sentinel│─▶│ Sidecar  │ │                     │
│                    │ │        │  │(Envoy/   │ │                     │
│                    │ └────────┘  │ Linkerd) │ │                     │
│                    └─────────────┴──────────┴─┘                     │
│                                                                      │
└─────────────────────────────────────────────────────────────────────┘

Service Discovery Methods

Sentinel supports multiple discovery backends that integrate with service mesh control planes:

MethodMesh CompatibilityUse Case
DNSAll (Istio, Linkerd, Consul)Simple, universal
ConsulConsul ConnectNative Consul integration
KubernetesIstio, LinkerdK8s-native endpoint discovery

DNS Discovery

Works with any service mesh that provides DNS-based service discovery (all major meshes do).

upstream "api-service" {
    discovery "dns" {
        hostname "api.default.svc.cluster.local"
        port 8080
        refresh-interval 30
    }
}

Mesh DNS patterns:

MeshDNS Format
Kubernetes<service>.<namespace>.svc.cluster.local
Consul<service>.service.consul
IstioStandard K8s DNS (with VirtualService routing)
LinkerdStandard K8s DNS

Consul Discovery

Native integration with Consul’s service catalog and health checking.

system {
    worker-threads 0
}

listeners {
    listener "http" {
        address "0.0.0.0:8080"
        protocol "http"
    }
}

upstream "backend" {
    discovery "consul" {
        address "http://consul.service.consul:8500"
        service "backend-api"
        datacenter "dc1"
        only-passing #true
        tag "production"
        refresh-interval 10
    }
}

routes {
    route "default" {
        matches { path-prefix "/" }
        upstream "backend"
    }
}

upstreams {
    upstream "backend" {
        targets {
            target { address "127.0.0.1:3000" }
        }
    }
}

OptionDefaultDescription
addressRequiredConsul HTTP API address
serviceRequiredService name in catalog
datacenterNoneTarget datacenter
only-passingtrueOnly healthy instances
tagNoneFilter by service tag
refresh-interval10Seconds between refreshes

Consul Connect Integration

When using Consul Connect (service mesh), Sentinel can discover services but connects directly (not through Connect proxies). For full Connect mTLS:

system {
    worker-threads 0
}

listeners {
    listener "http" {
            tls {
                // Use Consul-provisioned certificates
                client-cert "/etc/consul/certs/client.crt"
                client-key "/etc/consul/certs/client.key"
                ca-cert "/etc/consul/certs/ca.crt"
            }
        address "0.0.0.0:8080"
        protocol "http"
    }
}

upstream "secure-backend" {
    discovery "consul" {
        address "http://consul:8500"
        service "backend"
        only-passing #true
    }

}

routes {
    route "default" {
        matches { path-prefix "/" }
        upstream "backend"
    }
}

upstreams {
    upstream "backend" {
        targets {
            target { address "127.0.0.1:3000" }
        }
    }
}

Kubernetes Endpoint Discovery

Direct integration with Kubernetes Endpoints API for real-time pod discovery.

upstream "k8s-backend" {
    discovery "kubernetes" {
        namespace "production"
        service "api-server"
        port-name "http"
        refresh-interval 10
    }
}

Authentication Methods

In-cluster (recommended for K8s deployments):

upstream "backend" {
    discovery "kubernetes" {
        namespace "default"
        service "my-service"
        // Uses service account token automatically
    }
}

Kubeconfig file (for external access):

upstream "backend" {
    discovery "kubernetes" {
        namespace "production"
        service "api"
        kubeconfig "~/.kube/config"
    }
}
Auth MethodSourceUse Case
Service AccountIn-cluster tokenPods running in K8s
KubeconfigFile on diskExternal access, dev
TokenBearer token in kubeconfigCI/CD pipelines
Client CertmTLS in kubeconfigHigh security
ExecExternal command (e.g., aws eks)Cloud provider auth

Istio Integration

Sentinel works alongside Istio as an ingress gateway or within the mesh.

As Istio Ingress Gateway

Deploy Sentinel outside the mesh to handle external traffic:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sentinel-gateway
  namespace: istio-system
spec:
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "false"  # No Istio sidecar
    spec:
      containers:
      - name: sentinel
        image: ghcr.io/raskell-io/sentinel:latest

Configure Sentinel to discover Istio services:

upstream "frontend" {
    discovery "kubernetes" {
        namespace "default"
        service "frontend"
        port-name "http"
    }
    // Connect directly to pods, bypassing Istio sidecar
}

Within Istio Mesh

Deploy Sentinel with Istio sidecar injection:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sentinel
spec:
  template:
    metadata:
      annotations:
        sidecar.istio.io/inject: "true"
    spec:
      containers:
      - name: sentinel
        # Traffic flows through Envoy sidecar

In this mode, Sentinel routes to localhost and Istio handles service discovery:

upstream "backend" {
    targets {
        target { address "127.0.0.1:15001" }  // Istio outbound
    }
    // Istio sidecar handles discovery and mTLS
}

Linkerd Integration

Linkerd uses a transparent proxy model. Sentinel works naturally within Linkerd-meshed namespaces.

Meshed Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sentinel
  annotations:
    linkerd.io/inject: enabled
spec:
  template:
    spec:
      containers:
      - name: sentinel

Sentinel discovers services normally; Linkerd handles mTLS:

upstream "api" {
    discovery "kubernetes" {
        namespace "default"
        service "api"
        port-name "http"
    }
    // Linkerd proxy handles connection security
}

Unmeshed (Ingress) Deployment

For ingress, deploy without Linkerd injection:

metadata:
  annotations:
    linkerd.io/inject: disabled

Use Kubernetes discovery to find meshed services:

upstream "meshed-service" {
    discovery "kubernetes" {
        namespace "production"
        service "api"
    }
    // Direct connection to pod IPs
}

mTLS Configuration

For direct mTLS (without mesh sidecar), configure upstream TLS:

upstream "secure-backend" {
    discovery "kubernetes" {
        namespace "production"
        service "secure-api"
    }
    tls {
        sni "secure-api.production.svc.cluster.local"
        client-cert "/etc/sentinel/certs/client.crt"
        client-key "/etc/sentinel/certs/client.key"
        ca-cert "/etc/sentinel/certs/ca.crt"
    }
}

Certificate Sources

SourceConfiguration
Kubernetes SecretMount as volume
Consul PKIUse Consul CA endpoints
cert-managerAutomatic certificate provisioning
VaultDynamic secrets

Example with cert-manager:

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: sentinel-client-cert
spec:
  secretName: sentinel-client-tls
  issuerRef:
    name: mesh-ca
    kind: ClusterIssuer
  dnsNames:
  - sentinel.default.svc.cluster.local
---
apiVersion: apps/v1
kind: Deployment
spec:
  template:
    spec:
      volumes:
      - name: client-certs
        secret:
          secretName: sentinel-client-tls
      containers:
      - name: sentinel
        volumeMounts:
        - name: client-certs
          mountPath: /etc/sentinel/certs

Health Checks

Configure health checks that work with mesh health reporting:

upstream "backend" {
    discovery "kubernetes" {
        namespace "default"
        service "api"
    }
    health-check {
        type "http" {
            path "/health"
            expected-status 200
        }
        interval-secs 10
        unhealthy-threshold 3
    }
}

Sentinel health checks run independently of mesh health checks, providing defense in depth.

Load Balancing

Sentinel performs client-side load balancing across discovered endpoints:

upstream "api" {
    discovery "kubernetes" {
        namespace "default"
        service "api"
    }
    load-balancing "least_connections"
}
AlgorithmMesh Compatibility
round_robinAll
least_connectionsAll
consistent_hashAll (good for caching)
randomAll
power_of_two_choicesAll

Note: When running inside a mesh with sidecar, the sidecar may also perform load balancing. Consider using round_robin in Sentinel to avoid double load balancing.

Observability

Sentinel exposes metrics compatible with mesh observability:

observability {
    metrics {
        enabled #true
        endpoint "/metrics"
    }
}

Key Metrics for Mesh Deployments

MetricDescription
sentinel_upstream_healthy_backendsHealthy endpoints per upstream
sentinel_upstream_attempts_totalConnection attempts
sentinel_upstream_failures_totalFailed connections by reason
sentinel_requests_totalRequest count by route/status

Integrate with mesh observability:

  • Prometheus: Scrape /metrics endpoint
  • Jaeger/Tempo: Configure OpenTelemetry export
  • Grafana: Use provided dashboard template

Limitations

Current service mesh integration limitations:

FeatureStatusNotes
xDS API (Envoy config)Not supportedNo Istio control plane integration
Automatic mTLS rotationManualUse cert-manager or Vault
Traffic policies from meshNot supportedConfigure in Sentinel directly
SPIFFE identityNot supportedUse standard X.509 certs
Canary/subset routingManualConfigure via route weights

Workarounds

For automatic mTLS rotation:

  • Use cert-manager with short-lived certificates
  • Mount certificates from Kubernetes secrets
  • Use SIGHUP to reload certificates

For traffic policies:

  • Configure timeouts, retries, and circuit breakers in Sentinel
  • Use Sentinel’s rate limiting instead of mesh rate limiting

Complete Example

Full Kubernetes deployment with Consul discovery:

apiVersion: v1
kind: ConfigMap
metadata:
  name: sentinel-config
data:
  sentinel.kdl: |
    listener "http" {
        address "0.0.0.0:8080"
    }

    upstream "api" {
        discovery "consul" {
            address "http://consul.consul:8500"
            service "api"
            only-passing true
            refresh-interval 10
        }
        health-check {
            type "http" { path "/health" }
            interval-secs 10
        }
        load-balancing "least_connections"
    }

    routes {
        route "api" {
            matches { path-prefix "/api/" }
            upstream "api"
        }
    }
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: sentinel
spec:
  replicas: 2
  selector:
    matchLabels:
      app: sentinel
  template:
    metadata:
      labels:
        app: sentinel
    spec:
      containers:
      - name: sentinel
        image: ghcr.io/raskell-io/sentinel:latest
        ports:
        - containerPort: 8080
        volumeMounts:
        - name: config
          mountPath: /etc/sentinel
        readinessProbe:
          httpGet:
            path: /_/health
            port: 8080
      volumes:
      - name: config
        configMap:
          name: sentinel-config
---
apiVersion: v1
kind: Service
metadata:
  name: sentinel
spec:
  ports:
  - port: 80
    targetPort: 8080
  selector:
    app: sentinel

Next Steps