Table of contents
In Kubernetes, a pod is the smallest and simplest unit in the Kubernetes object model. It represents a single instance of a running process in a cluster and can contain one or more containers.
Pod Lifecycle
The lifecycle of a Pod goes through several phases. Here's an overview of the Pod lifecycle:
Pending: This is the initial phase. A Pod is in the "Pending" phase while Kubernetes is trying to schedule the Pod to run on a node. This could be because the necessary resources are not available, or the Pod's scheduling constraints are not met.
Running: Once a Pod is scheduled and has access to the required resources, it enters the "Running" phase. In this phase, the containers within the Pod are started, and the application is actively running.
Succeeded: A Pod enters the "Succeeded" phase when all containers within the Pod have successfully executed and completed their tasks. This is common for batch jobs or Jobs in Kubernetes.
Failed: If any container in the Pod terminates with an error, the entire Pod enters the "Failed" phase. This could happen due to an application error, a misconfiguration, or a resource constraint.
Unknown: If the state of the Pod cannot be obtained, the Pod is in the "Unknown" phase. This typically occurs due to a communication issue between the Kubernetes control plane and the node hosting the Pod.
Terminating: When a user or a controller initiates the deletion of a Pod, it enters the "Terminating" phase. The containers in the Pod are sent a termination signal, allowing them to perform cleanup operations before the Pod is completely removed.
Terminated: Once all containers in the Pod have gracefully terminated, the Pod enters the "Terminated" phase. The Pod remains in this state until it is removed from the system.
Container States
In Kubernetes, containers within a pod can go through various states as part of their lifecycle. Understanding these states is crucial for managing and troubleshooting containerized applications. The lifecycle of a container can be summarized in several states:
Waiting: The container is in the "Waiting" state when it has been created but is not yet running. This could be due to the container waiting for other containers or resources to become available.
Running: The container is actively executing its main process in the "Running" state. This is the normal state when everything is functioning as expected.
Terminated: The "Terminated" state indicates that the container has stopped running. This could happen due to the container completing its task successfully (in the case of a job), encountering an error, or being manually stopped by a user.
Substates of "Terminated" include:
Completed: The container finished its execution successfully.
Error: The container encountered an error during execution.
OOMKilled: The container was killed due to an out-of-memory condition.
CrashLoopBackOff: If a container repeatedly fails to start and exit, Kubernetes might put the container into a "CrashLoopBackOff" state. This could be due to a misconfiguration, an issue with the application, or a failure to start the main process.
ImagePullBackOff: This state occurs when Kubernetes is unable to pull the container image specified in the Pod definition. It could be due to image unavailability, permission issues, or network problems.
Pending: Similar to the Pod level, a container can be in the "Pending" state if the necessary resources are not available or if the container is waiting for dependencies.
Init: Containers can be designated as init containers, which run and complete before the main containers start. Init containers have their own set of states, including "Pending," "Running," and "Completed."
Init Containers
Init Containers in Kubernetes are specialized containers that run and complete their execution before the application containers in the same Pod start running. They are primarily used to perform setup tasks, such as initializing a database, downloading configuration files, or any other task required before the main application can start.
Here are some key points about Init Containers:
Initialization Order:
Init Containers are executed in order of appearance in the Pod specification.
Each Init Container must complete successfully before the next one starts, and before the application containers start.
Purpose:
Init Containers are commonly used for tasks like database schema initialization, pre-populating data, or performing network setup.
They help ensure that the application containers have everything they need to run successfully.
Image and Environment:
Init Containers are defined similarly to regular containers but are specified under the
initContainers
field in the Pod manifest.They use the same container image format and can be based on any container image available in the container registry.
Init Containers can share storage volumes with the main application containers.
Completion Criteria:
An Init Container is considered successful only if it completes with an exit code of 0.
If an Init Container fails, Kubernetes takes actions based on the Pod's restart policy. It might restart the Pod or delay the startup of the main containers until the issue is resolved.
Example YAML:
apiVersion: v1 kind: Pod metadata: name: myapp-pod labels: app.kubernetes.io/name: MyApp spec: containers: - name: myapp-container image: busybox:1.28 command: ['sh', '-c', 'echo The app is running! && sleep 3600'] initContainers: - name: init-myservice image: busybox:1.28 command: ['sh', '-c', "until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done"] - name: init-mydb image: busybox:1.28 command: ['sh', '-c', "until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done"]
Debugging:
When troubleshooting Pod initialization issues, examining the logs of Init Containers can provide insights into what went wrong during the initialization phase.
Use commands like
kubectl logs
to view the logs of a specific Init Container.
Init Containers play a crucial role in ensuring that the environment and dependencies required by the main application containers are properly set up before the application starts running. They enhance the reliability and robustness of containerized applications in Kubernetes.
Now let us run this Example YAML file.
kubectl apply -f initcontainer.yaml
To describe our Pod :
kubectl describe pod myapp-pod
Here you can see that in our myapp-pod there is an init status for 2 pods, which is for our service and db pods.
This is how the Pod description looks like :
Name: myapp-pod
Namespace: default
Priority: 0
Service Account: default
Node: lol-control-plane/172.18.0.2
Start Time: Wed, 06 Dec 2023 13:54:08 +0530
Labels: app.kubernetes.io/name=MyApp
Annotations: <none>
Status: Pending
IP: 10.244.0.9
IPs:
IP: 10.244.0.9
Init Containers:
init-myservice:
Container ID: containerd://c86f6bf6f479e6765aa060f99c7d6c1c2362c1cbf74a21a518d0ff2082096937
Image: busybox:1.28
Image ID: docker.io/library/busybox@sha256:141c253bc4c3fd0a201d32dc1f493bcf3fff003b6df416dea4f41046e0f37d47
Port: <none>
Host Port: <none>
Command:
sh
-c
until nslookup myservice.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for myservice; sleep 2; done
State: Running
Started: Wed, 06 Dec 2023 13:55:04 +0530
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-m6vfd (ro)
init-mydb:
Container ID:
Image: busybox:1.28
Image ID:
Port: <none>
Host Port: <none>
Command:
sh
-c
until nslookup mydb.$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace).svc.cluster.local; do echo waiting for mydb; sleep 2; done
State: Waiting
Reason: PodInitializing
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-m6vfd (ro)
Containers:
myapp-container:
Container ID:
Image: busybox:1.28
Image ID:
Port: <none>
Host Port: <none>
Command:
sh
-c
echo The app is running! && sleep 3600
State: Waiting
Reason: PodInitializing
Ready: False
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-m6vfd (ro)
Conditions:
Type Status
Initialized False
Ready False
ContainersReady False
PodScheduled True
Volumes:
kube-api-access-m6vfd:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: BestEffort
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 9m11s default-scheduler Successfully assigned default/myapp-pod to lol-control-plane
Normal Pulling 9m11s kubelet Pulling image "busybox:1.28"
Normal Pulled 8m17s kubelet Successfully pulled image "busybox:1.28" in 33.151437243s (53.853217281s including waiting)
Normal Created 8m17s kubelet Created container init-myservice
Normal Started 8m16s kubelet Started container init-myservice
This was Part 1. We have covered about:
Pod Lifecycle
Container States
Init Containers (with hands on)