TT Lab
Get started
Learn Learning paths Courses

ICA — Istio Certified Associate

Customize the Install with IstioOperator, Upgrade with Revisions

Continue in TT Lab

In one line

An Istio installation is expressed as a single document called an IstioOperator, a profile is a bundle of defaults for that document, and MeshConfig is the configuration applied to the whole mesh. For upgrades, the canary approach of standing revisions up side by side is the default, and in-place is riskier and so comes with conditions.

Why this was needed

When Istio comes up with a single istioctl install line, it looks like you are done. But in operations, requirements soon arrive: "we need to turn on the access log," "we need to add an egress gateway," "we need to change external destinations to be blocked by default." If you attach --set flags one by one at that point, nobody remembers what was changed. The Istio documentation says that --set and -f do the same thing but strongly recommends passing a file with -f in production. This is because the installation state must be left in a single file so that you can reuse the same file at upgrade time.

Upgrades are the same. The in-place approach, which swaps the control plane where it stands, makes all sidecars look at the new istiod at once, so if a problem occurs the entire mesh is affected. So Istio recommends the canary approach, standing up one more new control plane alongside and moving over namespace by namespace. The Install/Upgrade/Config domain (20%) of the ICA exam asks exactly these two things: what you use to keep the installation consistent and when you choose between the two upgrade approaches.

How it works

IstioOperator — a configuration document that is not applied to the cluster

The file you pass to istioctl install -f is an IstioOperator resource of install.istio.io/v1alpha1. The official reference documentation explains that this resource "has a format similar to Kubernetes objects but is not applied to the cluster; it is file input for istioctl." That is, it is not something you put in with kubectl apply but material that istioctl reads to produce manifests.

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
  profile: default          # 기본값 묶음. 비우면 default
  revision: 1-31-0          # canary 업그레이드용 식별자. '.' 은 쓸 수 없다
  meshConfig:               # 메시 전체 설정
    accessLogFile: /dev/stdout
    outboundTrafficPolicy:
      mode: REGISTRY_ONLY
  components:               # 어떤 구성요소를 켜고 끌지, k8s 리소스 설정
    egressGateways:
    - name: istio-egressgateway
      enabled: true
  values: {}                # Helm values 로 바로 넘기는 통로(검증됨)

The main fields of spec are profile, hub/tag (the image location), revision, meshConfig, components (base, pilot, cni, ztunnel, istiodRemote, ingressGateways, egressGateways), and values. The documentation says values is a verified channel that passes through to Helm templates, and advises that items present in IstioOperatorSpec should be written in the upper fields instead of values. If you want to use an old Helm values path with --set, prepend the values. prefix.

profile — a named bundle of Helm values

A profile is a named bundle of values overrides built into the Helm chart. That is why the same names are used on both the helm and istioctl sides. The deployment profiles are as follows.

profile Purpose Components istioctl installs with it
default Recommended for production and multicluster primaries istiod, istio-ingressgateway
demo For feature demonstrations. It turns tracing and access logging up high, so it is unsuitable for performance tests istiod, ingress and egress gateways
minimal Same as default but only the control plane istiod
ambient For getting started with ambient mode istiod, CNI, ztunnel
remote / empty / preview For an external control plane / a base that installs nothing / experimental features —

There is one difference here that the exam likes. An istioctl profile includes even the list of which components to install, but a Helm profile is merely a bundle of values, so you must bring up each component one at a time with helm install. And it is recommended to give a platform profile (gke, eks, openshift, k3s, and so on) together with the deployment profile, as in --set profile=default --set values.global.platform=gke.

MeshConfig — values applied to the whole mesh

meshConfig is the "mesh-wide configuration." If accessLogFile is empty, the access log is off, and if you give it /dev/stdout, it is on. accessLogEncoding defaults to TEXT and can be changed to JSON. The default of outboundTrafficPolicy is ALLOW_ANY, so traffic can go out even to unregistered external destinations. enableTracing turns on span creation, but the proxy configuration must have a collector. One exception is defaultConfig (ProxyConfig). The documentation says this value is applied once at sidecar injection time and does not change while the Pod lives, while the rest of MeshConfig is deployed dynamically even at runtime. So if you changed the proxy configuration and it was not reflected, you must restart the Pods.

The difference between the istioctl and Helm installation paths

A Helm installation brings up three charts in order. base, which holds the cluster-scoped CRDs, istiod, which deploys istiod, and the optional gateway. When doing a revision install, you must give the base chart --set defaultRevision=<revision> for the resource validation webhook to work. Even if you delete with Helm, the CRDs remain, and this is an intended design. This is because deleting the CRDs would cascade-delete user resources such as VirtualServices and DestinationRules. When handing something installed with istioctl over to Helm, you can take over the existing resources with --take-ownership. The documentation states that the charts in the Helm guide are the same as the charts istioctl uses, except for the gateway chart.

Canary upgrade — standing revisions up side by side

If you give a revision, as in istioctl install --set revision=1-31-0, an istiod Deployment and Service and a sidecar injection webhook carrying the revision name appear as one more set. Existing sidecars are not affected at all. To move workloads, you remove the namespace's istio-injection=enabled label, attach istio.io/rev=<revision>, and then restart the Pods. The istio-injection label takes precedence over istio.io/rev for backward compatibility, so you must remove it.

Instead of going around fixing labels namespace by namespace, you use a revision tag. If you create a tag with istioctl tag set prod-stable --revision 1-30-1 and attach istio.io/rev=prod-stable to the namespaces, later a single istioctl tag set prod-stable --revision 1-31-0 --overwrite moves every namespace using that tag to the new revision. The default tag is special and handles istio-injection=enabled injection, resource validation, and the leader lock. When verification is finished, you remove the old control plane with istioctl uninstall --revision 1-30-1. The revision approach supports skipping two minor versions (1.15 → 1.17).

In-place upgrade — it has many conditions

istioctl upgrade swaps the control plane and gateways where they stand. The conditions the documentation states are these. The installed version must be lower than the new version by at most one minor version, it cannot be used on something installed with --revision, and if you do not pass along as is the -f file or --set values used at installation, custom settings revert to defaults. Afterward, you must restart the data plane yourself with kubectl rollout restart deployment. To reduce disruption, it recommends running at least two istiods and setting a PodDisruptionBudget with minimum availability of 1.

What it looks like in the field

There was a case where a team upgraded a mesh installed with five --set flags using istioctl upgrade, and the access log disappeared and outboundTrafficPolicy returned to ALLOW_ANY. It was because the same --set flags were not passed to the upgrade command, and finding the cause took a day. It would not have happened if the IstioOperator file had been kept in a repository and the same file had been passed with -f for both installation and upgrade.

Another is when rolling back a canary. In the default profile, gateways do not come up separately per revision but are upgraded in place to the new revision. So if you delete the canary revision, the gateway no longer points to the old control plane. The documentation says that before deleting the canary, you should first reinstall the gateway with the old istioctl and confirm it works normally. If you swap the order, ingress is cut.

What to check in the next quiz

It asks which components istioctl installs for each profile, why only defaultConfig needs a restart, the precedence of istio-injection and istio.io/rev, the command that moves a revision tag, and the conditions under which an in-place upgrade fails or loses settings. References: Install with Istioctl, Installation Configuration Profiles, Canary Upgrades, In-place Upgrades, Install with Helm.