Careful!

You are browsing documentation for the next version of Kuma. Use this version at your own risk.

MeshService

MeshService represents a destination for traffic within the mesh. It defines which data plane proxies serve traffic for a service, exposes ports, and tracks health status. Think of it as the Kuma equivalent of a Kubernetes Service.

Kuma automatically generates MeshService resources:

  • Kubernetes: From Service resources, reusing ClusterIPs and DNS names
  • Universal: From Dataplane inbounds with kuma.io/service tags

For concepts, migration guidance, and usage patterns, see the MeshService guide.

Spec fields

Field Description
selector Defines which data plane proxies belong to this service. Use either dataplaneTags or dataplaneRef.
selector.dataplaneTags Match proxies by tags on their inbounds. All specified tags must match.
selector.dataplaneRef.name Match a specific proxy by name. Used for headless services.
ports List of ports exposed by this service.
ports[].port Service port number (required).
ports[].targetPort Port on the data plane proxy. Can be a number or inbound name. Defaults to port value.
ports[].name Optional port name for referencing in policies via sectionName.
ports[].appProtocol Protocol hint: tcp (default), http, http2, grpc.
identities Service identities (auto-populated). Contains ServiceTag or SpiffeID entries.
state Service availability: Available (healthy endpoints exist) or Unavailable.

Examples

Basic MeshService

apiVersion: kuma.io/v1alpha1
kind: MeshService
metadata:
  name: redis
  namespace: kuma-demo
  labels:
    kuma.io/mesh: default
spec:
  selector:
    dataplaneTags:
      app: redis
      k8s.kuma.io/namespace: kuma-demo
  ports:
    - port: 6379
      targetPort: 6379
      appProtocol: tcp

MeshService with multiple ports

apiVersion: kuma.io/v1alpha1
kind: MeshService
metadata:
  name: backend
  namespace: app
  labels:
    kuma.io/mesh: default
spec:
  selector:
    dataplaneTags:
      app: backend
      k8s.kuma.io/namespace: app
  ports:
    - name: http
      port: 80
      targetPort: 8080
      appProtocol: http
    - name: grpc
      port: 9000
      targetPort: 9000
      appProtocol: grpc
    - name: metrics
      port: 9090
      targetPort: 9090
      appProtocol: http

MeshService with named targetPort

Reference inbound ports by name instead of number:

apiVersion: kuma.io/v1alpha1
kind: MeshService
metadata:
  name: api
  namespace: app
  labels:
    kuma.io/mesh: default
spec:
  selector:
    dataplaneTags:
      app: api
      k8s.kuma.io/namespace: app
  ports:
    - name: main
      port: 80
      targetPort: http-port  # references inbound name
      appProtocol: http

MeshService for headless service (single pod)

Use dataplaneRef to target a specific proxy instance:

apiVersion: kuma.io/v1alpha1
kind: MeshService
metadata:
  name: postgres-0
  namespace: database
  labels:
    kuma.io/mesh: default
    k8s.kuma.io/is-headless-service: "true"
spec:
  selector:
    dataplaneRef:
      name: postgres-0  # specific pod name
  ports:
    - port: 5432
      targetPort: 5432
      appProtocol: tcp

MeshService with custom labels

Add labels for policy targeting and organization:

apiVersion: kuma.io/v1alpha1
kind: MeshService
metadata:
  name: payment-service
  namespace: payments
  labels:
    kuma.io/mesh: default
    team: payments
    tier: backend
    pci-compliant: "true"
spec:
  selector:
    dataplaneTags:
      app: payment-service
      k8s.kuma.io/namespace: payments
  ports:
    - port: 443
      targetPort: 8443
      appProtocol: http2

Label propagation

In Universal zones, non-reserved Dataplane inbound tags and Dataplane resource labels are propagated into the generated MeshService’s metadata.labels. This lets you select generated MeshServices (for example with MeshMultiZoneService) by custom labels such as team or version without patching each MeshService manually. It does not apply to Kubernetes zones, where MeshServices are generated from Services.

For example, a Dataplane carrying a custom team label:

type: Dataplane
mesh: default
name: backend-1
labels:
  team: payments
networking:
  address: 10.0.0.1
  inbound:
  - port: 80
    tags:
      kuma.io/service: backend

produces a generated MeshService that carries the same label:

type: MeshService
name: backend
mesh: default
labels:
  team: payments
spec:
  selector:
    dataplaneTags:
      kuma.io/service: backend

This is opt-in. Enable it via the control plane configuration:

experimental:
  meshServiceLabelPropagation:
    enabled: true
    allowedLabelKeys: []  # empty = propagate all non-reserved keys

Rules:

  • kuma.io/* and k8s.kuma.io/* keys are never propagated. The generator writes system labels (kuma.io/mesh, kuma.io/zone, kuma.io/origin, kuma.io/managed-by, kuma.io/display-name, kuma.io/env) itself, and Dataplane tags or labels cannot override them.
  • allowedLabelKeys restricts propagation to an explicit set of keys. When empty, all non-reserved keys are propagated.
  • Keys and values must be valid Kubernetes label keys and values (63-character limit, restricted character set). Invalid entries are skipped and logged. They do not fail Dataplane validation.
  • Label removal propagates: removing a tag or label from the backing Dataplanes removes it from the generated MeshService. Removal only takes effect once the last Dataplane carrying the value is gone.

Conflict resolution

When the Dataplanes backing one MeshService disagree on the value of a non-reserved key:

  • Within a single Dataplane (its inbounds disagree on a tag): the generator drops the key, logs a warning, and increments component_meshservice_generator_dropped_labels_total. Disagreement between inbounds on the same Dataplane is a configuration error.
  • Across different Dataplanes: per-key majority wins.
  • Ties: the newest Dataplane wins by creation time. On identical timestamps, the lexicographically smallest value wins.

With only two backing Dataplanes, every key conflict is a tie, so the propagated value tracks whichever Dataplane was created most recently and can flip when a Dataplane is replaced. During a rolling deploy the value switches at the ~50% crossover point. If you use these labels as MeshMultiZoneService selectors, update the selectors in lockstep, or give workloads that must be routed separately distinct kuma.io/service values so they generate separate MeshServices.

Targeting MeshService in policies

In policy targetRef

Target a specific port using sectionName:

spec:
  to:
    - targetRef:
        kind: MeshService
        name: backend
        namespace: app      # Kubernetes only
        sectionName: http   # port name

In route backendRefs

Direct traffic to a MeshService:

spec:
  to:
    - targetRef:
        kind: MeshService
        name: frontend
        namespace: app
      rules:
        - default:
            backendRefs:
              - kind: MeshService
                name: backend
                namespace: app
                port: 80

Using labels for cross-zone targeting

Select MeshServices across zones:

spec:
  to:
    - targetRef:
        kind: MeshService
        labels:
          kuma.io/display-name: backend
          kuma.io/zone: east

Naming constraints

MeshService names must:

  • Be 63 characters or fewer
  • Conform to DNS-1035 (lowercase alphanumeric, hyphens allowed, cannot start/end with hyphen)

See also

All options

apiVersion string
APIVersion defines the versioned schema of this representation of an object. Servers should convert ...
kind string
Kind is a string value representing the REST resource this object represents. Servers may infer this...
metadata object
spec object
Spec is the specification of the Kuma MeshService resource.
type enum required
Values: ServiceTag | SpiffeID
value string required
appProtocol string
Protocol identifies a protocol supported by a service.
Default: "tcp"
name string
port integer required
targetPort any
matchLabels object
name string
dataplaneTags object
state enum
State of MeshService. Available if there is at least one healthy endpoint. Otherwise, Unavailable. I...
Values: Available | Unavailable
Default: "Unavailable"
status object
Status is the current status of the Kuma MeshService resource.
hostname string
coreName string required
origin string
Data plane proxies statistics selected by this MeshService.
connected integer
Number of data plane proxies connected to the zone control plane
healthy integer
Number of data plane proxies with all healthy inbounds selected by this MeshService.
total integer
Total number of data plane proxies.
Conditions is an array of hostname generator conditions.
message string required
message is a human readable message indicating details about the transition. This may be an empty st...
reason string required
reason contains a programmatic identifier indicating the reason for the condition's last transition....
status enum required
status of the condition, one of True, False, Unknown.
Values: True | False | Unknown
type string required
type of condition in CamelCase or in foo.example.com/CamelCase.
coreName string required
status enum
Values: Ready | NotReady
ip string