1.3.1 Docker, Kubernetes and Helm

Everything about the tools & technologies for building highly scalable and reliable microservice architectures

This chapter explains the tools behind microservice architectures. It requires reading the microservices chapter beforehand

Docker

Docker - the de-facto standard to package (“containerize”) software code into microservice

Docker is a program which simulates docker containers. These are similar to virtual machines, except that instead simulating hardware to install the required OS and dependencies on, docker container virtualize only the OS.

From this video you should learn what docker is, what the dockerfile is, what the image is and what a container is.

Kubernetes

Kubernetes - the operating system of the cloud. The tool to manage millions of microservices. Requires knowledge about Docker.

Kubernetes is highly complex, from this video all you need to take away as information is that kubernetes manages the container infrastructure and can replace, reboot, and scale the amount of containers of a docker architecture. You should also know pods as the smallest implementable running units on kubernetes and nodes as the machines you run pods on.

Helm

Kubernetes and Helm

As a broad explanation (from the right to the left): Docker containers Pods in Kubernetes, they are the smallest deployable unit.

There is also other stuff going on in Kubernetes like secret management or ingresses.

You define the final state (“I want to have one application based on this Docker image with these environment variables ….") and Kubernetes will take care of the rest using its magic. This could be seen equal to a docker-compose.yaml

The final state is defined using Kubernetes object descriptions.

Example for a Kubernetes object description:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 2 # tells deployment to run 2 pods matching the template
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.14.2
        ports:
        - containerPort: 80

You could now create and maintain all of them manually, which is what some companies do.

To do that automatically, you can use Helm.

Helm will take a values.yaml and will automatically create the corresponding Kubernetes object descriptions.

Example for a Helm template values:

### mqttbridge ###

mqttbridge:
  enabled: true
  image: unitedmanufacturinghub/mqtt-bridge
  storageRequest: 1Gi

### barcodereader ###

barcodereader:
  enabled: true
  image: unitedmanufacturinghub/barcodereader
  customUSBName: "Datalogic ADC, Inc. Handheld Barcode Scanner"
  brokerURL: "factorycube-edge-emqxedge-headless"  # do not change, points to emqxedge i
  brokerPort: 1883  # do not change
  customerID: "raw"
  location: "barcodereader"
  machineID: "barcodereader"

There is nothing comparable to Helm in the Docker world.

For this to work, one needs to import a so-called Helm chart first. This is nothing but a Kubernetes object description with some variables.

Example for a Kubernetes object description template (for Helm):

{{- if .Values.mqttbridge.enabled -}}
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: {{ include "factorycube-edge.fullname" . }}-mqttbridge
  labels:
    {{- include "factorycube-edge.labels.mqttbridge" . | nindent 4 }}
spec:
  serviceName: {{ include "factorycube-edge.fullname" . }}-mqttbridge
  replicas: 1
  selector:
    matchLabels:
      {{- include "factorycube-edge.labels.mqttbridge" . | nindent 6 }}
  template:
    metadata:
      labels:
        {{- include "factorycube-edge.labels.mqttbridge" . | nindent 8 }}
    spec:
      containers:
      - name: {{ include "factorycube-edge.fullname" . }}-mqttbridge
        {{- if .Values.mqttbridge.tag }}
        image: {{ .Values.mqttbridge.image }}:{{ .Values.mqttbridge.tag }}
        {{- else }}
        image: {{ .Values.mqttbridge.image }}:{{ .Chart.AppVersion }}
        {{- end }}

A Helm chart can either be stored in a folder (e.g., when you clone the United Manufacturing Hub repository) or in a Helm repository (which we use in our default installation script).

You might be tempted to just clone the repository and change stuff in the Kubernetes object description template (in the sub-folder templates). We consider this a bad idea as these changes are now hard to track and to replicate somewhere else. Furthermore, when updating the Helm chart to a newer version of the United Manufacturing Hub, these changes will be lost and overwritten.

In OpenLens, you can now change the underlying Kubernetes object descriptions by e.g., clicking on a Deployment and then selecting edit. However, these changes will be reverted once you apply the Helm chart again.

Therefore, we recommend in production setups to only adjust the values.yaml in the Helm chart.

What next?

You could deep-dive into how the United Manufacturing Hub builds their Docker containers and how their Helm chart looks like.

Otherwise, we recommend going to the next chapter.

Last modified October 5, 2022: Historian article (#107) (5f30dc0)