Upgrading Helm Chart on Kubernetes: Overcoming Challenges of Obsolete Helm v2

Diego Maia
5 min readMar 16, 2023

--

Software is a fundamental element in most modern businesses, allowing companies to work with greater efficiency, productivity, and innovation. However, a lack of software updates can lead to a range of problems, from security vulnerabilities to performance and compatibility issues. When it comes to updating an application, the costs can be significant, especially in complex environments like Kubernetes. The process of upgrading Helm Charts, in particular, can be especially challenging, especially when dealing with complex structures of applications installed via Helm v2. In this article, we will explore a challenge faced by companies during the upgrade of Helm Charts with regard to Kubernetes APIs that are deprecated.

What is Helm Chart and How is it Used in Kubernetes?

Helm Chart is a Kubernetes tool used for managing applications and services. It simplifies the deployment, definition, installation, and updating of applications in a Kubernetes cluster. It contains all the necessary information to run an application in Kubernetes, including how to create and configure an application container. With Helm, users can easily deploy applications with defined dependencies and resources, update them securely and reliably. It is a powerful tool that greatly simplifies application management in Kubernetes.

Don’t Worry, If You Encounter “Upgrade Failed: Current Release Manifest Contains Removed Kubernetes API(s)” Error, There is a Solution.

When upgrading Helm Charts, users may encounter errors like “Upgrade Failed: Current Release Manifest Contains Removed Kubernetes API(s).” This error typically occurs when the current release manifest contains removed Kubernetes API(s) that are incompatible with the current version of Kubernetes. As a result, Helm is unable to build the Kubernetes objects needed to perform the upgrade and the process fails.

One common cause of this error is using a deprecated Kubernetes API version in the Helm Chart. For example, the error message may indicate that there are no matches for the kind “Ingress” in version “networking.k8s.io/v1beta1”. This version of the Kubernetes API has been deprecated and is no longer supported in the latest version of Kubernetes.

To resolve this error, users must update their Helm Charts to use the latest supported Kubernetes API version. This may require updating the dependencies of the Helm Chart or making changes to the configuration of the application. In addition to these solutions, a helpful script has been developed that can manipulate the configmap of the Helm Charts installed in the cluster. This script can facilitate the upgrade process by simplifying the updating of the Helm Chart to use the latest supported Kubernetes API version. With the help of this script and other solutions, users can ensure a successful upgrade of their Helm Charts and avoid encountering errors like:

Error: current release manifest contains removed kubernetes api(s) for this kubernetes version

To resolve this problem, you should update the local chart that contains the deprecated APIs to use the latest Kubernetes APIs and execute the script before your next Helm upgrade.

#!/usr/bin/env sh

# This script was generated to run on Mac, so there may be incompatibility with other operating systems
# Locations that you should provide before starting the installation process, such as:
# >>> brew install protobuf
# >>> brew install gsed
#What does this script do?
# When upgrading the k8s cluster, its APIs may undergo changes, causing a Helm chart
# once deployed, to no longer be updated due to API incompatibility.

set -e

CHART_INSTALLED_NAME=$1
LOCAL_REALM_VERSION="2.17"

# Check if all necessary dependencies are installed
command -v git kubectl helm gunzip base64 protoc gsed >/dev/null 2>&1 || { echo "Missing dependency" && exit 1; }

# Clone the Helm and Google Protobuf repositories
[ -d "./helm_repo" ] || git clone https://github.com/helm/helm.git --branch release-$LOCAL_REALM_VERSION ./helm_repo
[ -d "./proto_repo" ] || git clone https://github.com/google/protobuf ./proto_repo

# Get the latest ConfigMap for the installed chart
kubectl get configmaps --namespace kube-system --selector "NAME=${CHART_INSTALLED_NAME},STATUS=DEPLOYED" -o yaml > "${CHART_INSTALLED_NAME}_configmap.yaml"
kubectl get configmaps --namespace kube-system --selector "NAME=${CHART_INSTALLED_NAME},STATUS=DEPLOYED" --output jsonpath='{ .items[0].data.release }' | base64 --decode | gunzip | protoc --proto_path ./helm_repo/_proto --proto_path ./proto_repo/src --decode hapi.release.Release ./helm_repo/_proto/hapi/**/* > "${CHART_INSTALLED_NAME}_configmap_decoded.yaml"

# Back up the current file
cp "${CHART_INSTALLED_NAME}_configmap.yaml" "${CHART_INSTALLED_NAME}_configmap_bkp_$(date '+%Y%m%d%H%M%S').yaml"

# Copy the decoded file to be updated
cp "${CHART_INSTALLED_NAME}_configmap_decoded.yaml" "${CHART_INSTALLED_NAME}_configmap_decoded_updated.yaml"

# Replace old versions of Kubernetes API
gsed -i \
-e 's|apiVersion: extensions/v1beta1\\nkind: Deployment|apiVersion: apps/v1\\nkind: Deployment|g' \
-e 's|apiVersion: extensions/v1beta1\\nkind: DaemonSet|apiVersion: apps/v1\\nkind: DaemonSet|g' \
-e 's|apiVersion: extensions/v1beta1\\nkind: StatefulSet|apiVersion: apps/v1\\nkind: StatefulSet|g' \
-e 's|apiVersion: extensions/v1beta1\\nkind: ReplicaSet|apiVersion: apps/v1\\nkind: ReplicaSet|g' \
-e 's|apiVersion: apps/v1beta1\\nkind: Deployment|apiVersion: apps/v1\\nkind: Deployment|g' \
-e 's|apiVersion: apps/v1beta2\\nkind: Deployment|apiVersion: apps/v1\\nkind: Deployment|g' \
-e 's|apiVersion: apps/v1beta2\\nkind: DaemonSet|apiVersion: apps/v1\\nkind: DaemonSet|g' \
-e 's|apiVersion: apps/v1beta2\\nkind: StatefulSet|apiVersion: apps/v1\\nkind: StatefulSet|g' \
-e 's|apiVersion: apps/v1beta2\\nkind: ReplicaSet|apiVersion: apps/v1\\nkind: ReplicaSet|g' \
-e 's|apiVersion: extensions/v1beta1\\nkind: NetworkPolicy|apiVersion: networking.k8s.io/v1\\nkind: NetworkPolicy|g' \
-e 's|apiVersion: extensions/v1beta1\\nkind: PodSecurityPolicy|apiVersion: policy/v1beta1\\nkind: PodSecurityPolicy|g' \
-e 's|apiVersion: extensions/v1beta1\\nkind: Ingress|apiVersion: networking.k8s.io/v1beta1\\nkind: Ingress|g' \
-e 's|apiVersion: networking.k8s.io/v1\\nkind: Ingress|apiVersion: networking.k8s.io/v1beta1\\nkind: Ingress|g' \
"${CHART_INSTALLED_NAME}_configmap_decoded_updated.yaml"

# Update the value of the release key in the ConfigMap
patched_data="$(protoc --proto_path ./helm_repo/_proto --proto_path ./proto_repo/src --encode hapi.release.Release ./helm_repo/_proto/hapi/**/* < "${CHART_INSTALLED_NAME}_configmap_decoded_updated.yaml" | gzip | base64)"
gsed -Ei "s|^([ ]+)release:([ ]+).*$|\1release:\2$patched_data|" "${CHART_INSTALLED_NAME}_configmap.yaml"

echo "To apply in the environment, run: \n\n\tkubectl apply -f ${CHART_INSTALLED_NAME}_configmap.yaml -n kube-system\n\n"

The script generates four files:

  1. ${CHART_INSTALLED_NAME}_configmap.yaml: a YAML file that contains the ConfigMap for the installed Helm Chart. It is retrieved from the Kubernetes cluster using the kubectl get configmaps command.
  2. ${CHART_INSTALLED_NAME}_configmap_decoded.yaml: a YAML file that contains the decoded version of the ConfigMap retrieved in step 1. It is decoded using the protoc command with the Google Protobuf schema.
  3. ${CHART_INSTALLED_NAME}_configmap_bkp_$(date '+%Y%m%d%H%M%S').yaml: a backup of the original ConfigMap file created in step 1. It is created using the cp command.
  4. ${CHART_INSTALLED_NAME}_configmap_decoded_updated.yaml: a YAML file that contains the updated version of the ConfigMap. It is created by replacing the deprecated Kubernetes API versions with the latest supported versions using the gsed command.

This script performs a set of actions to update the ConfigMap of Helm Charts installed on a Kubernetes cluster. The script checks if all necessary dependencies are installed, clones the Helm and Google Protobuf repositories, gets the latest ConfigMap for the installed chart, makes a backup of the current file, copies the decoded file to be updated, replaces old versions of Kubernetes API, and updates the value of the release key in the ConfigMap. However, it’s important to note that the script only generates files and does not apply anything directly to the environment. The decision to apply the updates generated by the script to the Kubernetes cluster must be made by the person executing the script.

Conclusion

It is crucial for all businesses to keep their software up to date to avoid security vulnerabilities, performance issues, and compatibility problems. Upgrading applications can be complex and costly, especially in environments like Kubernetes. Helm Chart is a Kubernetes tool that simplifies application management in Kubernetes, but it can encounter errors during the upgrade process due to the use of deprecated Kubernetes API versions. ;)

--

--

Diego Maia

I am a cloud and Kubernetes enthusiast. In my free time, I enjoy contributing to open source projects and helping others learn about cloud technologies.