# The Main Concepts in Kubernetes

In 
Published 2022-12-03

This tutorial explains some main concepts in Kubernetes (K8s).

Kubernetes = open source container orchestration tool, developed by Google.

# Pods

Things to retain:

  • Pods are a layer of abstraction over containers.
  • In K8s you cannot deploy containers directly. You deploy pods which contains one or more containers.
  • Pods don't run anything it is just a sandbox for containers
  • Pods are collections of containers that share the same resources (memory, volumes, IPs etc) and local network. This enables easy communication between containers in a pod.
  • The containers in a pod can use localhost interface for container-to-container communication.
  • The simple model is to deploy 1 container per Pod. The multi-container Pods are used when the containers work very tightly (in a service mesh configuration, for instance).
  • If you want to scale up, you need to deploy another pod containing that container.
  • All containers in a pod are deployed on the same machine (node).
  • When a pod fails, a new one is created (with a different IP and new ID).

When we create a pod, we generally add some labels to that pod. The labels add more information regarding what is running in the pods, on which environment, etc.

Example labels:

  • "release" : "stable" or "release" : "canary"
  • "environment" : "dev" or "environment" : "qa" or "environment" : "production"
  • "tier" : "frontend" or "tier" : "backend" or "tier" : "cache"

# Replica Set

When you deploy pods there is no mechanism to monitor that pod. If the pod fails it will not be created again.

A Replica Set is a layer of abstraction over pods. When a Replica Set is created, a Controller monitors the pods to ensure that we have the desired number of pods running on Kubernetes cluster.

A Replica Set has a selector which identifies the pods it takes care of. If you have a Pod with label matching the ReplicaSet label, ReplicaSet will take control over the pod.

For instance, if you deploy Replica Set with 3 replicas and Pod with labels matching the Replica Set labels was deployed before that, then RS will spawn only 2 Pods with the matching labels.

ReplicaSet helps perform load balancing between multiple instances of the pod.

# Deployments

Replica set keeps the number of pods and performs load balancing, but is not able to change the image used for creating the containers. This is done by "deployment" object in Kubernetes.

A Deployment is a layer of abstraction over Replica Set. A Deployment could change, the image on which the containers are created. This feature let us deploy a new version of the container/application. We can also rollback a deployment.

The deployment, as any other K8s object has 3 parts:

  • the metadata : identifies the pods for that deployment
  • specification : how to create the objects (configuration we want to apply)
  • status : what we have (generated and added by Kubernetes)

When a deployment is created a Replica Set is created automatically and is managed by the deployment.

There are multiple strategies for deploying your application to your Kubernetes cluster:

  • RollingUpdate (default strategy) : New pods are brought online, and traffic is directed to them to ensure they are working as expected before old pods are removed.

This type of deployment can be fine-tuned by two more options:

  • maxSurge: The number of pods that can be created above the desired amount of pods during an update ("surge" = "wave")
  • maxUnavailable: The number of pods that can be unavailable during the update process

Example of defining Rolling Updates in deployment yaml file:

spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 2        # how many pods we can add at a time
      maxUnavailable: 0  # how many pods can be unavailable during the rolling update

maxSurge: The number of pods that can be created above the desired amount of pods during an update maxUnavailable: The number of pods that can be unavailable during the update process

  • Recreate : Kills the currently running pod instances and creates other instances running the new version.

Example of defining Recreate in deployment yaml file:

spec:
  replicas: 3
  strategy:
    type: Recreate

We can use also various tools in order to implement other deployment types:

  • Blue/Green Deployment : new pods are deployed alongside the existing pods. The new pods are tested before redirecting traffic to them. This strategy requires double the resources for a period of time. On all looks good, the blue (old) pods/replica set are/is removed from Kubernetes.

Blue deployment = the old version

Green deployment = the new version

  • Canary Deployment : Both old and new version are running simultaneous for a period of time. A small number of users are routed to the new version of the application. If an error occurs, the damage is limited, and the change can be rolled back. If there are no major issues and all looks ok with the new version, the canary (new) version is expanded to more users, until it completely replaces the old version.

  • A/B Testing Deployment : is usually used to see the users' response (for instance, how much they like a new feature), when we know that the new version works.

# Services

The pods don't have stable IPs and this is a problem for an external service to call the services inside pods.

A Kubernetes service group the pods (by using labels and selectors) and give them a fix

  • IP
  • DNS name
  • port

We can access the services inside these pods through this service, which acts as a load balancer as well. Each Service that is created, automatically gets an associated Endpoint object. This Endpoint object is a dynamic list of all the healthy Pods on the cluster that match the Service’s label selector.

The services could be of several types:

  • ClusterIP
  • NodePort
  • LoadBalancer

ClusterIP service type (the default service type)

All the services inside cluster can communicate by using the Cluster IP (or the name of the cluster which is resolved to the Cluster IP). This IP address is accessible only inside Kubernetes cluster, but, a Kubernetes proxy can be used to access a service (Cluster IP).

NodePort service type

The NodePort Service type add a new layer over the ClusterIP Service type. This layer let you access the service on each node on a particular port (defined during the NodePort service definition).

With this type of service, you can access the services we have in pods by using node_ip:nodePort, where node_ip is the IP of any node, and nodePort is a port defined during the service definition. If there are multiple nodes, then multiple IP addresses with the same port will be exposed.

LoadBalancer service type

These integrate with load-balancers from your cloud provider such as AWS, Azure, and GCP. This service is build on the top of NodePort service type. A cloud load balancer will forward the external requests (including the ones from the Internet) to the Kubernetes service. Every time you want to expose a service to the outside world, you have to create a new LoadBalancer and get an IP address.

# DaemonSet

A DaemonSet ensures that all (or some) Nodes run a copy of a Pod.

Some typical uses of a DaemonSet are:

  • running a cluster storage daemon on every node
  • running a logs collection daemon on every node
  • running a node monitoring daemon on every node

# StatefulSet

A StatefulSet is needed when we need :

  • stable pod name (the name will be podname-0 .. podname-n), however the IPs are not identical
  • persistent volumes (when a pod is deleted the volume will not be deleted automatically)
  • Ordered, graceful deployment and scaling
  • Ordered, automated rolling updates

StatefulSets assign a sticky identity (an ordinal number starting from zero) to each Pod instead of assigning random IDs for each replica Pod. A new Pod is created by cloning the previous Pod's data.

# Ingress vs Ingress Controller

The Kubernetes Ingress resource is a native kubernetes resource where you specify the DNS routing rules. This means, that you map the external DNS traffic to the internal Kubernetes service endpoints.

It requires an ingress controller for routing the rules specified in the ingress object.

# Sidecar container vs Main container

Sidecar containers are containers that are needed to run alongside the main container in the same pod. The sidecar containers shares most of the resources such as volume, network, CPU, memory with the main container. This makes the pattern capable of solving a wide array of common problems such as logging, monitoring, security, etc.