← Back to posts

GCP ACE: Introduction to Cloud Service Mesh on GKE

Everything networking-related so far in this series — Services, Ingress, multi-cluster Services, the multi-cluster Gateway — routes traffic based on where a Pod is and what port it listens on. None of it looks inside the traffic, encrypts it automatically, or lets you make fine-grained routing decisions based on request content. That’s what a service mesh adds, and Cloud Service Mesh is Google’s managed implementation, built on Istio.

What a service mesh actually adds

A Kubernetes Service gives you a stable address and basic load balancing. A service mesh sits a layer underneath that, injecting a lightweight network proxy (a sidecar) next to every workload container. Every bit of traffic in or out of that Pod passes through its sidecar first — which means the mesh can, without any application code changes:

Provisioning: managed vs. in-cluster

Cloud Service Mesh offers a managed control plane: Google runs the control plane itself and handles its reliability, upgrades, scaling, and security. You still configure the mesh with the familiar Istio APIs, but on current fleets nothing istiod-shaped runs in your cluster — the control plane is Google’s globally managed TRAFFIC_DIRECTOR implementation (more on that below). This is the default recommendation; you no longer run and patch your own control plane.

Enabling it at the fleet level, once:

gcloud container fleet mesh enable --project FLEET_PROJECT_ID

Turning on automatic management for a specific registered cluster:

gcloud container fleet mesh update \
   --management automatic \
   --memberships MEMBERSHIP_NAME \
   --project FLEET_PROJECT_ID \
   --location MEMBERSHIP_LOCATION

Fleet-default enablement — so every new cluster registered afterward gets the managed mesh automatically, without a per-cluster step:

# mesh.yaml
management: automatic
gcloud container fleet mesh enable --project FLEET_PROJECT_ID \
    --fleet-default-member-config mesh.yaml

This only applies going forward — clusters already registered before you set the fleet default have to be synced separately.

Verifying:

gcloud container fleet mesh describe --project FLEET_PROJECT_ID

The control plane state should read ACTIVE, and the implementation field shows ISTIOD or TRAFFIC_DIRECTOR. This isn’t a minor detail to skim past: Google formally announced the deprecation of managed ISTIOD (and the in-cluster control plane) on September 28, 2026 — support for both ends on March 1, 2028. Managed fleets still on ISTIOD must modernize to TRAFFIC_DIRECTOR before then, either customer-triggered or Google-driven. In-cluster installations can’t be modernized in place; they have to migrate to the managed control plane on a new cluster. TRAFFIC_DIRECTOR has been the default for every new fleet since July 1, 2024 (and provisioning ISTIOD for new fleets ended September 8, 2024), so if you see ISTIOD in the output today, it almost always means a fleet that’s been running since before that cutover and hasn’t modernized yet.

How a Pod actually joins the mesh: sidecar injection

Enabling Cloud Service Mesh on a cluster doesn’t automatically put every Pod into the mesh — injection is opt-in, per namespace:

kubectl label namespace NAMESPACE istio.io/rev- istio-injection=enabled --overwrite

The istio.io/rev- clears any revision-specific label first, so the plain istio-injection=enabled label takes effect. Existing workloads in a newly-labeled namespace don’t automatically get a sidecar — they need to be restarted (a rolling restart of the Deployment, for instance) before the injection webhook actually adds the proxy container to them.

How a request actually flows through the mesh

For a Pod with an injected sidecar, every request — inbound and outbound — is transparently intercepted by that Pod’s own sidecar proxy before it reaches (or leaves) the application container:

  1. Service A’s sidecar intercepts an outbound call meant for Service B.
  2. It consults the mesh’s traffic rules (covered in the next article — VirtualServices, DestinationRules) to decide exactly where that request should actually go.
  3. It opens a connection to Service B’s sidecar — encrypted with mutual TLS if that’s configured — not directly to Service B’s application container.
  4. Service B’s sidecar receives it, decrypts it, applies any authorization checks, and only then hands it to Service B’s actual application code.

The application containers on both ends never see any of this — they just make or receive plain HTTP/gRPC calls as if the mesh weren’t there. That transparency is the entire design point: existing app code doesn’t need to change to get mTLS, retries, or traffic-shaping.

Dashboards and support

Cloud Service Mesh integrates with Google Cloud’s observability stack rather than requiring a separate monitoring setup: service-level metrics (latency, request volume, error rate — the so-called “golden signals”) for every meshed service show up in the Cloud Console, correlated by service, not just by Pod or node. This is also where you’d check mesh health and configuration state day to day, alongside the gcloud container fleet mesh describe command above for a quick CLI check.

Exam Takeaways

Sources

↗ LinkedIn