Kubernetes: Pods

As the first step, we take our application and create a Docker image. Once the image is created, it works as a portable runtime for our application.

Now we can create a container from that image and run it in a Docker environment or in a container orchestration system like Kubernetes.

What is a Pod?

The minimum unit of deployment in Kubernetes is a Pod. So pod is the smallest unit that we can run inside Kubernetes.

Container runs inside the Pods.

NOTE

Typically, we would run a single container inside a Pod.

But it is possible(and sometimes necessary) to run multiple containers inside a Pod.

Pods Inside Nodes

NOTE

How to determine if 2 containers should stay in the same Pod or not?

Ask -> can we run these two application on two different hosts?

If the answer is yes, then these 2 containers should be on separate pods.

Containers inside a Node
Containers inside a Node

Elements Inside a Pod

Container inside a Pod
Container inside a Pod

Elements Isolated for Container inside a Pod

Inside Kubernetes, Pods have the following things isolated for each container-

Process-level isolation, or PID namespace.
Root file system namespace.
Users have it’s own namespace separated.

Elements common for Containers inside a Pod

The following elements are common for all pods-

Network: networks are shared between pods.
Hostname: the hostname and its namespace are going to be the same.
Volumes: we can have shared common volumes for the container between Pods.

NOTE

The network namespace is shared so that containers can communicate with each other over localhost.

This is helpful as the containers are related and that is why we put those in the same Pod. These containers often need to communicate with each other.

Configuration

NOTE

To remember the components of a K8s configuration, just remember-

AKMS

AapiVersion
Kkind
Mmetadata
Sspec

Create a YAML file and add the following lines. Here we are creating a file named simple-nginx.yml-

# simple-nginx.yml

apiVersion: v1
kind: Pod
metadata:
  name: simple-nginx
  labels:
    app: web
    type: ui
    tier: frontend
    env: staging
spec:
  containers:
  - name: nginx
    image: nginx:1.25-alpine
    ports:
    - containerPort: 80
YAML

Use the YAML file to create Pod-

# Apply the YAML file to create Pod
$ kubectl apply -f simple-nginx.yml

pod/simple-nginx created


# Check the Pods in the cluster
# The simple-nginx pod is not ready yet
$ kubectl get pod

NAME           READY   STATUS              RESTARTS   AGE
simple-nginx   0/1     ContainerCreating   0          4s


# Let's check again
# This time the simple-nginx Pod is running
$ kubectl get pod

NAME           READY   STATUS    RESTARTS   AGE
simple-nginx   1/1     Running   0          22s
Bash

WARNING

Generally, Pods are not directly created in Kubernetes.

Kubernetes does not automatically monitor Pod state, so it does not ensure that the Pod is restarted when there is any issue.

In most cases, Pods are created using Deployment. We have discussed Deployment in detail in the next section.

$ kubectl describe pod simple-nginx

Name:             simple-nginx
Namespace:        default
Priority:         0
Service Account:  default
Node:             desktop-worker2/172.18.0.5
Start Time:       Mon, 28 Jul 2025 22:57:14 +0600
Labels:           app=web
                  env=staging
                  tier=frontend
                  type=ui
Annotations:      <none>
Status:           Running
IP:               10.244.1.2
IPs:
  IP:  10.244.1.2
Containers:
  nginx:
    Container ID:   containerd://4e2dd26250ab64f2a1dd04c5a29800ba948c967f639f22ee6191ea930e76b574
    Image:          nginx:1.25-alpine
    Image ID:       docker.io/library/nginx@sha256:516475cc129da42866742567714ddc681e5eed7b9ee0b9e9c015e464b4221a00
    Port:           80/TCP
    Host Port:      0/TCP
    State:          Running
      Started:      Mon, 28 Jul 2025 22:57:35 +0600
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-jvvzj (ro)
Conditions:
  Type                        Status
  PodReadyToStartContainers   True 
  Initialized                 True 
  Ready                       True 
  ContainersReady             True 
  PodScheduled                True 
Volumes:
  kube-api-access-jvvzj:
    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  23m   default-scheduler  Successfully assigned default/simple-nginx to desktop-worker2
  Normal  Pulling    23m   kubelet            Pulling image "nginx:1.25-alpine"
  Normal  Pulled     23m   kubelet            Successfully pulled image "nginx:1.25-alpine" in 19.674s (19.674s including waiting). Image size: 20461242 bytes.
  Normal  Created    23m   kubelet            Created container nginx
  Normal  Started    23m   kubelet            Started container nginx
Bash
$ kubectl logs simple-nginx

/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/07/28 16:57:35 [notice] 1#1: using the "epoll" event method
2025/07/28 16:57:35 [notice] 1#1: nginx/1.25.5
2025/07/28 16:57:35 [notice] 1#1: built by gcc 13.2.1 20231014 (Alpine 13.2.1_git20231014)
2025/07/28 16:57:35 [notice] 1#1: OS: Linux 5.15.167.4-microsoft-standard-WSL2
2025/07/28 16:57:35 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/07/28 16:57:35 [notice] 1#1: start worker processes
2025/07/28 16:57:35 [notice] 1#1: start worker process 34
2025/07/28 16:57:35 [notice] 1#1: start worker process 35



$ kubectl logs -f simple-nginx

/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2025/07/28 16:57:35 [notice] 1#1: using the "epoll" event method
2025/07/28 16:57:35 [notice] 1#1: nginx/1.25.5
2025/07/28 16:57:35 [notice] 1#1: built by gcc 13.2.1 20231014 (Alpine 13.2.1_git20231014)
2025/07/28 16:57:35 [notice] 1#1: OS: Linux 5.15.167.4-microsoft-standard-WSL2
2025/07/28 16:57:35 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
2025/07/28 16:57:35 [notice] 1#1: start worker processes
2025/07/28 16:57:35 [notice] 1#1: start worker process 34
2025/07/28 16:57:35 [notice] 1#1: start worker process 35
2025/07/28 16:57:35 [notice] 1#1: start worker process 36
Bash
$ kubectl exec -it simple-nginx -- sh


/ # ls

bin                   docker-entrypoint.sh  lib                   opt                   root                  srv                   usr
dev                   etc                   media                 proc                  run                   sys                   var
docker-entrypoint.d   home                  mnt                   product_uuid          sbin                  tmp


/ # ifconfig 
eth0      Link encap:Ethernet  HWaddr 06:96:9D:27:29:98  
          inet addr:10.244.1.2  Bcast:10.244.1.255  Mask:255.255.255.0
          inet6 addr: fe80::496:9dff:fe27:2998/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:5 errors:0 dropped:0 overruns:0 frame:0
          TX packets:14 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:446 (446.0 B)  TX bytes:1076 (1.0 KiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
Bash
$ kubectl delete -f simple-nginx.yml

pod "simple-nginx" deleted


$ kubectl get pods

No resources found in default namespace.
Bash
# Delete the pod
$ kubectl delete pod simple-nginx

pod "simple-nginx" deleted


# Let's check the pod
# It is gone
$ kubectl get po

No resources found in default namespace.
Bash

Leave a Comment


The reCAPTCHA verification period has expired. Please reload the page.