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.
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:
- teams use different naming conventions per cluster;
- an acquisition merges two previously independent platforms with clashing names;
- dev and prod environments reuse the same service names but must stay separate;
- partial peering topologies create conflicting definitions of “the same” service.
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>.
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:
| Variable | Resolves 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:
- Not traffic isolation. Cross-segment or intra-segment isolation still needs explicit
AuthorizationPolicyresources. - Not configuration isolation. RBAC and namespace scoping remain your responsibility.
- Not discovery hiding. A tenant can still learn a service exists via DNS; segments organise naming, they don't conceal it.
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
- The Solo distribution of Istio with an enterprise license (Solo Enterprise for Istio).
- Ambient mesh mode enabled.
- A registered multi-cluster mesh; clusters you intend to group must be reachable to one another (HBONE east-west connectivity).
- Version 1.30.x for the customizable
spec.hostnamespatterns.
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.