From Ever changing code

< Kubernetes

Default scheduler rules

  1. Identify if a node has adequate hardware resources
  2. Check if a node is running out of resources. check for memory or disk pressure conditions
  3. Check if a pod schedule is scheduled to a node by a name
  4. Check if a node has a label matching node selector in a pod spec
  5. Check if a pod is requesting to bound to a specific host port and if so, does the node have that port available
  6. Check if a pod is requesting a certain type of volume be mounted and if other pods are using the same volume
  7. Check if a pod tolerates taints of the node, eg. master nodes is tainted with "noSchedule"
  8. Check if a pod or a node affinity rules and checking if scheduling the pod would break these rules
  9. If there is more than one node could schedule a pod, the scheduler priorities the nodes and choose the best one. If they have the same priority it chooses in round-robin fashion.

Label nodes

kubectl label node share-type=dedicated

YAML for the deployment to include the node affinity rules:

apiVersion: extensions/v1beta1
kind: Deployment
  name: pref
  replicas: 5
        app: pref
          preferredDuringSchedulingIgnoredDuringExecution: #all pods,but not current pod on the node
          - weight: 80
              - key: availability-zone
                operator: In
                - zone1
          - weight: 20              #4 time less priority then AZ
              - key: share-type     #label key
                operator: In
                - dedicated         #label value
      - args:
        - sleep
        - "999"
        image: busybox:v1.28.4
        name: main

Cluster nodes capacity and resources

Check node's capacity

kubectl describe nodes | grep -A 20 Capacity:
# ...(output omitted)...
 cpu:                2
 ephemeral-storage:  20263528Ki
 hugepages-2Mi:      0
 memory:             4044936Ki
 pods:               110
 cpu:                2
 ephemeral-storage:  18674867374
 hugepages-2Mi:      0
 memory:             3942536Ki
 pods:               110
System Info:
 Machine ID:                 ******c49b4bed31684a******
 System UUID:                ******-D110-CB50-EAA3-*******
 Boot ID:                    ****8-be21-45ca-b86c-311a479******
 Kernel Version:             4.4.0-1087-aws
 OS Image:                   Ubuntu 16.04.6 LTS
 Operating System:           linux
 Architecture:               amd64
 Container Runtime Version:  docker://18.6.1
 Kubelet Version:            v1.13.10
 Kube-Proxy Version:         v1.13.10
Non-terminated Pods:         (3 in total)
  Namespace                  Name                           CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------                  ----                           ------------  ----------  ---------------  -------------  ---
  default                    busybox                        0 (0%)        0 (0%)      0 (0%)           0 (0%)         18h
  kube-system                kube-flannel-ds-amd64-p7c7m    100m (5%)     100m (5%)   50Mi (2%)        50Mi (2%)      5d9h
  kube-system                kube-proxy-27dbb               0 (0%)        0 (0%)      0 (0%)           0 (0%)         5d9h
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests   Limits
  --------           --------   ------
  cpu                100m (5%)  100m (5%)
  memory             50Mi (2%)  50Mi (2%)
  ephemeral-storage  0 (0%)     0 (0%)
# ...(output omitted)...

Resource request and limit

resource request
the amount of resources necessary to run a container; a pod will only run on a node that has enough resources to run pod's containers
resource limit
a maximum value for the resource usage of a container.
  • Exceeding a memory limit makes your container process a candidate for oom-killing
  • process basically can’t exceed the set cpu quota, and will never get evicted for trying to use more cpu time than allocated. The system enforces the quota at the scheduler so the process just gets throttled at the limit.

Units k8s docs

  • memory 64Mi - measures in bytes, it means 64 Mebibytes
  • cpu 250m - measured in cores, it means 250 miliCPUs or 0.25 CPU core

Note: 1 MiB = 220 bytes = 1048576bytes = 1024 kibibytes

Schedule a pod with resources request on the specific node

apiVersion: v1
kind: Pod
  name: resource-pod1
  nodeSelector: ""
  - image: busybox
    command: ["dd", "if=/dev/zero", "of=/dev/null"]
    name: budybox-dd
        cpu: 800m     # mili cores -> 2000m=20% of cpu (large for 2nd deployment)
        memory: 20Mi  # Mb

Create a pod and watch resource request balance changing

kubectl apply -f resource-pod1.yml
watch -d 'kubectl describe nodes  | grep -A 25 Non-terminated'
Non-terminated Pods: (6 in total)
  Namespace          Name                                CPU Requests  CPU Limits  Memory Requests  Memory Limits  AGE
  ---------          ----                                ------------  ----------  ---------------  -------------  ---
  default            busybox                             0 (0%)        0 (0%)      0 (0%)           0 (0%)         24h
  default            nginx-loadbalancer-86bb844fb7-bl5fs 0 (0%)        0 (0%)      0 (0%)           0 (0%)         2d
  default         -->resource-pod1<--                    800m (40%)    0 (0%)      20Mi (0%)        0 (0%)         6m7s
  kube-system        kube-flannel-ds-amd64-97hvr         100m (5%)     100m (5%)   50Mi (1%)        50Mi (1%)      14d
  kube-system        kube-proxy-fxl6f                    0 (0%)        0 (0%)      0 (0%)           0 (0%)         14d
  rbac1              test-f57db4bfd-ghshj                0 (0%)        0 (0%)      0 (0%)           0 (0%)         12d
Allocated resources:
  (Total limits may be over 100 percent, i.e., overcommitted.)
  Resource           Requests    Limits
  --------           --------    ------
  cpu                900m (45%)  100m (5%) # <- resources balance
  memory             70Mi (1%)   50Mi (1%)
  ephemeral-storage  0 (0%)      0 (0%)

Then deploying another pod, requesting 2000mi cpus, will end up with scheduling error when describing the pod

kubectl describe pod pod2-2000mi-cpu
  Type     Reason            Age                   From               Message
  ----     ------            ----                  ----               -------
  Warning  FailedScheduling  44s (x10 over 4m57s)  default-scheduler  0/3 nodes are available: 2 node(s) didn't match node selector, 3 Insufficient cpu.

Limits YAML, Unlike requests, limits can go above total utilisation of CPU and memory. K8s will detect if overcommitted and kill the pod. Be aware Containers within pods are not aware of limits sets to pods, this can be seen from top command within a container.

apiVersion: v1
kind: Pod
  name: pod-limit-resources
  - image: busybox
    command: ["dd", "if=/dev/zero", "of=/dev/null"]
    name: main
        cpu: 2        #by default requests are eq limits if not specified
        memory: 40Mi  #


A DaemonSet ensures that all (or some) Nodes run a copy of a Pod. As nodes are added to the cluster, Pods are added to them. As nodes are removed from the cluster, those Pods are garbage collected. Deleting a DaemonSet will clean up the Pods it created. DaemonSets do not use a scheduler to deploy pods, DS used to ignore nodes taints. Some typical uses of a DaemonSet are:

  • running a cluster storage daemon, such as glusterd, ceph, on each node.
  • running a logs collection daemon on every node, such as fluentd or logstash.
  • running a node monitoring daemon on every node, such as Prometheus Node Exporter, collectd

Monitor events and logs

kubectl get events --all-namespaces
kubectl get events --watch #short -w

#See scheduler logs
kubectl logs [kube_scheduler_pod_name] -n kube-system
tail -f /var/log/kube-scheduler.log #run on control plane node