Octonote AI
Make your own →

What happens when you run kubectl apply

Sunil Tiwari · Oct 12, 2026 · 2 min read

From a YAML file to running containers: the API server, etcd, controllers, the scheduler and the kubelet.

You type kubectl apply -f deployment.yaml and, seconds later, pods are running. In between, six components cooperate without ever calling each other directly. They all just watch the API server.

The manifest

apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
spec:
  replicas: 3
  selector:
    matchLabels: { app: web }
  template:
    metadata:
      labels: { app: web }
    spec:
      containers:
        - name: web
          image: nginx:1.27
          ports: [{ containerPort: 80 }]

Step by step

  1. kubectl validates the file, computes a diff and sends it to the API server.
  2. The API server authenticates you, runs admission controllers and writes the Deployment to etcd.
  3. The Deployment controller notices it and creates a ReplicaSet.
  4. The ReplicaSet controller creates 3 Pod objects with no node assigned.
  5. The scheduler picks a node for each pod (resources, affinity, taints) and writes the binding.
  6. The kubelet on that node sees a pod bound to it, pulls the image and starts the container via the runtime.
sequenceDiagram
  participant K as kubectl
  participant A as API server
  participant E as etcd
  participant C as Controllers
  participant S as Scheduler
  participant L as Kubelet
  K->>A: apply Deployment
  A->>E: persist
  C-->>A: watch: new Deployment
  C->>A: create ReplicaSet + 3 Pods
  S-->>A: watch: unscheduled Pods
  S->>A: bind Pod → node-2
  L-->>A: watch: Pod on node-2
  L->>L: pull image, start container
  L->>A: status: Running

The key idea: reconciliation

Every controller runs the same loop: compare desired state (in etcd) with actual state, then act to close the gap. That is why deleting a pod just makes a new one appear.

Nothing in Kubernetes calls anything else. Everything watches the API server and reconciles.

Check it yourself

kubectl apply -f deployment.yaml
kubectl get events --sort-by=.metadata.creationTimestamp
kubectl get pods -o wide -w

Published with Octonote AI · Make your own