Learning: Kubernetes – Deployments & StatefulSet

Deployments

Deployments are the way we manage pods in k8s. We specify all possible information about the pods like which version image it is going to pick and how many replicas of the pod will be there.

  • Properties
    • The spec.selector specify which pod it needs to manage.
    • When we update a deployment, it first creates a new pod, deletes an old pod, and makes sure that 125% of the desired number of pods is available at any time.
  • Rollout to a Previous Version When rolling out to a previous version we just use – kubectl rollout undo deployment/nginx-deployment When rolling out to another previous version we use – kubectl rollout undo deployment/nginx-deployment --to-revision=2

StatefulSet

Just like we manage the stateless applications with deployments we work with stateful applications with StatefulSet.

  • Properties
    • The StatefulSet cannot be created/deleted at the same time
    • can’t be accessed randomly
    • The replica set here is not identical.
    • Each pod gets a unique identifier in increasing order and these are required while rescheduling.
    • Each pod has its own physical store.
    • There is a master pod that is only allowed to change data.
    • All the slave pods sync with the master pod in order to achieve data consistency.
    • When a new pod joins the replica set it first clones all the data from one of the slave pods and after that starts to sync.
  • StatefulSets are valuable for applications that require one or more of the following.
    • Stable, unique network identifiers.
    • Stable, persistent storage.
    • Ordered, graceful deployment and scaling.
    • Ordered, automated rolling updates.
  • Data Persistence If a pod dies then all its data will be lost. So in order to counter this, we use persistent volume attached to every pod.
    • The storage has all the synchronized data with the pod’s state data.
    • When a pod gets replaced the persistent volume gets reattached to the pod and the state of the pod gets resumed.

What is System Call

System Call – It is the interface between the userspace program and kernel program to requests for resources.

Now why we need system calls-

  • Reading and writing from files demand system calls.
  • If a file system wants to create or delete files, system calls are required.
  • System calls are used for the creation and management of new processes.
  • Network connections need system calls for sending and receiving packets.
  • Access to hardware devices like scanner, printer, need a system call.

Here are the five types of System Calls in OS:

  • Process Control – This system call deals with process creation and termination, wait & signal events and allocate and free memory.
  • File Management – This deals with the file manipulation like create, update, delete, read, write and add attributes to the file.
  • Device Management – This deals with the device buffers like reading and writing as well as adding and removing logical devices.
  • Information Maintenance – It handle the data transfer between user and OS kernel.
  • Communications – This is used for inter process communication. Create and delete communication connections, send and receive messages etc.

Learning: Kubernetes – Persistent Volume & Persistent Volume Claim

Volume – Volume in Kubernetes can be thought of as a directory that can be accessed by containers in the pod. Volume helps persists the data even if the pod restarts.

  • PV
    • A Persistent Volume (PV) is a piece of storage in the cluster.
    • It is a cluster-level resource like a pod and doesn’t have any namespace.
    • It is been manually provisioned by an administrator, or dynamically provisioned by Kubernetes using a StorageClass.
  • PVC
    • A PersistentVolumeClaim (PVC) is a request for storage by a user that can be fulfilled by a PV.
    • Persistent Volumes and PersistentVolumeClaim are independent of Pod lifecycles and preserve data through restarting, rescheduling, and even deleting Pods.
  • Access Modes
    • ReadWriteOnce – It is used when we allow only one node to read & write on the volume. Multiple pods running on the same node can access the volume.
    • ReadOnlyMany – It is used when we allow read access to many pods.
    • ReadWriteMany – It is used when we allow read & write access to many nodes.
    • ReadWriteOncePod – It is used when we allow only one pod in a node for reading & writing.

Learning: Kubernetes – Container Runtime Interface & Garbage Collection

Container Runtime Interface

The Container Runtime Interface (CRI) is the primary protocol for the communication between the kubelet and Container Runtime.

Container Runtime – It is the software that helps run & manage containers in a host operating system. There are a number of Container runtimes in the market from Docker, runC, containerd, etc.

So in order to make an abstraction over all the container runtime supported by the Kubernetes the community has introduced a new concept called CRI(Container Runtime Interface) that talks to the container runtime.

The kubelet talks to the Container Runtime Interface(CRI) using a gRPC framework where kubelet is the client and CRI is the server.

Garbage Collection

It is term that k8s use to clean up the cluster resource.

  • Owner & Dependents In k8s there are some objects that are dependent on others. So k8s clean up the related object before deleting the object.
  • Cascading Deletion k8s deletes an object that no longer has owner references. Like the pods left after deleting the ReplicaSet.
    • Foreground Cascading Deletion –
      • The object we are trying to delete goes in a progressive state.
      • The Kubernetes API server sets the object’s metadata. deletion timestamp field to the time the object was marked for deletion.
      • The Kubernetes API server also sets the metadata. finalizers field to foregroundDeletion.
      • After going into the in-progress state the controller deletes all the dependent and removes the parent object.
    • Background Cascading Deletion –
      • Here the k8s deletes the owner object immediately.
      • Then the controller clean up the dependent objects.

Learning: Kubernetes – Why We Need Pod Abstraction Above Containers

I have discussed pods in the previous blog. Now in the short, a container is a standard unit of software that packages up code and all its dependencies in a virtualized environment that has its own file system.

As nodes are the VM or Physical Machine we could have run the container inside it without having the pod abstraction. But there will be some major problems that will arise in terms of managing the cluster and that is networking.

As we all know the container application runs in a specific port and more than one application can’t occupy a port. So if you need two containers of the same application running in a node then the same application needs to run in a different port and connection between them will be very messy.

And that is why Kubernetes solves the problem with pod abstraction. Each pod has a unique network namespace. This means each pod will have its own virtual ethernet. It’s like the pod is a small VM inside the node. And now each pod will have the application container running with the same port and there will be no conflict because all the containers running in self-contained isolated machines.

Now suppose a pod has more than one container(The main container and a helper container) then the container inside the pod will communicate with each other using the localhost.

Learning: Kubernetes – Controller & Cloud Controller

Controller

k8s controller is like a thermostat in a room. It checks the current temperature and maintains the temperature by turning off & on the switch. Same here the k8s controller checks the current state and verify that if the current state is equal to the desired state or not. If the current state is not matched with the desired state it makes the necessary changes and brings to the desired state.

Types of the controller –

  • ReplicaSet – It is responsible for maintaining the set desired number of pods.
  • Deployment – Deployment is the most common way to get your app on Kubernetes. It maintains a ReplicaSet with the desired configuration.
  • StatefulSet – A StatefulSet is used to manage stateful applications with persistent storage.
  • Job – A Job creates one or more short-lived Pods and expects them to successfully terminate.
  • CronJob – A CronJob creates Jobs on a schedule.
  • DaemonSet – A DaemonSet ensures that all (or some) Nodes run a copy of a Pod. As nodes are added to the cluster, Pods are added to them.

Cloud Controller

The cloud controller manager lets you link your cluster into your cloud provider’s API, and separates out the components that interact with that cloud platform from components that only interact with your cluster.

  • Different functions
    • Node Controller –
      • It updates node objects when new servers are created in the cloud.
      • Annotating and labeling the node object with the cloud-specific information.
      • Obtain node hostname & network address.
      • Checks the node health. If the node has been deleted from the cloud then it also removes the node from the k8s cluster.
    • Route Controller – It configures the routes properly so the nodes on the k8s cluster can communicate with each other.
    • Service Controller – It interacts with the cloud provider’s API to set up a load balancer and other infrastructure components.

Learning: Kubernetes – ConfigMaps & Secrets

Every application has configuration data like API key, DB URL, DB user, DB password, etc. Yes, you can hardcode these data in your application but after some time it will be unmanageable. You need some kind of dynamic solution where you define all these data once and every component of your cluster can access these data.

Suppose our application DB URL changes for that we need to change every place where the URL is used. So, for this our application needs to be rebuilt again and we have to change the code inside the application. To encounter this situation we use ConfigMaps and Secrets for storing the application’s required data.

ConfigMaps – A ConfigMaps is an API object used to store non-confidential data in key-value pairs. Pods can consume ConfigMaps as environment variables, command-line arguments, or as configuration files in a volume.

Ex – ConfigMaps contains the URL of the database, user, and other non-credential data.

Secrets – A secret is similar to ConfigMaps, except a secret is used for sensitive information such as credentials. One of the main differences is that you have to explicitly tell kubectl to show you the contents of a secret.

  • It is encoded in base64.

Learning: Kubernetes – Labels & Selectors, Finalizers

Labels & Selectors

Labels – Labels are key-value pairs attached to pods, ReplicaSet & Services. They are used for identifying objects for pods and ReplicaSet. It can be added at the creation time or can be modified or added at the run time.

Some properties –

  • must be 63 characters or less (can be empty),
  • unless empty, must begin and end with an alphanumeric character ([a-z0-9A-Z]),
  • could contain dashes (“), underscores (_), dots (.), and alphanumeric between.

Selectors – Kubernetes API currently supports two type of selectors −

  • Equality-based selectors – We use = == != as equality selector.
environment = production
tier != frontend
  • Set-based selectors – It allows filtering of object in a set of values. There are three king of operator allowed in notin exists.
environment in (production, qa)
tier notin (frontend, backend)
partition
!partition

Finalizers

Deleting an object isn’t as simple as it looks because it involves a lot of conditional checks about the used resources. Finalizers are certain conditions be met before an object can be deleted.

When you run kubectl delete namespace/example k8s check the finalizers defined on that object.

  1. Issue a deletion command. – Kubernetes marks the object as pending deletion. This leaves the resource in the read-only “Terminating” state.
  2. Run each of the actions associated with the object’s Finalizers. – Each time a Finalizer action completes, that Finalizer is detached from the object, so it’ll no longer appear in the metadata.finalizers field.
  3. Kubernetes keeps monitoring the Finalizers attached to the object. – The object will be deleted once the metadata.finalizers field is empty, because all Finalizers were removed by the completion of their actions.

Learning: Kubernetes – Service, Scalability, Rolling Updates

Service

There multiple challenges with pods. Suppose we have two pods with one front-end and one back-end. Now we have couple of questions –

  • How does the front-end app expose to the outside world?
  • How the front-end app talks to the back-end app?
  • When a pod dies a new pod gets created and get assigned with a new IP Address. How to resolve Pod IP changes, when pod die?

So, the services are the way of grouping of pods in a cluster. We can have as many as services in cluster. There are mainly three type of services in k8s –

  1. ClusterIP – It actually deals with the pod IP change problem. It’s a static IP address that can be attached with each pod. So even the pod dies the service stays in place and don’t change. Exposes the Service on an internal IP in the cluster. Here the service only reachable within the cluster.
  2. NodePort – Makes a Service accessible from outside the cluster.
  3. Load Balancer – Creates an external load balancer in the current cloud (if supported) and assigns a fixed, external IP to the Service.
# Get the running services
$ kubectl get services

# Expose service to outside of the world
$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

# Delete a specific service
$ kubectl delete service -l app=kubernetes-bootcamp

Scalability

When we want to scale our app then we create multiple replica of the pods on the nodes and to balance the request on each pods we use load balancer service.

Rolling Update

K8s allows us to do rolling updates and let’s see how it does –

  • First it creates the new pod with updated config.
  • Then it replaces the new pods with old ones one by one and change the pod IP addresses.

It allows app to update in zero down time.

# Update image of the application
$ kubectl set image

# Get Rollout update status
$ kubectl rollout status <service_name>

# Get the service info
$ kubectl describe <service_name>

# Roll Back to the deployment to your last working version
$ kubectl rollout undo <deployment_name>

Learning: Kubernetes – Pods and ReplicaSet Simplified

Pods

A Pod is the smallest execution unit of a Kubernetes application. Each Pod represents a part of a workload that is running on your cluster.

We usually have one pod per application. Inside that pod we could have multiple container.

  • A Pod is a Kubernetes abstraction that represents a group of one or more application containers and some shared resources.
    • It has shared volumes.
    • Cluster IP(Every pod has unique IP even in same Node)
    • Info about how to run container.
  • We don’t deal with containers instead we work with pods.
  • If a container dies inside a pod it will be automatically restarted.
  • Each pod is tied to one node until termination.
  • Pods that are running inside k8s are only visible from other pods and services inside the k8s cluster.
  • We have to expose the app to outside the k8s.

Multiple Container Pods – The pods are always designed to support multiple correlated containers. The containers in a pod is automatically scheduled in same VM or physical machine in the cluster.

The containers can communicate to each other and share resources.

Pods Networking –

  • Each pod is assigned with a unique IP address.
  • Each container in pods share the network share the same IP address with port.
  • The containers inside a pod can communicate to each other with localhost.
  • The containers inside a pod can also communicate using Inter Process Communication.

Life Cycle of a Pod

  • A pod is said to be ephemeral.
  • A pod is never rescheduled to a different node Instead the pod is replaced by a new one.
  • If a node fails the pods assigned to it also fail.

Generally a pod has 5 phases –

  1. Pending – Pod has been accepted by the cluster but one or more container haven’t been setup.
  2. Running – A pod has been bound to a node and containers have started.
  3. Succeeded – All containers in the pod have been terminated successfully.
  4. Failed – At least one container have been terminated in failure.
  5. Unknown – For some reason the state of pod could not be obtained.
# Create a deployment
$ kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

# Get deployment info
$ kubectl get deployments

# Get the list of pods running
$ kubectl get pods

# See which containers are running inside a pod
$ kubectl describe pods

# Run a command inside a container
$ kubectl exec $POD_NAME -- env

# Open bash inside a container
$ kubectl exec -it $POD_NAME -- bash

ReplicaSet

We don’t create the pods directly. The reason is suppose we need 4 pods in our deployment always and if we create the pods directly and the one pod goes down then we have to create the pods manually.

That’s why we use ReplicaSet. It is a management system that ensure that I have the desired set of pods in the k8s cluster. And the controller check the current state with the desired state and see if the current pod count match the ReplicaSet count or not. If not it creates or deletes pods.

# Get the replica set
$ kubectl get rs

# Scale up the app and change replicaset
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4

# Scale down the app
$ kubectl scale deployments/kubernetes-bootcamp --replicas=2

# To see a pod in managed by ReplicaSet
$ kubectl get pods <pod_name> -o yaml

# Delete the ReplicaSet
$ kubectl delete rs <replica_name>

# Delete the replica set but keep the pods
$ kubectl delete rs <replica_name> --cascade=false