Istio 1.17 has been running really well in my Garage Kubernetes lab, but I thought it’s time to give it an upgrade. It was installed and configured using istioctl utility last time when I bootstrapped the cluster. Since I’ve automated a lot of Kubernetes resources using ArgoCD I would like to upgrade Istio the git-ops way too.
First I configured istio-operator as an ArgoCD application, so it will be installed using its upstream Helm templates. The ArgoCD application looks like this:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: istio-operator
namespace: argocd
spec:
destination:
namespace: istio-operator
server: https://kubernetes.default.svc
project: default
source:
# the Helm chart is at https://github.com/istio/istio/blob/master/manifests/charts/istio-operator/Chart.yaml
path: manifests/charts/istio-operator
repoURL: https://github.com/istio/istio
targetRevision: master
helm:
values: |
# ref. https://github.com/istio/istio/blob/master/manifests/charts/istio-operator/values.yaml
# by default it will use latest which is 1.23 alpha ATM
# also I chose 2 minor versions above my existing one(1.17). This is not officially recommended.
tag: 1.19.0-releasebuilder.c356675
deploymentHistory: 3
syncPolicy:
automated:
prune: true
syncOptions:
- CreateNamespace=true
Once the application has been sync’ed I can verify it in ArgoCD:

I can see there’s an istiooperators.install.istio.io Custom Resource(CR) called installed-state and it coincidentally matches the configuration of my existing Istio 1.17 installation. I don’t know if it’s really there for 306 days – maybe it was created by the istioctl command last time.
$ k get istiooperators.install.istio.io NAME REVISION STATUS AGE installed-state 306d
But anyways there’s no blocker so far. Following the official instructions for upgrading using the operator, I need to create 2 new CRs like these:
# istio-control-plane.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: control-plane-1-19
namespace: istio-system
spec:
# as the name suggests, minimal profile only has the control plane
profile: minimal
revision: 1-19
---
# istio-gateways.yaml
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
name: gateways
namespace: istio-system
spec:
profile: empty
revision: 1-19
components:
ingressGateways:
- name: istio-ingressgateway
enabled: true
After the above yaml sync’ed, I verified that 2 new CRs have been created:
$ k get istiooperators.install.istio.io NAME REVISION STATUS AGE control-plane-1-19 1-19 HEALTHY 153m gateways 1-19 HEALTHY 152m installed-state 306d
I didn’t pay much attention because it’s my garage Kubernetes cluster and nobody would really care if I break it. But as a nice surprise, the ingress gateway was upgraded in-place so there is hardly any downtime caused to my stuff including this blog.
The next step is to migrate all workloads to use the new Istio revision, which is 1-19 stated above. This can be done by replacing all old sidecar.istio.io/inject: true labels with istio.io/rev: 1-19. These are pod labels just in case because I prefer to do it at pod level to reduce the number of Istio sidecar containers.
After all labels were done, I verified this with istioctl:
$ istioctl proxy-status NAME CLUSTER CDS LDS EDS RDS ECDS ISTIOD VERSION argocd-server-7c98587c9c-5rr96.argocd Kubernetes SYNCED SYNCED SYNCED SYNCED NOT SENT istiod-1-19-7987854944-v5hd5 ...
When all the entries above go through the new 1-19 revision, the old Istio revision can be safely deleted.
🙂
