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.

Elements Inside a Pod

Elements Isolated for Container inside a Pod
Inside Kubernetes, Pods have the following things isolated for each container-
Elements common for Containers inside a Pod
The following elements are common for all 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
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
YAMLUse 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