Skip to main content

Istio Addon

The Istio Addon ships the platform-curated Istio service mesh, packaged as the p6m-istio-gateway-api wrapper Helm chart. It runs Istio in ambient mode (no sidecars), bundles the Kubernetes Gateway API CRDs that istiod is built against, and wires some of the platform Gateways to oauth2-proxy for external authorization.

For background on what an Installable / Installation actually does at the platform layer, see Installation. For how traffic moves through the mesh once it's running, see Istio Ambient Mode Architecture.

What Lands on the Cluster​

When the addon is enabled, ArgoCD reconciles a Helm release that produces:

ResourcePurpose
Gateway API CRDsGatewayClass, Gateway, HTTPRoute, GRPCRoute, ReferenceGrant, BackendTLSPolicy from the Gateway API v1.4.1 standard channel.
istio/baseThe Istio CRDs and cluster-wide resources.
istiodThe control plane, with the ambient profile and a minimum of 2 replicas (autoscaleMin: 2).
istio-cni DaemonSetRedirects pod traffic into the mesh on every node. Ambient mode is on.
ztunnel DaemonSetThe per-node layer-4 proxy that carries mTLS traffic between ambient workloads.
AuthorizationPolicy istio-system/ext-authzSends requests for *.<cluster domain> through the oauth2-proxy extension provider. Targets the ingress-gateway, public-oidc, and internal-oidc Gateways. Always rendered.
Telemetry opentelemetryOnly when observability.tracing.enabled: true. Samples 5% of requests to the otel-tracing provider.
PrometheusOnly when observability.prometheus.enabled: true. Deployment + Service in istio-system.
KialiOnly when observability.kiali.enabled: true. Deployment + Service in istio-system.

The chart doesn't create any Gateway resources. The ingress-gateway, public-oidc, and internal-oidc Gateways that the AuthorizationPolicy targets are managed by the platform-operator.

Custom Gateways

The ext-authz policy targets those three Gateways by name. A Gateway you create yourself isn't covered, so requests through it skip oauth2-proxy. To put a custom Gateway behind oauth2-proxy, add your own AuthorizationPolicy in the Gateway's namespace that uses the oauth2-proxy extension provider:

apiVersion: security.istio.io/v1
kind: AuthorizationPolicy
metadata:
name: <your-gateway-name>-ext-authz
namespace: <gateway-namespace>
spec:
action: CUSTOM
provider:
name: oauth2-proxy
rules:
- to:
- operation:
hosts:
- "<your-host>"
targetRefs:
- group: gateway.networking.k8s.io
kind: Gateway
name: <your-gateway-name>

Each targetRefs entry must name a Gateway in the policy's own namespace. Don't name the policy ext-authz: in istio-system it would replace the chart's policy and drop oauth2-proxy from the platform Gateways.

Extension providers​

istiod's meshConfig registers two extension providers that other resources reference by name:

ProviderTypeBackend
oauth2-proxyenvoyExtAuthzHttpoauth2-proxy.oauth2-proxy.svc.cluster.local:80
otel-tracingopentelemetryalloy.alloy.svc.cluster.local:4317

On an allowed request, oauth2-proxy forwards path, x-auth-request-email, and x-auth-request-preferred-username to the upstream service. Your app can read the signed-in user from those headers.

Add the Installation​

Cluster enablement happens in the org's .platform repo. Create installations/istio-gateway-api.yaml:

apiVersion: p6m.dev/v1alpha1
kind: Installation
metadata:
name: istio-gateway-api
spec:
cd:
enabled: true
autoPromote: true
installableRef:
kind: Installable
name: istio-gateway-api
namespace: installables
destinations:
- clusterRef:
name: <your-cluster-name>

Push and merge.

The release installs into the istio-system namespace. Chart defaults apply, so the Installation needs no overrides unless you turn on observability. To change a setting, add overrides.source.template to the destination with the keys from the Settings Reference below:

  destinations:
- clusterRef:
name: <your-cluster-name>
overrides:
source:
template: |
observability:
tracing:
enabled: true

To enable on multiple clusters in the same org, add additional destinations[].clusterRef.name entries. Each destination can have its own overrides.

Set from cluster context​

The Installable fills these from the cluster's context — you don't set them on the Installation:

  • p6m.cluster.domainName, from the cluster's DNS domain. The ext-authz policy builds its *.<domainName> host match from it.
  • The cloud, environment name, cluster unique name, and cloud-specific identity details (AWS region and account, or Azure location and subscription).
  • On Azure, istiod is pinned to the AKS system node pool (kubernetes.azure.com/mode: system) and tolerates the CriticalAddonsOnly taint.

Settings Reference​

The chart exposes its own observability block. Everything else is passed through to the upstream Istio subcharts under their subchart key (istiod, cni, ztunnel, base).

The "Override snippet" column shows the minimal values needed to change a setting. Paste it under template: | in the Installation above.

observability​

All three are off by default.

SettingOverride snippetNotes
prometheus.enabled (bool)
default: false
observability:
prometheus:
enabled: true
In-cluster Prometheus at prometheus.istio-system:9090. Stores data in an emptyDir with 15-day retention, so metrics are lost when the pod restarts.
kiali.enabled (bool)
default: false
observability:
kiali:
enabled: true
Kiali mesh console at kiali.istio-system:20001, path /kiali. Kiali reads mesh metrics from Prometheus, so enable both.
tracing.enabled (bool)
default: false
observability:
tracing:
enabled: true
Renders a mesh-wide Telemetry that samples 5% of requests to Alloy over OTLP. Requires Alloy in the alloy namespace.

Upstream subchart values​

The wrapper sets these on the Istio subcharts:

SettingValueWhy
istiod.profileambientAmbient mesh, no sidecar injection.
istiod.autoscaleMin2Keeps the control plane available through node drains.
istiod.meshConfig.extensionProvidersotel-tracing, oauth2-proxySee Extension providers.
cni.ambient.enabledtrueRequired for ambient mode.
cni.affinity, ztunnel.affinityNot on eks.amazonaws.com/compute-type: fargateFargate nodes can't run node-level DaemonSets.
*.global.hubp6m.jfrog.io/p6m-dev-docker-remote/istioPull through the platform's Artifactory mirror.

For any other subchart setting, see the upstream chart values for istiod, cni, and ztunnel. If you need one changed, mention it on the rollout ticket so the chart can be extended; don't edit the rendered resources directly on the cluster.

Upgrading​

Istio's components have strict version compatibility, so the wrapper chart ships a minor upgrade as two releases so that you can manage the upgrade properly.

Process​

Scenario: To go from addon version a.b.c to a.b+1.d:

  1. Perform any manual patches and updates to the CRDs and their resources as needed.
  2. Upgrade the addon to a.b+1.0. This will upgrade all CRDs and the istiod component to the desired version.
  3. istiod and all Gateway pods will be restarted as part of the previous step. Pause upgrades until they are stable.
  4. Upgrade the addon to a.b+1.d. This will upgrade CNI and Ztunnel and could result in an outage of a few seconds to a few minutes depending on the number of nodes you have on your cluster.
note

The version of the addon is usually not the same as the version of istio that will be installed. See the appropriate upgrade runbook for specifics on which exact version of each component is being installed.

Runbooks for specific versions: COMING SOON

warning
  • istiod upgrades restart every Gateway. A Gateway with a single replica goes down during the restart. Run 2 or more replicas on every Gateway before taking an a.b+1.0 release.
  • CNI and ztunnel upgrades cause a short outage. Both are DaemonSets, so every node restarts a pod. Schedule the a.b+1.d release in an upgrade window.

Verification​

After ArgoCD syncs, expect the following on the target cluster:

# Control plane: at least 2 Running pods
kubectl --context=<your-cluster> -n istio-system get pods -l app=istiod
# Data plane: one pod per non-Fargate node for each DaemonSet
kubectl --context=<your-cluster> -n istio-system get daemonset istio-cni-node ztunnel
# Gateway API CRDs at the bundled version
kubectl --context=<your-cluster> get crd gateways.gateway.networking.k8s.io \
-o jsonpath='{.metadata.annotations.gateway\.networking\.k8s\.io/bundle-version}'
# ext-authz policy
kubectl --context=<your-cluster> -n istio-system get authorizationpolicy ext-authz

For symptoms and diagnostics once the mesh is running, see Istio Issues.

Gotchas​

  • ext-authz depends on oauth2-proxy. The ext-authz policy calls oauth2-proxy.oauth2-proxy.svc.cluster.local:80. If oauth2-proxy is missing or unhealthy, requests through the targeted Gateways fail authorization.
  • ext-authz only matches *.<cluster domain>. Requests to a host outside the cluster's domainName, such as a custom hostname, don't match this policy's rule.
  • Tracing needs Alloy. observability.tracing.enabled: true sends spans to alloy.alloy.svc.cluster.local:4317. Without Alloy in the alloy namespace, spans are dropped.
  • The bundled Prometheus is not durable. It stores data in an emptyDir, so a pod restart loses all metrics. Use it for short-term mesh debugging, not as the cluster's metrics store.
  • Kiali uses anonymous auth. Anyone who can reach the kiali Service can use the console. The chart creates no ingress for it; reach it with kubectl port-forward.
  • Fargate nodes aren't in the mesh. CNI and ztunnel don't schedule on EKS Fargate, so pods on Fargate nodes run outside ambient mode.