1. Introduction

To modify a Helm release, we can install its updated chart using helm upgrade. Beyond installing updated charts, we can also update values, disable hooks, create namespaces, and do other things using the same command.

In this tutorial, we’ll discuss how to update helm values in Kubernetes using helm upgrade.

2. Installing a Helm Release for Illustration

To illustrate how to update Helm values in Kubernetes, we’ll create an Apache web server using helm install:

$ helm install apache oci://registry-1.docker.io/bitnamicharts/apache

Then, we’ll run helm get values -a to retrieve our release’s current values, so we can see how they change later:

$ helm get values -a apache
COMPUTED VALUES:
...truncated...
command: []
...truncated...
containerPorts:
  http: 8080
  https: 8443
...truncated...
replicaCount: 1
...truncated...

We retained only the outputs of the command, containerPorts, and replicaCount parameters because we’ll be using them subsequently.

If we wanted our release’s USER-SUPPLIED VALUES only, we would’ve run helm get values instead of helm get values -a:

$ helm get values apache
USER-SUPPLIED VALUES:
null

Since we installed the release without supplying any value, fetching USER-SUPPLIED VALUES returned null. However, when we update the values using helm upgrade, the return won’t be null anymore.

3. Using –set

We use the –set flag with helm upgrade when editing values from the command line:

$ helm upgrade [release] [chart] --set key=value

We can also pass multiple key-value pairs, but we must separate each key-value pair with a comma:

$ helm upgrade [release] [chart] --set key1=value1,key2=value2

In the previous section, the replicaCount of our apache release was 1. Now, we’ll change it to 2 using the –set flag:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --set replicaCount=2

Let’s grep the new value of replicaCount to confirm the change:

$ helm get values -a apache | grep replicaCount
replicaCount: 2

Of course, our USER-SUPPLIED VALUES will not return null anymore:

$ helm get values apache
USER-SUPPLIED VALUES:
replicaCount: 2

3.1. Specifying the Key of a Complex Parameter

The replicaCount parameter is a simple YAML dictionary. So, specifying its key to the –set flag was straightforward.

But if we want to change the value of a complex parameter, such as the child item of a nested dictionary, the key will be the parameter’s dot notation.

We can readily get a parameter’s dot notation from the chart’s README using helm show readme:

$ helm show readme oci://registry-1.docker.io/bitnamicharts/apache
...truncated...
| `containerPorts.http`                               | Apache server HTTP container port
                                              | `8080`                   |
| `containerPorts.https`                              | Apache server HTTPS container port
                                              | `8443`                   |
...truncated...

The problem is that the output can be very long sometimes, making it hard to read. In place of getting the chart’s README, we can convert YAML to the properties format using the yq utility:

$ helm get values -a apache | yq -o props
COMPUTED\ VALUES =
...truncated...
containerPorts.http = 8080
containerPorts.https = 8443
...truncated...

Now that we know the dot notation of the containerPorts‘ child items (http and https), we can change their values. Let’s change the container’s http port from 8080 to 1234:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --set containerPorts.http=1234

Combining yq and grep for easier matching, we’ll check for the new http port:

$ helm get values -a apache | yq -o props | grep 'containerPorts.http '
containerPorts.http = 1234

Sometimes, when converting YAML to props using yq, special characters may show up in our output even though they weren’t in the YAML. So, we typically limit our use of yq to getting our parameter’s dot notations.

When dealing with mixed data structures, such as a list of dictionaries or dictionaries with list child items, using dot notation with –set can be tricky. At such times, specifying the values in JSON using the –set-json flag would be better.

4. Using –values

We can update our release’s values using the –values flag of helm upgrade if the values are in a YAML file or URL:

$ helm upgrade [release] [chart] --values values.yml

Alternatively, we can use -f in place of –values:

$ helm upgrade [release] [chart] -f values.yml

The helm upgrade –values command comes in handy when we’re updating the values of many parameters. Instead of typing out multiple key-value pairs on the command line, we can have our keys and values in one file and update them all at once.

Let’s cat the content of our values.yml file:

$ cat values.yml
containerPorts:
  http: 5555
  https: 4321
replicaCount: 3

Now, let’s update our release’s values:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --values values.yml

Once again, we’ll check for the new values using yq and grep for easier matching:

$ helm get values -a apache | yq -o props | grep 'containerPorts.http\|replicaCount'
containerPorts.http = 5555
containerPorts.https = 4321
replicaCount = 3

As expected, the values of all three parameters changed to the values we specified in the values.yml file.

Both flags, –set and –values, override changes made by the other. So, if we update our release’s values using –set after we’ve used the –values flag, all the values assigned using –values will return to default before the new values are applied. The reverse also holds true.

5. Using –set-file

The –set-file flag comes in handy when values are too lengthy for the CLI. It is also useful for dynamically generated values.

It uses a syntax similar to –set:

$ helm upgrade [release] [chart] --set-file key1=path1,key2=path2

However, the values passed to –set-file are file paths.

We’ll demonstrate this by changing our release’s default container command. First, let’s see the content of our file, default_cmd:

$ cat default_cmd
["/bin/bash", "-c", "echo 'Welcome' $HOME"]

Now, let’s change the value of command from [] to the content of default_cmd:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --set-file command=default_cmd

As expected, command has a new value:

$ helm get values -a apache | yq -o props | grep command
command = ["/bin/bash", "-c", "echo 'Welcome' $HOME"]\n

6. Using –set-json

As its name suggests, the –set-json flag is used to specify JSON values from the command line. It uses the same syntax as –set but its values are JSON:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --set-json containerPorts='{"http":9100, "https":9200}'

In the command above, we changed the values of our release’s containerPorts:

$ helm get values -a apache | yq -o props | grep containerPorts.http
containerPorts.http = 9100
containerPorts.https = 9200

7. Using –set-string

The –set-string option enforces string values. This means that if we use –set-string while passing a value to a parameter that doesn’t accept strings, we’ll get an error.

The replicaCount parameter only accepts integers, so we’ll get an error if we try to change its value with –set-string:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --set-string replicaCount=3
...truncated...
Error: UPGRADE FAILED: values don't meet the specifications of the schema(s) in the following chart(s):
apache:
- replicaCount: Invalid type. Expected: integer, given: string

8. Using –set-literal

The –set-literal flag enforces literal values. Its syntax is the same as –set, and it comes in handy when we’re passing a value containing a backslash:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --set-literal secret=b@el\\!dung

In the above, one of the backslashes in b@el\\!dung escapes the other. So, the actual value passed to the secret parameter should contain one backslash, b@el\!dung:

$ helm get values -a apache | grep secret
secret: b@el\!dung

If we used –set or –set-string, both backslashes would’ve been ignored:

$ helm upgrade apache oci://registry-1.docker.io/bitnamicharts/apache --set-string secret=b@el\\!dung

$ helm get values -a apache | grep secret
secret: b@el!dung

9. Conclusion

In this article, we talked about how to update Helm values using the –set and –values flags of the helm upgrade command.

We also mentioned –set-json, –set-string, and –set-literal, which are used to set JSON, string, and literal values, respectively. Then we discussed –set-file, a flag for updating dynamically-generated values or lengthy values from files.