From DevOps to GitOps

Everyone likes a camp romance. Argo Cd and Tekton are a match made in Kubernetes heaven. See what makes them tick!

 

Helm is a package manager for Kubernetes. It provides an easy way to deploy a set of resources on a Kubernetes or Red Hat OpenShift clusters. This article starts with a quick introduction to Helm. Then we'll use it to deploy a .NET application.

Overview of Helm

A Helm chart describes a set of resources to deploy. The chart uses templates that can be configured on the command line or through a YAML file.

Charts can be distributed by hosting them on an HTTP server called a chart repository. The helm executable can fetch charts from the repository.

A Helm chart deployed on Kubernetes is called a release. After you install the initial release, it can be updated. Each update has a corresponding release number. The release can also be rolled back to an earlier version.

Helm prerequisites and setup

To use Helm, you need the helm binary and an OpenShift cluster.

You can download the binary from the GitHub release page. After you’ve extracted the tarball, add the directory containing the command to your PATH environment variable. You can check that the command works by executing helm version as follows:

$ helm version
version.BuildInfo{Version:"v3.5.4", GitCommit:"1b5edb69df3d3a08df77c9902dc17af864ff05d1", GitTreeState:"clean", GoVersion:"go1.15.11"}

Use the oc client command to log in to your OpenShift cluster:

$ oc login --token=xxx --server=https://yyy

Note: If you are not familiar with the OpenShift client, check out the Getting started with the OpenShift CLI documentation.

For our example, we’ll use the .NET Core 3.1 and .NET 5.0 versions. You can check which versions are available globally using the following command:

$ oc get -n openshift is dotnet --template='{{range .spec.tags}}{{.name}}{{"\n"}}{{end}}'
2.1
2.1-el7
2.1-ubi8
3.1
3.1-el7
3.1-ubi8
latest

The output shows that the .NET 5 version is not available on my cluster. Because I am not an administrator. I will import the images into my project namespace using the Bash shell script install-imagestreams.sh from the s2i-dotnetcore repository. The repository has a PowerShell script, too:

$ wget https://raw.githubusercontent.com/redhat-developer/s2i-dotnetcore/master/install-imagestreams.sh
$ chmod +x install-imagestreams.sh
$ ./install-imagestreams.sh --os rhel

When the shell script finishes, you can check the versions available in the project namespace by running the previous command without the -n openshift argument:

$ oc get is dotnet --template='{{range .spec.tags}}{{.name}}{{"\n"}}{{end}}'
2.1
2.1-el7
2.1-ubi8
3.1
3.1-el7
3.1-ubi8
5.0
5.0-ubi8
latest

The output shows that .NET 5.0 is available now.

Using the .NET Helm chart

First, we’ll configure Helm to fetch templates from the redhat-helm-charts repository:

$ helm repo add redhat-charts https://redhat-developer.github.io/redhat-helm-charts

You can see the available charts using the helm search command:

$ helm search repo redhat-charts
NAME                    CHART VERSION ...
redhat-charts/dotnet    0.0.1         ...
redhat-charts/nodejs    0.0.1         ...
redhat-charts/quarkus   0.0.3         ...

To get more information about the dotnet chart, you can use the helm inspect command. The readme subcommand displays a description of the template. The values subcommand shows the configuration values of the template:

$ helm inspect readme redhat-charts/dotnet | less
...
You must change the `build.uri`, `build.ref` and `build.startupProject` to refer to your own application. `build.imageStreamTag.name` must be set to match the .NET version used by your application.
...

I showed here, from the output of the readme subcommand, the line that describes the mandatory values to set.

Deploy the .NET Core 3.1 application

Let’s now use the chart to deploy the .NET Core 3.1 version of the s2i-dotnetcore-ex sample application:

$ helm install mydotnetapp \
     --set build.uri=https://github.com/redhat-developer/s2i-dotnetcore-ex \
     --set build.ref=dotnetcore-3.1 \
     --set build.startupProject=app \
     --set build.imageStreamTag.name=dotnet:3.1 \
     --set build.imageStreamTag.useReleaseNamespace=true \
     redhat-charts/dotnet
NAME: mydotnetapp
LAST DEPLOYED: Thu May 20 10:22:14 2021
NAMESPACE: demo
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES: Your .NET app is building! To view the build logs, run: oc logs bc/mydotnetapp --follow Note that your Deployment will report "ErrImagePull" and "ImagePullBackOff" until the build is complete. Once the build is complete, your image will be automatically rolled out.

The first argument (mydotnetapp) is the name for our release. We’ve specified the Git repository (build.uri), the Git branch name (build.ref), and the location of the .NET project file in the repository (build.startupProject). Using build.imageStreamTag.name, we selected the s2i-dotnetcore image for .NET 3.1 that is used to build and run our application.

You can visually follow the build's progress in the OpenShift web console, as shown in Figure 1.

The Resources tab of the OpenShift console shows the status of the application.
Figure 1: Resources tab for the application in the OpenShift console.

Update the release to .NET 5

Using the helm upgrade command, you can make changes to the release. Let’s change the release to the .NET 5 version.

As we saw during the prerequisites, my cluster didn’t include a .NET 5 image. To use the image that was installed into the project namespace, I’ve added the argument --set build.imageStreamTag.useReleaseNamespace=true to the upgrade subcommand:

$ helm upgrade mydotnetapp \
    --set build.ref=dotnet-5.0 \
    --set build.imageStreamTag.name=dotnet:5.0 \
    --set build.imageStreamTag.useReleaseNamespace=true \
    redhat-charts/dotnet
Release "mydotnetapp" has been upgraded. Happy Helming!
NAME: mydotnetapp
LAST DEPLOYED: Thu May 20 10:25:39 2021
NAMESPACE: demo
STATUS: deployed
REVISION: 2
TEST SUITE: None

Instead of specifying these values on the command line, you can read them from a YAML file. For example, the values could be placed in a values.yaml file that lives in a .helm folder next to the .NET csproj project file. The values.yaml file can be checked into version control to track changes and to make the file available to other developers deploying the application. For our current release, we’re using the following values:

build:
  uri: https://github.com/redhat-developer/s2i-dotnetcore-ex
  startupProject: app
  ref: dotnet-5.0
  imageStreamTag:
	name: dotnet:5.0
	useReleaseNamespace: true

The filename can be passed to helm using the -f argument:

$ helm upgrade mydotnetapp -f values.yaml redhat-charts/dotnet
Release "mydotnetapp" has been upgraded. Happy Helming!
NAME: mydotnetapp
LAST DEPLOYED: Thu May 20 10:32:33 2021
NAMESPACE: demo
STATUS: deployed
REVISION: 3
TEST SUITE: None

Changes to a BuildConfiguration do not automatically trigger a new build. You need to start it manually:

$ oc start-build mydotnetapp

View and configure the Helm chart in OpenShift

The OpenShift console recognizes Helm charts. Under the Helm tab, you can navigate to your chart and see the three revisions you’ve deployed, as shown in Figure 2.

The application's Revision History tab shows three revisions, and shows which is currently deployed.
Figure 2: The application's revision history in the OpenShift console.

Under the Actions dropdown menu, you can remove the release completely or roll back to an earlier version. These operations can also be performed from the terminal using the helm history and helm rollback commands.

The dotnet Helm chart provides many configuration settings that make it usable for a wide range of .NET applications. These settings support adding probes, sidecar containers, and more. If you want to do something that is not supported by the chart, you can download the chart into your source repository and customize it. When running helm install or helm upgrade, you can point to the chart that lives with your sources:

$ helm pull --untardir charts --untar redhat-charts/dotnet
$ git add charts
...
make some changes to the chart at charts/dotnet
…
$ helm upgrade mydotnetapp -f values.yaml charts/dotnet

Conclusion

This article has illustrated the purpose and use of Helm. We went through the steps of deploying and updating a .NET application on OpenShift using the .NET helm chart from redhat-helm-charts. To learn more about Helm, you can read the Helm documentation. To learn more about the .NET Helm chart, you can run the helm inspect readme redhat-charts/dotnet command.

Previous resource
Deploy a Java application using Helm, Part 1
Next resource
Deploy Node.js applications to Red Hat OpenShift with Helm