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 ์ ์ฒด์ ๋ฆฌ์์ค ์์ฒญ ๋ฐ ์ ํ์ ์ค์ ํ ์ ์๋ค.