Migrate Workloads from OpenShift Templates to Helm Charts

Table of Contents

Introduction

The DevOps team at QloudX recently completed a large-scale migration of 160+ containerized microservices from OpenShift to Amazon EKS for one of our enterprise customers. Although not a migration per se, the primary objective of this 7-month project, was to make all our workloads deployable on any Kubernetes platform, not just OpenShift.

Broadly speaking, there are 2 steps to accomplish this:

  1. Convert all OpenShift templates to Helm charts
  2. Migrate running customer production workloads from OpenShift templates to Helm charts

This article is all about step 1: converting OpenShift templates to Helm charts.

A Bit of A Background

Our products have been running as containers on OpenShift for many years now. They benefit immensely from all the features & addons that OpenShift provides over & above vanilla Kubernetes. However, this convenience comes at a cost.

All our microservices are defined as OpenShift templates. The end customers of our products are also force to use OpenShift since that’s the only supported platform. And so, it was only a matter of time, before customers requested compatibility with other Kubernetes platforms.

Sometime last year, we finally took the leap & decided to migrate everything from OpenShift templates to Helm charts, that can be installed on any Kubernetes platform, including OpenShift. The biggest driver for this decision was the huge savings we could bring our customers, by providing them the option to avoid OpenShift licensing fees.

OpenShift Templates to Helm Chart Conversion

Fortunately, Red Hat provides a CLI tool for converting OpenShift templates to Helm charts:

template2helm (t2h)

However, t2h has a sneaky catch. The Helm charts it generates are only deployable on OpenShift because the objects in the charts are still OpenShift-specific, such as DeploymentConfigs & Routes.

Let’s see step-by-step how to build Helm charts compatible with vanilla Kubernetes.

First, run t2h on your templates one-by-one:

template2helm convert \
--template my-ocp-template.yaml \
--chart my-helm-chart

Next, you can delete any ImageStream YAMLs (imagestream.yaml) that might have been generated, since ImageStreams aren’t recognized by vanilla Kubernetes.

Also rename all deploymentconfig.yaml to deployment.yaml & all route.yaml to ingress.yaml.

Finally, either remove or provide a default value to all params with a TODO comment in the chart’s values.yaml:

my_param_1: '# TODO: must define a default value for .my_param_1'
my_param_2: '# TODO: must define a default value for .my_param_2'
my_param_3: '# TODO: must define a default value for .my_param_3'

Convert DeploymentConfig to Deployment

Here is a sample DeploymentConfig:

apiVersion: v1
kind: DeploymentConfig
metadata:
  name: my-app
spec:
  replicas: 1
  strategy:
    rollingParams:
      timeoutSeconds: 300
    type: Rolling
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - ...
  triggers:
  - type: ConfigChange

Make the following changes:

  1. Set apiVersion to apps/v1
  2. Change kind: DeploymentConfig to kind: Deployment
  3. Remove triggers
  4. If spec.strategy.type = Rolling, set it to RollingUpdate
  5. Add selector to spec:
spec:
  selector:
    matchLabels:
      # Copy the contents of spec.template.metadata.labels here

The final deployment looks like this:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
spec:
  replicas: 1
  strategy:
    rollingParams:
      timeoutSeconds: 300
    type: RollingUpdate
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - ...

Convert Route to Ingress

Here is a sample Route:

apiVersion: v1
kind: Route
metadata:
  name: my-app
spec:
  host: my-app.com
  port:
    targetPort: 8080-tcp
  to:
    kind: Service
    name: my-app
    weight: 100
  wildcardPolicy: None

To convert routes to ingress:

  1. Set apiVersion to networking.k8s.io/v1
  2. Set kind to Ingress
  3. Restructure the entire spec section as follows:
spec:
  rules:
  - host: # Route's host
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: # Target service name
            port:
              # Provide either port name or number
              name: # Port name
              number: # Port number

Conclusion

And that’s it! That’s all you need to do to get Helm charts deployable on vanilla Kubernetes. There will of course be some more work to do based on your specific use cases, such as the ingress annotations based on the choice of your ingress controller.

Head on over to part 2 of this blog series to learn how to orchestrate the migration of running workloads from OpenShift templates to Helm charts.

About the Author ✍🏻

Harish KM is a Principal DevOps Engineer at QloudX & a top-ranked AWS Ambassador since 2020. 👨🏻‍💻

With over a decade of industry experience as everything from a full-stack engineer to a cloud architect, Harish has built many world-class solutions for clients around the world! 👷🏻‍♂️

With over 20 certifications in cloud (AWS, Azure, GCP), containers (Kubernetes, Docker) & DevOps (Terraform, Ansible, Jenkins), Harish is an expert in a multitude of technologies. 📚

These days, his focus is on the fascinating world of DevOps & how it can transform the way we do things! 🚀

One Reply to “Migrate Workloads from OpenShift Templates to Helm Charts”

Leave a Reply

Your email address will not be published. Required fields are marked *