> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Lab Solution Manual Scheduling optional

> Hands-on lab showing how to diagnose a Pending Kubernetes Pod when kube-scheduler is absent and manually schedule it to a node by setting nodeName

In this lab you will diagnose a Pending Pod caused by a missing scheduler and manually schedule it onto a specific node using `nodeName`. This exercise demonstrates how Kubernetes schedules Pods, what happens when the scheduler is not available, and how to place a Pod on a chosen node manually.

Objective: create a Pod from `nginx.yaml` and manually schedule it onto specific nodes when the kube-scheduler is not available.

***

## Initial environment and Pod creation

Environment summary:

* Cluster with two nodes (controlplane and node01).
* A file named `nginx.yaml` defines a simple Pod using the `nginx` image.
* We'll create the Pod and observe its status.

Check nodes and list files:

```shell theme={null}
root@controlplane:~# kubectl get nodes
NAME            STATUS   ROLES                 AGE   VERSION
controlplane    Ready    control-plane,master  14m   v1.20.0
node01          Ready    <none>                14m   v1.20.0

root@controlplane:~# ls
nginx.yaml  sample.yaml
```

Contents of `nginx.yaml` (initial version):

```yaml theme={null}
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  containers:
  - image: nginx
    name: nginx
```

Create the Pod:

```shell theme={null}
root@controlplane:~# kubectl create -f nginx.yaml
pod/nginx created
```

***

## Check Pod status

Immediately after creation the Pod appears in Pending state:

```shell theme={null}
root@controlplane:~# kubectl get pods
NAME   READY   STATUS    RESTARTS   AGE
nginx  0/1     Pending   0          12s
```

***

## Why is the Pod Pending?

A Pending Pod typically means it has not been scheduled to any node. Inspecting the Pod shows `Node: <none>` and there are no scheduling events:

```shell theme={null}
root@controlplane:~# kubectl describe pod nginx
Name:         nginx
Namespace:    default
Priority:     0
Node:         <none>
Labels:       <none>
Annotations:  <none>
Status:       Pending
IP:
IPs:          <none>
Containers:
  nginx:
    Image:        nginx
    Port:         <none>
    Host Port:    <none>
    Environment:  <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-kpdm6 (ro)

Volumes:
  default-token-kpdm6:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-kpdm6
    Optional:    false
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:         <none>
```

Check core control-plane Pods in the `kube-system` namespace:

```shell theme={null}
root@controlplane:~# kubectl get pods -n kube-system
NAME                                  READY   STATUS    RESTARTS   AGE
coredns-74ff55c5b-csz5x               1/1     Running   0          16m
coredns-74ff55c5b-vzlnv               1/1     Running   0          16m
etcd-controlplane                     1/1     Running   0          16m
kube-apiserver-controlplane           1/1     Running   0          16m
kube-controller-manager-controlplane  1/1     Running   0          16m
kube-flannel-ds-9pcnm                 1/1     Running   0          16m
kube-flannel-ds-nzbns                 1/1     Running   0          16m
# Note: There is no kube-scheduler Pod listed here.
```

Because the scheduler Pod (`kube-scheduler`) is not present, no automated scheduling occurs and the Pod remains in the Pending state.

***

## Manually scheduling the Pod

You can bypass the kube-scheduler by setting `nodeName` in the Pod spec. This pins the Pod to the named node during creation.

Edit `nginx.yaml` and add `nodeName: node01` under `spec`:

```yaml theme={null}
---
apiVersion: v1
kind: Pod
metadata:
  name: nginx
spec:
  nodeName: node01
  containers:
  - image: nginx
    name: nginx
```

Apply the change by replacing the existing Pod. `kubectl replace --force -f` deletes and recreates the resource:

```shell theme={null}
root@controlplane:~# kubectl replace --force -f nginx.yaml
pod "nginx" deleted
pod/nginx replaced
```

Monitor the Pod as it is being created (it typically moves from `ContainerCreating` to `Running`):

```shell theme={null}
root@controlplane:~# kubectl get pods
NAME   READY   STATUS              RESTARTS   AGE
nginx  0/1     ContainerCreating   0          8s

root@controlplane:~# kubectl get pods --watch
NAME   READY   STATUS    RESTARTS   AGE
nginx  1/1     Running   0          19s
```

Verify which node the Pod landed on using wide output:

```shell theme={null}
root@controlplane:~# kubectl get pods -o wide
NAME   READY   STATUS    RESTARTS   AGE   IP           NODE
nginx  1/1     Running   0          1m    10.244.1.2   node01
```

***

<Callout icon="lightbulb" color="#1CB2FE">
  You cannot move a running Pod from one node to another directly. To "move" a Pod, delete the Pod on its current node and recreate it with a different `nodeName` (or let the kube-scheduler place it). Pods are host-bound until recreated elsewhere.
</Callout>

<Callout icon="lightbulb" color="#1CB2FE">
  Deleting a Pod includes a graceful termination period: Kubernetes sends termination signals to the container and waits for shutdown. This can take a few seconds and is expected behavior.
</Callout>

***

## Scheduling the Pod on the control-plane node

For practice, set `nodeName: controlplane` in `nginx.yaml` and repeat the replace step. This forces the Pod onto the control-plane node even if the scheduler would not place regular workloads there.

Important: control-plane nodes often include taints (for example, `node-role.kubernetes.io/master:NoSchedule`) that prevent regular workloads from being scheduled. Manually setting `nodeName` bypasses the scheduler, but NoExecute taints can still evict a Pod unless it has matching tolerations.

Example replace & watch commands:

```shell theme={null}
# Edit nginx.yaml to set nodeName: controlplane, then:
kubectl replace --force -f nginx.yaml
kubectl get pods -o wide --watch
```

***

## Quick command reference

| Task | Command / Example |
| - | - |
| View nodes | `kubectl get nodes` |
| Create a Pod from a file | `kubectl create -f nginx.yaml` |
| Replace (force) a resource | `kubectl replace --force -f nginx.yaml` |
| Describe a Pod | `kubectl describe pod nginx` |
| Watch Pod status | `kubectl get pods --watch` |
| Show Pod with node info | `kubectl get pods -o wide` |
| List kube-system Pods | `kubectl get pods -n kube-system` |

***

## Links and references

* Kubernetes documentation: [https://kubernetes.io/docs/](https://kubernetes.io/docs/)
* Scheduling in Kubernetes (concepts): [https://kubernetes.io/docs/concepts/scheduling-eviction/](https://kubernetes.io/docs/concepts/scheduling-eviction/)
* Taints and tolerations: [https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/](https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/)

***

This completes the manual scheduling exercise: create a Pod, diagnose Pending status due to a missing scheduler, and manually schedule it using `nodeName`.

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/cka-certification-course-certified-kubernetes-administrator/module/cd124bdf-9911-4cc1-8177-f2d8b6dfd2a0/lesson/2ed5e46b-50bc-43bf-bb38-3c2ad9f00030" />
</CardGroup>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.