Chapter 4 - Pods

Yusuf IsahYusuf Isah
8 min read

Introduction

In Kubernetes, the smallest and simplest unit of deployment is a Pod. Pods represent a single instance of a running process in your cluster. They encapsulate one or more containers, their storage resources, a unique network IP, and options that govern how the containers should run. This chapter will explore the concept of Pods, how to create and manage them, and how to ensure their health and performance in a Kubernetes cluster.

Pods in Kubernetes

In Kubernetes, a Pod is the basic execution unit that comprises one or more containers. The term, Pod, is a nod to the Docker whale theme, as it refers to a group of whales swimming together. Similarly, a Pod groups containers together to work as a single, cohesive unit that can share resources and dependencies, communicate with each other, and be co-scheduled.

Key Points About Pods:

  • Single Unit of Deployment: Pods are the smallest deployable units in Kubernetes.

  • Shared Context: Containers within a Pod share the same network namespace, Inter-Process Communication (IPC) namespace, and can share storage volumes.

  • Lifecycle: Pods are created, scheduled, and managed by the Kubernetes control plane.

The Pod Manifest

A Pod manifest is a YAML file that defines the desired configuration of a Pod, utilizing Kubernetes' declarative approach. This means you specify the ideal state of your Pod in the manifest file, and then Kubernetes works to ensure that the actual state matches your declared intentions.

Creating a Pod

You can create a Pod by defining a manifest in YAML and applying it to your Kubernetes cluster.

Creating a Pod Manifest

To create a Pod manifest:

  • Define the apiVersion, kind, and metadata sections.

  • Under spec, specify the containers that the Pod should run.

Example Manifest:

apiVersion: v1
kind: Pod
metadata:
  name: greetings-pod
spec:
  containers:
  - name: greetings-container
    image: dockeryu853/greetings:1.1
    ports:
    - containerPort: 8080

Let's name the manifest above greetings.yaml. To apply the manifest to your Kubernetes cluster, run:

kubectl apply -f greetings.yaml

Running Pods

Once a Pod is created, you can perform various operations to manage and inspect it.

Listing Pods

Run the command below to list all Pods in your cluster:

kubectl get pods

You can see the name of the Pod (greetings-pod) that we gave it in the YAML file. In addition to the number of ready containers (1/1), the output also shows the status, the number of times the Pod was restarted, and the age of the Pod.

If you ran this command immediately after the Pod was created, you might see:

ContainerCreating means that Kubernetes has received the YAML manifest and is in the process of creating the containers specified in the manifest. If what you see in the status field is Pending, it means that the Pod has been submitted but hasn’t been scheduled yet. If a more significant error occurs, such as an attempt to create a Pod with a container image that doesn’t exist, it will also be listed in the status field.

To see a list of the pods running in your Kubernetes cluster and observe dynamic changes in real-time, run:

kubectl get pods -w

The command above allows you to observe the dynamic changes in your Pod landscape without needing to repeatedly run the kubectl get pods command. Press Ctrl+C to exit watch mode.

In addition, adding -o wide to any kubectl command will print out slightly more information (while still keeping the information to a single line).

kubectl get pods -o wide

Pod Details

To get detailed information about a specific Pod, run:

kubectl describe pod <pod-name>

Deleting a Pod

To delete a Pod, run:

kubectl delete pod <pod-name>

NB: When you delete a Pod, any data stored in the containers associated with that Pod will be deleted as well. If you need to persist data across multiple instances of a Pod, you need to use Persistent Volumes, described at the end of this chapter.

Accessing Your Pod

Kubernetes provides several ways to interact with and troubleshoot Pods.

Getting More Information with Logs

To view the logs of a container in a Pod, run:

kubectl logs <pod-name> -c <container-name>

Running Commands in Your Containers with exec

To execute a command in a running container:

kubectl exec -it <pod-name> -- <command>

To exec into the greetings-pod, run the command below:

kubectl exec -it greetings-pod /bin/sh

To exit, simply run the exit command inside the pod.

Copying Files to and From Containers

To copy files between your local system and a container:

kubectl cp <file-path> <pod-name>:/path/in/container
kubectl cp <pod-name>:/path/in/container <local-path>

Health Checks

Kubernetes allows you to define health checks to ensure your containers are running as expected.

Liveness Probe

The liveness probe checks if a container is still running. If the check fails, Kubernetes restarts the container.

Example Liveness Probe:

livenessProbe:
  httpGet:
    path: /healthz
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 3

The Liveness Probe configuration above will:

  • Wait 3 seconds after the container starts.

  • Send an HTTP GET request to http://localhost:8080/healthz every 3 seconds.

  • If the request fails or returns an error, Kubernetes will consider the container unhealthy and restart it.

Readiness Probe

The readiness probe checks if a container is ready to serve traffic.

Example Readiness Probe:

readinessProbe:
  httpGet:
    path: /ready
    port: 8080
  initialDelaySeconds: 3
  periodSeconds: 3

The readiness Probe configuration above will:

  • Wait 3 seconds after the container starts.

  • Send an HTTP GET request to http://localhost:8080/ready every 3 seconds.

  • If the request succeeds (returns a 200 OK response), the container is considered ready to receive traffic.

  • If the request fails or returns an error, the container is not considered ready, and Kubernetes will not send traffic to it.

Resource Management

You can specify the resources that your Pod's containers require, ensuring they run efficiently.

Resource Requests: Minimum Required Resources

Resource requests define the minimum amount of resources a container needs. These requests serve as a hint to the Kubernetes scheduler to ensure the Pod is placed on a node with sufficient resources. If the node doesn't have enough resources, the Pod won't be scheduled to that node.

Example:

  resources:
    requests:
      memory: "64Mi"
      cpu: "250m"

The pod in the YAML manifest above is requesting:

  • At least 64 MB of memory to be allocated

  • At least 250 millicores (or 0.25 cores) of CPU processing power

Note that these are requests, not limits. The container can use more resources if available, but it's guaranteed to get at least the requested amount.

Capping Resource Usage With Limits

Resource limits specify the maximum resources a container can use. These limits prevent the container from consuming excessive resources and impacting other workloads running on the same node. If the container tries to use more resources than specified, Kubernetes will take action to enforce the limits, such as terminating the container if it exceeds the memory limit.

Example:

resources:
  limits:
    memory: "128Mi"
    cpu: "500m"

The Pod in the YAML manifest above is restricted to:

  • Using no more than 128 MB of memory

  • Using no more than 500 millicores (or 0.5 cores) of CPU processing power

Persisting Data with Volumes

Kubernetes Volumes provide persistent storage to Pods, ensuring data is retained across restarts.

Using Volumes with Pods

apiVersion: v1
kind: Pod
metadata:
  name: greetings-pod
spec:
  containers:
  - name: greetings-container
    image: dockeryu853/greetings:1.1
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: static-files
      mountPath: /static
  volumes:
  - name: static-files
    hostPath:
      path: /home/yusbuntu/static
      type: Directory

In the YAML manifest above, the VolumeMount is trying to achieve the following:

  • It's mounting a volume named static-files into the container at the path /static.

  • The static-files volume is defined in the volumes section and is of type hostPath, which means it's a directory on the host machine (the machine running the Kubernetes node).

  • The path field specifies the directory on the host machine (in this case, my Minikube Virtual Machine), /home/yusbuntu/static, which will be mounted into the container. Make sure to change /home/yusbuntu to your home directory or any other path you prefer.

As stated earlier, if you are using Minikube, you have to create this directory inside Minikube and not on your computer. Below are the steps to follow to create the directory inside Minikube.

minikube ssh
sudo mkdir -p /home/your_user_name/static

Make sure to change your_user_name to your actual user name.

Putting it all Together

Kubernetes offers a comprehensive set of features, including persistent volumes for data storage, readiness and liveness probes for health monitoring, and resource restrictions for efficient resource allocation, making it an ideal platform for running stateful applications with high reliability and consistency. The manifest below puts this all together.

apiVersion: v1
kind: Pod
metadata:
  name: greetings-pod
spec:
  containers:
  - name: greetings-container
    image: dockeryu853/greetings:1.1
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: static-files
      mountPath: /static
    resources:
      limits:
        memory: "128Mi"
        cpu: "500m"
      requests:
        memory: "64Mi"
        cpu: "250m"
    readinessProbe:
      httpGet:
        path: /ready
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3
    livenessProbe:
      httpGet:
        path: /healthz
        port: 8080
      initialDelaySeconds: 3
      periodSeconds: 3
  volumes:
  - name: static-files
    hostPath:
      path: /home/yusbuntu/static
      type: Directory

NB: Before applying the greetings.yaml manifest above, make sure to change the path (/home/yusbuntu/static) in your manifest to the path you specified in your Minikube VM.

Next, apply the manifest:

kubectl apply -f greetings.yaml

Follow the steps below to see the contents of the container:

  • Once the container starts running, run the command below:

      kubectl get pods -o wide
    

  • As you can see from the image above, my IP is 10.244.0.214

  • Next, SSH into Minikube:

      minikube ssh
    
  • Run the command below to see the contents of the container running inside the pod:

 curl http://10.244.0.214:8080

Conclusion

Understanding Pods is fundamental to working with Kubernetes. They encapsulate your application's containers, along with their storage, network, and configuration, into a single deployable unit. By mastering Pods and their associated operations, you can effectively manage your applications in a Kubernetes environment.

Feel free to leave comments and share this article. Follow my blog for more insights on Kubernetes!

0
Subscribe to my newsletter

Read articles from Yusuf Isah directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Yusuf Isah
Yusuf Isah

Hello. I am a DevOps enthusiast from Nigeria. I am also passionate about Technical Writing. As a passionate DevOps enthusiast, I'm dedicated to bridging the gap between development and operations teams. With a strong foundation in Linux, Git, Docker, and Kubernetes, I excel in creating efficient, scalable, and reliable software delivery pipelines. With a keen eye for detail and a passion for continuous learning, I stay up-to-date with industry trends and best practices. My goal is to collaborate with like-minded professionals, share knowledge, and drive innovation in the DevOps space. I look forward to sharing with you, all I've learned so far in my DevOps journey.