Table of Contents
A Pod is the smallest unit of a Kubernetes deployed cluster. Pods are imperative entities, and the Kubernetes ecosystem needs them to function. Kubernetes uses a container to package dependencies and resources required to run an application. Kubernetes must track different container states.
Pods are transient; they are short lived and can be created, rebuilt, deleted, and replaced at any time. Pods status represents the lifecycle of how Kubernetes manages running your code for you. This guide provides an introductory overview of managing the Kubernetes Pod lifecycle.
Why Pod Lifecycles Matter
Kubernetes Pods are often managed using higher-level controllers PodTemplate fields, such as Deployments, ReplicaSets, DaemonSets, StatefulSets, or Jobs. They determine how a Pod is created and updated.
Pods are generally used to troubleshoot issues around your application. Thus, understanding Pods and their lifecycle provides snapshots of how to troubleshoot issues while running your application.
How Pods Record Lifecycles
Kubernetes Pods record the states of its status. A Pod's state is recorded at any stage in its lifecycle using a PodStatus API object. It provides information that summarizes the current states of a pod using fields such as phase, conditions, initContainerStatuses, and containerStatuses.
Phase describes the current phase of your Pod's lifecycle. It gives details of which state the Pod is within the clusters. Let's say you've executed the following kubectl command:
kubectl get pods
Kubernetes often returns the current phase of a Pod lifecycle using keywords such as the following:
- Pending, which tells you the Kubernetes API has accepted the Pod but its containers are not created yet.
- Running, which means your Pod is currently scheduled on a node. The Kubernetes API has accepted its container, and the application is running as expected in your Kubernetes cluster.
- Succeeded, which means the Pod container processes were successfully terminated and won't be restarted.
- Failed, which indicates the Pod containers have terminated, but at least one has returned a non-zero status (failed).
- Unknown, meaning the pod has problems connecting to the node on which it is running, and Kubernetes can't determine the state of the Pod.
- CrashLoopBackoff, which signals that Kubernetes has tried to restart your Pods repeatedly, causing the container to enter a loop of crashing and restarting, and the containers fail to start.
How to Read Pod Lifecycle Status
To get into further details of your Pod's lifecycle, the PodStatus API object uses detailed commands such as the following:
- The conditions command to get detailed information about a specific Pod. It allows you to dig deeper into a given pod, check its events, and find out Pod conditions. Conditions are recorded if a Pod is PodScheduled to run on a node in the cluster, containers in the Pod are Ready, init containers in the Pod Initialized successfully, and Pod is Unschedulable to run on any node in the cluster for reasons such as limited resources.
kubectl describe pod <pod-name>
The following example shows the conditions of a running Pod:
If the Pod has another status, such as CrashLoopBackoff, you would expect the following conditions:
- The containerStatuses command checks container states within a selected Pod to know whether the container is running, waiting, or terminated.
kubectl logs <pod-name>
These commands provide insight into your Pods lifecycle. However, you can integrate the Pod lifecycle with hooks to instruct kubelet to perform various actions before or after specific events in the Pod lifecycle.
Kubernetes Container Lifecycle Hooks
Pod lifecycle hooks trigger events at specific stages in the cluster lifecycle. For instance, if a Pod container is being terminated, you can create a hook script that will let you know the container graceful shutdown before it terminated or a hook script to let you know initContainer is running before the main application container is started.
The lifecycle hooks role is to configure the right handlers to manage your workloads perfectly. For example, a load balancer can still send traffic to a Pod that is already terminated. Lifecycle hooks manage such situations by executing asynchronous tasks that start initializations and the deregistration process of your containers. They verify these tasks have been completed and then proceed to start the Pod container or terminate it. Kubernetes provides Containers with the following lifecycle hooks:
- postStart: Its handlers are sent immediately after a container is started to execute initialization tasks.
- preStop: Its events are executed right before a container is terminated. It performs tasks such as cleanup and gracefully shuts down the container before it's terminated.
Kubernetes provides the following two approaches to implement these hook handlers:
- Exec runs a specified command within a container.
- HTTP creates HTTP request handlers to a URL running inside the container.
Using Lifecycle Hooks
These hooks apply only to the container in which they're defined. Let’s create a few Kubernetes manifests to demonstrate how the hooks mechanism works. Below is a simple example of how to execute a basic postStart hook:
apiVersion: v1
kind: Pod
metadata:
name: test-pod
spec:
containers:
- name: testcontainer
image: nginx
# lifecycle hook spec
lifecycle:
postStart:
# Your Exec handler
exec:
command: ["/bin/sh", "-c", "date", "echo postStart hook executed > /test.log"]
Go ahead and run the kubectl command and deploy Pod to your cluster:
kubectl apply -f you_manifest.yaml
To test your postStart hook, use kubectl to execute a shell that accesses your running Pod container:
kubectl exec --stdin --tty test-pod -- sh
You can now read the contents logged to your test.log file as follows:
# cat /test.log
postStart hook executed
Since postStart has no errors, the containers will be created successfully:
Kubelet must be able to execute postStart before creating the container. If the exec command is successful, kubelet won’t proceed to other container creating events. Consider the following invalid command:
lifecycle:
postStart:
exec:
command: ["broken command"]
Kubelet won’t be able to execute the postStart hook, and the API won’t be able to successfully create your containers:
In this instance, kubelet has started successfully. However, you have a postStart hook in your lifecycle. If the command this hook executes isn't successful, your containers fail to create and eventually exit with a CrashLoopBackOff status. A perfect use case of postStart would be running a script to set up a database schema/migration or performing health checks before the container starts.
Using a PreStop Lifecycle Hook
The preStop hook executes a command just before the container is terminated. Check the following example that executes the redis-cli shutdown command using a preStop hook.
apiVersion: v1
kind: Pod
metadata:
name: redis-pod
spec:
containers:
- name: redis-container
image: redis
ports:
- containerPort: 6379
volumeMounts:
- name: redis-data
mountPath: /src/redis/data
lifecycle:
preStop:
exec:
command: ["redis-cli shutdown"]
volumes:
- name: redis-data
emptyDir: {}
To learn how preStop works in this scenario, check the logs of the redis-container container created above:
kubectl logs -f redis-pod -c redis-container
Try to terminate the redis-pod while watching the logs of your container in the above terminal output:
kubectl delete pod/redis-pod
When you delete the above Pod object, your preStop hook is executed before the Pod is terminated. Kubernetes sends a TERM signal to the main process of the Pod to allow any containers to gracefully shut down and terminate any child processes.
Best Practices for Managing the Pod Lifecycle
The Pod lifecycle is an important concept for managing your Kubernetes cluster. The following practices are necessary to ensure Pods runs smoothly:
- Use liveness and readiness container probes to determine if a container in a Pod is running correctly and ready to accept traffic.
- Configure container restartPolicy to ensure they are automatically restarted if they fail.
- Create container lifecycle hooks to perform initialization, terminations, and cleanup tasks.
- Monitor your Pods to ensure they're running correctly and to detect and troubleshoot issues.
- Design for high availability with tools like replica sets and deployments to ensure your applications are automatically scaled and can recover from failures.
- Use a Pod garbage collector (PodGC) to avoid a resource leak as Pods is created and terminated.
Conclusion
Pod lifecycle trigger events for managing your workloads. They create practical handling scenarios to understand events of your application's runtime. This guide introduced you to Kubernetes Pods lifecycle and how to use them. I hope you found it helpful!
This post was written by Rose Chege. Rose is a technical writer, a lover of technology, and an upright individual unafraid to get out of her comfort zone and try new programming paradigms. She loves writing code and solving programming problems while sharing her skill using articles.