Converting Helm Charts Into Jenkins X Apps

Your cluster is bound to run quite a few third-party applications. They need to be installed and managed somehow. This article offers one possible way to install and maintain third-party applications using Jenkins X Apps. We'll use Istio as an example of such an application and try to figure out how to convert its official Helm charts into Jenkins X Apps and, during that process, explore some of the benefits they provide.

If you hope to run the examples in this article, you'll need a Kubernetes cluster with Jenkins X installed using Jenkins X Boot.

If you read Istio documentation, you'll discover that two charts need to be installed; istio-init and istio. You'll also find out that the repository where the charts are stored is available from https://storage.googleapis.com/istio-release/releases/1.3.2/charts/. Given than one Jenkins X App references one Helm chart, we'll need to add two Apps; one for istio-init and the other for istio. Equipped with that knowledge, we can add the first of the two Apps. The command is as follows.

jx add app istio-init \
    --repository https://storage.googleapis.com/istio-release/releases/1.3.2/charts/

Just as before, the output of that command will differ depending on whether you used Jenkins X Boot with the dev repo, or you didn't.

You should see the link to the newly created pull request. Open it and click the Files changed tab so that we review the suggested changes.

By adding istio-init, the same files changed as with Prometheus, except that two (of three) are in different directories.

The env/istio-init/README.MD file contains information about the App and the whole README from the original chart. Next, we have env/istio-init/templates/app.yaml that is the definition of the App, with the information about the repository jenkins.io/chart-repository, the name of the chart (jenkins.io/app-name), and the version(jenkins.io/app-version). Finally, istio-init was added together with other dependencies in env/requirements.yaml.

As you can see, it does not matter much whether an App was added from the catalog of those supported by the Jenkins X community, or from any available Helm chart. In all the cases, it is based on a Helm chart, and as long as Jenkins X has the information about the name, version, and the repository where the chart resides, it will convert it into an App.

To finish the process, please select the Conversation tab, and click Merge pull request, followed with the Confirm Merge button. As you already know, that will trigger a webhook that will notify the cluster that there is a change in one of the repositories and, as a result, a new pipeline activity will be created.

CLUSTER_NAME=[...] # Replace `[...]` with the name of your cluster

jx get activity \
    --filter environment-$CLUSTER_NAME-dev/master \
    --watch

Press ctrl+c to stop watching the activity once it is successfully finished.

Finally, we'll confirm that istio-init was installed correctly by outputting the Custom Resource Definitions (CRDs) that contain istio.io in their name. If you're not familiar with Istio, all that istio-init does is install those CRDs. The rest of the setup comes afterward.

kubectl get crds | grep 'istio.io'

Unless Istio changed since the time I wrote this (October 2019), there should be twenty-three CRDs in the output, and we can conclude that the first part of the Istio setup was done correctly.

That's it. You saw how you can create Jenkins X Apps through the jx add app command. We also explored how those Apps can be updated or removed. If you're using the dev repository, you saw some of the benefits of the Apps, mainly their support for GitOps processes. Every time an App is added or removed, jx creates a new branch and a pull request, and it waits for you to review and approve the changes by merging it to the master.

In some cases, however, you might want to skip reviewing and merging pull requests. You might want to let Jenkins X do that for you, as well. In such cases, you can add the --auto-merge argument.

The --auto-merge argument might not work due to the issues 5761. Feel free to monitor it to see whether it was resolved.

You should understand that jx add app and jx delete app commands are only manipulating files in the dev repository and pushing them to Git. Everything else is done by Jenkins X running in the cluster. That means that you do not have to use those commands. Think of them more as "helpers" than as requirements for working with Apps. We can accomplish the same without them. We can create the files we need and push them to Git. As a result, a new App will be added without us executing any command (excluding git).

We still need to apply the second chart (istio), so we'll use that as an excuse to try to add an App without executing jx commands.

Since we are about to create and modify a few files in the local copy of the dev repository, we should start by pulling the latest codebase from GitHub.

git pull

Now that we have a local copy of the latest version of the repository, we can create a new App. Remember, this time, we're exploring how to do that by creating the files ourselves instead of using the jx add app command.

We can approach this challenge from two directions. One option could be to create all the files from scratch. The other is to copy a directory of one of the existing Apps and modify it to suit our needs. We'll go with the second option since it is probably an easier one. Given that we already have the App that's using istio-init, its files are probably the best candidate to be used as the base for istio.

cp -r env/istio-init env/istio

Now that we copied the istio-init directory as istio, all we have to do is change a few files. We'll skip modifying the README. It is important only for humans (we might read it), but it plays no role in the process. In the "real world" situations, I'd expect you to change it as well. But since this is not the "real world" but rather a learning experience, there's no need for us to spend time with it.

There are three files that we might need to change. We might create env/istio/templates/values.yaml if we'd like to change any of the chart's default values. We'll skip that one because istio is good as-is. Instead, we'll focus on the other two files.

cat env/istio/templates/app.yaml

That's the definition of the App we're about to add to the cluster. It is a copy of istio-init, so all we need to do is change the jenkins.io/app-name and name values from istio-init to istio. We'll also change jenkins.io/chart-description. It serves only informative purposes. But, since we're nice people and don't want to confuse others, changing it might provide additional clarity to whoever might explore it later.

The command that should make those changes is as follows.

cat env/istio/templates/app.yaml \
    | sed -e 's@istio-init@istio@g' \
    | sed -e \
    's@initialize Istio CRDs@install Istio@g' \
    | tee env/istio/templates/app.yaml

The definition of an App is useless by itself. Its existence will not result in it running inside the cluster. We need to add it as yet another dependency in env/requirements.yaml. So, let's take a quick peek at what's inside it.

cat env/requirements.yaml

The output is a follows.

dependencies:
- name: jxboot-resources
  repository: http://chartmuseum.jenkins-x.io
- alias: tekton
  name: tekton
  repository: http://chartmuseum.jenkins-x.io
- alias: prow
  condition: prow.enabled
  name: prow
  repository: http://chartmuseum.jenkins-x.io
- alias: lighthouse
  condition: lighthouse.enabled
  name: lighthouse
  repository: http://chartmuseum.jenkins-x.io
- name: jenkins-x-platform
  repository: http://chartmuseum.jenkins-x.io
- name: istio-init
  repository: https://storage.googleapis.com/istio-release/releases/1.3.2/charts/
  version: 1.3.2

All but the last dependency are those of the system at its default configuration. Later on, we used jx add app to add istio-init to the mix. Now we're missing an entry for istio as well. The repository and the version are the same, and the only difference is in the name.

echo "- name: istio
  repository: https://storage.googleapis.com/istio-release/releases/1.3.2/charts/
  version: 1.3.2" \
  | tee -a env/requirements.yaml

All that's left is to push the changes to GitHub and let the system converge the actual into the desired state, which we just extended with an additional App. Normally, we'd create a branch, push the changes there, create a pull request, and merge it to the master branch. That would be the correct way to handle this or any other change. But, in the interest of time, we'll skip that with the assumption that you already know how to create PRs. If you don't, you're in the wrong industry.

git add .

git commit -m "Added Istio"

git push

jx get activity \
    --filter environment-$CLUSTER_NAME-dev/master \
    --watch

We committed and pushed the changes to the master branch and started watching the activities to confirm that the changes are applied to the cluster. Once the new activity is finished, please press ctrl+c to stop watching.

Istio should be fully up-and-running. We can confirm that by listing all the Pods that contain istio in their names.

kubectl get pods | grep istio

This is neither the time nor the place to dive deeper into Istio. That was not the goal. I used it only as an example of different ways to add Jenkins X Apps to the system.

Speaking of the Apps, let's see which ones are currently running in the cluster. You already saw that jx has a helper command for almost anything, so it should be no surprise to find out that retrieving the apps is available as well.

jx get apps

The output is as follows, at least for those who installed Jenkins X using the Boot.

Name       Version Chart Repository                                                    Namespace Status               Description
istio-init 1.3.2   https://storage.googleapis.com/istio-release/releases/1.3.2/charts/           READY FOR DEPLOYMENT Helm chart to initialize Istio CRDs
istio      1.3.2   https://storage.googleapis.com/istio-release/releases/1.3.2/charts/           READY FOR DEPLOYMENT Helm chart to install Istio

That's it. We explored a few commonly used ways to add, manage, and delete Jenkins X Apps. We'll have a short discussion around them soon. For now, we'll remove istio and istio-init since we do not need them anymore.

git pull

jx delete app istio

You know what to do next. Merge the PR so that the change (istio removal) is applied to the system. We can see that through the proposed changes to the env/requirements.yaml file.

You'll notice that the jx delete app command works no matter whether the App was added through jx add app or by fiddling with the files directly in Git. It always operates through Git (unless you are NOT using the dev repo).

The next in line for elimination is istio-init, and the process is the same.

git pull

jx delete app istio-init

I'll leave you to do the rest yourself (if you're using the Boot). Merge that PR!

That's it. You learned the basics of extending the Jenkins X platform by adding Apps. As a matter of fact, it's not only about extending Jenkins X but more about having a reliable way to add any third-party application to your cluster. However, not all are equally well suited to be Jenkins X Apps.

Jenkins X Apps are beneficial for at least two scenarios. When we want to extend Jenkins X, adding Apps is, without a doubt, the best option. Given that the Apps can be any Helm chart, we can convert any application to be an App.

Besides those designed to extend Jenkins X, excellent candidates are the charts that do not need to be in multiple repositories. For example, if we'd like to run two instances of Prometheus (one for testing and the other for production), we're better of adding them to the associated permanent environment repositories. However, many are not well suited to run in testing or are not worth validating. Prometheus might be such a case. If we upgrade it and that turns out to be a bad choice, no harm will be done to the cluster. We might not be able to retrieve some metrics, but that would be only temporary until we roll back to the previous version. The exception would be if we hook HorizontalPodAutoscaler to Prometheus metrics, in which case testing it before deploying a new version to production is paramount. So, when applications should run only in production (without a second instance used for testing), Apps are a better way to manage them due to a few additional benefits they provide.

At the core, Jenkins X Apps follow the same GitOps principles as any other. Their definitions are stored in Git, we can create pull requests and review changes, and only a merge to the master branch will change the state of the cluster. Using Apps is not much different from defining dependencies in staging, production, or any other permanent environment repository. What makes them "special" is the addition of a few helper features and a few conventions that make management easier. We have a better-defined pipeline. Branches and pull requests are created automatically. Secrets are stored in Vault. Dependencies are better organized. And so on, and so forth. We explored only a few of those features. Later on, we'll see a few more in action, and the community is bound to add more over time.

The DevOps 2.6 Toolkit: Jenkins X

The article you just read is an extract from The DevOps 2.6 Toolkit: Jenkins X.

You can get the book from Amazon, LeanPub, or look for it through your favorite book seller.

2 thoughts on “Converting Helm Charts Into Jenkins X Apps

  1. Zakir Hossain

    I’d like to convert wordpress helm from the following repository but getting error.
    https://github.com/helm/charts/tree/master/stable/wordpress

    ~$ jx add app wordpress –repository https://github.com/helm/charts/tree/master/stable/wordpress
    Adding missing Helm repo: github.com https://github.com/helm/charts/tree/master/stable/wordpress
    error: adding helm repo: failed to add the repository ‘github.com’ with URL ‘https://github.com/helm/charts/tree/master/stable/wordpress’: failed to run ‘helm repo add github.com https://github.com/helm/charts/tree/master/stable/wordpress‘ command in directory ”, output: ‘Error: Looks like “https://github.com/helm/charts/tree/master/stable/wordpress” is not a valid chart repository or cannot be reached: Failed to fetch https://github.com/helm/charts/tree/master/stable/wordpress/index.yaml : 404 Not Found’

    Reply

Leave a Reply