Mujo Hadzimehanovic
2 articles
February 16, 2022
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
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.