Udemy CKA course 3. Scheduling (스케줄링): Labels and Selectors, Taints and Tolerations, Node Affinity, Resource requests and limits, DaemonSets, Static Pods, Multiple Schedulers

jihyelee·2024년 1월 3일
0

kubernetes

목록 보기
4/15

Certified Kubernetes Administrator (CKA) with Practice Tests (강의 링크, 레퍼런스 노트)

  • 평소 강의 할인도 많이 하고, 연습문제도 풀어볼 수 있으니 실제 강의 수강을 추천
  • 아래는 강의 내용 번역 및 정리본 (문제 시 댓글로 알려주세요)

Manual Scheduling

스케줄링 작동 방법

  • pod를 생성할 때에 nodeName 필요
    • 사용자가 yaml 파일에 해당 필드 작성하지 않아도 자동으로 생성됨
  • nodeName의 값이 없는 pod들이 스케줄링의 대상(후보)
  • 스케줄링 알고리즘을 통해 어떤 노드에 스케줄링할지 결정
  • pod와 node를 연결
    • nodeName에 값이 결정됨

스케줄러가 없다면

    1. 직접 nodeName에 노드의 이름을 값으로 지정 (pod yaml 파일)
    • pod 생성 시에만 nodeName에 값을 작성할 수 있음
    • 생성된 pod 삭제 후 nodeName에 값을 지정한 파일로 재생성하는 방법도 있음
      • kubectl replace --force -f [파일명].yaml
    1. Binding 객체 생성
    • pod 생성 이후 node에 할당하고 싶을 때 사용
    • e.g. curl --header "Content-Type:application/json" --request POST --data '{"apiVersion": "v1", "kind": "Biding", ...} http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/
  • 스케줄러 있는지 여부 확인
    • kubectl get pods -n kube-system

Pod-bind-definition.yaml 예시

  • apiVersion: v1
  • kind: Binding
  • metadata:
    • name: nginx
  • target:
    • apiVersion: v1
    • kind: Node
    • name: node02 [실제 노드명]

Labels and Selectors

  • 그룹화 및 필터링(분류)을 도와주는 방법
    • 타입 (e.g. pod, replicaset), 어플리케이션, 기능 (e.g. front-end) 등을 기준으로 분류 가능

Labels

  • yaml 파일의 metadata 하위에 위치
  • key, value 형태로 자유롭게 레이블 추가 가능
  • 레이블 내 키를 기준으로 조회하는 명령어
    • kubectl get pods --selector app=App1

Selectors

  • yaml 파일의 spec 하위에 위치
    • selector: matchLabels와 같은 형식
  • ReplicaSet에서 template 하위의 내용은 포함하는 pod의 정보
    • metadata 하위의 labels가 ReplicaSet의 레이블임에 주의
    • 참고로, template의 경우 매칭하려는 pod의 정보를 상세히 기입할 필요가 있을 때 사용

Annotations

  • yaml 파일의 metadata 하위에 작성
  • 버전, 빌드 정보, 연락처 등의 추가 정보를 작성하는 용도

명령어

  • 필터링한 pod 결과 조회 (개수)
    • kubectl get pods --selector env=dev --no-headers | wc -l
    • wordcount 옵션은 헤더까지 포함하기 때문에 --no-headers 사용
    • -l은 line(행) 개수를 세기 위한 옵션
  • 필터링한 모든 객체 결과 조회
    • kubectl get all --selector env=prod --no-headers
  • 여러 개의 조회조건 사용
    • kubectl get all --selector env=prod,bu=finance,tier=frontend
    • 쉼표로 연결

Taints and Tolerations

  • 어떤 pod가 노드에 스케줄링될 수 있는지를 제한
    • e.g. 특정 노드에는 특정 응용 프로그램과 관련된 pod만 배포되도록
  • node에 taint 옵션을 지정, pod에 tolerance 옵션을 지정
    • tolerant한 pod만 해당 taint를 가진 node에 위치됨
  • pod에게 특정 node에 배정되는 것을 요구하는 것이 아니라, node로 하여금 특정 toleration을 가진 pod만 받아들이도록 지정하는 것임
    • node affinity 개념 참고
  • 마스터 노드의 경우 사용자가 만든 pod가 배포되지 않는 것이 유리
    • kubectl describe node kubemaster | grep Taint
      • taint-effect가 NoSchedule로 지정됨

Taints

  • 노드에 지정
  • taint 지정 명령어
    • kubectl taint nodes [노드명] [key=value:taint-effect]
    • e.g. kubectl taint nodes node1 app=blue:NoSchedule
  • untaint 명령어
    • kubectl taint nodes [노드명] [key=value:taint-effect]-
    • 맨 마지막에 - 추가
  • taint-effect
    • NoSchedule
      • pod가 node에 스케줄되지 않음
    • PreferNoSchedule
      • pod가 node에 스케줄되지 않을 것이나, 보장되지는 않음
    • NoExecute
      • 새로운 pod는 node에 스케줄되지 않음
      • 만약 이미 배정된 pod 중 intolerant pod가 있다면 해당 pod는 퇴출됨(evict)

Tolerations

  • pod에 지정
  • yaml file에 spec 하위에 작성됨
    • 위의 예시와 매칭되는 tolerations 작성법
    • 값은 모두 "" 안에 작성되어야 하며, Equal은 = 연산자를 의미
    • tolerations:
      • -key: "app"
      • operator: "Equal"
      • value: "blue"
      • effect: "NoSchedule"

Node Selectors

  • 특정 pod가 특정 node에 위치하도록 지정하는 간편한 방법
  • pod yaml 파일의 spec 하위에 nodeSelector 지정
    • nodeSelector:
      • size: Large
  • pod 생성 이전에 node에 관련 key, value 지정해줘야 함
    • kubectl label nodes [노드명] [label-key=label-value]
    • e.g. kubectl label nodes node-1 size=Large
  • 한계
    • 복잡한 요구사항을 수행하기에는 적절하지 않음
      • e.g. Large OR Medium / Not Small

Node Affinity

  • 특정 pod가 특정 node에 위치하도록 지정하는 방법
    • node selector의 한계를 극복하였으나 다소 복잡
  • pod yaml 파일의 spec 하위에 위치
    • 만약 deployment와 같은 객체의 yaml 파일을 수정해야 한다면, template 하위의 spec에 작성해줘야 함 (pod 정보이므로)
    • affinity:
      • nodeAffinity:
        • requiredDuringSchedulingIgnoredDuringExecution:
          • nodeSelectorTerms:
            • -matchExpressions:
              • -key: size
              • operator: In
              • values: list 형태로 작성
                • -Large
                • -Medium
    • operator의 경우 NotIn, Exists 등 존재
      • Exists의 경우 key의 존재여부만 필요로 하기 때문에 values 필요없음

Node Affinity Types

  • requiredDuringSchedulingIgnoredDuringExecution
    • during scheduling은 pod가 존재하지 않고 처음으로 생성되는 시기를 의미
    • 매칭되는 레이블을 가진 노드가 존재해야 pod가 스케줄링됨
    • 노드의 레이블이 변경되어도 스케줄링된 pod는 유지됨 (변경사항 무시)
  • preferredDuringSchedulingIgnoredDuringExecution
    • 매칭되는 레이블을 가진 노드가 존재하지 않아도 pod가 스케줄링됨 (있으면 해당 노드에 스케줄링)
  • requiredDuringSchedulingRequiredDuringExecution
    • 추가 예정
    • 노드의 레이블이 변경된다면 스케줄링된 pod 중 조건에 맞지 않는 pod는 해당 노드에서 퇴출됨(evict)

Node Affinity vs. Taints and Tolerations

  • 목표: 특정 pod와 특정 node를 매칭시키기
    • 5개의 node, pod가 존재
    • 그 중 각각 세 개에 대해서 green, red, blue로 지정되었다고 가정
  • taints and tolerations
    • 만약 taint되지 않은 node들이 존재한다면, toleration 옵션이 추가된 pod가 taint되지 않은 node에 위치할 수 있음
    • e.g. red pod가 untainted node에 위치
  • node affinity
    • affinity 옵션이 적용되지 않은 pod가 추가적으로 특정 node에 위치될 수 있음
    • e.g. 아무런 옵션이 없는 pod가 blue node에 위치
  • 두 개를 함께 사용해서 특정 node에 특정 pod를 지정할 수 있음

Resource Requirements and Limits

  • kube-scheduler는 노드의 자원(e.g. CPU, 메모리)을 고려하여 pod를 배치
  • 자원 요청 및 자원 제한은 pod 내 container마다 지정 가능

자원 요청 (resource request)

  • 컨테이너는 각각의 자원 요청을 가질 수 있음
  • pod yaml 파일의 spec: containers 하위에 다음과 같이 작성
    • resources:
      • requests:
        • memory: "4Gi"
        • cpu: 2
  • CPU
    • 1m (100m = 0.1) 부터 사용 가능
    • 1 CPU = 1 AWS vCPU = 1 GCP Core = 1 Azure Core = 1 Hyperthread
  • 메모리
    • 1G (Gigabyte) = 1,000,000,000 bytes
    • 1M (Megabyte) = 1,000,000 bytes
    • 1K (Kilobyte) = 1,000 bytes
    • 1Gi (Gibibyte) = 1,073,741,824 bytes
    • 1 Mi (Mebibyte) = 1,048,576 bytes
    • 1 Ki (Kibibyte) = 1,024 bytes

자원 제한 (resource limit)

  • pod가 node의 자원을 모두 사용하지 않도록 제한을 가할 수 있음
  • pod yaml 파일의 spec: containers 하위에 다음과 같이 작성
    • resources:
      • limits:
        • memory: "2Gi"
        • cpu: 2
  • 메모리의 경우 제한보다 더 많은 메모리를 사용할 수 있음
    • 지속적으로 메모리를 초과할 경우 OOM (Out Of Memory) 에러 발생

기본 동작방식

  • 요청과 제한 모두 없는 경우
    • 하나의 pod가 모든 자원을 다 사용해 다른 pod가 자원을 사용하지 못할 수 있음
  • 요청은 없지만 제한은 있는 경우
    • requests = limits
    • 각각의 pod가 제한만큼의 자원을 사용할 수 있음
  • 요청과 제한이 모두 있는 경우
    • 하나의 pod가 예상했던 것보다 많은 자원을 사용하지 않을 때, 해당 자원을 다른 pod가 사용 가능하도록 하는 것이 유리하나 이것이 불가능
  • 요청만 있고 제한이 없는 경우
    • 이용 가능한 자원이 있을 때 다른 pod가 해당 자원을 사용할 수 있음
    • 동시에, 각각 필요한 자원은 보장받을 수 있음
    • 가장 이상적인 시나리오
    • 메모리의 경우, 쓰로틀링이 불가능하기 때문에 요구되는 자원을 다시금 사용하고 싶다면 해당 메모리를 더 사용하고 있던 pod를 멈춘 후 해당 메모리 회수해야 함

Limit Range (제한범위)

  • 컨테이너들로 하여금 기본 자원값들을 가질 수 있게 함
  • LimitRange가 생성된 다음 생성되는 pod/container에 대해서만 적용됨
  • yaml file 예시
    • 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

Resource Quota (자원 할당)

  • namespace 별로 생성할 수 있는 자원 할당범위
  • yaml file 예시
    • apiVersion: v1
    • kind: ResourceQuota
    • metadata:
      • name: my-resource-quota
    • spec:
      • hard:
        • requests.cpu: 4
        • requests.memory: 4Gi
        • limits.cpu: 10
        • limits.memory: 10Gi

DaemonSets

  • ReplicaSet과 유사하게 pod의 여러 개의 인스턴스를 배포하도록 도움
  • ReplicaSet과 다른 점은, 노드마다 하나의 pod가 생성된다는 점임
    • 클러스터의 모든 노드에 pod의 복사본 하나가 존재하는 것을 보장
  • 모니터링, 로깅, 네트워킹 등에 유리
    • e.g. kube-proxy
  • 기본 스케줄러와 node affinity를 활용

YAML

  • apiVersion: apps/v1
  • kind: DaemonSet
  • metadata:
    • name: [이름]
  • spec:
    • selector: DeamonSet이 연결하고자 하는 pod 정보를 담음
      • matchLabels:
        • [key]: [value]
    • template: pod에 대한 구체적인 정보를 담음
      • metadata:
        • labels:
          • [key]: [value]
      • spec:
        • containers:
          • -name: [컨테이너명]
          • image: [이미지명]

명령어

  • kubectl create -f [파일명].yaml
    • 쉽게 yaml 파일 만드는 법: deployment 활용하기
      • kubectl create deployment [이름] --image=[이미지명] --dry-run=client -o yaml > [파일명].yaml
      • 파일에디터로 replicas, strategy, status 필드 삭제
      • 파일에디터로 Deployment를 DaemonSet으로 변경
  • kubectl get daemonsets(ds)
  • kubectl describe daemonsets [이름]

Static Pods

  • master node도 없고 클러스터 구성이 없을 때는 kube-apiserver가 없기 때문에 worker node의 kubelet이 직접 pod yaml 파일을 읽도록 해야 함
    • 일반적으로 /etc/kubetnetes/manifests에 pod yaml 파일 위치
    • kubelet.service의 --pod-manifest-path= 에 경로 지정
    • kubelet.service의 --config=kubeconfig.yaml 파일에서 staticPodPath: 로 지정도 가능
    • 경로 확인은 /var/lib/kubelet/config.yaml에서 확인할 수 있음
    • replicasets, deployment 등의 객체는 이런 방식으로 만들 수 없음
  • kubelet에 의해 만들어진 pod = Static Pods

명령어

  • docker ps
    • kube-apiserver가 없기 때문에 kubectl 명령어 사용 불가
  • kubectl get pods
    • master node가 있어서 kube-apiserver가 있는 경우 해당 명령어 사용 가능
    • 하지만 kubelet에 의해 생성된 pod의 경우 오직 yaml 파일을 수정하거나 삭제하는 방식만 가능
      • kubectl edit, delete 명령어 사용 불가
    • pod 이름 뒤에 -controlplane이 붙어있거나, pod 파일 안에 ownerReferences의 kind: Node, name: controlplane인 경우 static pod라고 볼 수 있음
  • Static Pod 생성
    • kubectl run [이름] --image=[이미지명] --dry-run=client -o yaml --command -- [명령어: e.g. sleep 1000] > [파일명].yaml
      • command 옵션은 맨 마지막에 위치해야 함
    • cp [파일명].yaml [staticPodPath 경로] 로 이동하면 static pod가 생성됨
    • 수정 시에는 해당 파일로 들어가서 직접 수정하면 됨 (별도 명령어 필요 없음)
  • 다른 노드에 생성된 Static Pod 삭제
    • kubectl get nodes -o wide
      • internal-IP 확인
    • ssh [internal-IP]
    • cat /var/lib/kubelet/config.yaml
      • static pod의 경로 확인
    • rm [pod 파일명].yaml && exit
      • controlplane으로 돌아가 pod 상태 확인
      • kubectl get pods -A --watch

Static Pods 사용할 때

  • 여러 개의 controlplane (master node) 있을 때
    • 바이너리 파일을 다운로드 받을 필요도 없고, 서비스가 충돌할 염려도 없음
    • e.g. apiserver.yaml, etcd.yaml, controller-manager.yaml

Static Pods vs. DaemonSets

  • Static Pods
    • kubelet에 의해 생성
    • Control Plane 구성요소들을 static pod로 배포
  • DaemonSets
    • kube-apiserver에 의해 생성 (DaemonSet Controller)
    • 모니터링, 로깅 에이전트들을 노드에 배포
  • 둘 다 kube-scheduler에 의해 무시됨

Multiple Schedulers

  • 여러 개의 스케줄러를 동시에 사용 가능
  • scheduler configuration yaml file
    • apiVersion: kubescheduler.config.k8s.io/v1
    • kind: KubeSchedulerConfiguration
    • profiles:
      • -schedulerName: my-scheduler

스케줄러 배포 및 사용

  • 추가적인 스케줄러 배포하는 방법
    • wget https://../kube-scheduler로 바이너리 파일 다운로드
    • my-scheduler.service에서 ExecStart=/usr/local/bin/kube-scheduler --config=/etc/kubernetes/config/[yaml 파일명].yaml
  • 추가적인 스케줄러를 Pod로 배포하는 방법
    • pod yaml 파일에 spec: containers: 하위에 다음과 같이 작성 가능
      • -command:
        • kube-scheduler
        • --address=[주소]
        • --kubeconfig=/etc/kubernetes/scheduler.conf
        • --config=[yaml 파일위치]
    • scheduler configuration yaml 파일에 다음과 같은 내용 추가
      • 동일한 스케줄러의 복사본이 여러 개의 master node에서 필요할 경우, 한 번에 하나만 활성화될 수 있음
      • leaderElection:
        • leaderElect: true
        • resourceNamespace: kube-system
        • resourceName: lock-object-my-scheduler
  • pod에서 다른 스케줄러를 사용하는 방법
    • yaml 파일의 spec: 하위에 다음과 같이 작성
      • schedulerName: [스케줄러명]

스케줄러 사용여부 확인

  • kubectl get events -o wide
  • kubectl logs [스케줄러명] --name-space=[namespace명]

스케줄러 프로파일 설정

    1. 스케줄링을 기다리는 pod들은 Scheduling Queue에 위치
    • 이 단계에서 정의된 우선순위에 따라 스케줄링됨
  • PriorityClass (yaml file)
    • apiVersion: scheduling.k8s.io/v1
    • kind: PriorityClass
    • metadata:
      • name: high-priority
    • value: 1000000
    • globalDefault: false
    • description: "[설명]"
  • Pod (yaml file)
    • spec:
      • priorityClassName: high-priority
    1. 사용할 수 있는 노드들을 필터링 (Filtering)
    1. 점수 매기기 (Scoring)
    • 남는 공간을 기반으로 어떤 노드가 더 유리한지 점수를 매김
    1. 연결 (Binding)
    • pod와 node가 연결

스케줄링 플러그인

  • 각 단계마다 사용하는 플러그인이 다름
    • 스케줄링 큐: PrioritySort
    • 필터링: NodeResourceFit, NodeName, NodeUnschedulable
    • 점수 매기기: NodeResourceFit, ImageLocality
    • 연결: DefaultBinder
  • Extension Points
    • 플러그인이 붙을 수 있는 곳
    • 이를 통해 플러그인을 새로 정의하고 사용할 수도 있음
    • e.g. queueSort, preFilter, filter, postFilter, preScore, score, reserve, permit, preBind, bind, postBind, ...

스케줄러 프로파일

  • 1.18 버전 이후로 하나의 yaml 파일에 여러 개의 프로파일을 관리할 수 있게 됨
  • apiVersion: kubescheduler.config.k8s.io/v1
  • kind: KubeSchedulerConfiguration
  • profiles:
    • -schedulerName: [스케줄러명]
    • plugins:
      • score: [Extension Points] (e.g. preScore, ..)
        • disabled:
          • -name: TaintToleration (e.g. '*'는 전체를 의미)
        • enabled:
          • -name: MyCustomPluginA
          • -name: MyCustomPluginB
    • -schedulerName: ...

참고사항

POD 수정하기 (edit)

  • 존재하고 있는 pod의 수정할 수 있는 spec은 아래와 같음
    • containers.image
    • initContainers.image
    • activeDeadlineSeconds
    • tolerations
  • 서비스 계정, 자원 제한, 환경 변수 등은 수정 불가
    • 해당 부분들을 수정하고 싶다면 두 가지 방법이 있음
      1. 임시 파일 이용
      • kubectl edit pod [pod명] : 임시 파일이 저장됨
      • kubectl delete pod [pod명] : 기존 pod 삭제
      • kubectl create -f [임시파일명].yaml : 임시 파일로 새로운 pod 생성
      • 혹은 delete + create 말고 replace 사용할 수 있음
        • kubectl replace --force -f [임시파일명].yaml
      1. yaml 파일 이용
      • kubectl get pod [pod명] -o yaml > [파일명].yaml : 새로운 파일로 저장
      • vi [파일명].yaml
      • kubectl delete pod [pod명]
      • kubectl create -f [파일명].yaml

Deployment 수정하기 (edit)

  • Deployment에서 Pod 템플릿의 필드 및 속성값을 쉽게 수정할 수 있음
  • Deployment에서 템플릿 수정 시 pod가 자동으로 삭제되고 변화를 반영한 새로운 pod가 생성됨
  • kubectl edit deployment [deployment명]
profile
Graduate student at Seoul National University, majoring in Artificial Intelligence (NLP). Currently AI Researcher at LG CNS AI Lab

0개의 댓글