Convert Kubernetes deployment YAML into Helm Chart YAML




In this article we are going to look how can we convert Kubernetes YAMLs into Helm Chart YAMLs.

Objective 1 : - At first we are going to create simple Kubernetes deployment(k8s-deployment.yaml)` and in that deployment we are going to deploy a microservice application.

Objective 2 : - Secondly we are going to `create service(k8s-service.yaml) for exposing the deployment as a service on NodePort.

Objective 3 : - Here we are going to convert Kubernetes deployment(k8s-deployment.yaml) and create service(k8s -service.yaml) into a Helm Chart YAMls.

1. On a high level this is how it looks -



2.Create kubernetes deployment YAML(k8s-deployment.yaml)

Before we jump to Helm Chart lets create simple YAMLs for kubernetes.

2.1 k8s-deployment.yaml

We are going to keep k8s-deployment.yaml very simple and we are going to deploy very small microservice application.

Let’s create k8s-deployment.yaml

1touch k8s-deployment.yaml

Open the deployment YAML into vi mode

1vi k8s-deployment.yaml

Copy following deployment configs and save

 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  creationTimestamp: null
 5  labels:
 6    app: demo
 7  name: demo
 8spec:
 9  replicas: 1
10  selector:
11    matchLabels:
12      app: demo
13  strategy: {}
14  template:
15    metadata:
16      creationTimestamp: null
17      labels:
18        app: demo
19    spec:
20      containers:
21      - image: rahulwagh17/kubernetes:jhooq-k8s-springboot
22        name: kubernetes
23        resources: {}
24status: {}

2.2 Deploy k8s-deployment.yaml

After creating the k8s-deployment.yaml now you need to deploy it inside the kubernetes cluster

Run the following kubectl command to deploy

1kubectl apply -f k8s-deployment.yaml 

Check the deployment status by running following command

1kubectl get deployment demo

It should return the following status on successful deployment

1NAME   READY   UP-TO-DATE   AVAILABLE   AGE
2demo   1/1     1            1           4m52s

3. Create kubernetes service YAML(k8s-service.yaml)

After successful deployment, now we need to create service YAML .i.e. - k8s-service.yaml

Let’s create k8s-service.yaml

1touch k8s-service.yaml

Open the service YAML into vi mode

1vi k8s-service.yaml

Copy following deployment configs and save

 1apiVersion: v1
 2kind: Service
 3metadata:
 4  creationTimestamp: null
 5  labels:
 6    app: demo
 7  name: demo-service
 8spec:
 9  ports:
10  - port: 8080
11    protocol: TCP
12    targetPort: 8080
13  selector:
14    app: demo
15  type: NodePort
16status:
17  loadBalancer: {}

Run the following kubectl command to expose the service as NodePort on port 8080

1kubectl apply -f k8s-service.yaml 

Check the service status by running following command

1kubectl get service demo-service

It should return the following status once you expose it successfully

1NAME           TYPE       CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
2demo-service   NodePort   10.233.10.61   <none>        8080:30036/TCP   9s

We could tes it by accessing the successfully deployed application on browser


4. Convert kubernetes YAML to Helm Chart

Now lets start converting kubernetes(k8s) YAMLs into Helm Chart.

4.1 Create your Helm Chart

The first step for this conversion is to create the Helm Chart, so that we can have all the necessary YAMLs generated.

Here is comparision of YAMLs generated by Helm Chart and Kubernetes(k8s) -

YAMLs Generated by Helm Chart Kubernetes(k8s) YAMLs
1 Chart.yaml
2 helper.tpl
3 deployment.yaml k8s-deployment.yaml
4 hpa.yaml
5 ingress.yaml
6 service.yaml k8s-service.yaml
7 serviceaccount.yaml
8 test-connection.yaml
9 values.yaml In k8s-deployment.yaml
1. replicas: 1
2. docker image =rahulwagh17/kubernetes:jhooq-k8s-springboot

Lets create demo-helm-chart

1helm create demochart

Verify the YAML files generated after running the helm create command

1tree demochart

It should return you back with following file tree structure

 1demochart
 2├── Chart.yaml
 3├── charts
 4├── templates
 5│ ├── NOTES.txt
 6│ ├── _helpers.tpl
 7│ ├── deployment.yaml
 8│ ├── hpa.yaml
 9│ ├── ingress.yaml
10│ ├── service.yaml
11│ ├── serviceaccount.yaml
12│ └── tests
13│     └── test-connection.yaml
14└── values.yaml 

4.2 Convert and Update Chart.yaml, deployment.yaml, service.yaml and values.yaml

Follow the instructions for updating the each YAML

4.2.1 Chart.yaml

The first YAML which we are converting is chart.yaml but it is optional and does not require any change but it would be nice to update some value with regards to your project name.

So update the following values inside your chart.yaml

1apiVersion: v2
2name: demochart
3description:  Convert Kubernetes(yamls) to Helm Chart
4type: application
5version: 0.1.0
6appVersion: 1.16.0

4.2.2 deployment.yaml

The next YAML to convert is deployment.yaml but here we need to disable the livenessProbe and readinessProbe because it is very small application and we can verify the application deployment manually.

When we generate the Helm Chart then by default deployment.yaml is prefilled/pre-populated with some configs, so we need to update only -

  1. containerPort : 8080
 1apiVersion: apps/v1
 2kind: Deployment
 3metadata:
 4  name: {{ include "demochart.fullname" . }}
 5  labels:
 6    {{- include "demochart.labels" . | nindent 4 }}
 7spec:
 8  {{- if not .Values.autoscaling.enabled }}
 9  replicas: {{ .Values.replicaCount }}
10  {{- end }}
11  selector:
12    matchLabels:
13      {{- include "demochart.selectorLabels" . | nindent 6 }}
14  template:
15    metadata:
16      {{- with .Values.podAnnotations }}
17      annotations:
18        {{- toYaml . | nindent 8 }}
19      {{- end }}
20      labels:
21        {{- include "demochart.selectorLabels" . | nindent 8 }}
22    spec:
23      {{- with .Values.imagePullSecrets }}
24      imagePullSecrets:
25        {{- toYaml . | nindent 8 }}
26      {{- end }}
27      serviceAccountName: {{ include "demochart.serviceAccountName" . }}
28      securityContext:
29        {{- toYaml .Values.podSecurityContext | nindent 8 }}
30      containers:
31        - name: {{ .Chart.Name }}
32          securityContext:
33            {{- toYaml .Values.securityContext | nindent 12 }}
34          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
35          imagePullPolicy: {{ .Values.image.pullPolicy }}
36          ports:
37            - name: http
38              containerPort: 8080 #update the port here to 8080
39              protocol: TCP
40          livenessProbe:
41            httpGet:
42              path: /
43              port: http
44          readinessProbe:
45            httpGet:
46              path: /
47              port: http
48          resources:
49            {{- toYaml .Values.resources | nindent 12 }}
50      {{- with .Values.nodeSelector }}
51      nodeSelector:
52        {{- toYaml . | nindent 8 }}
53      {{- end }}
54      {{- with .Values.affinity }}
55      affinity:
56        {{- toYaml . | nindent 8 }}
57      {{- end }}
58      {{- with .Values.tolerations }}
59      tolerations:
60        {{- toYaml . | nindent 8 }}
61      {{- end }}
62 

4.2.3 service.yaml

The next YAML which we need to convert is service.yaml and here we do not need to update anything configs, we can pretty much keep it in the same shape.

 1apiVersion: v1
 2kind: Service
 3metadata:
 4  name: {{ include "demochart.fullname" . }}
 5  labels:
 6    {{- include "demochart.labels" . | nindent 4 }}
 7spec:
 8  type: {{ .Values.service.type }}
 9  ports:
10    - port: {{ .Values.service.port }}
11      targetPort: http
12      protocol: TCP
13      name: http
14  selector:
15    {{- include "demochart.selectorLabels" . | nindent 4 }}
16

4.2.4 values.yaml

The last YAMLs which is left for conversion is values.yaml and here we need to update couple values -

  1. repository : rahulwagh17/kubernetes:jhooq-k8s-springboot
  2. port : 8080

Here is how it should look like

 1replicaCount: 1
 2
 3image:
 4  repository: rahulwagh17/kubernetes:jhooq-k8s-springboot #update the docker image name
 5  pullPolicy: IfNotPresent
 6  # Overrides the image tag whose default is the chart appVersion.
 7  tag: ""
 8
 9imagePullSecrets: []
10nameOverride: ""
11fullnameOverride: ""
12
13serviceAccount:
14  # Specifies whether a service account should be created
15  create: true
16  # Annotations to add to the service account
17  annotations: {}
18  # The name of the service account to use.
19  # If not set and create is true, a name is generated using the fullname template
20  name: ""
21
22podAnnotations: {}
23
24podSecurityContext: {}
25  # fsGroup: 2000
26
27securityContext: {}
28  # capabilities:
29  #   drop:
30  #   - ALL
31  # readOnlyRootFilesystem: true
32  # runAsNonRoot: true
33  # runAsUser: 1000
34
35service:
36  type: NodePort
37  port: 8080
38
39ingress:
40  enabled: false
41  annotations: {}
42    # kubernetes.io/ingress.class: nginx
43    # kubernetes.io/tls-acme: "true"
44  hosts:
45    - host: chart-example.local
46      paths: []
47  tls: []
48  #  - secretName: chart-example-tls
49  #    hosts:
50  #      - chart-example.local
51
52resources: {}
53  # We usually recommend not to specify default resources and to leave this as a conscious
54  # choice for the user. This also increases chances charts run on environments with little
55  # resources, such as Minikube. If you do want to specify resources, uncomment the following
56  # lines, adjust them as necessary, and remove the curly braces after 'resources:'.
57  # limits:
58  #   cpu: 100m
59  #   memory: 128Mi
60  # requests:
61  #   cpu: 100m
62  #   memory: 128Mi
63
64autoscaling:
65  enabled: false
66  minReplicas: 1
67  maxReplicas: 100
68  targetCPUUtilizationPercentage: 80
69  # targetMemoryUtilizationPercentage: 80
70
71nodeSelector: {}
72
73tolerations: []
74
75affinity: {}
76 

5. Verify the Conversion of YAMLs

Lets verify the conversion of the YAMLs with helm template command. This command will show us the serviceaccount.yaml, service.yaml and deployment.yaml which will be equivalent of the kubernetes(k8s) YAMLs which we generated manually.

1helm template demoHelmChart

It should return you back with -

  1---
  2# Source: demochart/templates/serviceaccount.yaml
  3apiVersion: v1
  4kind: ServiceAccount
  5metadata:
  6  name: RELEASE-NAME-demochart
  7  labels:
  8    helm.sh/chart: demochart-0.1.0
  9    app.kubernetes.io/name: demochart
 10    app.kubernetes.io/instance: RELEASE-NAME
 11    app.kubernetes.io/version: "1.16.0"
 12    app.kubernetes.io/managed-by: Helm
 13---
 14# Source: demochart/templates/service.yaml
 15apiVersion: v1
 16kind: Service
 17metadata:
 18  name: RELEASE-NAME-demochart
 19  labels:
 20    helm.sh/chart: demochart-0.1.0
 21    app.kubernetes.io/name: demochart
 22    app.kubernetes.io/instance: RELEASE-NAME
 23    app.kubernetes.io/version: "1.16.0"
 24    app.kubernetes.io/managed-by: Helm
 25spec:
 26  type: NodePort
 27  ports:
 28    - port: 8080
 29      targetPort: http
 30      protocol: TCP
 31      name: http
 32  selector:
 33    app.kubernetes.io/name: demochart
 34    app.kubernetes.io/instance: RELEASE-NAME
 35---
 36# Source: demochart/templates/deployment.yaml
 37apiVersion: apps/v1
 38kind: Deployment
 39metadata:
 40  name: RELEASE-NAME-demochart
 41  labels:
 42    helm.sh/chart: demochart-0.1.0
 43    app.kubernetes.io/name: demochart
 44    app.kubernetes.io/instance: RELEASE-NAME
 45    app.kubernetes.io/version: "1.16.0"
 46    app.kubernetes.io/managed-by: Helm
 47spec:
 48  replicas: 1
 49  selector:
 50    matchLabels:
 51      app.kubernetes.io/name: demochart
 52      app.kubernetes.io/instance: RELEASE-NAME
 53  template:
 54    metadata:
 55      labels:
 56        app.kubernetes.io/name: demochart
 57        app.kubernetes.io/instance: RELEASE-NAME
 58    spec:
 59      serviceAccountName: RELEASE-NAME-demochart
 60      securityContext:
 61        {}
 62      containers:
 63        - name: demochart
 64          securityContext:
 65            {}
 66          image: "rahulwagh17/kubernetes:jhooq-k8s-springboot:1.16.0"
 67          imagePullPolicy: IfNotPresent
 68          ports:
 69            - name: http
 70              containerPort: 8080
 71              protocol: TCP
 72          livenessProbe:
 73            httpGet:
 74              path: /
 75              port: http
 76          readinessProbe:
 77            httpGet:
 78              path: /
 79              port: http
 80          resources:
 81            {}
 82---
 83# Source: demochart/templates/tests/test-connection.yaml
 84apiVersion: v1
 85kind: Pod
 86metadata:
 87  name: "RELEASE-NAME-demochart-test-connection"
 88  labels:
 89    helm.sh/chart: demochart-0.1.0
 90    app.kubernetes.io/name: demochart
 91    app.kubernetes.io/instance: RELEASE-NAME
 92    app.kubernetes.io/version: "1.16.0"
 93    app.kubernetes.io/managed-by: Helm
 94  annotations:
 95    "helm.sh/hook": test
 96spec:
 97  containers:
 98    - name: wget
 99      image: busybox
100      command: ['wget']
101      args: ['RELEASE-NAME-demochart:8080']
102  restartPolicy: Never
103

There is one more command lint which will tell you if there are any syntactical errors in the YAMls.

1helm lint demochart
1==> Linting demochart
2[INFO] Chart.yaml: icon is recommended
3
41 chart(s) linted, 0 chart(s) failed 

6. Run/Install Helm Chart

The final step which we need to do is to install the Helm Chart and verify the rest endpoint so that we can test conversion of YAMLs.

Run the following helm command to install the chart

1helm install k8sToHelmChart demochart

Read More -

  1. Helm chart - How to Add/Install plugins
  2. Getting started with Helm Chart
  3. Helm chart - WordPress Installation with MariaDB on Kubernetes
  4. Helm chart - Build you first helm chart with Spring Boot
  5. Helm Chart - Convert Kubernetes YAML into Helm Chart YAML
  6. Helm Chart - Pass environment variables
  7. Helm Chart - Plugin
  8. Helm Chart - Dry Run Install
  9. Helm Chart - How to create multiple values files inside helm chart?
  10. Helmfile - How to use Helmfile for managing helm chart?