Manual Scheduling


apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
    - containerPort: 8080
  nodeName:

Pod ๋ฅผ ์ƒ์„ฑํ•˜๋ฉด ์œ„ ์ฒ˜๋Ÿผ nodeName ์ด ๋นˆ ์นธ์ธ ์ƒํƒœ๊ฐ€ K8s memory ์— ์ €์žฅ๋œ๋‹ค. kube-scheduler ๋Š” ์ƒ์„ฑ๋œ Pod ์ค‘ scheduling ๋Œ€์ƒ์ด ๋  Pod ๋“ค์„ nodeName ํ•„๋“œ๊ฐ€ ๋นˆ ์นธ์ธ ๊ฒƒ์„ ํ†ตํ•ด ์ฐพ์•„๋‚ธ๋‹ค. ์ดํ›„ scheduling algorithm ์œผ๋กœ Pod ๋ฅผ ๋ฐฐ์น˜ํ•  ์ ์ ˆํ•œ Node ๋ฅผ ์ฐพ์•„๋‚ธ ํ›„ Pod ๋ฅผ ๋ฐฐ์น˜ํ•œ ๋’ค nodeName ์— Node ์˜ ์ด๋ฆ„์„ ์ถ”๊ฐ€ํ•œ๋‹ค.

apiVersion: v1
kind: Binding
metadata:
  name: nginx
target:
  apiVersion: v1
  kind: Node
  name: node02
curl --header "Content-Type:application/json" --request POST --data '{"apiVersion":"v1", "kind":"Binding", ...}' http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/

๋งŒ์•ฝ kube-scheduler ๊ฐ€ ์‹คํ–‰ ์ค‘์ด์ง€ ์•Š๋‹ค๋ฉด Pod ๋ฅผ ์ƒ์„ฑํ•ด๋„ Pending ์ƒํƒœ๋กœ Pod ๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š”๋‹ค. ๋•Œ๋ฌธ์— ์ˆ˜๋™์œผ๋กœ Pod ๋ฅผ scheduling ํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ ์ง์ ‘ nodeName ์„ ์ง€์ •ํ•ด์ค€ ์ƒํƒœ๋กœ Pod ๋ฅผ ์ƒ์„ฑํ•˜๊ฑฐ๋‚˜, Pod ๊ฐ€ ์ด๋ฏธ ์ƒ์„ฑ๋œ ๊ฒฝ์šฐ ์œ„ ์ฒ˜๋Ÿผ Binding ์„ ๋งŒ๋“ค๊ณ  curl ์š”์ฒญ์„ ํ†ตํ•ด ๋™์ ์œผ๋กœ Pod ๋ฅผ ๋ฐฐ์น˜ํ•  ์ˆ˜๋„ ์žˆ๋‹ค.

Labels and Selectors


 apiVersion: v1
 kind: Pod
 metadata:
   name: simple-webapp
   labels:
     app: App1
     function: Front-end
 spec:
   containers:
   - name: simple-webapp
     image: simple-webapp
     ports:
     - containerPort: 8080

Label ์€ ์—ฌ๋Ÿฌ K8s Object ์ค‘ ๊ด€๋ จ๋œ Object ๋“ค๋งŒ ์ฐพ์•„๋‚ด๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ์ž๊ฐ€ ์ง€์ •ํ•œ ์ผ์ข…์˜ ๋ณ„๋ช…๊ณผ ๊ฐ™๋‹ค. ์œ„์™€ ๊ฐ™์€ Pod ๋ฅผ ์ƒ์„ฑํ•˜์˜€์„ ๊ฒฝ์šฐ,

kubectl get pods --selector app=App1

Selector ์˜ต์…˜์„ ํ†ตํ•ด Label ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š” Pod ๋งŒ ์ฐพ์•„๋‚ผ ์ˆ˜ ์žˆ๋‹ค.

 apiVersion: apps/v1
 kind: ReplicaSet
 metadata:
   name: simple-webapp
   labels:
     app: App1
     function: Front-end
 spec:
   replicas: 3
   selector:
     matchLabels:
       app: App1
   template:
     metadata:
       labels:
         app: App1
         function: Front-end
     spec:
       containers:
       - name: simple-webapp
         image: simple-webapp

์œ„์™€ ๊ฐ™์€ ReplicaSet ์„ ์ƒ์„ฑํ•  ๋•Œ metadata.labels ๋Š” ํ•ด๋‹น ReplicaSet ์— ๋Œ€ํ•œ Label ์ด๊ณ , spec.selector.matchLabels ๋Š” ReplicaSet ์ด ์ œ์–ดํ•  Pod ์„ ํŠน์ •ํ•˜๊ธฐ ์œ„ํ•œ Label ์ด๊ณ , spec.template.metadata.labels ๊ฐ€ ReplicaSet ์— ์˜ํ•ด ์ƒ์„ฑ๋  Pod ์˜ Label ์ด๋‹ค.

apiVersion: v1
kind: Service
metadata:
  name: my-service
spec:
  selector:
    app: App1
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376 

Service ๋„ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ spec.selector ๋ฅผ ํ†ตํ•ด ์—ฐ๊ฒฐํ•  Pod ๋ฅผ ํŠน์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

Annotations


apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: simple-webapp
  labels:
    app: App1
    function: Front-end
  annotations:
    buildversion: 1.34
spec:
  replicas: 3
  selector:
    matchLabels:
      app: App1
template:
  metadata:
    labels:
      app: App1
      function: Front-end
  spec:
    containers:
    - name: simple-webapp
      image: simple-webapp

Label ์€ Selector ๋ฅผ ํ†ตํ•ด Object ๋ฅผ ํŠน์ •ํ•˜๊ธฐ ์œ„ํ•ด ์“ฐ์ด๋Š” ๋ฐ˜๋ฉด, Annotation ์€ ๋‹ค๋ฅธ ์ผ๋ฐ˜์ ์ธ ์ •๋ณด๋ฅผ ๊ธฐ๋กํ•˜๊ธฐ ์œ„ํ•ด ์“ฐ์ธ๋‹ค.

Taints and Tolerations


kubectl taint nodes {node-name} {key}={value}:{taint-effect}
# Taint ์„ค์ •
kubectl taint nodes node1 app=blue:NoSchedule
# Taint ์ œ๊ฑฐ
kubectl taint nodes node1 app=blue:NoSchedule-

Taint ๋Š” Pod ๊ฐ€ ํŠน์ • Node ์— ๋ฐฐ์น˜๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์„ค์ •์ด๋‹ค. ์œ„์™€ ๊ฐ™์€ ๋ช…๋ น์–ด๋ฅผ ํ†ตํ•ด ํŠน์ • Node ๋ฅผ Taint ์‹œํ‚ฌ ์ˆ˜ ์žˆ๋‹ค. taint-effect ๋Š” ์ด 3๊ฐ€์ง€๋กœ ์•„๋ž˜์™€ ๊ฐ™๋‹ค.

  • NoSchedule: Tolerant ํ•˜์ง€ ์•Š์€ Pod ๋Š” schedule ๋˜์ง€ ์•Š๋Š”๋‹ค. ์ด๋ฏธ ๋ฐฐ์น˜๋œ Intolerant ํ•œ Pod ๋Š” ๊ทธ๋Œ€๋กœ ์‹คํ–‰๋œ๋‹ค.
  • PreferNoSchedule: ์›ฌ๋งŒํ•˜๋ฉด schedule ๋˜์ง€ ์•Š์ง€๋งŒ ๋ณด์žฅ๋˜์ง„ ์•Š๋Š”๋‹ค.
  • NoExecute: Tolerant ํ•˜์ง€ ์•Š์€ Pod ๊ฐ€ ์ œ๊ฑฐ๋œ๋‹ค.
apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: nginx-container
    image: nginx
  tolerations:
  - key: "app"
    operator: "Equal"
    value: "blue"
    effect: "NoSchedule"

Pod ์— Tolerantion ์„ ๋ถ€์—ฌํ•˜๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ, spec.tolerations ์— Taint ์™€ ๊ฐ™์€ ์„ค์ •์„ ์ง€์ •ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. kube-scheduler ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ Taint ์™€ Toleration ์„ ๊ณ ๋ คํ•˜๋ฉฐ Pod ๋ฅผ ๋ฐฐ์น˜ํ•˜๋Š”๋ฐ, ๋งŒ์•ฝ Pod definition ์— spec.nodeName ํ•„๋“œ๊ฐ€ ๋ช…์‹œ๋˜์–ด ์žˆ๋‹ค๋ฉด NoSchedule ์ด์–ด๋„ scheduling ์„ ๊ฑด๋„ˆ๋›ฐ๊ณ  Pod ๊ฐ€ ๋ฐฐ์น˜๋œ๋‹ค. NoExecute ์˜ ๊ฒฝ์šฐ๋ผ๋ฉด Pod ๊ฐ€ ๋ฐฐ์น˜๋˜๋”๋ผ๋„ ์ œ๊ฑฐ๋  ์ˆ˜ ์žˆ๋‹ค.

kubectl describe node kubemaster | grep Taint

Master Node ๋„ ์‚ฌ์‹ค์€ Taint ๋˜์–ด ์žˆ์–ด์„œ Core Component ์™ธ Object ๊ฐ€ ๋ฐฐ์น˜๋˜์ง€ ์•Š๋Š” ๊ฒƒ์ด๋‹ค.

Node Selectors


apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: data-processor
    image: data-processor
  nodeSelector:
    size: Large

์ƒ๋Œ€์ ์œผ๋กœ ๋งŽ์€ ํ•˜๋“œ์›จ์–ด ๋ฆฌ์†Œ์Šค๋ฅผ ์š”๊ตฌํ•˜๋Š” ์ปจํ…Œ์ด๋„ˆ๋ฅผ ์ ์ ˆํ•œ Node ์—์„œ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•ด์„œ spec.nodeSelector ์„ค์ •์„ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. Node Selector ์—ญ์‹œ label ์„ ํ™œ์šฉํ•ด ๋Œ€์ƒ์ด ๋  Node ๋ฅผ ํŠน์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

kubectl label nodes {node-name} {label-key}={label-value}
kubectl label nodes node-1 size=Large

์œ„์™€ ๊ฐ™์€ ์ปค๋งจ๋“œ๋กœ ํŠน์ • Node ์— label ์„ ๋‹ฌ์•„์ฃผ๊ณ  Pod definition file ์—์„œ ํ•ด๋‹น label ์„ ๊ฐ€์ง„ Node ๋ฅผ ์ง€์ •ํ•ด์ค€ ๋’ค ์ƒ์„ฑํ•˜๋ฉด ์›ํ•˜๋Š” Node ์— Pod ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹ค๋งŒ spec.nodeSelector ์„ค์ •์€ ๋‹จ์ˆœํžˆ label ๋งŒ ํ™•์ธํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋ณต์žกํ•œ ์กฐ๊ฑด์œผ๋กœ Node ๋ฅผ ์„ค์ •ํ•˜๊ณ  ์‹ถ์„ ๋•Œ Node Affinity ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

Node Affinity


apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
spec:
  containers:
  - name: data-processor
    image: data-processor
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: size
            operator: In
            values:
            - Large
            - Medium

์œ„์™€ ๊ฐ™์ด Node Affinity ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด size In Large, size NotIn Small, size Exists ๋“ฑ ๋” ๋ณต์žกํ•œ ์กฐ๊ฑด๋ฌธ์„ ํ†ตํ•ด Pod ๊ฐ€ ๋ฐฐ์น˜๋  Node ๋ฅผ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. Pod ๊ฐ€ ๋ฐฐ์น˜๋  ์ ์ ˆํ•œ Node ๋ฅผ ์ฐพ๊ธฐ ์œ„ํ•ด requiredDuringSchedulingIgnoredDuringExecution ๊ณผ ๊ฐ™์€ ์„ค์ •๊ฐ’์„ ์ค„ ์ˆ˜ ์žˆ๋Š”๋ฐ,

  • Available
    • requiredDuringSchedulingIgnoredDuringExecution
    • preferredDuringSchedulingIgnoredDuringExecution
  • Planned
    • requiredDuringSchedulingRequiredDuringExecution
    • preferredDuringSchedulingRequiredDuringExecution ํ˜„์žฌ 2๊ฐ€์ง€๊ฐ€ ์ œ๊ณต๋˜๊ณ  ์ถ”ํ›„ 2๊ฐ€์ง€๊ฐ€ ๋” ์ถ”๊ฐ€๋  ์˜ˆ์ •์ด๋‹ค. ํ•ด๋‹น ์„ค์ •์€ ์ด๋ฆ„ ๊ทธ๋Œ€๋กœ ์ž‘๋™ํ•˜๋Š”๋ฐ, DuringScheduling ์€ Pod ๊ฐ€ Schedule ๋˜๋Š” ์‹œ์ ์— Node ์— ์•Œ๋งž๋Š” label ์ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๋Š” ๊ฒƒ์ด๊ณ  DuringExecution ์€ Node ๊ฐ€ Pod ๋ฅผ ํ˜ธ์ŠคํŒ…ํ•˜๋Š” ์ค‘ label ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ์‹œ ์ฒ˜๋ฆฌ๋ฅผ ์ง€์ •ํ•˜๋Š” ๊ฒƒ์ด๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, preferredDuringSchedulingIgnoredDuringExecution ์€ ์›ฌ๋งŒํ•˜๋ฉด Node label ์ด ์„ค์ •๋œ ๊ณณ์— Pod ๋ฅผ ๋ฐฐ์น˜ํ•˜๊ณ  ์‹ถ๋‹ค๋Š” ๊ฒƒ์ด๊ณ , ๋ฐฐ์น˜๋œ ์ดํ›„ Node label ์ด ๋ณ€๊ฒฝ๋˜๋”๋ผ๋„ ๊ทธ๋Œ€๋กœ ํ˜ธ์ŠคํŒ…ํ•ด๋‹ฌ๋ผ๋Š” ์˜๋ฏธ๋‹ค.

Taints and Tolerations vs Node Affinity


Taints and Tolerations ๊ธฐ๋Šฅ๊ณผ Node Affinity ๋ฅผ ์ ์ ˆํžˆ ์กฐํ•ฉํ•˜์—ฌ ์‚ฌ์šฉํ•˜๋ฉด ์›ํ•˜๋Š” Pod ๋ฅผ ์›ํ•˜๋Š” Node ์— ๋ฐฐ์น˜์‹œํ‚ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•  ์ˆ˜ ์žˆ๋‹ค. ์œ„ ๊ทธ๋ฆผ์ฒ˜๋Ÿผ Node ๋ฅผ Taint ์‹œ์ผœ ์›ํ•˜๋Š” Pod ์™ธ์˜ Pod ๊ฐ€ ๋ฐฐ์น˜๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ณ , Node Affinity ๋ฅผ ํ†ตํ•ด Pod ๊ฐ€ ํŠน์ • Node ์— ๋ฐฐ์น˜๋˜๊ฒŒ๋” ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

Resource Requirements and Limits


apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: app
    image: images.my-company.example/app:v4
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"
  - name: log-aggregator
    image: images.my-company.example/log-aggregator:v6
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

Pod ๊ฐ€ Node ์— ๋ฐฐ์น˜๋˜๋ฉด Node ์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋˜๋Š”๋ฐ ์œ„์ฒ˜๋Ÿผ ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰์„ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค. Request ์™€ Limit ์€ ๋ง ๊ทธ๋Œ€๋กœ Pod ๊ฐ€ ํ•„์š”ํ•œ ์ตœ์†Œ ์šฉ๋Ÿ‰์˜ ๋ฆฌ์†Œ์Šค์™€ ์ตœ๋Œ€๋กœ ์ ์œ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฆฌ์†Œ์Šค๋ฅผ ์˜๋ฏธํ•œ๋‹ค. CPU ์˜ ๊ฒฝ์šฐ Limit ์„ ์ ˆ๋Œ€ ์ดˆ๊ณผํ•˜์ง€ ์•Š์ง€๋งŒ ๋ฉ”๋ชจ๋ฆฌ์˜ ๊ฒฝ์šฐ ์–ด๋Š์ •๋„ ์ดˆ๊ณผ๋ถ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•œ๋‹ค. ๋‹ค๋งŒ ๋„ˆ๋ฌด ์˜ค๋žœ ๊ธฐ๊ฐ„ Limit ์„ ์ดˆ๊ณผํ•˜๋ฉด OOM ์ด ๋ฐœ์ƒํ•˜๋ฉฐ Pod ๊ฐ€ ์ œ๊ฑฐ๋  ์ˆ˜ ์žˆ๋‹ค.

LimitRange

apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-resource-constraint
spec:
  limits:
  - default:        # ๊ธฐ๋ณธ Limit
      cpu: 500m
    defaultRequest: # ๊ธฐ๋ณธ Request
      cpu: 500m
    max:            # ์ตœ๋Œ€ Limit
      cpu: "1"
    min:            # ์ตœ์†Œ Request
      cpu: 100m
    type: Container

K8s Cluster ์— ๋ฐฐ์น˜๋  ๋ชจ๋“  Pod ์— ๋Œ€ํ•œ ๊ธฐ๋ณธ๊ฐ’์„ ์„ค์ •ํ•ด์ฃผ๊ณ  ์‹ถ์€ ๊ฒฝ์šฐ LimitRange Object ๋ฅผ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. LimitRange ๋Š” namespace ๋‚ด์—์„œ ์ ์šฉ๋˜๋ฉฐ ๋ฉ”๋ชจ๋ฆฌ๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค. LimitRange Object ๊ฐ€ ์ƒ์„ฑ๋œ ์ดํ›„ ์ ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ค‘๊ฐ„์— ์ˆ˜์ •ํ•œ๋‹ค ํ•˜๋”๋ผ๋„ ๊ธฐ์กด์— ์ƒ์„ฑ๋˜์–ด ์žˆ๋Š” Pod ์—” ์ ์šฉ๋˜์ง€ ์•Š๊ณ  ์ƒˆ๋กœ ์ƒ์„ฑํ•˜๋Š” Pod ์—๋งŒ ์ ์šฉ๋œ๋‹ค. ๋ฒ”์œ„๋ฅผ ์„ค์ •ํ•ด์ฃผ๋Š” ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— requests.cpu: 700m ์งœ๋ฆฌ Pod ๋ฅผ ์ƒ์„ฑํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๋ฒ”์œ„ ์™ธ ์š”์ฒญ์ด๊ธฐ์— Pod ์ƒ์„ฑ์ด ์ œํ•œ๋œ๋‹ค.

ResourceQuota

apiVersion: v1
kind: ResourceQuota
metadata:
  name: my-resource-quota
spec:
  hard:
    requests.cpu: 4
    requests.memory: 4Gi
    limits.cpu: 10
    limits.memory: 10Gi

namespace ๋งˆ๋‹ค ๋ฆฌ์†Œ์Šค ์‚ฌ์šฉ๋Ÿ‰์„ ์ œํ•œํ•˜๊ณ  ์‹ถ์„ ๊ฒฝ์šฐ ResourceQuota ๋ฅผ ํ™œ์šฉํ•˜์—ฌ namespace ์ „์ฒด์— ๋ฆฌ์†Œ์Šค ์š”์ฒญ ๋ฐ ์ œํ•œ์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

DaemonSets


Static Pods


Multiple Schedulers


Configuring Scheduler Profiles


Admission Controllers


Validating and Mutating Admission Controllers


References