Streamlining Helm to Kustomize Migration: Simplifying Complex Workflows with Kubectl-Neat

Introduction

Deniz TÜRKMEN
5 min readSep 6, 2024

I am facing a new challenge: the process of migrating from Helm to Kustomize. I will explain how I completed this process step by step in a simple and clear way.

  • Helm: is a package manager for Kubernetes that simplifies the deployment, management, and versioning of applications using pre-configured templates called charts.
  • Kustomize: is a Kubernetes configuration management tool that allows you to customize and deploy YAML manifests without modifying the original files by using overlays and patches.
Helm vs Kustomize

Pre-requisites;

  • Helm must be installed on the system.
  • Kustomize must be installed on the system.
  • Kubectl-Neat tool must be installed on the system.
  • Kubernetes tool must be installed on the system.

Install helm-3 with the following command.

curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /usr/share/keyrings/helm.gpg > /dev/null

sudo apt-get install apt-transport-https --yes

echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list

sudo apt-get update

sudo apt-get install helm

Version checking;

helm version

Install kubeclt-neat with the following command. Let’s not forget that kubetl-neat has a krew dependency.

# run
(
set -x; cd "$(mktemp -d)" &&
OS="$(uname | tr '[:upper:]' '[:lower:]')" &&
ARCH="$(uname -m | sed 's/x86_64/amd64/' | sed 's/arm.*$/arm/')" &&
KREW="krew-${OS}_${ARCH}" &&
curl -fsSLO "https://github.com/kubernetes-sigs/krew/releases/latest/download/${KREW}.tar.gz" &&
tar zxvf "${KREW}.tar.gz" &&
./"${KREW}" install krew
)

# export to ~/.bashrc
export PATH="${KREW_ROOT:-$HOME/.krew}/bin:$PATH"

# install
kubectl krew install neat

# verify
kubectl neat --help
  • Verify the installation;
kubectl neat --help

Let me walk you through my step-by-step approach to tackling this challenge.

First, When migrating from Helm to Kustomize, the complexity of Helm made the process difficult. After doing some online research, I discovered kubectl-neat, a tool that simplifies Kubernetes object outputs. Here’s how it helped me: it cleaned up and clarified the output, making the migration much more manageable.

Since the deployments were already running on the Kubernetes cluster with Helm, I didn’t waste time translating the values.yaml, template, and chart.yaml files from Helm to Kustomize. Instead, I used kubectl-neat to simplify the process.

So how did I do that 🚀🚀🚀🚀🚀

Let’s take a look at the objects we’ll be transforming. In this example, I will convert the objects in the poc namespace from Helm to Kustomize. As you can see, there are two objects: a Deployment and a Service. But first, let me show you the Helm deployment output.

helm output

and

k8s objects
├── kustomize
├── base
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── namespace.yaml
│ ├── kustomization.yaml
└ overlays
├── dev-poc
│ └── kustomization.yaml
├── ── ── ── ── ── ── ── ── ──

Let’s start by setting up the base-directory for this.

Let’s use kubectl-neat.

kubectl get deployments.apps -n poc -o yaml | kubectl neat > deployment.yaml

Next, open the deployment YAML file with vim, remove the Helm-specific sections, and here’s the final version of the deployment.

apiVersion: v1
items:
- apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app.kubernetes.io/instance: hello-wolrd
name: hello-wolrd
namespace: poc
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app.kubernetes.io/instance: hello-wolrd
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/instance: hello-wolrd
spec:
containers:
- image: nginx:1.16.0
imagePullPolicy: IfNotPresent
livenessProbe:
failureThreshold: 3
httpGet:
path: /
port: http
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
name: hello-wolrd
ports:
- containerPort: 80
name: http
protocol: TCP
readinessProbe:
failureThreshold: 3
httpGet:
path: /
port: http
scheme: HTTP
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
serviceAccount: hello-wolrd
serviceAccountName: hello-wolrd
terminationGracePeriodSeconds: 30
kind: List
metadata: {}

Let’s do the same operations in the service.

kubectl get service -n poc hello-wolrd -o yaml | kubectl neat > service.yaml

Next, open the deployment YAML file with vim, remove the Helm-specific sections, and here’s the final version of the service.

apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/instance: hello-wolrd
name: hello-wolrd
namespace: poc
spec:
clusterIP: 10.97.35.67
clusterIPs:
- 10.97.35.67
ipFamilies:
- IPv4
ipFamilyPolicy: SingleStack
ports:
- name: http
port: 80
targetPort: http
selector:
app.kubernetes.io/instance: hello-wolrd

Here’s the final version of the namespace.yaml as well;

apiVersion: v1
kind: Namespace
metadata:
name: base

Finally, let’s write the kustomization.yaml file for the base setup.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
metadata:
name: convert

resources:
- namespace.yaml
- service.yaml
- deployment.yaml

Next, navigate to the overlays/dev-poc folder and write the kustomization.yaml file.

Now it’s time to run the build command… but first, let’s look at the contents of kustomization.yaml.

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization

resources:
- ../../base

namePrefix: dev-poc
nameSuffix: "-001"
namespace: dev-poc

images:
- name: nginx
newTag: latest

Next,

kubectl kustomize .

or

kustomize build .

Result;

Success! We smoothly translated the manifests from Helm to Kustomize in a simple and straightforward way.

Conclusion

Converting from Helm to Kustomize can be challenging due to Helm’s complex structure, but tools like kubectl-neat can significantly simplify the process. By leveraging kubectl-neat, we were able to clean up Kubernetes object outputs, making the migration smoother and more manageable. We set up the Kustomize file structure, created base and overlay configurations, and utilized simple commands to transform and deploy our resources effectively. This approach highlights the importance of using the right tools to streamline workflows, making complex migrations more approachable and efficient.

--

--