MastertheMesh
istio · ambient · multicluster
Field guide

Multi-cluster Segments and customizable global hostnames in ambient Istio

TO
Tom O'Rourke
EMEA Field CTO · Solo.io

Stretching an ambient mesh across clusters runs into one stubborn assumption: namespace sameness — that a service is only “the same” service across clusters if its name and namespace match exactly. Segments break that constraint. They carve a multi-cluster mesh into tenant domains, give every service a predictable global hostname, and — new in Solo Enterprise for Istio 1.30 — let you template those hostnames however you like and reference them straight from your routing rules and policies.

Segments Namespace sameness Global hostnames Ambient Multicluster Solo Enterprise for Istio New in 1.30

What a Segment is

A Segment is a Solo custom resource that logically partitions a multi-cluster ambient mesh into discrete units. Each segment has its own domain, and the clusters you assign to it form a single connectivity boundary: services in any cluster of the segment can reach one another through stable, segment-scoped hostnames, without you having to keep service names and namespaces identical across every cluster.

That last part is the point. Segments exist to solve the namespace-sameness problem — and, as of Solo Enterprise for Istio 1.30, to give you full control over the global hostnames services are reachable at.

Distribution and scope. Segments are a Solo Enterprise for Istio feature, in ambient mode, on the Solo distribution of Istio. This guide follows the 1.30.x docs — docs.solo.io/istio/1.30.x · multicluster · segments. These CRDs iterate field-level between releases, so confirm the exact schema for the version you run before committing YAML to git.

Namespace sameness, and why it breaks

“Namespace sameness” is the default assumption in multi-cluster meshes: a service named foo in namespace bar on cluster A and a foo in bar on cluster B are treated as one logical, load-balanced service. That's elegant when it holds — and a problem the moment it doesn't:

In all of these, blind name-matching aggregates services that should be distinct, or fails to connect services that should be one. Segments give you an explicit boundary and an explicit naming scheme instead of relying on coincidental name matches.

How segments work

Three moving parts: you declare a Segment with a domain, you assign clusters to it, and you mark which services should be reachable across the segment.

1. Declare the segment (one CR, in istio-system):

apiVersion: admin.solo.io/v1alpha1
kind: Segment
metadata:
  name: acme-segment
  namespace: istio-system
spec:
  domain: mesh.acme        # the segment's unique domain

2. Assign each cluster to the segment by labelling its istio-system namespace. A cluster belongs to exactly one segment:

kubectl label namespace istio-system admin.solo.io/segment=acme-segment

3. Expose a service across the segment with the service-scope label, on the Service or its whole namespace:

kubectl label service foo -n bar solo.io/service-scope=global

With that, foo in namespace bar becomes reachable anywhere in the segment at its global hostname — by default foo.bar.mesh.acme, following the pattern <service>.<namespace>.<segment-domain>.

SEGMENT — acme-segment spec.domain: mesh.acme · istio-system labelled admin.solo.io/segment=acme-segment CLUSTER · west Service foo namespace bar solo.io/service-scope=global CLUSTER · east Service foo namespace bar solo.io/service-scope=global GLOBAL HOSTNAMES foo.bar.mesh.acme default foo.global custom · spec.hostnames (1.30) first-class host on the ServiceEntry → usable in routing one hostname → endpoints in any cluster of the segment

Both clusters join one segment; foo is reachable at its default hostname and, from 1.30, any custom hostname you template.

Segment hostnamesNew in 1.30

The default <service>.<namespace>.<segment-domain> hostname is predictable, but it's rigid — it bakes the namespace and the segment domain into every name. The 1.30 GA release adds fully customizable global hostnames: you template them with spec.hostnames on the Segment, using variables drawn from each service's identity, labels, and annotations.

apiVersion: admin.solo.io/v1alpha1
kind: Segment
metadata:
  name: acme-segment
  namespace: istio-system
spec:
  domain: mesh.acme
  hostnames:
  - pattern: "{service}.{namespace}.acme.com"
  - pattern: "{annotations['company.com/global-hostname']}.global"

Each pattern is expanded per matching service and added as a first-class host on the generated ServiceEntry. That's the part that matters for the title of this section: because these names are real hosts, you can point HTTPRoute, DestinationRule, and authorization policies straight at them — no synthetic VIP juggling, no hard-coded cluster-local names.

The variables you can use in a pattern:

VariableResolves to
{service}the service name
{namespace}the service's namespace
{segmentDomain}the segment domain from spec.domain
{segment}the Segment resource name
{labels['key']}the value of a service label
{annotations['key']}the value of a service annotation

This is what unlocks vanity and convention-driven naming: a tenant can expose checkout.acme.com instead of checkout.payments.mesh.acme, or derive a hostname entirely from an annotation the platform team controls — while the underlying service keeps its ordinary cluster-local name.

Referencing global hostnames in routing and policy

Because a segment hostname is a genuine host on the ServiceEntry, it behaves like any other mesh hostname. A consuming workload anywhere in the segment simply calls it, and an HTTPRoute can route on it:

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: checkout
  namespace: payments
spec:
  hostnames:
  - checkout.acme.com          # a custom segment hostname
  rules:
  - backendRefs:
    - name: checkout
      port: 8080

The same applies to traffic policy (DestinationRule subsets, timeouts, retries) and to AuthorizationPolicy rules keyed on the host. The hostname is the stable contract; which cluster actually serves the request is the mesh's problem, not the caller's.

What segments don't give you

Segments are an organisational and connectivity primitive, not a security boundary on their own. Worth being explicit, because the name invites the wrong assumption:

A complete multi-tenancy posture combines segments with authorization policy, RBAC, and observability scoping. Segments make the naming and connectivity tractable; they don't replace the controls.

Prerequisites and getting started

From there: create the Segment, label each cluster's istio-system into it, label the services you want global, and — if you want them — add spec.hostnames patterns. Verify the generated hosts on the ServiceEntry before you wire routing to them.

See also. For where segments sit in the broader “manual federation vs the Solo management plane” trade-off, see Manual multi-cluster vs Solo Enterprise for Istio management plane. For the east-west data path that carries cross-cluster traffic, see HBONE east-west connectivity. The canonical reference is the Solo docs: multicluster · segments · namespace sameness.