Kubernetes

Day – 5 | How Kubernetes Schedules and Runs a Pod

How Kubernetes Schedules and Runs a Pod – Complete Workflow

When you create a Pod in Kubernetes, it passes through several components before it starts running on a worker node.

This article explains the complete lifecycle of a Pod from the moment you execute kubectl apply until the container is running.


Step 1: User Creates a Pod

Run the following command:

kubectl apply -f nginx.yaml

kubectl reads the YAML file and sends a REST API request to the kube-apiserver.

kubectl
    |
    | HTTP REST API
    v
kube-apiserver

Step 2: API Server Validates the Request

The API Server performs several checks before accepting the request:

  • Authentication
  • Authorization (RBAC)
  • Admission Controllers
  • Schema Validation

If everything is valid, the API Server stores the Pod object inside etcd.

kubectl
     |
     v
kube-apiserver
     |
     | Store Pod
     v
    etcd

At this stage, the Pod exists only as an object inside etcd.

It is not running on any node yet.

Example Pod object:

Pod:
    name: nginx
    nodeName: ""
    status: Pending

Notice that:

nodeName = empty

No worker node has been selected yet.


Step 3: kube-scheduler Notices a Pending Pod

The kube-scheduler continuously watches the API Server.

It does not communicate directly with etcd.

Conceptually:

Scheduler

Watch all Pods

IF nodeName == empty
      schedule it

Communication flow:

Scheduler
      |
Watch API Server
      |
API Server

Step 4: Scheduler Reads the Pod Information

The scheduler retrieves the Pod details through the API Server, including:

  • Pod requirements
  • CPU requests
  • Memory requests
  • Affinity rules
  • Taints
  • Tolerations
  • Node labels
  • Volume requirements

The API Server fetches this information from etcd.

Scheduler
      |
      | Watch Pod
      v
API Server
      |
      | Read
      v
etcd

Step 5: Scheduler Selects the Best Worker Node

Suppose the cluster contains three worker nodes:

Worker-1
Worker-2
Worker-3

The scheduler evaluates each node.

Example:

Worker1
CPU: 90%

Worker2
CPU: 10%

Worker3
CPU: 50%

The scheduler selects:

Worker2

Step 6: Scheduler Informs the API Server

Important:

The scheduler does not write directly to etcd.

Instead, it tells the API Server:

Assign Pod nginx
to Worker2

The API Server updates the Pod object inside etcd.

Before scheduling:

nodeName=""

After scheduling:

nodeName="worker2"

Flow:

Scheduler
      |
      v
API Server
      |
      v
etcd

Step 7: kubelet Watches the API Server

Every worker node runs a kubelet.

Worker1
   kubelet

Worker2
   kubelet

Worker3
   kubelet

Each kubelet continuously watches the API Server.

It periodically checks:

Do you have any Pods assigned to me?

The kubelet communicates only with the API Server.

It never communicates directly with:

  • etcd
  • kube-scheduler
kubelet
      |
Watch
      |
API Server

Step 8: Worker2 Receives the Pod

The kubelet running on Worker2 discovers:

Pod nginx

Assigned to Worker2

It then downloads the complete Pod specification.

containers
volumes
environment variables
ports
container image

The API Server retrieves these details from etcd.

kubelet
      |
      v
API Server
      |
      v
etcd

Step 9: kubelet Communicates with the Container Runtime

The kubelet does not create containers itself.

Instead, it communicates with the container runtime.

Examples:

  • containerd
  • CRI-O
  • Docker (older Kubernetes versions)

This communication happens through the Container Runtime Interface (CRI).

kubelet
      |
      | CRI
      v
containerd

Step 10: containerd Creates the Pod

containerd performs several operations:

  • Pulls the container image
docker.io/nginx
  • Creates the Pod Sandbox
  • Creates the Network Namespace
  • Prepares the Container Filesystem

Finally, containerd invokes:

runc

runc interacts with the Linux kernel to create the actual Linux containers.

Flow:

kubelet

      |

containerd

      |

runc

      |

Linux Kernel

Step 11: Pod Starts Running

Once the container starts, the kubelet reports the Pod status back to the API Server.

Status progression:

Pending

↓

ContainerCreating

↓

Running

Flow:

kubelet
      |
      v
API Server
      |
      v
etcd

Step 12: kube-proxy Configures Networking

One important clarification:

kube-proxy does not create networking rules simply because a Pod is created.

Instead, kube-proxy watches:

  • Services
  • Endpoints / EndpointSlices

When a Service points to one or more Pods, kube-proxy creates networking rules using:

  • iptables
  • IPVS
  • nftables (depending on the configuration)

Example:

Service

10.96.0.5

↓

Pod1
Pod2
Pod3

Requests sent to 10.96.0.5 are automatically load-balanced across the available Pods.

Flow:

API Server
      |
Watch Services / EndpointSlices
      |
kube-proxy
      |
iptables / IPVS / nftables rules

Complete Kubernetes Pod Scheduling Flow

                 kubectl
                     |
                     |
                     v
             kube-apiserver
                     |
                     | Store Pod
                     v
                   etcd
                     ^
                     |
        (Only API Server talks to etcd)
                     |
                     |
             kube-scheduler
        Watches API Server
                     |
                     | Select Worker2
                     v
             kube-apiserver
                     |
                     | Update nodeName
                     v
                   etcd
                     ^
                     |
                     |
        Worker2 kubelet watches API Server
                     |
                     | Get Pod Specification
                     v
             kube-apiserver
                     |
                     v
                   etcd
                     |
                     |
                     v
                 kubelet
                     |
                     | CRI
                     v
                 containerd
                     |
                     v
                    runc
                     |
                     v
               Linux Kernel
                     |
                     v
                  Pod Running

kube-proxy
     |
     | Watches Services and EndpointSlices
     | through the API Server
     v
Creates iptables / IPVS / nftables rules

Key Takeaways

  • kubectl → kube-apiserver → etcd is the correct initial flow.
  • ✔ The kube-scheduler watches the API Server for Pods whose nodeName is empty.
  • ✔ The scheduler selects the most suitable worker node based on available resources and scheduling constraints.
  • ✔ The scheduler informs the API Server, which updates the Pod object in etcd.
  • ✔ Every kubelet watches the API Server. When it detects a Pod assigned to its node, it retrieves the Pod specification.
  • ✔ The kubelet asks the container runtime (such as containerd) to create the Pod using the Container Runtime Interface (CRI).
  • containerd uses runc to create the Linux containers.
  • kube-proxy watches Services and EndpointSlices and configures networking rules using iptables, IPVS, or nftables.
  • ✔ The kube-apiserver is the central communication hub. Every Kubernetes core component communicates with the API Server, and only the API Server reads from and writes to etcd.

Add Comment

Click here to post a comment

Topics