Kubernetes is used to deploy, manage, and scale containerized applications across multiple node servers. It offers an easier alternative to performing such operations manually or using custom scripts, making it increasingly popular among developers and DevOps engineers.
To get started with this tool, you’ll need to understand its basic concepts, such as Kubernetes pods. The pod, which is the smallest deployable unit in Kubernetes, contains one or more containers tightly coupled together and sharing the same resources.
In this article, you’ll learn about Kubernetes pods, how they work, and why you need to monitor them.
Why Are Pods Important?
Pods abstract one or more containers in your Kubernetes cluster. Each container in a pod shares resources provided by the pod, including IP and storage.
What Pods Offer
There are several essential features that pods provide to Kubernetes users.
Kubernetes pods can be created and deleted as needed. For example, you can add pods to handle an increase in your application traffic and discard them once the traffic returns to normal.
Your Kubernetes controller can delete pods when they’re done with their process execution, and they can also be deleted when your cluster doesn’t have enough resources to run the pod.
They’re Executed in a Node Environment
Kubernetes pods are tightly coupled to the node environment, such that if the node fails, all the pods associated with it die. Sometimes, a node can also evict pods from its environment if the pods exceed their memory limit consumption on the node. Furthermore, if a pod is using more CPU resources than normal, the node throttles the CPU resource consumption for that pod. This is done to ensure the node is healthy for a longer time.
They Can Run Multiple Containers
Pods can abstract multiple containers that share the resources provided by the pod, such as network, storage, and memory. It’s generally important to have a one-to-one relationship between a pod and a container, but there are scenarios where it’s necessary to run multiple containers in a pod.
For example, say you deployed an application on your Kubernetes cluster, and you configured a volume storage to save your application logs. However, it becomes difficult for you to view and analyze your application logs from your command-line terminal. Instead of manually exporting these logs to a log analyzer tool, you can create a separate service that extracts logs from the storage and sends them to a central log system for visualizing and analyzing the logs properly. This process can be done using a multi-container pod while taking advantage of the shared volume storage and network feature, which allows multiple containers in the same pod to share the same storage and network.
How Kubernetes Pods Work
Here’s what you need to know about how pods function and what their lifecycle looks like.
Single vs Multiple Container Pods
Pods can contain either a single container or multiple containers sharing the same resources.
A common option for shared container pods is the sidecar design, where the pod contains a main container and a helper, or sidecar, container that extends the functionality of the main container. For example, your main container could be a community forum application that allows users to upload photos, and your sidecar container could reduce photo sizes before they’re saved to your file storage.
Pods and Controllers
Kubernetes controllers make sure that the cluster always remains in the desired state. The controller replicates the pods in your cluster based on your application workload, and when a pod dies, it creates another pod and puts in a healthy node with the resources to run it. The controller also removes pods from the cluster when they’re no longer needed.
How Pods Are Created
There are several ways to create pods in your Kubernetes cluster. They include using the pod object, using the ReplicaSet, and using Deployments.
Using the Pod Object
Create a YAML file named <terminal inline>my_app_pod.yaml<terminal inline> and paste the code below:
In your terminal, run the command <terminal inline>kubectl apply -f my_app_pod.yaml<terminal inline>, which automatically creates a pod in your cluster.
You can also create pods using the imperative approach:
Using the ReplicaSet
Create a YAML file named <terminal inline>my_app_replica_set.yaml<terminal inline> and paste the code below:
In your terminal, run the command <terminal inline>kubectl apply -f my_app_replica_set.yaml<terminal inline>. This creates a ReplicaSet in your cluster, which ensures that the <terminal inline>my_app<terminal inline> pod has a set number of pods always running.
Create a YAML file named <terminal inline>my_app_deployment.yaml<terminal inline> and paste the code below:
Run the command <terminal inline>kubectl apply -f my_app_deployment.yaml<terminal inline> in your terminal.
<terminal inline>Deployment<terminal inline> performs similarly to <terminal inline>ReplicaSet<terminal inline>, ensuring that a specified number of pods is available in the cluster. However, <terminal inline>Deployment<terminal inline> offers the additional feature of rolling updates. This ensures that whenever you update your <terminal inline>Deployment<terminal inline> file, it gets to the desired state without causing downtime. For instance, in your YAML file, if you replace your container image with a new version, <terminal inline>Deployment<terminal inline> updates all the pods in your cluster with the new version one by one, so that if there is a bug with the new image, you can quickly roll back without causing downtime.
How Pods and Nodes Work Together
Nodes are either physical or virtual computing machines that run your pods’ processes. Managing your applications independently on multiple nodes can be a herculean task. Pods are an abstraction of your containerized applications, and the pods run on nodes in the Kubernetes cluster. Kubernetes uses the control plane to distribute workloads to the available nodes in the cluster in order to increase efficiency and performance.
How Pods and Containers Work Together
Containers are applications that are packaged with their execution environments. They bundle all the dependencies, libraries, and binaries required for your application to work, so that the difference in operating system distribution and the underlying infrastructure is abstracted away.
Pods were introduced so that Kubernetes wouldn’t be tied to a specific vendor. They abstract the containers in the cluster, meaning that you can package your application using any vendor recognized by Kubernetes.
Each pod in the Kubernetes cluster has a unique IP address. The containers in a pod share network resources including the IP and port, and they can communicate with each other using localhost. However, if a container wants to communicate with another container in a different pod, it is advisable to use Kubernetes services for communication.
There are different service type options available depending on how you want to expose the pod communication, either internally available in the cluster or externally outside of the cluster. The service types include <terminal inline>ClusterIp<terminal inline>, <terminal inline>NodePort<terminal inline>, <terminal inline>LoadBalancer<terminal inline>, and <terminal inline>ExternalName<terminal inline>; more information about these service types can be found here.
Kubernetes pods go through different series of states from creation to termination. When you create a pod, the initial state is “pending,” or waiting for the network to download the application image. Once the image is downloaded, the container is ready to run and is bound to the pod. Now its state is “running,” meaning the pod is ready to receive and process requests.
Once the container has completed its process, the pod is terminated and the status changes to “succeeded.” If the pod is terminated due to an error, its status changes to “failed” and an event is recorded. An “unknown” status indicates that the pod status can’t be obtained, which typically means there is an error in communication between the running pod and the node.
Pods have a <terminal inline>PodStatus<terminal inline> that contains an array called <terminal inline>PodConditions<terminal inline>. <terminal inline>PodConditions<terminal inline> has a type and status field that shows the conditions causing its current status. Its conditions include:
- <terminal inline>PodScheduled<terminal inline>: This means the pod has been scheduled for a node.
- <terminal inline>Initialized<terminal inline>: This means that init containers have been completed successfully. These are containers that run before the main app containers. They must run completely before the next container can run. If the <terminal inline>init container<terminal inline> fails, it’s restarted until it succeeds.
- <terminal inline>ContainersReady<terminal inline>: This shows that all the containers are in a ready state.
- <terminal inline>Ready<terminal inline>: The pod is ready to receive and process requests.
It’s better to gracefully terminate a pod when it’s no longer needed instead of terminating it abruptly. This ensures that the pod cleans up before it’s deleted completely. By default, Kubernetes provides a graceful termination period of thirty seconds from the time of the termination request initiation.
In order to override the default grace period when deleting a pod, add this <terminal inline>--grace-period<terminal inline> option:
Using the container’s file system for storage is ephemeral, meaning that the storage will be available as long as the container is running. If you end and restart your container, everything you’ve stored will disappear. For consistent storage that isn’t dependent on containers, use volumes.
Some volumes are available until the pod dies, while others aren’t dependent on pods. Kubernetes supports several types of volumes for storage.
Monitoring the pods is important for the overall health and performance of the Kubernetes cluster. It allows you to see how your pods are functioning, spot bottlenecks, reduce wasted costs, and improve the performance of your application. You can check the number of pod instances available, the health of the pod, the memory usage of the pod, and the CPU consumption, among other factors.
ContainIQ’s Pods dashboard is helpful for viewing core metrics, statuses, changes over time, and to associate events to each pod. Using ContainIQ, users are able to set alerts on events related to changes in pod status. For example, using ContainIQ, users are able to set events on pods restarting, memory issues, and also on significant changes in memory or CPU.
Pods are an essential part of using Kubernetes. Having a solid understanding of how pods function and how best to use them can help you better manage your Kubernetes clusters and your applications.
If you need a tool to monitor your Kubernetes cluster, consider ContainIQ. The platform offers pre-built dashboards for ease of use and helps you track memory, latency, events, and logs so that you can optimize your Kubernetes usage. For more info, see the documentation.