Skip to content
MH

Mujo Hadzimehanovic

2 articles

February 16, 2022

Structural container patterns in Kubernetes

Software Development

Structural container patterns in Kubernetes

Introduction If you have a cloud-native microservices application, you will probably think of using a containerized approach together with Kubernetes for orchestration. In order to use containers properly, you should take into account container design patterns.  (more…)

October 19, 2021

Deploying an application to Kubernetes with Helm

Software Development

Deploying an application to Kubernetes with Helm

Deploying an application to Kubernetes with Helm   Introduction This Tech Bite will show you how to deploy a simple frontend application to a Kubernetes cluster and the benefits of using Helm charts. Plain k8s approach In order to deploy our application and make it usable we have to generate 3 Kubernetes objects - Deployment, Service and Ingress. In the classical approach we need to create three files for each object. deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:   name: nginx-test   labels:     app.kubernetes.io/name: nginx-test     app.kubernetes.io/instance: ngx-test spec:   replicas: 1   selector:     matchLabels:       app.kubernetes.io/name: nginx-test       app.kubernetes.io/instance: ngx-test   template:     metadata:       labels:         app.kubernetes.io/name: nginx-test         app.kubernetes.io/instance: ngx-test     spec:       serviceAccountName: default       securityContext:         {}       containers:         - name: nginx-test           securityContext:             {}           image: "nginx"           imagePullPolicy: Always           ports:             - name: http               containerPort: 80               protocol: TCP service.yaml apiVersion: v1 kind: Service metadata:   name: nginx-test   labels:     app.kubernetes.io/name: nginx-test     app.kubernetes.io/instance: ngx-test spec:   type: ClusterIP   ports:     - port: 80       targetPort: 80       protocol: TCP       name: http   selector:     app.kubernetes.io/name: nginx-test     app.kubernetes.io/instance: ngx-test ingress.yaml apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata:   name: nginx-test   labels:     app.kubernetes.io/name: nginx-test     app.kubernetes.io/instance: ngx-test   annotations:     cert-manager.io/cluster-issuer: letsencrypt-nginx spec:   tls:     - hosts:         - "nginx-test.example.com"       secretName: tls-nginx   rules:     - host: "nginx-test.example.com"       http:         paths:           - path: /             backend:               serviceName: nginx-test               servicePort: 80 However, this problem can be solved by merging those three yaml files into a single one and executing kubectl apply -f frontend-app.yaml to spin up needed k8s objects. But what if we have multiple environments? To which one should the application be deployed? For every environment we need to change the pod name, ingress host address etc… In order to replace those values we will need to create a yaml file for every environment with almost the same data. The solution is simple - we are going to use Helm which is “The package manager for Kubernetes”. Helm As we have stated before, Helm is the package manager for Kubernetes applications which allows us to define blueprints for application deployment. All the necessary resources are going to be packed into Helm Charts and deployed to the cluster. Let’s get to work and create a Helm chart for our application. helm create test-appAfter helm create command is executed we will get a test-app folder and the structure is going to be similar to this: We are going to put the Kubernetes objects that we need to generate in the templates/ folder (deployment.yaml, service.yamland ingress.yaml).  You will also notice the values.yaml file which in combination with Helm templates generates our k8s objects. Our files, ready for chart deployment, should look like this: deployment.yaml apiVersion: apps/v1 kind: Deployment metadata:   name: {{ include "test-app.fullname" . }}-ui   labels: {{ include "test-app.labels" . | indent 4 }} spec:   replicas: {{ .Values.replicaCount }}   selector:     matchLabels:       app.kubernetes.io/name: {{ include "test-app.name" . }}-ui       app.kubernetes.io/instance: {{ .Release.Name }}   template:     metadata:       labels:         app.kubernetes.io/name: {{ include "test-app.name" . }}-ui         app.kubernetes.io/instance: {{ .Release.Name }}     spec:     {{- with .Values.imagePullSecrets }}       imagePullSecrets:         {{- toYaml . | nindent 8 }}     {{- end }}       serviceAccountName: {{ template "test-app.serviceAccountName" . }}       securityContext:         {{- toYaml .Values.podSecurityContext | nindent 8 }}       containers:         - name: {{ .Chart.Name }}-ui           securityContext:             {{- toYaml .Values.securityContext | nindent 12 }}           image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"           imagePullPolicy: {{ .Values.image.pullPolicy }}           ports:             - name: http               containerPort: 80               protocol: TCP service.yaml apiVersion: v1 kind: Service metadata:   name: {{ include "test-app.fullname" . }}-ui   labels: {{ include "test-app.labels" . | indent 4 }} spec:   type: {{ .Values.service.ui.type }}   ports:     - port: {{ .Values.service.ui.port }}       targetPort: 80       protocol: TCP       name: http   selector:     app.kubernetes.io/name: {{ include "test-app.name" . }}-ui     app.kubernetes.io/instance: {{ .Release.Name }} ingress.yaml apiVersion: extensions/v1beta1 kind: Ingress metadata:   name: {{ $fullName }}-ui   labels: {{ include "test-app.labels" . | indent 4 }}   {{- with .Values.ingress.ui.annotations }}   annotations:     {{- toYaml . | nindent 4 }}   {{- end }} spec: {{- if .Values.ingress.ui.tls }}   tls:   {{- range .Values.ingress.ui.tls }}     - hosts:       {{- range .hosts }}         - {{ . | quote }}       {{- end }}       secretName: {{ .secretName }}   {{- end }} {{- end }}   rules:   {{- range .Values.ingress.ui.hosts }}     - host: {{ .host | quote }}       http:         paths:         {{- range .paths }}           - path: {{ . }}             backend:               serviceName: {{ $fullName }}-ui               servicePort: {{ $svcPort }}         {{- end }}   {{- end }} {{- end }} In our deployment.ymltemplate file you can see variable definitions between two pairs of curly braces. These values are just references to the values.yaml file. For example, image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}” says that image name is going to take image.repository and image.tag values and generate full image name. A snippet of these values is shown below. Once we have all the files set in the templates/ folder we can proceed with generating and deploying the chart to the k8s cluster.  helm install test-app app/ If the command was successfully executed, after running kubectl get po,svc,ing we should see our objects up and running. In case we have dev and prod environments for the application, we can simply create values-dev.yml and values-prod.yml and reference them when creating charts. helm install --namespace dev --create-namespace --values values-dev.yaml test-app app/ for DEV environment helm install --namespace prod --create-namespace --values values-prod.yaml test-app app/ for PROD environment --namespace - defines namespace of the environment to which we are deploying --create-namespace - generates new namespace if it is not existing --values - location to values file You can find the full example code on Github. Follow this link.   "Deploying an application to Kubernetes with Helm" Tech Bite was brought to you by Mujo Hadžimehanović, DevOps Engineer at Atlantbh. (more…)

Ready to Achieve More?

We’ll help you reach your goals quickly with an easy and straightforward process to kick off our collaboration. Here’s what happens next.

STEP 1

Discovery Call

Let’s chat to understand your company, project needs, and answer any questions along the way.

STEP 2

Free Consultation

Work closely with our experts to explore the right solutions for your business.

STEP 3

Collaboration Proposal

We'll recommend the best strategy for your goals, ensuring you get the most from our expertise.

STEP 4

30-Day Cancellation
Policy Contract

Spoiler: It’s Never Been Used

Enjoy peace of mind while we deliver excellence from day one—our track record speaks for itself.

Services you're interested in (Optional)