Service mesh see history edit this page

Talks about: , , , , and

The Helm chart ships an opt-in service-mesh authorization layer for the controller pod. It is off by default and renders only when serviceMesh.enabled is true. Where the network policy operates at L3/L4 — which pods and IP ranges may reach which ports — the service mesh operates at L7 with identity-based authorization and mTLS: it asks which mesh identity is calling, proven by a cryptographic workload certificate, not merely which IP the packet came from.

serviceMesh and networkPolicy are separate fields and compose additively. They solve different problems and are best enabled together: the network policy draws the L3/L4 perimeter, and the mesh authorizes meshed callers by SPIFFE identity on top of it. Enabling one does not require the other, and neither weakens the other.

Opt-in and explicit engine

serviceMesh.engine selects which mesh dialect the chart renders. It is explicit, not auto-detected: a chart that sniffed the running mesh would render different objects on different clusters from identical values, which breaks GitOps determinism. You name the engine, and the rendered manifest is the same everywhere.

engineRendersAPI
istio (default)AuthorizationPolicy + (optional) PeerAuthenticationsecurity.istio.io/v1
linkerdServer + AuthorizationPolicy + MeshTLSAuthenticationpolicy.linkerd.io

The rendered objects are inert unless the named mesh is actually installed and the controller pod is injected into it. Enabling serviceMesh on an un-meshed pod renders the manifests but changes nothing about how traffic flows.

serviceMesh:
  enabled: true
  engine: istio

Per-port authorization

Each mesh-reachable port carries a from list naming the mesh identities allowed to call it. An empty from list leaves that port open to any meshed caller, mirroring networkPolicy’s empty-from-is-open semantics; a non-empty list restricts the port to the listed identities.

The mesh-reachable ports are the stage-gate port and the metrics port:

PortModefrom restricts
Gate (ports.gate, 8082)gateFlagger polling the read-only stage-gate endpoint
Metrics (ports.metrics, 8080)alwaysPrometheus scraping /metrics

A from entry is a source matcher with two fields:

serviceMesh:
  enabled: true
  engine: istio
  # Restrict the gate to Flagger's identity.
  gate:
    from:
      - principals:
          - cluster.local/ns/flagger-system/sa/flagger
  # Scope metrics scraping to the monitoring namespace.
  metrics:
    from:
      - namespaces:
          - monitoring

Non-mesh clients keep working

The kube-apiserver (which dials the admission webhook) and the kubelet (which dials the readiness and liveness probes) are not part of the mesh. They carry no mesh identity and present no workload certificate, so any authorization rule that demanded one would reject them — admission would break and probes would fail.

The chart deliberately leaves the webhook and health probe ports open so these non-mesh clients always connect:

This is why admission and probes keep working with the mesh fully enabled. Authenticity on the webhook port is enforced by TLS and the CA bundle on the ValidatingWebhookConfiguration, not by the mesh — see the admission webhook page.

mTLS

serviceMesh.mtls sets the mTLS posture and applies to the Istio engine only; Linkerd negotiates mTLS automatically between meshed pods, so the knob is ignored there.

mtlsEffect (Istio)
"" (default)Defers to the mesh’s own default (mesh-wide PeerAuthentication / MeshConfig) — no PeerAuthentication is rendered
permissiveRenders a PeerAuthentication accepting both mTLS and plaintext
strictRequires mTLS on the workload’s ports, except the webhook and health ports, which get a port-level PERMISSIVE carve-out
serviceMesh:
  enabled: true
  engine: istio
  mtls: strict

Under strict, every mesh-reachable port enforces mTLS while the apiserver and kubelet still reach the webhook and probes over plaintext via the carve-out above.

Default-deny

serviceMesh.defaultDeny.enabled (default false) additionally renders a namespace-wide default-deny so every pod in the install namespace rejects unauthorized mesh traffic and the per-workload allows become the only exceptions (a zero-trust namespace).

Enable this only when the controller owns its namespace, because the deny-all also denies every co-located workload that does not have its own allowing authorization.

serviceMesh:
  enabled: true
  engine: istio
  defaultDeny:
    enabled: true   # only when the controller owns this namespace

Native passthrough

Anything the per-port from knobs cannot express goes into the engine’s native passthrough list, merged verbatim into the rendered objects.

Under the istio engine, serviceMesh.istio.rules are merged into the AuthorizationPolicy’s spec.rules (the security.istio.io/v1 rule schema) — use it for path/method matchers, when JWT-claim conditions, ipBlocks, and similar:

serviceMesh:
  enabled: true
  engine: istio
  istio:
    rules:
      - from:
          - source:
              namespaces:
                - flagger-system
        to:
          - operation:
              methods:
                - GET
              paths:
                - /gate/*

Under the linkerd engine, serviceMesh.linkerd.authorizations are appended verbatim as additional documents after the rendered Server / AuthorizationPolicy / MeshTLSAuthentication set — each entry must be a complete policy.linkerd.io object:

serviceMesh:
  enabled: true
  engine: linkerd
  linkerd:
    authorizations:
      - apiVersion: policy.linkerd.io/v1beta3
        kind: AuthorizationPolicy
        metadata:
          name: stageset-extra
        spec:
          targetRef:
            group: policy.linkerd.io
            kind: Server
            name: stageset-gate
          requiredAuthenticationRefs:
            - kind: ServiceAccount
              name: flagger
              namespace: flagger-system

Which traffic gets authorized

The mesh authorizes only meshed callers on the mesh-reachable ports; the non-mesh ports stay open by design so the control plane keeps working.

PortAuthorized by the mesh?Why
Gate (8082)Yes — serviceMesh.gate.fromMeshed Flagger polling the stage gate
Metrics (8080)Yes — serviceMesh.metrics.fromMeshed Prometheus scrapers
Webhook (9443)No — open carve-outThe kube-apiserver is not in the mesh
Health probes (8081)No — open carve-outThe kubelet is not in the mesh

For the full set of chart values, see Helm chart values.