Ok, let’s forget Tiller. What else has changed?

As I mentioned at the beginning — removal of Tiller was a big thing, but not the only major change. Let’s take a look at other:

Three-way strategic merge patch

Helm 2 used a two-way strategic merge patch. It means that when you wanted to perform any helm operation, it compared the most recent manifest chart against the proposed chart manifest. It checked for the differences between these two charts to determine what changes needed to be applied to the resources in Kubernetes. Sounds pretty smart, right? The problem is that if changes were applied to the cluster “manually” (for example via kubectl edit), they were not considered. This resulted in resources being unable to roll back to its previous state because Helm2 only checked the last applied chart’s manifest as its current state, and since there were no changes in the chart’s state (we only changed live state on the cluster) Helm simply did not see the need for performing a rollback.

And that’s were three-way strategic merge patch comes to the rescue. How does Helm3 do that? It simply takes the live state into consideration too (thus 3-way instead of 2-way since now we have the old manifest, its live state, and the new manifest). For example, let’s say you deployed an application with:

helm install very_important_app ./very_important_app

and for example, this application Chart was set to have 3 replica sets. Now, if someone by mistake will perform kubectl edit or:

kubectl scale -replicas=0 deployment/very_important_app

and then someone from your team will realise that for some mysterious reason very_important_app is down and will try to execute:

helm rollback very_important_app

In Helm 2, it would generate a patch, comparing the old manifest against the new manifest. Because this is a rollback and someone only changed live state(so the manifest did not change) Helm would determine that there is nothing to rollback because there is no difference between the old manifest and the new manifest (both expect to have 3 replicas). Rollback is not performed then and the replica count continues to stay at zero. You start panicking now…

In Helm 3 on the other hand, the patch is generated using the old manifest, the live state, and the new manifest. Helm recognizes that the old state was at three, the live state is at zero and so it determines that the new manifest wishes change it back to three, so it generates a patch to fix that. You stop panicking now…

A similar process happens with Helm 3 when performing upgrades. Since it takes the live state into account now, then for example if some controller-based application (or something like a service-mesh) inject anything into kubernetes object which was deployed via Helm — it will get removed during helm upgrade process using Helm2. Helm 3 doesn’t do that —again, it takes the live state into consideration. Let’s assume that we want to install for example Istio on our cluster. Istio will start injecting sidecar containers into any deployment, so assuming you deployed something with Helm and your deployment consist of:

containers:

- name: server

image: my_app:2.0.0

Then you installed Istio so your container definition looks like this now instead:

containers:

- name: server

image: my_app:2.0.0

- name: istio-sidecar

image: istio-sidecar-proxy:1.0.0

And if you now execute upgrade process with Helm2, you’ll end up with this:

containers:

- name: server

image: my_app:2.1.0

Istio sidecar gets removed since it wasn’t in the Chart. Helm 3 however, generates a patch of the containers object between the old manifest, the live state, and the new manifest. It notices that the new manifest changes the image tag to 2.1.0, but live state contains something extra. So upgrade with Helm 3 will work as you would expect:

containers:

- name: server

image: my_app:2.1.0

- name: istio-sidecar

image: istio-sidecar-proxy:1.0.0

Three-way strategic merge patch makes Helming way more predictable and safer. You don’t have to worry anymore that something goes bananas.