In our previous we post, we looked at how to set up the Kubernetes cluster using kubeadm. Now is the time where we start creating our first objects called Pods and also look at the lifecycle of the Pods. Hence, the title Kubernetes Pods and Pod Lifecycle.
Kubernetes does not deploy containers directly on the worker nodes. The containers are encapsulated within a Kubernetes Object called Pod.
A pod is the smallest unit that can be created on a Kubernetes Cluster. A pod can have one or more containers within it. If the application has multiple containers and those containers have the same lifecycle, then they can be created within the same pod and they are called Multi-Container Pods.
Although you can create multiple containers within the same pod, it is usually not recommended due to the way Kubernetes handles the lifecycle of pods. If a pod needs to be scaled up or down, then all containers within the pod will be scaled up or down.
There are some uses where multiple containers are required and we can discuss them in another post.
Now that we understand what a Pod is, let us create one using kubectl. If you are wondering what kubectl is, check this post which explains the Kubernetes architecture and the components.
There are two ways of creating objects in Kubernetes are called imperative and declarative. The imperative way is to just create the object from the command line using kubectl which defeats the whole purpose and is not scalable in the long run.
The declarative way is the most suitable method where the Kubernetes objects are defined in YAML files and these YAML files are used to create the Kubernetes objects.
What is YAML?
According to Wikipedia, YAML (a recursive acronym for "YAML Ain't Markup Language") is a human-readable data serialization language.
Kubernetes uses a YAML file to define the specifications of the objects and various associated things for those objects using key-value pair.
Here is a nice video that explains YAML in 10 minutes if you want to know more.
Creating our first pod
Let's create our first pod using the imperative method first using the below command.
kubectl run nginx --image=nginx
This will create a pod on one of the worker nodes called Nginx and running an image called Nginx which is just a web server.
But remember, Kubernetes is not about creating objects in an imperative way. So, let us see how to create the same object using the declarative way using a pod definition file.
Every yaml file should have the below 4 required fields:
- apiVersion: Defines what version is used to create the Kubernetes Object.
- kind: Defines what object needs to be created.
- metadata: You can add data here that helps uniquely identify objects in the Kubernetes cluster like name, type, etc.
- spec: This is the most important where you describe the description of the characteristics you want the resource to have, its desired state, etc.
apiVersion: v1 kind: Pod metadata: labels: type: web-server name: first-pod spec: containers: - image: nginx name: nginx
Let's try and direct the yaml file further.
apiVersion for Pod objects will be v1 for Pods and some objects can have different apiVersion types which I can write a complete blog post on.
The next required field is kindĀ and it is self-explanatory that we will be using Pod since we are creating a Pod in this example. The other examples are ReplicaSets, Deployments, Namespaces, etc.
Then comes the metadata field where we provide the name of the pod and some labels to help us identify the pod in the future.
Finally, the specĀ field which is where we define the resources and the desired state, etc for this pod. Here we are saying the one container that we want in this pod will be called nginx and it will use the nginx image.
Note that the above yaml file consists of the bare minimum fields required to create the pod. Obviously more fields can be added and we will explore them in the future when we start looking at different Kubernetes Objects and we can use them with each other.
Now, to finally create this object, we will run the below command.
kubectl apply -f pod-definition.yaml
kubectl apply creates the pod for us on one of the worker nodes.
And you can check the running using the command.
kubectl get pods -o wide
We get additional information like the Pod IP address and the worker node on which the pod was created.
Pods and Pod Lifecycle
Alright, in this section let us look at Pods and Pod Lifecycle. Basically, we will be looking at what actually happened behind the scenes when the kubectl apply command was run and what phases did the pod transition to before getting into the Running state.
- Pending: This is the first phase that the pod goes through in its lifecycle. In this phase, the pod has been accepted and the scheduler is trying to find a suitable node to run this container on.
- Creating: In this phase, the pod has already been scheduled on a worker node and the worker node is pulling the image from the repository if not already present on the node.
- Running: This is self-explanatory. The pod has been created on the worker node and at least one or more containers in the pod are in running state.
- CrashLoopBackOff: This is a phase where for some reason has been restarting many times and the cluster decides to wait for sometime before trying to create the pod. This usually happens when an image cannot be downloaded, etc.
- Succeeded: All containers within a pod have successfully been terminated after doing their job and the Kubernetes cluster will not try to restart them.
- Failed: All Containers in the Pod have terminated, and at least one Container has terminated in failure.
- Unknown: This is a very rare scenario where the Kubernetes cluster cannot find the state of the pod, usually when it cannot communicate to the worker node where the pod was running.
And some of these phases can be seen using the below command under the events section.
kubectl get pods first-pod
Well, that's all I wanted to share in this post. And in the coming posts, we will look at various other Kubernetes Objects.
I hope this has been informative and thank you for reading!