새소식

Recent Study/udemy - CKA with Practice Tests

Section 4 : Scheduling & Logging, Monitoring

  • -

1. Manual Scheduling

: 만약 클러스터에 스케줄러가 없을 때는 어떻게 할까요? 이때는 직접 Pod를 스케줄링 할 수 있습니다. 먼저 기본 스케줄링부터 알아보죠. Pod의 yaml 파일에는 nodeName 이라는 설정이 가능합니다. 스케줄러는 모든 Pod를 보고 이 속성이 없는 것을 찾습니다. 스케줄링 알고리즘을 실행해 Pod의 올바른 노드를 식별해서 지정합니다. 

 

스케줄러가 없을땐 직접 설정해주면 됩니다. Pod의 yaml에 nodeName 속성에다가 노드의 이름을 작성해주면 되는 것이지요. 노드 이름은 생성할 때만 지정할 수 있습니다. 이미 노드에 속해있는 Pod는 노드를 변경할 수 없으며, 이를 가능하게 하는 방법은 바인딩 개체를 생성하고, Pod의 바인딩 API에 요청하는 것 입니다. 

 

 

2. Labels and Selectors

: 쿠버네티스의 Label은 쿠버네티스의 리소스를 논리적인 그룹으로 나누기 위해 붙이는 레이블링이다. selector는 Label을 이용하여 조회하려는 리소스만 조회할 수 있게 하는 기능이다.

 

 

3. Taints and Tolerations

D pod는 Toleration을 설정하여, 노드 1에 Tatint를 설정했지만 놓일 수 있는 것입니다.

 

: 이해하기 쉽게 하기 위해 예를 들어보면, 사람을 노드 벌레를 Pod라고 가정하겠습니다. Taints와 Toleration은 한 노드에 어떤 Pod로 스케줄링할 수 있는지 제한을 설정하기 위해 사용됩니다. Taints는 노드에 설정, Toleration은 Pod에 설정합니다. 

 

taint-effect의 3가지 옵션이 아래와 같이 있습니다.

 

1) NoSchedule : toleration이 없으면 pod가 스케줄되지 않음, 기존 실행되던 pod에는 적용 안됨

2) PreferNoSchedule : toleration이 없으면 pod을 스케줄링 안하려고 하지만 필수는 아님, 클러스터내에 자원이 부족하거나 하면 taint가 걸려있는 노드에서도 pod가 스케줄링될 수 있음

3) NoExecute : toleration이 없으면 pod가 스케줄되지 않으며 기존에 실행되던 pod도 toleration이 없으면 종료시킴.

 

 추가로 스케줄러는 마스터 노드의 어떤 Pod도 스케줄링 하지 않습니다. k8s 클러스터가 처음 설정되면 자동으로 마스터 노드에 Taint 설정이 자동으로 되기 때문입니다.

 

 

4. Node Selectors & Node Affinity

: NodeSelector는 파드를 정의하기 전에 노드에 미리 nodeSelector 속성을 키, 밸류 값으로 작성해서 정의해주면 특정 오브젝트가 실행될 때 해당 노드에서 선택을 간단하게 할 수 있다. 

 

: Node Affinity는 특정 노드에 Pod가 host 되는것을 보장합니다. 이는 특정 노드에 Pod 배치를 제한하는 기능을 제공합니다. .yml 작성하는 것은 k8s docs를 참고하면 좋을 것 같고, 중요한 것은 operator 여러 종류의 연산자와 value의 다중 허용입니다.

 

Node Affinity Types

: Pod에는 2가지 Lifecycle 상태가 존재합니다. DuringScheduling과 DuringExecution입니다.

DuringSchedulingPod가 존재하지 않다가 처음으로 생성되는 상태입니다. 만약 일치하는 Label이 없다면? 2가지 경우가 있습니다.

1) Required : Pod의 배치가 중요할 때 사용되며, 일치하는 노드가 없다면 Pod는 배치되지 않습니다.

2) Preferred : 일치하는 노드가 없다면, Node Affinity 규칙을 무시하고, 사용 가능한 노드에 Pod를 배치합니다.

 

DuringExecution Pod가 실행 중이고, 노드 레이블 변경과 같이 Node Affinity도에 영향을 미치는 환경 변경이 발생한 상태입니다.

1) Ignored : 파드는 계속 실행되며 Node Affinity의 변경 사항은 일단 예약되면 파드에 영향을 미치지 않습니다.

 

Planned Node Affinity Type은 DuringExecution 부분에서 차이가 있습니다. `RequiredDuringExecution`이라는 새 옵션이 나타났으며, 이 옵션은 Node Affinity을 충족하지 않는 노드에서 실행 중인 파드를 제거합니다.  즉, Large 노드에서 실행 중인 파드는 Large 레이블이 노드에서 제거되면 제거되거나 종료됩니다.

 

 

5. Resource Requirements

: 컨테이너 자체적으로는 노드에서 얼마나 많은 리소스를 사용할지 결정할 수 없다. 그래서 자신이 써도 되는 수준의 리소스보다 더욱 많이 사용하게 될 수 있고, 이는 결국 다른 컨테이너나 노드에 영향을 주게 된다. 따라서 파드에서 컨테이너에 대한 자원을 설정해서 제한하는 방법을 사용해야 한다.

 

클러스터가 제한된 CPU 값을 초과하려 하면, 쿠버네티스가 이를 throttle하여 막는다. 즉, 제한값을 초과하지 못하는 것이다. 반면에 메모리 사용의 경우는 컨테이너의 자원 사용이 제한된 값을 넘을 수는 있는데, 이때는 파드가 terminate 되고 만다.

 

기본동작 방식은 4가지가 있다.

1) 요청과 제한이 없는 경우 : 하나의 pod가 모든 자원을 다 사용해 다른 pod가 자원을 사용하지 못할 수 있음

2) 요청은 없고, 제한만 있는 경우 : 각각의 pod가 제한만큼의 자원을 사용할 수 있음

3) 요청과 제한이 모두 있는 경우 :하나의 pod가 예상했던 것보다 많은 자원을 사용하지 않을 때, 해당 자원을 다른 pod가 사용 가능하도록 하는 것이 유리하나 이것이 불가능

4) 요청만 있고 제한이 없는 경우 : 이용 가능한 자원이 있을 때 다른 pod가 해당 자원을 사용할 수 있음. 동시에, 각각 필요한 자원은 보장받을 수 있음, 가장 이상적인 시나리오

 

Limit Range : 컨테이너들로 하여금 기본 자원값들을 가질 수 있게함. Limit Range 생성 후 다음 생성되는 pod/container에 대해서만 적용됨.

 

Resource Quota : Namespace 별로 생성할 수 있는 자원 할당 범위.

 

 

6. Daemon Sets

: Pod의 복사본을 클러스터 내 모든 노드에 항상 존재하게 합니다. kube-proxy, Networking 사용 예시 입니다. 노드가 삭제되면 해당 Pod도 함께 삭제됩니다. DaemonSets 위치 찾을 때 namespace도 함께 써줘야한다.

 

 

7. Static Pods

: Kubelet은 노드를 독립적으로 관리할 수 있습니다. Kubelet은 pod의 yaml파일을 저장하는 디렉터리가 있는데, 이는 외적인 API 서버나 k8s 클러스터의 변경에 영향을 받지 않고, 내부에서의 변경에만 바뀌고, 유일하게 이렇게 생성되어야만 Static Pods라고 할 수 있습니다.

 

위는 Kubelet이 Pod를 생성하는 방법은 2가지가 있습니다. pod.yaml을 자체적으로 생성하는 첫번째 방법이고, 두번째는 kube-apiserver로 부터 HTTP API 엔트포인트를 kubelet에 입력으로 이용한 것 입니다.

 

Static Pods vs DaemonSets

 

 kubelet은 각 node에 특정 path(/etc/kubernetes/manifests)에서 control plane이 아닌 노드 자체적으로 생성하고 관리할 수 있는 Pod yaml을 가지게 할 수 있다.

 

사용시기

1) control plane에 독립적이기 때문에 control plane 컴포넌트 자체를 띄우고 싶을 때 쓸 수 있음 (HA를 위해 마스터를 여러개 만들고 싶은 경우 등)

 

2) 각 마스터 노드에 kubelet을 설치하고, manifest 경로에 control plane component 매니페스트 파일을 넣으면 됨

 

 

8. Multiple Schedulers

: 여러개의 스케줄러가 있을 때 이름이 달라야 합니다. 그래야 구분할 수 있기 때문입니다. 기본 스케줄러 이름은 default-scheduler입니다. 각 스케줄러는 개인의 config.yaml을 사용합니다.  

 

  • scheduler가 어떤 pod를 pickup 했는지 아는 법 by event > kubectl get events -o wide
  • scheduler가 어떤 pod를 pickup 했는지 아는 법 by log > kubectl logs my-custom-scheduler --name-space=kube-system

 

 

9. Scheduler profile

: scheduler는 pod의 조건을 충족하는 node에 호스팅시켜주는 역할이었다. 아래는 전체적인 스케줄러의 동작과정입니다.

 

1) Scheduling Queue에 pod들이 담긴다. 이때 priority에 의해 queue에서 순서가 생성된다

2) highest priority pod에 대해, 호스팅 시킬 수 없는 node들을 filter out한다. (Filtering Phase)

3) 2까지 통과한 노드들에 대해 점수를 매긴다. 더 높은 점수 == pod을 호스팅할 자격! (Scoring Phase)

4) 가장 높은 노드에 pod이 binding 된다. (Binding Phase)

 

 위 과정은 모두 plugin으로 진행된다. 가령, 1에는 PrioritySort, 2에는 NodeResourcesFit, NodeName, NodeUnschedulable, 3에는 NodeResoucesFit, ImageLocality, 4에는 DefaultBinder

  • 위는 default일 뿐이고, 우리의 plugin은 'extension point'를 사용하여 꽂을 수 있다. queueSort plugin, preFilter, filter, postFilter, preScore, score ... 다양한 플러그인이 있다.
  • 위와 같은 scheduler 내부 내용을 정리, 명문화해놓은게 profile이다.
  • Multiple Schedule을 사용하는 가장 기본적인 방법은 각자 다 yaml 파일 만들어서 create하는 것이다. 그러나 이 방법은 귀찮고, 불필요한 자원이 투입된다. 무엇보다, scheduler간 race condition 발생 가능성이 있다.
  • 1.18부터는 한 scheduler 내에 여러 profile을 둘 수 있게 되었다.

 

 

10. Monitor Cluster Components

: k8s의 자원 소비를 어떻게 모니터링할 수 있을까요? 무엇을 관찰해야 할까요? 이는 너무나 다양합니다. 다양한 Metric을 모니터링하고 저장하고 데이터에 대한 분석을 제공할 수 있는 솔루션이 필요합니다. 사용할 수 있는 것으로 프로메테우스, Elastic Stack, DATADOG 등등 있습니다. 

 

 Heapster는 original 프로젝트였습니다. k8s 분석과 모니터링이 가능하게 말이죠. 하지만 현재는 Heapster Deprecated 되었고, Metrics Server가 대체되었습니다. k8s 클러스터 당 Metrics Server는 1개가 사용됩니다. Metrics Server는 k8s 노드, pod 각각 그들의 집합체로부터, 메모리에 저장합니다.

 

 Metrics Server는 인메모리(디스크가 아닌 주 메모리에 모든 데이터를 보유) 모니터링 솔루션입니다. 디스크에 데이터를 저장하지 않는 것이죠. 그래서 과거의 수행 데이터는 볼 수 없습니다. kubelet은 각 노드에 Agent로 수행되고 있습니다. k8s Master 서버로부터 지시 받는 것을 책임지고, 노드에서 pod가 실행될 수 있게 합니다. 

 

 kubelet은 또한 sub component를 포함합니다. cAdvisor or Container Advisor로 알려져있습니다. cAdvisor는 Metrics Server를 위해 pods로 부터 metrics 수행 결과를 뽑는 것과 kubelet API를 통해 그들을 노출시키는 것을 책임지도록 합니다. 

 

Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.