A release is a named, numbered thing you can undo
Loose kubectl apply files travel loose. They share values you copy-paste between them, and nothing binds them into a single thing you can name, version, or reverse in one move — "undo the last deploy" becomes an archaeology project through your shell history. Helm packages manifests as a chart; installing one produces a release, a named, numbered instance running in the cluster. helm upgrade ships a change and bumps the revision. helm rollback <release> 1 puts revision one back exactly as it was, in one line, without you reconstructing which files changed. This lab proves both halves: a real upgrade you can see land, and a real rollback you can prove reverted — not by trusting the command's exit code, but by checking the cluster and the values Helm actually stored.
Undo, as a single line with a number in it.
You need a free Azure account and the Azure CLI (az), signed in with az login. First time? The 15-minute Set up your machine page covers the account, the installs, and sign-in. Prefer zero installs? Run everything in Azure Cloud Shell (Bash) — az, kubectl, and helm are all preinstalled and already signed in.
This lab assumes the cluster from Your first AKS cluster. If you already tore that one down, Step 1 recreates it with the same command. Nothing here provisions a load balancer or public IP — the release stays on a ClusterIP Service and you reach it with kubectl port-forward, so the only cost is the node you were already paying for. The teardown step removes all of it.
The cluster
If you still have the cluster from Your first AKS cluster, skip to Step 2. Otherwise recreate it with the identical command.
# Windows/Git Bash: stop it mangling /subscriptions/... arguments (harmless on macOS/Linux) export MSYS_NO_PATHCONV=1 RG="campux-lab-aks-rg" az group create -n "$RG" -l eastus # same command as the first-cluster lab: free control plane, one small node az aks create -n campux-aks -g "$RG" \ --tier free \ --node-count 1 \ --node-vm-size Standard_B2s \ --enable-managed-identity \ --generate-ssh-keys az aks get-credentials -n campux-aks -g "$RG" helm version --short
helm version --short prints a v3.x.x version with no error — Cloud Shell already has it installed, pointed at the same kubeconfig kubectl uses. Nothing extra to install before Step 2.Add a chart repo, install a release
podinfo is a small, well-known demo chart built for exactly this kind of exercise — a real Deployment and Service with values worth changing. Install it as a release named shop-release, starting deliberately small.
helm repo add podinfo https://stefanprodan.github.io/podinfo helm repo update kubectl create namespace helmdemo helm install shop-release podinfo/podinfo \ --namespace helmdemo \ --set replicaCount=1 helm list -n helmdemo
helm list -n helmdemo shows shop-release, STATUS: deployed, REVISION: 1. That revision number is the whole point of everything that follows — it is what helm rollback will target.The release is one thing, not a pile of files
Confirm the pod is real and reachable, then look at the release the way Helm sees it — as a single named, versioned object, not as "whatever is currently in the namespace."
kubectl get pods -n helmdemo
kubectl get deploy,svc -n helmdemo
# fullname template = release name + chart name, since "shop-release" doesn't already contain "podinfo"
kubectl port-forward -n helmdemo svc/shop-release-podinfo 9898:9898 &
sleep 2
curl -s localhost:9898/ | head -c 200
echo
kill %1
helm status shop-release -n helmdemo
curl returns a JSON body from the running pod, and helm status reports REVISION: 1 and deployed again. One Deployment, one Service, one release name covering both — helm uninstall shop-release later removes everything this install created, not a manually tracked list of objects.Upgrade with a changed value, watch the rollout land
Ship a real change — triple the replica count — and watch Kubernetes actually create the new pods before you check anything with Helm.
helm upgrade shop-release podinfo/podinfo \
--namespace helmdemo \
--set replicaCount=3
kubectl get pods -n helmdemo -w # Ctrl-C once three pods read Running
helm status shop-release -n helmdemo helm history shop-release -n helmdemo
helm status shows REVISION: 2. helm history lists two rows — revision 1 (install) and revision 2 (upgrade), both deployed/superseded appropriately. The upgrade did not overwrite revision 1's record; it added a new one on top of it, which is exactly what makes the next step possible.Roll back to revision one — then prove it, do not just trust it
One command, one number. Do not stop at "the command exited zero" — check the pod count and the values Helm actually stored, the same way you would in an incident at three in the morning.
helm rollback shop-release 1 -n helmdemo
kubectl get pods -n helmdemo -w # Ctrl-C once back down to one pod
helm history shop-release -n helmdemo helm get values shop-release -n helmdemo
helm history now lists three revisions — the rollback did not erase revision 2's history, it added revision 3, whose description reads Rollback to 1. helm get values shows replicaCount: 1, matching revision 1's values exactly. Three revisions on record, one pod running, one value reverted — that is proof, not a claim.Helm never "goes back in time" — it stores the fully rendered manifest for every revision it has ever produced, and a rollback is really a forward-moving upgrade whose target state happens to match an earlier revision's. That is why the history keeps growing instead of rewinding: revision 3 exists, and it happens to look like revision 1. It is also why this works with a single command at three in the morning — the alternative, reconstructing "what did the manifests look like before the bad deploy" from memory or shell history, is exactly the archaeology project a release exists to prevent.
Tear it down
helm uninstall removes every object this release created — the Deployment and the Service both — in one command. Then remove the namespace and the cluster.
helm uninstall shop-release -n helmdemo
kubectl delete namespace helmdemo
az group delete -n campux-lab-aks-rg --yes --no-wait
az group exists -n campux-lab-aks-rg # -> false once complete
helm list -n helmdemo returns nothing before the namespace is even gone — the release is deleted. Confirm the resource group and its auto-managed node group (named like MC_campux-lab-aks-rg_campux-aks_eastus) are both gone.What you can now honestly claim
You installed a chart as a named release and watched its revision number, upgraded it with a value you could see change in the pod count, and rolled it back to revision one with a single command — then proved the rollback was real by checking the running pods and the values Helm had actually stored, not by trusting a green exit code. You know a release is one thing covering many objects, that helm history only ever grows, and that a rollback is a new revision that matches an old one, not a rewind. That is the mechanism behind "undo the last deploy" as a single line with a number in it.