쿠버네티스 node의 pods들의 scheduling을 관리하는 컴포턴트로, 클러스터 내에서 실행될 파드(pod)를 적절한 노드(node)에 배치하는 역할을 한다. 즉, 어떤 파드를 어떤 노드에서 실행할 것인가를 결정한다.
√ pod를 node에 두는 것을 결정하는 것이 아니다 ☞ kubelet의 업무
주요 역할
- 파드 배치 결정: 스케줄링이 필요한 새 파드가 생성되면, kube-apiserver가 이를 kube-scheduler로 전달하고, 클러스터 내 노드 중 가장 적합한 노드를 선택한다.
- 스케줄링 조건 평가:
- 파드 요구사항과 노드 리소스 상태를 고려하여 적합한 노드를 선택한다.
- 예: CPU, 메모리, 태그(label), 노드 셋(label selector) 등의 조건
- 파드 요구사항과 노드 리소스 상태를 고려하여 적합한 노드를 선택한다.
- 클러스터 리소스 최적화: 클러스터 전체의 리소스 사용률을 최적화하기 위해 스케줄링 수행
- 다양한 스케줄링 정책 지원: 기본 스케줄링 외에도 사용자 정의 정책과 우선순위(Preemption) 지원
구성 파일 설정
- /etc/kubernetes/manifests/kube-scheduler.yaml
동작 원리
- 스케줄링 요청 수신:
- 새로운 파드가 생성되면, kube-apiserver가 이를 kube-scheduler로 전달한다.
- 적합한 노드 선택:
- kube-scheduler는 아래 두 단계를 통해 적합한 노드를 선택한다.
- 필터링 단계(Predicates):
- 노드 중에서 파드의 요구사항을 충족하지 못하는 노드를 제외시킨다.
- 예: 노드에 리소스 부족, 태그 불일치(Label Selector), 노드 준비 상태, Taint/Toleration 등
- 노드 중에서 파드의 요구사항을 충족하지 못하는 노드를 제외시킨다.
- 점수화 단계(Priorities):
- 필터링을 통과한 노드들에 대해 점수를 매기고, 가장 높은 점수를 받은 노드를 선택한다.
- 리소스 효율성, 노드 간 거리(Topology), 노드 선호도
- 필터링을 통과한 노드들에 대해 점수를 매기고, 가장 높은 점수를 받은 노드를 선택한다.
- 필터링 단계(Predicates):
- kube-scheduler는 아래 두 단계를 통해 적합한 노드를 선택한다.
- 스케줄링 결정:
- 선택된 노드를 해당 파드의 "NodeName" 필드에 기록하여 스케줄링 완료
- 스케줄링 결과 전달:
- kube-scheduler는 스케줄링 결과를 kube-apiserver에 전달하고, 파드는 지정된 노드에서 실행된다.
Manual Scheduling
만약 Pod의 노드를 배정하지 못했다면 Binding 개체를 생성하고, Pod의 binding API에 post request를 보내 scheduler의 역할을 대신한다.
# Pod-bind-definition.yaml
apiVersion: v1
kind: Binding
metadata:
name: nginx
target:
apiVersion: v1
kind: Node
name:
nodeName: node02
# curl --header "Content-Type:application/json" --request POST --data http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/
실습]
controlplane ~ $ cat nginx.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
controlplane ~ ➜ kubectl create -f nginx.yaml
pod/nginx created
controlplane ~ ➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 Pending 0 15s
# 현재 scheduler가 작동중지 않아서 Node가 배정되지 않았다.
controlplane ~ ➜ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-77d6fd4654-4pjh9 1/1 Running 0 5m33s
coredns-77d6fd4654-4vnf4 1/1 Running 0 5m33s
etcd-controlplane 1/1 Running 0 5m38s
kube-apiserver-controlplane 1/1 Running 0 5m38s
kube-controller-manager-controlplane 1/1 Running 0 5m38s
kube-proxy-mf9m5 1/1 Running 0 5m2s
kube-proxy-w76tl 1/1 Running 0 5m34s
controlplane ~ ➜ kubectl describe pod nginx | grep Node
Node: <none>
Node-Selectors: <none>
Multi-Scheduler
Reference: https://kubernetes.io/docs/tasks/extend-kubernetes/configure-multiple-schedulers/
Multi-Scheduler의 사용 목적
- 특정 요구사항 처리:
- 기본 스케줄러로 충족할 수 없는 복잡한 스케줄링 로직 구현.
- 예: 특정 하드웨어(GPU, 고속 네트워크 등)에 대한 스케줄링.
- 다양한 워크로드 지원: 서로 다른 워크로드를 다양한 스케줄링 정책으로 처리.
- 리소스 격리: 고유한 스케줄링 로직을 통해 워크로드가 특정 노드나 리소스를 차지하도록 보장.
쿠버네티스는 기본적으로 default-scheduler (scheduler-config.yaml) 사용한다.
그러나 default-scheduler가 needs에 맞지 않을때 custom scheduler를 만들고, 동시에 돌릴 수 있다.
각각의 scheduler는 별개의 config file을 사용해야 하고,
추가로 생성하는 custom-scheduler는 my-scheduler-config.yaml, my-scheduler-2-config.yaml와 같이 지어줄 수 있다.
# Use Custom Scheduler
custom scheduler가 deploy되고나서 해야할 것은 다음과 같다.
1. configure pod or custom scheduler를 사용하기 위한 deployment 만들기
✨사용자 정의 스케줄러는 일반적으로 Deployment로 배포
2. Pod Definition file을 만든다.
- scheduler를 Pod처럼 동작시켜주려면, Pod Definition file을 만들어 줘야 한다.
- scheduler conf file(auth 정보로 API server에 연결할 수 있다)의 Path 지정
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- image: nginx
name: nginx
schedulerName: custom-scheduler # schedulerName 필드를 사용하여 특정 스케줄러를 지정
3. Pod 생성 (kubectl create -f pod-definition.yaml)
- yaml파일이 잘못되면 pod는 계속 pending상태로 남아 있는다.
Multi-Scheduler의 동작 원리
- Pod 스케줄링 요청:
- Pod이 생성되면 schedulerName 필드에 따라 스케줄러가 선택된다. (기본값은 default-scheduler)
- 스케줄러 선택:
- Kubernetes는 Pod의 schedulerName에 따라 적절한 스케줄러로 요청을 전달한다.
- 노드 선택:
- 선택된 스케줄러는 해당 Pod에 가장 적합한 노드를 결정.
- 스케줄링 완료: 선택된 노드에 Pod 실행.
# leaderElection
고가용성을 보장하기 위해 리더(Leader)를 선출하고, 클러스터 내에서 리더가 작업을 독점적으로 수행하도록 하는 메커니즘이다. 이를 통해 같은 작업을 중복 수행하지 않도록 방지하고, 리더가 실패했을 경우 새로운 리더를 선출하여 작업을 지속할 수 있다.
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
leaderElection:
leaderElect: true
leaseDuration: 15s
renewDeadline: 10s
retryPeriod: 2s
leaderElect: 리더 선출 기능 활성화 여부.
- true: 리더 선출을 활성화.
- false: 모든 인스턴스가 작업을 수행.
leaseDuration:
- 리더로 유지되는 최대 시간. 이 시간이 지나면 다른 후보가 리더로 선출될 수 있음.
- 리더는 주기적으로 리스를 갱신하여 자신의 리더십을 유지
- 리더가 실패하거나 리스를 갱신하지 못하면, 리스가 만료되고 새로운 리더가 선출
# View Events
$ kubectl get events
controlplane ~ ➜ kubectl get events
LAST SEEN TYPE REASON OBJECT MESSAGE
27m Warning InvalidDiskCapacity node/controlplane invalid capacity 0 on image filesystem
27m Normal NodeHasSufficientMemory node/controlplane Node controlplane status is now: NodeHasSufficientMemory
27m Normal NodeHasNoDiskPressure node/controlplane Node controlplane status is now: NodeHasNoDiskPressure
27m Normal NodeHasSufficientPID node/controlplane Node controlplane status is now: NodeHasSufficientPID
27m Normal NodeAllocatableEnforced node/controlplane Updated Node Allocatable limit across pods
27m Normal Starting node/controlplane Starting kubelet.
27m Warning InvalidDiskCapacity node/controlplane invalid capacity 0 on image filesystem
27m Normal NodeHasSufficientMemory node/controlplane Node controlplane status is now: NodeHasSufficientMemory
27m Normal NodeHasNoDiskPressure node/controlplane Node controlplane status is now: NodeHasNoDiskPressure
27m Normal NodeHasSufficientPID node/controlplane Node controlplane status is now: NodeHasSufficientPID
27m Normal NodeAllocatableEnforced node/controlplane Updated Node Allocatable limit across pods
27m Normal RegisteredNode node/controlplane Node controlplane event: Registered Node controlplane in Controller
27m Normal Starting node/controlplane
27m Normal NodeReady node/controlplane Node controlplane status is now: NodeReady
100s Normal Scheduled pod/nginx Successfully assigned default/nginx to controlplane
99s Normal Pulling pod/nginx Pulling image "nginx"
94s Normal Pulled pod/nginx Successfully pulled image "nginx" in 4.994s (4.994s including waiting)
94s Normal Created pod/nginx Created container nginx
94s Normal Started pod/nginx Started container nginx
# View scheduler logs
$ kubectl logs <component-pod-name> -n kube-system
$ kubectl logs my-scheduler -n kube-system
# 실습
# custom-scheduler가 사용할 ServiceAccount 와 ClusterRoleBinding 생성해 놓은 상태.
$ kubectl get sa my-scheduler -n kube-system
NAME SECRETS AGE
my-scheduler 0 33s
$ kubectl get clusterrolebinding
NAME ROLE AGE
cluster-admin ClusterRole/cluster-admin 8m11s
flannel ClusterRole/flannel 8m7s
kubeadm:cluster-admins ClusterRole/cluster-admin 8m10s
kubeadm:get-nodes ClusterRole/kubeadm:get-nodes 8m9s
kubeadm:kubelet-bootstrap ClusterRole/system:node-bootstrapper
...
# Let's create a configmap that the new scheduler will employ using the concept of ConfigMap as a volume.
# We have already given a configMap definition file called my-scheduler-configmap.yaml at /root/ path that will create a configmap with name my-scheduler-config using the content of file /root/my-scheduler-config.yaml.
$ cat my-scheduler-config.yaml
apiVersion: kubescheduler.config.k8s.io/v1
kind: KubeSchedulerConfiguration
profiles:
- schedulerName: my-scheduler
leaderElection:
leaderElect: false
$ kubectl create configmap my-scheduler-config --from-fi
le /root/my-scheduler-config.yaml -n kube-system
configmap/my-scheduler-config created
$ kubectl get configmap my-scheduler-config -n kube-system
NAME DATA AGE
my-scheduler-config 1 93s
$ kubectl get pods -A
NAMESPACE NAME READY STATUS RESTARTS AGE
kube-flannel kube-flannel-ds-j4m5q 1/1 Running 0 14m
kube-system coredns-69f9c977-pftw7 1/1 Running 0 14m
kube-system coredns-69f9c977-z2m6q 1/1 Running 0 14m
kube-system etcd-controlplane 1/1 Running 0 14m
kube-system kube-apiserver-controlplane 1/1 Running 0 14m
kube-system kube-controller-manager-controlplane 1/1 Running 0 14m
kube-system kube-proxy-44z4g 1/1 Running 0 14m
kube-system kube-scheduler-controlplane 1/1 Running 0 14m
# current scheduler.
# 사용자 정의 scheduler를 deploy해준다.
# /root/my-scheduler.yaml에 제공된 manifest file을 사용하고,
# default kubernetes scheduler에 의해 사용된 같은 image를 사용한다.
controlplane ~ ➜ cat my-scheduler.yaml
apiVersion: v1
kind: Pod
metadata:
labels:
run: my-scheduler
name: my-scheduler
namespace: kube-system
spec:
serviceAccountName: my-scheduler
containers:
- command:
- /usr/local/bin/kube-scheduler
- --config=/etc/kubernetes/my-scheduler/my-scheduler-config.yaml
image: registry.k8s.io/kube-scheduler:v1.31.0
livenessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
initialDelaySeconds: 15
name: kube-second-scheduler
readinessProbe:
httpGet:
path: /healthz
port: 10259
scheme: HTTPS
resources:
requests:
cpu: '0.1'
securityContext:
privileged: false
volumeMounts:
- name: config-volume
mountPath: /etc/kubernetes/my-scheduler
hostNetwork: false
hostPID: false
volumes:
- name: config-volume
configMap:
name: my-scheduler-config
$ kubectl describe pod kube-scheduler-controlplane -n kube-system | grep Image
Image: registry.k8s.io/kube-scheduler:v1.29.0
Image ID: registry.k8s.io/kube-scheduler@sha256:5df310234e4f9463b15d166778d697830a51c0037ff28a1759daaad2d3cde991
$ kubectl create -f my-scheduler.yaml
pod/my-scheduler created
$ kubectl get pods -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-69f9c977-pftw7 1/1 Running 0 22m
coredns-69f9c977-z2m6q 1/1 Running 0 22m
etcd-controlplane 1/1 Running 0 22m
kube-apiserver-controlplane 1/1 Running 0 22m
kube-controller-manager-controlplane 1/1 Running 0 22m
kube-proxy-44z4g 1/1 Running 0 22m
kube-scheduler-controlplane 1/1 Running 0 22m
my-scheduler 1/1 Running 0 5s
controlplane ~ ➜ cat nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
schedulerName: my-scheduler # 이렇게 사용할 scheduler 지정해주기
containers:
- image: nginx
name: nginx
controlplane ~ ➜ kubectl create -f nginx-pod.yaml
pod/nginx created
controlplane ~ ➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 0/1 ContainerCreating 0 3s
# my-scheduler로 작동 최종 확인
controlplane ~ ➜ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 56s
# 참고문서
2. https://kubernetes.io/blog/2017/03/advanced-scheduling-in-kubernetes/
3. https://jvns.ca/blog/2017/07/27/how-does-the-kubernetes-scheduler-work/
4. https://stackoverflow.com/questions/28857993/how-does-kubernetes-scheduler-work
'Container > Kubernetes' 카테고리의 다른 글
[K8S] SW Version & Cluster Upgrade (0) | 2024.04.26 |
---|---|
[K8S] Logging & Monitoring (1) | 2024.04.26 |
[K8S] ETCD Backup 및 Restore (0) | 2024.04.21 |
CKA 시험준비 (0) | 2024.04.16 |
[K8S] cordon & drain (0) | 2024.04.13 |