Skip to content

Migrating from Tailor to Helm

Michael Sauter edited this page Sep 6, 2021 · 26 revisions

Scope and Goal of this document

Tailor has been developed for OpenShift 3.11. Back in the days, Helm 2 required the use of a privileged Tiller service and did not work well with OpenShift-specific resources. With Helm 3 and OpenShift 4, this situation as changed.

While Tailor also works in an OpenShift 4 cluster, OpenShift has integrated Helm into its product, and Helm has a huge and growing community. Therefore, it is recommended to use Helm instead of Tailor in an OpenShift 4 cluster.

This document will describe how to migrate from Tailor to Helm.

Tailor is based on OpenShift templates, which define the Kubernetes resources to apply. Helm uses a different templating language / engine, but in the end the templates also describe Kubernetes resources. Therefore, migration effort is relatively low as one only needs to change the syntax of the definition, not the definition itself. Further, there are differences between the CLI of the two tools and not all features of Tailor are available in Helm and vice-versa. Once migration to Helm is complete, it is also recommended to look at the best practices in the Helm community and adopt these.

Migrating templates

There are basically two options how to approach this: you can either convert your existing OpenShift templates to chart templates, or you can start with a blank chart and adjust it as necessary.

Option 1: Converting OpenShift templates

If you want to convert your existing templates, you may use template2helm. This method should require less effort, but you are left with a template that might have some errors and does not follow best practices from the Helm community.

Example usage:

template2helm convert -t openshift/template.yml -c . # Will create a "chart" folder in .

Option 2: Starting with a blank chart

The other option is to start from a blank chart and adjust this as necessary to match the live configuration. This will almost certainly be more effort than converting the templates, but you will learn more about Helm templating and can start out with some best practices.

Example usage:

helm create chart

Verifying the new chart

It is recommended to use helm lint to check for errors before continuing.

Next, you’d want to check whether the new Helm templates match the old OpenShift templates. For this task, it is recommended to make use of the helm-diff plugin. This will show all differences that exist between live configuration and the Helm template (note that you might need to adopt the resources first, see the next section). Adjust the new chart until there is no difference to the live configuration. Then your new chart is equivalent to the old templates, and you can remove the old templates from your repository.

Adopting existing resources

Helm does not simply take ownership on already existing resources. You need to adopt them first. To achieve this, you could use the following script (based on comments in https://github.com/helm/helm/pull/7649):

#!/usr/bin/env bash
set -eu
set -o pipefail

NAMESPACE=$1 # e.g. foo-dev
LABEL=$2     # e.g. app=foo-bar
RELEASE=$3   # e.g. bar


KINDS='ImageStream,BuildConfig,Service,DeploymentConfig,Deployment,Route,ConfigMap,Secret,PersistentVolumeClaim,ServiceAccount,RoleBinding'
RESOURCES=$(oc -n $NAMESPACE get $KINDS -l $LABEL -o template='{{range .items}}{{.kind}}/{{.metadata.name}} {{end}}')

for RESOURCE in $RESOURCES; do
    echo "Adopting $RESOURCE ..."
    oc -n $NAMESPACE annotate $RESOURCE meta.helm.sh/release-name=$RELEASE
    oc -n $NAMESPACE annotate $RESOURCE meta.helm.sh/release-namespace=$NAMESPACE
    oc -n $NAMESPACE label $RESOURCE app.kubernetes.io/managed-by=Helm
done

Example usage: ./adopt.sh foo-dev app=foo-bar bar

Notable behaviour differences between Tailor and Helm

  • Tailor supports diffing out-of-the-box, for Helm you can use the helm-diff plugin

  • Tailor supports encrypting secrets out-of-the-box, for Helm you can use the helm-secrets plugin

  • In Helm, manual changes in the cluster are not reported by helm-diff, nor does helm upgrade reset to the value in the chart. Even if the field ownership is changed back to "helm", the manual change is not reset. Only when the value in the chart changes, then the live configuration gets updated. Tailor will immediately report drift.

Tailor features for which there is no equivalent in Helm

  • Exporting of resources via tailor export. Helm does not offer this. You may want to take a look at chartify.

  • Preserving live configuration. This is due to the different patching algorithm, see the section about behaviour differences above.

Helm features for which there is no equivalent in Tailor

These are just some examples worth noting. The list is by no means complete.

Migrating secrets

Tailor supports encrypting parameter files (*.env) out-of-the-box. Helm doesn’t do that, but you can use the helm-secrets plugin. This plugin uses Mozilla SOPS under the hood, which gives you more options to encrypt secrets than just using PGP. However, the easiest transition from Tailor is using the existing PGP key.

Before you get started, ensure that you have gpg installed (on macOS you can get it from https://gpgtools.org).

Now, you should already have a private/public keypair from your Tailor setup. You’ll need to get the fingerprint of this key, e.g. by running run cat jenkins.key | gpg --import-options show-only --import. The fingerprint is the 40 character sequence on the second line.

With this fingerprint, create the following .sops.yaml file in your chart directory:

creation_rules:
  - pgp: "<fingerprint here>"

Now you are ready to create a file named secrets.yaml (or anything beginning with secrets), e.g. like this:

mysecret: s3cr3t

The file can then be encryptedvia the plugin, provided the private key belonging to the keypair as identified by the fingerprint is in your keyring. Example:

gpg --import private.key
helm secrets enc secrets.yaml

In your chart templates, you can make use of secrets like this:

data:
  my_secret_key: {{ .Values.mysecret | b64enc | quote }}

The secrets files can be decrypted either by the wrapper command secrets or via the secrets:// protocol, e.g.:

helm upgrade name . -f secrets://secrets.yaml

ODS Quickstarter Migration

The following will show one possible path to migrate an existing ODS quickstarter from Tailor to Helm. ODS quickstarters are created using Tailor, but the manifest files are not placed under version control automatically. If Helm is to be used, the manifest files need to be under version control as there is no export functionality in Helm in contrast to Tailor. As a result, migrating quickstarters means either converting manifest files in the repository (if you created them manually) or creating manifest files in the repo for the first time. Which resources you need to specify depends on the quickstarter used and if you made any changes after provisioning. This guide will assume the easiest case, which is no changes compared to the default, which is defined in https://github.com/opendevstack/ods-quickstarters/blob/master/common/ocp-config/component/template.yml. Further, it is assumed that you’ll want to use the resulting chart with the ods-pipeline project.

To get started, create a new Helm chart via helm create chart. In chart/Chart.yaml, you’ll need to change the name to the name of your component. Assuming your project is named foo and the repository foo-bar, then the component is simply bar.

Inside the new chart/templates folder, place two files, service.yaml and deployment.yaml:

deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "chart.fullname" . }}
  labels:
    {{- include "chart.labels" . | nindent 4 }}
spec:
  replicas: {{ required "replicaCount is required!" .Values.replicaCount }}
  selector:
    matchLabels:
      {{- include "chart.selectorLabels" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "chart.selectorLabels" . | nindent 8 }}
    spec:
      containers:
        - name: {{ .Chart.Name }}
          securityContext: {}
          image: "image-registry.openshift-image-registry.svc:5000/{{ .Release.Namespace }}/{{ .Chart.Name }}:{{ .Values.gitCommitSha | default .Chart.AppVersion }}"
          imagePullPolicy: IfNotPresent
          ports:
            - name: http
              containerPort: 8080
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: 8080
          readinessProbe:
            httpGet:
              path: /
              port: 8080
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ include "chart.fullname" . }}
  labels:
    {{- include "chart.labels" . | nindent 4 }}
spec:
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 8080
      protocol: TCP
      name: http
  selector:
    {{- include "chart.selectorLabels" . | nindent 4 }}

You’ll notice that:

  • instead of a DeploymentConfig, this configures a Deployment resource. Kubernetes-native Deployment resources are now recommended by OpenShift, see https://docs.openshift.com/container-platform/4.8/applications/deployments/what-deployments-are.html for more information.

  • the new Deployment resource configures health checks (livenessProbe and readinessProbe) which might not be present in the existing DeploymentConfig. Remove them if you do not want to use them, however it is recommended to configure health checks. If you keep them, make sure they make sense for your application.

  • the image tag is set to the value of .Values.gitCommitSha which is automatically provided by the ods-deploy-helm Tekton task.

As there are no specific names in those templates, you need to provide them via the chart/values.yaml file. Obviously the values in that file depend on your component, however the following defaults might work for you as-is:

values.yaml
replicaCount: 1

nameOverride: ""
fullnameOverride: ""

resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi

With the above in place, the Helm chart should be able to replace the existing Tailor manifests. Of course you can customise the templates further, and/or add more. When you try to release the Helm chart the first time, remember that you might need to adopt any existing resources beforehand, as explained above.