컨테이너나 가상 머신과 같은 인스턴스를 새롭게 생성할 때, 그 인스턴스를 어느 서버에 생성할 것인지 결정하는 일을 뜻함
컨테이너를 생성하기 전에 특정 목적에 최대한 부합하는 워커 노드를 선택하는 작업이 스케줄링에 해당
ectd
는 분산 코디네이터라고 불리는 도구의 일종으로, 클라우드 플랫폼 등의 환경에서 여러 컴포넌트가 정상적으로 상호 작용할 수 있도록 데이터를 조정하는 역할을 담당
인증, 인가, 어드미션 컨트롤러 등의 단계를 모두 거쳐 포드 생성 요청이 최종적으로 승인됐다면, API 서버는 etcd
에 포드의 데이터를 저장하지만, nodeName
항목을 설정하지 않은 상태로 저장한다. 스케줄링이 수행되어야, nodeName
이 지정될 수 있다.
kube-scheduler
는 API
서버의 Watch
를 통해 nodeName
이 비어 있는 포드 데이터가 저장됐다는 사실을 인지하고, 해당 포드를 스케줄링 대상으로 판단하고 포드를 할당할 적절한 노드를 선택한 다음 API
서버에게 해당 노드와 포드를 바인딩할 것을 요청한다.
포드를 할당할 수 있는 노드와 그렇지 않은 노드를 분리해 걸러내는 단계, 포드에 설정된 CPU
나 메모리의 Requests
만큼 가용 자원이 존재하지 않는 노드는 노드 필터링 단계에서 제외된다. 그 외에도 기본적으로 마스터 노드는 포드를 할당할 수 없는 노드로 취급되며, 장애가 발생해 kubectl get nodes
에서 STATUS
가 Ready
가 아닌 워커 노드 또한 제외된다.
노드 스코어링 단계에서는 쿠버네티스의 소스코드에 미리 정의된 알고리즘의 가중치에 따라서 노드의 점수를 계산, 포드가 사용하는 도커 이미지가 이미 노드에 존재할 때는 빠르게 포드를 생성할 수 있기 때문에 해당 노드의 점수가 증가될 수 있다(Image Locaity
). 또는 노드의 가용 자원이 많을수록 노드의 점수가 노게 평가될 수 있다(Least Requested
).
특정 워커 노드에 포드를 할당하는 가장 확실한 방법은 포드의 YAML
파일에 노드의 이름을 직접 명시하는 방법
노드의 이름을 고정으로 설정하면, 다른 환경에 유연하게 대처할 수 없음
노드의 이름보다는 노드의 라벨을 사용하는 것이 조금 더 나은 방법임
kubectl label nodes <노드 이름> <추가할 라벨>
명령어를 통해서, 노드에 라벨링을 할 수 있음
포드의 적용될 Yaml
변경
spec:
nodeSelector:
key : value
단순한 라벨링보다 조금 더 개선된 노드 선택방법
required
형태는 하나의 조건만 만족하면 선택될 수 있다.
조건식에서 In
외에도 NotIn
, Exists
, DoesNotExist
, Gt
, Lt
를 사용할 수 있어서 nodeSelector
보다 더욱 다양하게 활용할 수 있다는 것이 특징이다.
required
는 반드시 만족해야 하는 제약 조건을 정의할 때 쓰이므로, nodeSelcetor
의 기능을 확장했다고 생각할 수 있다.
preferred
는 조건에 만족하는 해당 노드에 가중치를 부여할 수 있음
Ignored
방식들은 포드를 할당할 당시에만 유효하므로, 런타임에서는 다른 노드로 포드가 옮겨가는 퇴거가 발생하지 않는다.
Node Affinity
가 특정 조건을 만족하는 노드를 선택하는 방법이라면, Pod Affinity
는 특정 조건을 만족하는 포드와 함께 실행되도록 스케줄링topologyKey
를 통해서, 토폴리지가 1, 2로 분리되고 동일한 노드에 포드가 할당될 수 있지만, 동일한 그룹(토폴로지)에 속하는 다른 노드에 포드가 할당될 수 있으므로, 노드 A와 B에 포드가 스케줄링될 가능성이 존재한다.
required
를 사용하면 토폴로지마다 반드시 하나의 포드만 할당하게 되지만, preferred
를 사용하면 각 토폴로지의 노드에 포드를 여러 개 할당할 수도 있다.
Pod Affinity
가 특정 포드와 동일한 토폴로지에 존재하는 노드를 선택한다면, Pod Anti-affinity
는 특정 포드와 같은 토폴로지의 노드를 선택하지 않는 방법
이 원리를 잘 이용하면 고가용성을 보장하기 위해 포드를 여러 가용 영역 또는 리전에 멀리 퍼뜨리는 전략을 세울 수도 있음
노드의 얼룩(Taints
)을 용인(Tolerations
)할 수 있는 포드만 해당 노드에 할당할 수 있도록 함
노드의 얼룩(Taints
)은 쿠버네티스 이벤트에 의해서도 발생한다.
라벨과 유사하지만, 라벨과는 다른점은 key=value
뒤에 `효과를 추가로 명시할 수 있음
Taint
효과는 Taint
가 노드에 설정됐을 때 어떠한 효과를 낼지 결정할 수 있으며, 효과에는 NoSchedule
, NoExecute
, PreferNoSchedule
총 3가지가 존재한다.
쿠버네티스는 기본적으로 다양한 Taint
를 노드에 설정하며, 마스터 노드가 아닌 워커 노드에 포드들이 생성되는 이유도 Taint
를 통해서 포드가 할당되는 것을 방지하고 있음
NoExecute
는 NoSchedule
과 달리 기존 포드를 모두 종료시킬 수 있다.
파드를 실행시켜보면, 기본적으로 설정되는 Toleration
이 존재한다.
Toleration
에 대해서 용인할 수 있는 Seconds
를 설정해서, 해당 노드가 문제가 발생하더라도 해당 Seconds
동안은 다른 포드로 이동하지 않을 수 있다.kubectl cordon
을 통해서 해당 노드에 더 이상 포드가 스케줄링되지 않도록 설정할 수 있다.
cordon
을 사용하면, STATUS
에 SchedulingDisabled
설정이 됐음을 확인할 수 있음
cordon
명령어는 NoExecute
가 아닌 NoSchedule
효과가 있는 Taint
를 노드에 추가하기 때문
drain
은 cordon
처럼 해당 노드에 스케줄링을 금지한다는 것은 같지만, 노드에서 기존에 실행중이던 포드를 다른 노드로 옮겨가도록 퇴거(Eviction
)를 수행한다는 점이 다름
커널 버전 업그레이드, 유지 보수 등의 이유로 인해 잠시 노드를 중지해야 할 때 유용하게 사용할 수 있는 명령어
디플로이먼트나 레플리카셋, 잡, 스테이트풀셋 등에 의해 생성되지 않은 포드, 즉 단일 포드가 노드에 존재할 때도 drain
명령어는 실패할 수 있다. type: Pod
처럼 정의해 생성한 단일 포드는 어떠한 이유로 종료되더라도 다른 노드로 옮겨가 다시 생성되지 않기 때문이다.
drain
과 같이 포드 퇴거 작업이 수행될 때는 애플리케이션 중단이 될 수 있음디플로이먼트에서 포드의 개수를 여러 개로 설정함으로써 일정 개수의 포드가 중지되더라도 애플리케이션에 장애가 발생하지 않도록 구성할 수도 있음
그렇지만, 포드의 개수가 줄어든다는 것은 처리할 수 있는 요청의 총량은 일시적으로 감소함
이러한 상황에 대처할 수 있는 PodDistruptionBudget
이라는 기능을 제공
maxUnavailable
는 비활성화될 수 있는 포드의 최대 개수 또는 비율을 의미하며, minAvailable
은 포드의 퇴거가 발생할 때, 최소 몇 개의 포드가 정상 상태를 유지해야 하는지를 의미
kube-scheduler
) 외에도 여러 개의 스케줄러를 동시에 사용할 수 있도록 지원