Wednesday, April 6, 2022

Helm

 Helm

 
What is Helm chart?
Package manager for your kubernetes cluster
PKG - Its responsible upgrading  installation/uninstall of s/w packages
what we can do - helm install, helm upgrade , helm delete - these are helm chart cmd

How to install helm chart?
Homebrew    brew install helm
Chocolatey    choco install kubernetes-helm
Scoop        scoop install helm

Install helm chart
#brew install helm
#choco install kubernetes-helm
#scoop install helm

GoFish
#gofish install helm

Snap
#sudo snap install helm-classic

Binary
1. Download - https://github.com/helm/helm/releases
2. tar -zxvf helm-xx.zip
3. mv helm /usr/local/bin/helm

Helm chart structure
Going through
1. Chart.yaml
2. templates
3. values.yaml

Ref link

https://jhooq.com/building-first-helm-chart-with-spring-boot/

Start
$helm create demochart         after you run this cmd, it will create a directory structure

 

chart.yml
it contains metadata for your helmchart
So no need to type it manually its create automattically from helm create cmd


values.yaml
its just like normal properties file, where you store basic config
so you dont have to update this info in each and individual file
Its one place, where you go and update and modify the config,

so that helm can fetch those values and update inside the deployment.yml
and serviceaccount.yml or any other yml



Question: - If you do not have helm chart then how your day to day kubernetes
operations would look like?

Setup Kubernetes cluster
Create deployment.yml
Create Service.yml
Create service-account.yml

May be you do these all config in dev / stage / prod

Basic cmd you use

#kubectl create deployment

#kubectl expose deployment demochart --type=LoadBalancer --name=demo-service
--external-ip=1.1.1.1 --port=8080
 


SO when you using helm, you dont need to do above things
You just do below 4 things

  1. Setup Kubernetes cluster
  2. Create Helm chart
  3. Fill in the values.yaml, or little bit config if require
  4. Run - $ helm install

Same Helm install cmd you use for dev / Stage / Prod


Building first Helm Chart with Spring Boot Microservices

Step 1:- Install Helm
Below are 2 way to download helm:

I - Binary
$ Download - https://github.com/helm/helm/releases
$ tar -zxvf helm-xx.zip
$ mv helm /usr/local/bin/helm

II - Using brew
$ brew install helm

verify
$ which helm

Step 2:- Let’s create Our First Helm Chart
$ kubectl get all
$ helm create springboot

Step 3:- Helm Chart Structure
$ tree springboot

Important file
Chart.yaml

apiVersion: v2 #mandatory
name: springboot #mandatory
description: A Helm chart for Kubernetes
type: application
version: 0.1.0 #mandatory
appVersion: 1.16.0

------------------------------------------
values.yaml

replicaCount: 1
image:
  repository: rahulwagh17/kubernetes:jhooq-k8s-springboot #updated url
  pullPolicy: IfNotPresent
  tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
  create: true
  annotations: {}
  name: ""
podAnnotations: {}
podSecurityContext: {}

securityContext: {}
service:
  type: ClusterIP
  port: 8080  #updated port
ingress:
  enabled: false
  annotations: {}
  hosts:
    - host: chart-example.local
      paths: []
  tls: []
resources: {}

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80

nodeSelector: {}
tolerations: []
affinity: {}
------------------------------------------------------
deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "springboot.fullname" . }}
  labels:
    {{- include "springboot.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
  replicas: {{ .Values.replicaCount }}
{{- end }}
  selector:
    matchLabels:
      {{- include "springboot.selectorLabels" . | nindent 6 }}
  template:
    metadata:
    {{- with .Values.podAnnotations }}
      annotations:
        {{- toYaml . | nindent 8 }}
    {{- end }}
      labels:
        {{- include "springboot.selectorLabels" . | nindent 8 }}
    spec:
      {{- with .Values.imagePullSecrets }}
      imagePullSecrets:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      serviceAccountName: {{ include "springboot.serviceAccountName" . }}
      securityContext:
        {{- toYaml .Values.podSecurityContext | nindent 8 }}
      containers:
        - name: {{ .Chart.Name }}
          securityContext:
            {{- toYaml .Values.securityContext | nindent 12 }}
          image: "{{ .Values.image.repository }}"   #update here
          imagePullPolicy: {{ .Values.image.pullPolicy }}
          ports:
            - name: http
              containerPort: 8080     #update here
              protocol: TCP           #comment it
              #livenessProbe:           #comment it
              #httpGet:           #comment it
              #path: /           #comment it
              #port: http           #comment it
              #readinessProbe:           #comment it
              #httpGet:           #comment it
              #path: /           #comment it
              #port: http           #comment it
          resources:
            {{- toYaml .Values.resources | nindent 12  }}
      {{- with .Values.nodeSelector }}
      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.tolerations }}
      tolerations:
        {{- toYaml . | nindent 8 }}
      {{- end }}

...
-------------------------------------------------------------           
service.yaml

apiVersion: v1
kind: Service
metadata:
  name: {{ include "springboot.fullname" . }}
  labels:
    {{- include "springboot.labels" . | nindent 4 }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: http
      protocol: TCP
      name: http
  selector:
    {{- include "springboot.selectorLabels" . | nindent 4 }}

-------------------------------------------------------------------

Step 4:- Run $ helm template springboot
$ helm template springboot



(You can not run the above command from inside the springboot directory, so you should get out from the springboot directory and then execute the command)

After running the above command it should return you service.yaml, deployment.yaml and test-connection.yaml with actual values

-----------------------------------------------------------------------

There is one more sanitary command lint provided by helm which you could run to identify possible issues forehand.

Find any errors or misconfiguration

$ helm lint springboot

----------------------------------------------------------

Step 5:- helm -debug -dry-run
helm install springboot --debug --dry-run springboot

it will validate your helm chart before install, it will check and give you all K8s resource file in output to check after checking against K8s



If there is something wrong with your Helm chart configuration then it will going to prompt you immediately.

-----------------------------------------

Step:- 6. helm install

$ helm install myfirstspringboot springboot

---------------------------------------------

Step:- 7. Verify the helm install

$ helm list -a

$ kubectl get all

verify
curl 10.233.28.240:8080/hello

---------------------------------------

Extra step for upgrade, downgrade, delete helm chart
Step:- 8 Upgrade helm release

Lets take the same myfirstspringboot release and update its replicaCount from 1 to 2

But before we need to update the replicaCount. First we need to udpate the version in Chart.yaml from 0.1.0 to 0.1.1

apiVersion: v2
name: springboot
description: A Helm chart for Kubernetes
type: application
version: 0.1.1
appVersion: 1.16.0


Go to value.yml
update the replicaCount in values.yaml

replicaCount: 2
image:
  repository: rahulwagh17/kubernetes:jhooq-k8s-springboot
  pullPolicy: IfNotPresent
  tag: ""
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
  create: true
  annotations: {}
  name: ""
podAnnotations: {}
podSecurityContext: {}

securityContext: {}
service:
  type: ClusterIP
  port: 8080
ingress:
  enabled: false
  annotations: {}
  hosts:
    - host: chart-example.local
      paths: []
  tls: []
resources: {}

autoscaling:
  enabled: false
  minReplicas: 1
  maxReplicas: 100
  targetCPUUtilizationPercentage: 80

nodeSelector: {}
tolerations: []
affinity: {}


$ helm upgrade myfirstspringboot .

verify
$ helm list -a
$ kubectl get deployments

-----------------------------------------

Step:- 9 Rollback Helm release

$ helm rollback myfirstspringboot 1

verify
$ helm list -a
$ kubectl get deployments

-----------------------------------------

Step:- 10 Delete Helm release

$ helm delete myfirstspringboot

verify
$ helm list -a
$ kubectl get deployments


How to do upgrade?

helm upgrade nginx springboot

helm upgrade [name] [chartname]


Create your own custom chart

1. Python Application with REST API
2. Create Docker Container
3. Push Docker image to docker repository
4. Create HelmChart for Python REST API app
5. Install the Helm chart
6. Verify the Helm chart after installation
 

 python-flask-rest-api-project

build the api with help of docker and push the image to docker hub

create helm chart
helm create python-flask-rest-api-project

now on same location you can see python-flask-rest-api-project directory and helm structure there.

edit Chart.yaml file
vi python-flask-rest-api-project/Chart.yaml
#appVersion: "1.16.0"

vi python-flask-rest-api-project/value.yaml
find here repository url
image:
  repository: rahulwagh17/python-flask-rest-api-project:python-project
  pullPolicy: IfNotPresent

service:
 type: NodePort
 port: 80

vi  python-flask-rest-api-project/templates/deployment.yaml
 ports:
  - name http
    containerPort: 9001
    protocol: TCP
comment out readynessProbe and livenessProbe
and remove tag from image
image: "{{.Value.image.repository }}"

install helm chart
helm install helloworld python-flask-rest-api-project

verify the app


Helmfile

What is Helmfile and why we need it?
Installing the Helmfile?
Manage your Helmchart using Helmfile?
Install Helmchart from remote Git Repo using Helmfile
Install multiple HelmChart

With help of helmfile you can manage you helmchart efficently,
and with some basic cmd can manage your helmchart instead of running multiple cmd like install,uninstall,delete,rollback
you can reley on single cmd


what is Helmfile and why we need it ?
helm cmd
helm install my-app ./my-app  -----|  helm sync
helm uninstall my-app        ---------|

what is Helmfile and why we need it?
helmfile
---
 releases:
 - name: helloworld       ------ Name of helmchart
   chart: ./helloworld    ------ Set true for install
   installed: true


Uninstall helm chart

This above helmfile seems setup for installation
what about if need to install helloworld helmchart
in that case we make installed false

vi helmfile.yaml
 - name: helloworldreleas
   chart: ./helloworld
   installed: false

helmfile sync
now it will uninstall helmchart

Use GitHub repository for installing helm chart using Helmfile

The one more feature of Helmfile - you can even install the helmchart from remote repository such as GitHub, Google Container Repository, AWS ECR
https://github.com/rahulwagh/helmchart

Add the following configuration attributes for working with remote repository -

1. Repository name - helloworld
2. Repository URL - git+https://github.com/rahulwagh/helmchart@helloworld?ref=master&sparse=0

we need a plugin for helmfile remote gitrepo
helm-git
install
use cli cmd - helm plugin install https://github.com/aslafy-z/helm-git --version 0.15.1
vi helmfile
---
repositories:
  - name: helloworld
    url: git+https://github.com/rahulwagh/helmchart@helloworld?ref=master&sparse=0
releases:
  - name: helloworld
    chart: helloworld/helloworld
    installed: false

Now you can run the $ helmfile sync command for installing the helm chart from remote repository

Deploy multiple Helmcharts using Helmfile

Use the following steps -
1. Create your first helm chart -
helm create helloworld1

2. Create your second helm chart
helm create helloworld2

3. Create a Helmfile for deploying multiple helmchart .i.e. helloworld1, helloworld2
---
releases:
  - name: helloworld1
    chart: ./helloworld1
    installed: true
  - name: helloworld2
    chart: ./helloworld2
    installed: true

4. Install the helmchart using Helmfile
helmfile sync

deploy the multiple helmchart from GitHub repository

---
 repositories:
     - name: helloworld
       url: git+https://github.com/rahulwagh/helmchart@helloworld?ref=master&sparse=0
 releases:
   - name: helloworld1
     chart: ./helloworld1
     installed: true
   - name: helloworld2
     chart: ./helloworld2
     installed: true
 

Use the following command to search for the wordpress repositories.
    helm search hub wordpress

In case if the URL is too long to see then you can put --max-col-width=0, so that you can view the complete URL
    helm search hub wordpress  --max-col-width=0


But before adding the bitnami/wordpress first check whether it already exists on your repo list or not?
    helm repo list
 

add your repo list -
helm repo add bitnami https://charts.bitnami.com/bitnami

Check Wordpress Version
helm search repo wordpress --versions

This Readme.md contains the installation instructions and it can be viewed using the following command
helm show readme bitnami/wordpress --version 10.0.3

If you are familiar with WordPress before then you need username and password to access the WordPress CMS, so you can view the default values
helm show values bitnami/wordpress --version 10.0.3
 

Hooks & Test

what is helm Hooks?
when to use the Helm Hooks?
Demo- Helm Hooks?
what is Helm Test?
How to use Helm Test? 

 

Chart Hooks
HOOK type

  • pre-install - Executes after templates are rendered, but before any resources are created in Kubernetes
  • post-install - Executes after all resources are loaded into Kubernetes
  • pre-delete - Executes on a deletion request before any resources are deleted from Kubernetes
  • post-delete - Executes on a deletion request after all of the release's resources have been deleted
  • pre-upgrade - Executes on an upgrade request after templates are rendered, but before any resources are updated
  • post-upgrade - Executes on an upgrade request after all resources have been upgraded
  • pre-rollback - Executes on a rollback request after templates are rendered, but before any resources are rolled back
  • post-rollback - Executes on a rollback request after all resources have been modified


When we use hook?
For example, you can use hooks to:

  • Load a ConfigMap or Secret during install before any other charts are loaded.
  • Execute a Job to back up a database before installing a new chart, and then execute a second job after the upgrade in order to restore data.
  • Run a Job before deleting a release to gracefully take a service out of rotation before removing it.

 Hooks folder available under templates directory

 

 

cat helloworld/templates/hooks/pre-install.yml
---
apiVersion: batch/v1
kind: job
metadata:
  name: "{{ include "helloworld.fullname"" . }}-pre-install-job-hook"
  labels:
    {{- include "helloworld.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": "pre-install"
    "helm.sh/hook-weight": "0"
    "helm.sh/hook-delete-policy": hook-succeeded
spec:
  template:
    spec:
      containers:
      - name: pre-install
        image: busybox
        imagePullPolicy: IfNotPresent
        command: ['sh', '-c', 'echo pre-install Pod is Running; sleep 10']
      restartPolicy: OnFailure
      terminationGracePeriodSeconds: 0
  backoffLimit: 3
  completions: 1
  parallelism: 1

 

Helm test

test is consider as unit test for your particular chart, so just like anyother programing languages write a unit test for Validate fuctionally of your program

its similar unit test for your helm chart

 

 Helm test
test is consider as unit test for your particular chart, so just like anyother programing languages write a unit test for Validate fuctionally of your program

its similar unit test for your helm chart

cat template/test/test-connection.yml
apiVersion: v1
kind: Pod
metadata:
  name: "{{ include "helloworld.fullname" .}}-test-connection"
  labels:
    {{- include "helloworld.labels" . | nindent 4 }}
  annotations:
    "helm.sh/hook": test
spec:
  containers:
  - name: wget
    image: busybox
    command: ['wget']
    args: ['{{ include "helloworld.fullname" . }}:{{ . Values.service.port }}']
  restartPolicy: Never

deployed helm chart with above test file.

run run test
helm test myhellorelease


No comments:

Post a Comment