How to create pods in Kubernetes

A pod is the smallest unit in the k8s (Kubernetes) ecosystem, like an atom in the universe.

Before creating any pods, I assume that the application is already developed along with the built Docker image that is available in a Docker repository (public or private). This way, whenever a Kubernetes cluster runs, a new pod will be able to pull the respective Docker images. I also assume that a Kubernetes cluster is up and running. In case you need one using kubeadm, visit create a Kubernetes cluster using kubeadm. Now that both prerequisites are met, we are ready to deploy an application into a Kubernetes cluster that will ultimately create a pod.

A pod is a group of containers that are deployed together on the same host. With the help of pods, we can deploy multiple dependent containers together. In other words, a pod acts as a wrapper around these containers so that we can interact and manage these containers primarily through the pod.

There are three ways you can create a pod (or resources) in a running k8s cluster.

  1. Imperative way
  2. Declarative way
  3. Using an API interface

We can also create resources from the Kubernetes Dashboard.

You can use the Kubernetes supported client-libraries to write applications using the Kubernetes REST API.

Imperatively, a pod can be created with many kubectl commands that directly apply to the k8s cluster. For example, if I want to deploy an nginx web server into a k8s cluster, then I can directly create a deployment that will create a replica set. This replica set, in turn, will create a pod using:

$ kubectl run --generator=run-pod/v1 nginx --image=nginx
pod/nginx created

In the latest version of Kubernetes, generators have been removed from the kubectl run command [Ref PR: Remove kubectl run generators] and a declarative way of creating resources has been suggested. It is never been recommended to create any resources in an imperative way as there will be less transparency while creating/updating them.

Declaratively, a pod can be created by writing manifests and using kubectl apply. This is good for reproducible deployments, i.e., for production — though you may still use some kubectl commands for debugging in production. So, this manifest contains the metadata and detail specification w.r.t. the type of object you want to create. This method is even helpful for updating the objects that are currently running in the k8s cluster.

Let’s create an nginx deployment the declarative way:

vim simple_deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
minReadySeconds: 5
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.14.2
ports:
- containerPort: 80
$ kubectl create -f simple_deployment.yaml
deployment.apps/nginx-deployment created

This declarative way of creating resources will keep a track of the specification we provided while creating a resource. Hence, 95% of system admins or DevOps engineers who manage a K8s cluster leverage this approach.

Creating a pod/deployment using REST API

In a typical Kubernetes cluster, the API is exported on port 443, which can be accessed through a TLS connection. The self-signed certificate, which is generated during the cluster creation or configuration, is available at $USER/.kube/config on the client machine.

The API server performs authentication, authorization, and admission control of clients.

cat > nginx-pod.json <<EOF
{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": {
"name": "nginx-deployment"
},
"spec": {
"selector": {
"matchLabels": {
"app": "nginx"
}
},
"minReadySeconds": 5,
"template": {
"metadata": {
"labels": {
"app": "nginx"
}
},
"spec": {
"containers": [
{
"name": "nginx",
"image": "nginx:1.14.2",
"ports": [
{
"containerPort": 80
}
]
}
]
}
}
}
}
EOF

Create the above deployment using the following curl request:

curl -k -v -X POST -H "Authorization: Bearer <JWT_TOKEN>" -H "Content-Type: application/json" https://K8s-master-ip:6443/api/v1/namespaces/default/pods -d@nginx-pod.json

Make sure you have created JWT_TOKEN, which will have the necessary permissions to create the deployment; otherwise, you will get the HTTP 401 Unauthorized response. Also, replace the K8s-master-ip with your k8s cluster’s master server’s IP.

Kubernetes Deployment Life-cycle from K8s Doc
Kubernetes Deployment Life-cycle from K8s Doc

As shown in the above deployment life cycle, the control plane and data plane components work together seamlessly to make sure your cluster is always in the desired state. Controllers make sure that the current state always matches the desired state. Kubernetes controllers watch the changes to Kubernetes objects in the API server and basic CRUD operations. When a change happens, controllers run their business logic. I will explain this in my next blog about, Nuts and Bolts of Kubernetes.

Kubernetes is one of the most extensible container orchestration engines and, day-by-day, it is becoming a de-facto standard for infrastructure. It brings the Google Borg experience to all, in order to run applications of internet-scale. The API-first approach makes Kubernetes programmable and extensible. The modular approach helps you to build on top of Kubernetes. So, no matter how you create the resources in the Kubernetes cluster, it will ultimately be converted into an API through which it will communicate with the Kubernetes API server.

Attributions:
  1. undefined by undefined