티스토리 뷰

Infrastructure/Kubernetes

[CKA] Scheduling

dev_jun 2022. 7. 27. 22:25

Manual Scheduling

how to work?

스케쥴러는 백엔드에서 어떻게 작동할까?

예시로 다음의 간단한 yaml 파일을 보자

apiVersion: v1
kind: Pod
metatdata:
  name: nginx
  labels:
    name: nginx
spec:
  containers:
  - name: nginx
    image: nginx
    ports:
      - containerPort: 8080
  nodeName: # 기본적으로 설정되지 않은 필드
  • 일반적으로는 nodeName 필드를 쿠버네티스가 자동으로 추가한다.
  • 스케쥴러는 모든 pods를 보면서 nodeName 필드가 설정되어있지 않은 pod를 탐색한다. 이 pod들이 스케쥴링 예약을 해야하는 pod들이다.
  • 그런 다음 스케쥴링 알고리즘을 실행하여 POD에 적합한 노드를 식별한다.
  • 식별되면 nodeName을 해당 노드의 이름으로 설정하여 노드에서 POD를 스케쥴에 예약한다.

스케쥴러가 없다면?

  • pod는 계속해서 pending 상태가 된다.

  • 스케쥴러 없이 매뉴얼하게 직접 파드를 노드에 할당할 수 있다.

    • 가장 쉬운 방법은 해당 pod의 매니페스트 파일에서 상기와 같이 nodeName 필드에서 노드를 직접 지정해주는 것이다.
  • 생성할 때에만 노드 네임을 직접 지정할 수 있다.

    • pod가 이미 생성되어있다면?

      • 쿠버네티스는 이미 pod가 생성되었다면 pod의 nodeName property를 수정하는것을 허용하지 않는다.

      • 따라서 다른 방법은 binding 객체를 생성하고 request를 보내서 이미 존재하는 pod에 노드를 assign 하는 것이다.

        apiVersion: v1
        kind: Binding
        metadata:
        name: nginx
        target:
        apiVersion: v1
        kind: Node
        name: # target Node name
      • 이때 yaml file을 이에 상응하는 Json 포맷으로 변경해야한다.

      • 이는 스케쥴러가 하는 일을 매뉴얼하게 따라하는 것과 비슷하다.

스케쥴러 상태 확인

kubectl get pods --namespace kube-system

Labels and Selector

labels와 selector는 함께 그룹화하는 표준 방법이다.

어떻게 사용될까?

우리는 쿠버네티스에서 pods, service, deployments, 등 다양한 다른 타입의 객체(리소스)를 생성할 수 있다. 시간이 지나면서 클러스터에는 아주 많은 다양한 객체가 생성되어 있을 것이다. 효율적으로 원하는 객체를 선택하기 위해서는 여러 카테고리에 따라 그룹화를 한다.

이때 labels and selector를 사용하여 각기 다른 그룹화되어 있는 객체를 필요에 따라서 구분지어 찾을 수 있다.

어떻게 사용할까?

  • 매니페스트 파일에서 key:value 쌍으로 값을 지정해주면 된다.
  • 커맨드로 간단하게 어떤 selector를 찾고자한다면 다음과 같이 할 수 있다.
kubectl get pods --selector app=App1

어떻게 작동할까?

  • labels와 selector는 내부적으로 다른 객체를 함께 연결한다.

주의

  • metadata field의 label과 template 하위 field의 label을 혼동하지 말자.
    • metadata - label: 매니페스트 구성 즉, kind 요소 자체의 label
    • template - label: pod의 label
  • selector 는 pod의 label과 동일하게 연결시켜주자.
    • 이는 servicepod와 연결할때도 사용됨.

Annotation

labels and selector는 그룹화하는데 사용되지만 annotation은 그 외 세부사항을 기록하는데 사용된다.

주로 사용하는 command

  • kubectl get pods —selector key=value
  • kubectl get all —selector key=value
  • kubectl get all —selector key=value,key2=value2,key3=value3

Taints And Tolerations

  • 사람은 nods, 벌레는 pods
  • tains and toleration은 노드에서 스케쥴링 될 수 있는 pod를 제한할 때 사용한다.
  • node와 pod가 어떠한 오염이나 제한이 있지 않은 경우 밸런싱되어 pod는 node에 스케쥴링되어 위치한다.
  • 이때 하나의 node가 taint=blue라는 오염을 주었을 때, pod는 이 오염된 노드에 위치하고 싶지 않다.
  • 이 때 하나의 pod에 blue라는 tolerance를 주게 되면 이 pod는 taint=bule node와의 접근을 할 수 있게 된다.
  • 이것이 pod가 스케쥴링 되는 방법이다.

how to use

kubectl taint nodes node-name key=value:taint-effect
  • taint-effect 종류: NoSchedule, PreferNoSchedule, NoExecute

      kubectl taint nodes node1 app=blue:NoSchedule
    • NoSchedule: taint가 허용되지 않는 pod는 Scheduling 하지 않는다. 이미 실행중인 POD는 관여하지 않는다.
    • PreferNoSchedule: taint가 허용되지 않는 pod는 scheduling 하지 않으려고 한다. 하지만 cluster 리소스가 부족한 상황 등에 대해서는 toleration을 만족하지 않아도 node에 scheduling 된다.
    • NoExecute: taint가 허용되지 않는 pod는 Scheduling 하지 않는다. 이미 실행중인 POD도 퇴출시킨다.
  • in yaml file - 위의 예시를 yaml file에 적용시켜보자

spec:
  containers:
  - name: nginx-container
    image: nginx
  tolerations:
  - key: "app"
    operator: "Equal"
    value: "blue"
    effect: "NoSchedule"
  • 모든 tolerations와 관련된 value는 큰따옴표로 묶어주어야 함에 주의하자.
  • pod가 새로운 toleration으로 생성되거나 업데이트되면 노드에서 스케쥴되지 않는다.

taint 확인하기

kubectl describe node [nodename] | grep Taint

Node Selector

node selector는 node selector에 설정된 label을 가지고 있는 node 중에 하나를 선택하여 스케쥴링 할 수 있도록 하는 기능.

  • pod의 yaml file에서 node selector를 사용하여 key=value로 값을 저장할 수 있다. 그런데 pod은 키값 쌍을 가진 노드를 어떻게 구분할까?
  • 노드에도 해당 키값에 해당하는 label을 지정해주어야 한다. 방법은 다음과 같다.
kubectl label nodes <node-name> <label-key>=<label-value>

하지만 node selector는 다음과 같은 한계를 가지고 있다.

label = small, medium, large 값을 가진 노드가 있다고 가정하자.

  • medium, large 값을 가진 노드만 선택하고 싶으면 어떡할까?
  • 같은 의미로, small이 아닌 노드만 선택하고 싶으면 어떡할까?

이러한 한계를 보완하기 위해 나온 것이 node affinity 기능이다.

Node Affinity

node affinity의 주된 기능은 특정 node에 pod를 확실하게 호스팅하기 위한 기능이다.

사용 방법은 다음과 같다.

# kind: Pod
spec:
  containers:
  - name:
    image:
  affinity:
    nodeAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
        nodeSelectorTerms:
        - matchExpressions:
          - key: size
            operator: In
            values:
            - Large
            - Medium

requiredDuringSchedulingIgnoredDuringExecution 이 용어가 되게 생소하게 보일 수 있다. 이는 공식문서에서 찾을 수 있었다.

  • requiredDuringSchedulingIgnoredDuringExecution: 규칙이 만족되지 않으면 스케줄러가 파드를 스케줄링할 수 없다. 이 기능은 nodeSelector
    와 유사하지만, 좀 더 표현적인 문법을 제공한다.
  • preferredDuringSchedulingIgnoredDuringExecution: 스케줄러는 조건을 만족하는 노드를 찾으려고 노력한다. 해당되는 노드가 없더라도, 스케줄러는 여전히 파드를 스케줄링한다.
  • 참고) IgnoredDuringExecution: 쿠버네티스가 파드를 스케쥴링 한 뒤에 노드 레이블이 변경되어도 파드는 계속 해당 노드에서 실행됨을 의미.

taint and toleration and node affinity

  • taint and toleration으로 물리적으로 완전히 노드를 분리 할 수는 없다. 예를 들어 blue, red, green으로 taint한 노드가 세개 있고, taint가 없는 노드가 두개 있고 pod 또한 각각의 blue, red, green의 toleration을 추가한 pod도 있다고 가정하자.

    이때 blue toleration pod는 blue taint node에만 스케줄링 된다고 보장할 수 있는가? 그렇지 않다. taint가 존재하지 않는 노드에도 스케줄링 될 수 있다.

  • 두번째 상황으로, blue, red, green의 node affinity를 추가한 노드가 있으며 각각의 pod에도 node affinity를 사용하여 node가 스케줄링되도록 적용한 상황이다. 이 상황에서의 문제는 어떠한 node affinity도 추가하지 않은 pod가 blue or red or green label의 node에 스케줄링 될 수 있다는 문제가 있다.

  • 따라서 taint and toleration과 node affinity를 조합해서 사용해야 완전한 물리적 노드 분리가 가능해진다.

Resource and Limits

Resource

  • 각 노드마다 할당된 자원이 있다. CPU, Memory, disk, etc…

    그리고 쿠버네티스 스케줄러에 의해서 각 노드의 자원 상황에 맞게 pod가 할당된다. 그런데 어떠한 노드도 추가적인 pod를 감당할 자원이 부족한 상황이 발생하면? 쿠버네티스는 해당 pod를 스케줄링하는 것을 보류한다. 그리고 해당 pod는 pending status가 된다.

    쿠버네티스는 디폴트로 pod에 0.5CPU, 256 Mi memory를 할당한다. 이것이 node에 pod를 할당할 때 컨테이너에 의해서 요청된 가장 최소의 cpu 또는 memory의 양이다. 이 숫자로 pod를 할당할 충분한 자원의 여유가 있는지를 판단한다. 그리고 이 숫자는 yaml file에서 튜닝이 가능하다.

resources:
  requests:
    memory: "1Gi"
    cpu: 1

Limit

  • 한정된 자원을 설정할 수 있다.
limits:  # requests와 같은 들여쓰기 수준
  memory: "2Gi"
  cpu: 2

초과하려고 하면?

만약 제한된 자원을 실행중에 초과하려고 하면 어떻게 할까?

  • CPU의 경우 쿠버네티스는 CPU가 지정된 제한을 초과하지 않도록 조절한다.
    • 컨테이너는 제한된 CPU보다 많은 자원을 사용할 수 없기 때문에
  • memory의 경우는 다르다. 지정된 제한을 초과할 수 있다.
    • 컨테이너가 지정된 메모리보다 더 많은 메모리 자원을 사용할 수 있기 때문에
  • 하지만 pod가 지속적으로 제한된 자원보다 많은 메모리를 사용하려고 하면 pod는 종료된다.

참고) 디폴트로 정해진 자원을 선택하기 위해서는 해당 네임스페이스에서 LimitRange 라는 리소스를 사전에 정의해놓아야 한다.

공식문서

apiVersion: v1
kind: LimitRange
metadata:
  name: mem-limit-range
spec:
  limits:
  - default:
      memory: 512Mi
    defaultRequest:
      memory: 256Mi
    type: Container

---
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-limit-range
spec:
  limits:
  - default:
      cpu: 1
    defaultRequest:
      cpu: 0.5
    type: Container

Daemonset

  • daemonset은 여러 pod를 배포하는데 도움을 주기 때문에 replica set와 비슷하다.
  • 하지만 daemonset은 각 pods가 배포되어 있는 node 하나당 하나만 복사한다.
  • 즉, daemonset은 클러스터의 모든 node에 항상 하나의 pod 복사본이 존재하도록 한다.
  • daemonset은 solution, log monitoring에 아주 적합하다.
  • replicaset과 kind를 제외하고는 아주 똑같은 양식으로 생성할 수 있다.
  • pod template의 label을 통해 선택할 수 있다.
  • node가 새로 생성되거나 삭제될 때 daemonset의 pod 역시 생성 또는 삭제된다.
  • taint and toleration 과 node affinity가 daemonset에도 적용된다.

Static Pods

master node의 kube api-server와 worker node의 kubelet이 통신을 한다는 것을 알고 있다. 그렇다면 master node의 모든 리소스가 없는 상태라면 worker node는 스스로 작동을 할 수 없을까? kubelet만 있다면 할 수 있다. 이것이 static pods다.

  • 하지만 manifest file과 통신할 api server도 없는데 kubelet 혼자서 어떻게 생성할까?
    • 서버의 디렉토리(/etc/kubernetes/manifests)에서 pod 정의 파일을 읽도록 kubet을 구성할 수 있다.
  • kubelet은 주기적으로 이 디렉토리에 있는 파일을 읽으며 호스트에 pod를 생성한다.
  • 생성 뿐만 아니라 활성 상태로 만든다. pod 충돌이 발생하면 kubelet은 충돌한 pod을 다시 시작할 수도 있다.
  • 이 디렉토리의 파일에 변경사항이 발생하면 kubelet은 이 변경사항을 적용하여 pod를 재생성한다.
  • 이 디렉토리의 파일이 삭제되면 pod도 자동으로 삭제된다.
  • 오직 pod만 생성이 가능하다는 것에 주의하자.

어디서 쓰는데?

  • Master Node에서 Control plane 역할을 하는 pod를 static pod를 이용해 생성할 수 있다.

'Infrastructure > Kubernetes' 카테고리의 다른 글

[CKA] Security  (0) 2022.08.03
[CKA] Cluster Maintenance  (0) 2022.07.30
[CKA] Application Lifecycle Management  (0) 2022.07.28
[CKA] Logging & Monitoring  (0) 2022.07.28
[CKA] Kubernetes Core Concepts  (0) 2022.07.27
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/03   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
글 보관함