-
[Kubernetes] 구성 - 노드 구성 및 리소스 관리공부/데이터 2025. 2. 6. 00:20
Cordon
쿠버네티스에서 Cordon은 특정 노드에 새로운 파드가 스케줄되지 않도록 하는 기능입니다. 노드를 유지보수하거나 문제를 해결하기 전에 해당 노드에서 실행 중인 파드들을 다른 노드로 안전하게 이동시키기 위해 사용됩니다.
작동 방식
Cordon 명령을 실행하면 해당 노드의 스케줄링 기능이 비활성화됩니다. 즉, 쿠버네티스 스케줄러는 Cordon된 노드에 새로운 파드를 할당하지 않습니다. 또한 Cordon은 이미 실행 중인 파드에는 영향을 주지 않습니다. 파드들은 계속해서 실행되지만 새로운 파드는 해당 노드에 생성되지 않습니다.
사용 시나리오
- 노드 유지보수: 하드웨어 업그레이드, OS 패치, 커널 업데이트 등 노드 유지보수를 수행하기 전에 Cordon을 사용하여 새로운 파드가 해당 노드에 배포되는 것을 방지합니다.
- 노드 문제 해결: 특정 노드에 문제가 발생했을 때 Cordon을 사용하여 해당 노드에 새로운 파드가 배포되는 것을 막고 문제 해결에 집중할 수 있습니다.
- 노드 자원 확보: 특정 노드의 자원을 다른 용도로 사용하기 위해 Cordon을 사용하여 해당 노드에 새로운 파드 배포를 중단시킵니다.
- DaemonSet의 목적은 모든 노드에서 데몬 애플리케이션을 실행하는 것이기 때문
명령어
# cordon 등록 명령어 $ kubectl cordon <node-name>
- Cordon 설정시 SchedulingDisabeld 상태 확인
# cordon 해제 명령어 $ kubectl uncordon <node-name>
유의사항
- Cordon은 노드에 새로운 파드 배포만 막을 뿐 이미 실행 중인 파드에는 영향을 주지 않습니다.
- 노드에서 실행 중인 파드들을 다른 노드로 안전하게 이동시키려면 Drain 명령어를 사용해야 합니다.
- DaemonSet 파드는 Cordon의 영향을 받지 않습니다. DaemonSet 파드는 각 노드에 하나씩 실행되도록 설계되었기 때문에 Cordon된 노드에도 DaemonSet 파드가 실행됩니다.
- GCP Autopilot의 경우 특정 노드를 cordon 설정하면 설정한 노드에 뜬 파드가 새로 생성된 노드의 파드로 이동하며 cordon 설정된 노드는 삭제됨
Drain
Drain은 특정 노드를 유지보수하거나 문제를 해결하기 전에 해당 노드에서 실행 중인 파드들을 다른 노드로 안전하게 이동시키는 명령어입니다. Cordon 명령어와 함께 사용되어 노드를 안전하게 관리하는 데 중요한 역할을 합니다.
작동 방식
Drain 명령어는 먼저 해당 노드를 Cordon하여 새로운 파드가 스케줄되지 않도록 합니다. 다음 Cordon된 노드에서 실행 중인 파드들을 다른 노드로 안전하게 퇴거(evict)시킵니다. Drain 명령어 실행 후, 노드는 격리 상태가 되어 더 이상 파드가 스케줄되지 않습니다.
사용 시나리오
- 노드 유지보수: 하드웨어 업그레이드, OS 패치, 커널 업데이트 등 노드 유지보수를 수행하기 전에 Drain을 사용하여 파드들을 다른 노드로 이동시킵니다.
- 노드 문제 해결: 특정 노드에 문제가 발생했을 때 Drain을 사용하여 해당 노드의 파드들을 다른 노드로 이동시키고, 문제 해결에 집중할 수 있습니다.
- 노드 자원 확보: 특정 노드의 자원을 다른 용도로 사용하기 위해 Drain을 사용하여 해당 노드의 파드들을 다른 노드로 이동시킵니다.
명령어
$ kubectl drain <node-name> [options]
유의사항
- Drain 명령어는 Cordon 명령어를 포함하고 있습니다. 즉, Drain 명령어를 실행하면 해당 노드는 자동으로 Cordon됩니다.
- Drain 시에는
-ignore-daemonsets
옵션을 사용하여 DaemonSet 파드를 무시하는 것이 일반적입니다. -delete-emptydir-data
옵션을 사용하면 emptyDir 볼륨의 데이터가 삭제되므로 주의해야 합니다.-force
옵션은 파드을 강제로 삭제하므로 가능한 한 사용하지 않는 것이 좋습니다.
Node label
키-값 쌍으로 노드에 추가되는 메타데이터입니다. label은 노드의 특징이나 속성을 나타내는 데 사용되며 파드를 특정 노드에 스케줄링하거나 노드를 그룹으로 관리하는 데 유용하게 활용됩니다.
node label을 사용하면 특정 label을 가진 노드에만 파드가 배포되도록 설정할 수 있고 label을 기준으로 노드를 그룹화하여 관리 작업을 효율적으로 수행할 수 있습니다. 또한 label을 사용하여 특정 노드를 선택하거나 제외하는 작업을 수행할 수 있습니다.
apiVersion: v1 kind: Node metadata: name: my-node labels: environment: production diskType: ssd region: us-central1 spec: ... ------ apiVersion: v1 kind: Pod metadata: name: my-pod spec: nodeSelector: environment: production containers: - name: my-container image: my-image
위 YAML 파일은
environment: production
label을 가진 노드에만my-pod
가 배포되도록 설정하는 것을 의미합니다.NodSelector
nodeSelector는 파드를 특정 노드에 스케줄링하기 위한 가장 기본적인 방법 중 하나입니다. 노드에 할당된 label을 기반으로 파드가 실행될 노드를 선택합니다.
특징
파드의
nodeSelector
에 지정된 label과 정확히 일치하는 label을 가진 노드에만 파드가 스케줄링됩니다. nodeSelector는 사용법이 간단하고 이해하기 쉽지만 복잡한 매칭 규칙이나 조건을 설정할 수 없습니다.작동 방식
쿠버네티스 스케줄러는 파드를 스케줄링할 때 노드의 label을 확인합니다. 스케줄러는 파드의
nodeSelector
에 지정된 label과 정확히 일치하는 label을 가진 노드를 찾습니다. 일치하는 label을 가진 노드가 있으면 파드는 해당 노드에 스케줄링됩니다.사용 사례
- 특정 하드웨어: 특정 CPU, GPU, SSD 등을 가진 노드에 파드를 배포해야 할 때
- 특정 운영체제: 특정 운영체제(Linux, Windows 등)가 설치된 노드에 파드를 배포해야 할 때
- 특정 환경: 개발, 테스트, 운영 환경 등 특정 환경에 맞는 노드에 파드를 배포해야 할 때
- GKE에서 spot VM으로 실행하려 할 때,
nodeSelector
를 사용할 수 있음
- GKE에서 spot VM으로 실행하려 할 때,
예시
apiVersion: v1 kind: Pod metadata: name: my-pod spec: containers: - name: my-container image: my-image nodeSelector: environment: production diskType: ssd
위 YAML 파일은
environment: production
과diskType: ssd
label을 모두 가진 노드에만my-pod
가 배포되도록 설정하는 것을 의미합니다. 만약 어떤 노드도 두 가지 label을 모두 가지고 있지 않다면 파드는 Pending 상태로 남게 됩니다.노드 어피니티(Affinity)와 노드 안티 어피니티(Anti-affinity)
노드 어피니티와 안티 어피니티는 파드를 특정 노드에 스케줄링하기 위한 고급 기능입니다.
nodeSelector
보다 더 다양한 조건을 설정하여 파드 스케줄링을 보다 유연하게 제어할 수 있습니다.NodeName과 NodeSelector의 한계, 노드 어피니티/안티 어피니티의 장점
NodeName은 특정 노드에만 파드를 스케줄링할 수 있지만 노드 이름이 변경되면 파드를 다시 스케줄링해야 합니다.
NodeSelector는 label이 정확히 일치하는 노드에만 파드를 스케줄링할 수 있으며 유연한 조건을 설정하기 어렵습니다.
노드 어피니티/안티 어피니티는 다양한 연산자(In, NotIn, Exists, DoesNotExist)를 사용하여 복잡한 조건을 설정할 수 있고 필수 조건 외에 선호하는 조건을 설정하여 스케줄링을 최적화할 수 있습니다. 또한 노드 label이 변경되어도 파드 스케줄링에 자동으로 반영됩니다.
특징 NodeName NodeSelector Node Affinity/Anti-Affinity 기능 특정 노드에 파드를 스케줄링 특정 레이블을 가진 노드에 파드를 스케줄링 특정 레이블을 가진 노드에 파드를 스케줄링 (더 다양한 조건 가능) 조건 노드 이름 레이블 레이블, 연산자, 가중치 유연성 낮음 중간 높음 확장성 낮음 중간 높음 사용 사례 특정 노드에 파드를 고정 특정 속성을 가진 노드 그룹에 파드를 배포 복잡한 조건을 기반으로 파드를 최적의 노드에 배포 장점 간단하고 직관적 비교적 간편하게 사용 가능 다양한 옵션으로 정밀한 제어 가능 단점 노드 이름 변경 시 재설정 필요 레이블 기반으로 제한적인 조건만 설정 가능 설정이 복잡할 수 있음 노드 어피니티(Affinity)
노드 어피니티는 파드를 특정 label을 가진 노드에 선호하거나 필수적으로 스케줄링하도록 설정하는 기능입니다.
requiredDuringSchedulingIgnoredDuringExecution
: 파드가 스케줄링될 때 필수적으로 만족해야 하는 조건을 지정합니다. 이 조건을 만족하는 노드가 없으면 파드는 스케줄링되지 않습니다.preferredDuringSchedulingIgnoredDuringExecution
: 파드가 스케줄링될 때 선호하는 조건을 지정합니다. 이 조건을 만족하는 노드가 있으면 파드는 해당 노드에 스케줄링되지만 조건을 만족하는 노드가 없어도 다른 노드에 스케줄링될 수 있습니다. 가중치를 사용해 대략적으로 할당률을 조절할 수 있습니다.
노드 안티 어피니티(Anti-affinity)
노드 안티 어피니티는 파드를 특정 label을 가진 노드에 절대적으로 스케줄링하지 않도록 설정하는 기능입니다.
requiredDuringSchedulingIgnoredDuringExecution
: 파드가 스케줄링될 때 절대적으로 만족하지 않아야 하는 조건을 지정합니다. 이 조건을 만족하는 노드에는 파드가 스케줄링되지 않습니다.preferredDuringSchedulingIgnoredDuringExecution
: 파드가 스케줄링될 때 선호하지 않는 조건을 지정합니다. 이 조건을 만족하는 노드를 피해서 파드가 스케줄링되지만 조건을 만족하는 노드가 없으면 다른 노드에 스케줄링될 수 있습니다.
파드 어피니티와 노드 어피니티 차이점
특징 Pod Affinity Node Affinity 기능 특정 파드와 함께 실행되어야 하는 파드를 지정 특정 Label을 가진 Node에 파드를 스케줄링 대상 파드 Node 관점 파드 간의 관계 파드와 Node 간의 관계 사용 사례 - 동일한 Node에서 함께 실행되어야 하는 파드 (예: frontend와 backend) - 특정 HW/SW spec을 가진 Node에 파드 배포 - 특정 서비스를 제공하는 파드를 함께 배포하여 latency를 줄임 - 특정 환경 (development, production) Node에 파드 배포 - 특정 Node에 파드가 너무 많이 몰리는 것을 방지 - 특정 Zone/Region에 파드 배포 종류 -requiredDuringSchedulingIgnoredDuringExecution (필수)
- preferredDuringSchedulingIgnoredDuringExecution (선호)- requiredDuringSchedulingIgnoredDuringExecution (필수)
- preferredDuringSchedulingIgnoredDuringExecution (선호)노드 어피니티/안티 어피니티의 연산자
In
지정된 값 중 하나와 일치하는 레이블을 가진 노드를 선택합니다.
예를 들면
environment In (production, staging)
의 경우,environment
label이production
또는staging
값을 가진 노드에 파드를 스케줄링합니다.NotIn
지정된 값과 일치하지 않는 레이블을 가진 노드를 선택합니다.
예를 들면
environment NotIn (development)
의 경우,environment
label이development
값을 가지지 않는 노드에 파드를 스케줄링합니다.Exists
지정된 키를 가진 레이블이 존재하는 노드를 선택합니다.
- 예를 들면
diskType Exists
의 경우,diskType
label이 존재하는 노드에 파드를 스케줄링합니다.
DoesNotExist
지정된 키를 가진 레이블이 존재하지 않는 노드를 선택합니다.
예를 들면
gpu DoesNotExist
의 경우,gpu
레이블이 존재하지 않는 노드에 파드를 스케줄링합니다.Gt
지정된 값보다 큰 값을 가진 레이블을 가진 노드를 선택합니다. (숫자형 레이블에만 사용 가능)
예를 들면
cpuCores Gt 4
의 경우,cpuCores
레이블이 4보다 큰 값을 가진 노드에 파드를 스케줄링합니다.Lt
지정된 값보다 작은 값을 가진 레이블을 가진 노드를 선택합니다. (숫자형 레이블에만 사용 가능)
예를 들면
memoryGB Lt 16
의 경우memoryGB
레이블이 16보다 작은 값을 가진 노드에 파드를 스케줄링합니다.
위 연산자들은
matchExpressions
필드 내에서 사용됩니다.matchExpressions
는 여러 개의 조건을 조합하여 복잡한 스케줄링 규칙을 정의할 수 있도록 합니다. 각 조건은key
,operator
,values
(operator에 따라 생략 가능) 필드로 구성됩니다.apiVersion: v1 kind: Pod metadata: name: my-pod spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: environment operator: In values: - production - key: region operator: NotIn values: - us-east1 containers: - name: my-container image: my-image
위 예시는 다음과 같은 조건을 만족하는 노드에 파드를 스케줄링합니다.
environment
레이블이production
값을 가진 노드region
레이블이us-east1
값을 가지지 않는 노드
예시
고성능 노드에 특정 파드를 무조건 배포 (Node Affinity)
apiVersion: v1 kind: Pod metadata: name: ml-training-pod spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: gpu operator: In values: - nvidia-tesla-t4 containers: - name: ml-container image: ml-image
노드에
gpu=nvidia-tesla-t4
레이블을 추가하고 파드 스펙에 다음과 같이 노드 어피니티를 설정합니다.spot VM을 담당하는 노드에 특정 파드를 무조건 배포 (Node Affinity)
apiVersion: v1 kind: Pod spec: ... affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: cloud.google.com/gke-spot operator: In values: - "true" ...
spot VM을 담당하는 노드에 특정 파드를 가중치에 따라 배포 (Node Affinity)
apiVersion: v1 kind: Pod spec: ... affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - weight: 50 preference: matchExpressions: - key: cloud.google.com/gke-spot operator: In values: - 'true'
spot 노드에 파드를 대략 50% (대략이므로 50%를 훨씬 초과하거나 미달할 수 있음)로 할당
특정 노드에 파드가 함께 배포되는 것을 무조건 방지 (Node Anti-Affinity)
apiVersion: v1 kind: Pod metadata: name: web-server-pod spec: affinity: nodeAntiAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: role operator: In values: - database containers: - name: web-server-container image: web-server-image
노드에
role=database
또는role=webserver
레이블을 추가하고 파드 스펙에 다음과 같이 노드 안티 어피니티를 설정합니다.Taints와 Tolerations
Taints와 Tolerations는 파드를 특정 노드에 스케줄링하거나 배제하는 데 사용되는 강력한 메커니즘입니다. 노드 어피니티(Node Affinity)와 유사한 기능을 수행하지만 Taints는 노드 측에서 파드의 배포를 제한하고 Tolerations는 파드 측에서 특정 Taints를 허용하는 방식으로 작동합니다.
즉, Taint는 자물쇠, Tolerations은 자물쇠를 여는 열쇠 역할을 합니다.
Taints
Taints는 노드에 특정 속성이나 제약 조건을 나타내는 표식입니다. Taints가 적용된 노드는 Tolerations가 없는 파드의 배포를 거부합니다. 각 Taint는 키, 값 이펙트로 구성됩니다.
이펙트는 Taint에 대한 파드의 Toleration 방식을 결정합니다. 주요 이펙트는 다음과 같습니다.
NoSchedule
: Toleration이 없는 파드는 해당 Taint가 적용된 노드에 스케줄링될 수 없습니다.- 기존 실행중인 파드는 유지하되 실행될 파드에 대해서만 스케줄링 제한
PreferNoSchedule
: Toleration이 없는 파드는 해당 Taint가 적용된 노드에 스케줄링되는 것을 선호하지 않습니다 (가능하면 다른 노드에 스케줄링).NoExecute
: Toleration이 없는 파드는 해당 Taint가 적용된 노드에서 즉시 축출됩니다.
Tolerations
Tolerations는 파드가 특정 Taint를 허용하도록 설정하는 속성입니다. Tolerations가 있는 파드는 해당 Taint가 적용된 노드에도 스케줄링될 수 있습니다. 각 Toleration은 키, 값, ,operator 이펙트로 구성됩니다. 파드의 Toleration이 노드의 Taint와 일치해야 해당 노드에 스케줄링될 수 있습니다.
이펙트는 Taints와 동일하고 operator는 다음과 같습니다.
Equal
: Taint의 키, 값, 이펙트가 Toleration과 정확히 일치하는 경우에만 Taint를 허용합니다.
tolerations: - key: "special-node" operator: "Equal" value: "true" effect: "NoSchedule"
Exists
: Taint의 키가 Toleration에 존재하는 경우 해당 Taint를 허용합니다. 값은 일치하지 않아도 됩니다.
tolerations: - key: "special-node" operator: "Exists" effect: "NoSchedule"
사용 사례
- 특정 노드에 특정 파드 배포: 특정 하드웨어나 속성을 가진 노드에 특정 파드만 배포하도록 제한할 수 있습니다.
- 노드 유지보수: 유지보수 작업을 위해 특정 노드를 오염시켜 파드 배포를 막고 해당 노드의 파드들을 다른 노드로 이동시킬 수 있습니다.
- 특정 파드 우선순위: 특정 Taint를 가진 노드에 우선순위가 높은 파드만 배포하도록 설정할 수 있습니다.
예시
# 노드에 Taint 추가 kubectl taint nodes node1 special-node=true:NoSchedule # Pod 스펙에 Toleration 추가 apiVersion: v1 kind: Pod metadata: name: my-pod spec: tolerations: - key: "special-node" operator: "Equal" value: "true" effect: "NoSchedule" containers: - name: my-container image: my-image
Taints와 Node affinity의 차이점
Node affinity는 파드에서 관리하고 Taints는 노드에서 관리합니다. 즉, Node affinity는 파드가 어떤 노드에 들어갈지를 결정하고 Taints는 노드가 특정 키가 있는 파드만 들어올 수 있게 결정합니다.
Taints/Tolerations과 Node Affinity 함께 사용 사례
3개의 노드(Red, Blue, Green)와 다른 노드들이 있고 3개의 파드(Red, Blue, Green) 다른 파드들이 있습니다. 목표는 Red 파드를 Red 노드에 Green 파드를 Green 노드에 Blue 파드를 Blue 노드에 배치하는 것입니다. 또한 다른 파드들이 Red, Green, Blue 노드에 배치되는 것을 원하지 않습니다. 마찬가지로 우리의 Red, Green, Blue 파드들이 다른 노드에 배치되는 것을 원하지 않습니다.
노드에 red, green, blue Taints를 적용한 다음, 파드에 red, green, blue Tolerations를 적용합니다. 이렇게 하면 해당 Toleration을 가진 파드들이 해당하는 Taint가 적용된 노드에 배치되는 데 도움이 되지만 Taint가 없는 노드에 파드가 배치되지 않는다는 것을 보장하지는 않습니다.
이제 노드 어피니티를 적용하기 위해 노드에 키-값 쌍의 label을 적용합니다. 다음 적절한 Affinity로 노드를 구성합니다. 이렇게 하면 파드를 적절한 노드에 배치하는 데 도움이 되지만 다른 파드들도 우리 노드에 배치될 수 있습니다.
# Red 노드에 Red Pod 배포 apiVersion: v1 kind: Pod metadata: name: red-pod spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: color operator: In values: - red tolerations: # Red 노드에만 허용 - key: color operator: Equal value: red effect: NoSchedule containers: - name: red-container image: <red-pod-image> # Red Pod 이미지 --- # Blue 노드에 Blue Pod 배포 apiVersion: v1 kind: Pod metadata: name: blue-pod spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: color operator: In values: - blue tolerations: # Blue 노드에만 허용 - key: color operator: Equal value: blue effect: NoSchedule containers: - name: blue-container image: <blue-pod-image> # Blue Pod 이미지 --- # Green 노드에 Green Pod 배포 apiVersion: v1 kind: Pod metadata: name: green-pod spec: affinity: nodeAffinity: requiredDuringSchedulingIgnoredDuringExecution: nodeSelectorTerms: - matchExpressions: - key: color operator: In values: - green tolerations: # Green 노드에만 허용 - key: color operator: Equal value: green effect: NoSchedule containers: - name: green-container image: <green-pod-image> # Green Pod 이미지 --- # 다른 Pod들이 Red, Blue, Green 노드에 배포되는 것을 방지 # (Taint & Toleration 활용) # Red 노드에 Taint 적용 kubectl taint nodes red-node color=red:NoSchedule # Blue 노드에 Taint 적용 kubectl taint nodes blue-node color=blue:NoSchedule # Green 노드에 Taint 적용 kubectl taint nodes green-node color=green:NoSchedule # 다른 Pod들이 Red, Blue, Green 노드에 배포되지 않도록 Toleration 설정 apiVersion: v1 kind: Pod metadata: name: other-pod spec: tolerations: # Red, Blue, Green 노드에는 배포 불가 - key: color operator: Exists effect: NoSchedule containers: - name: other-container image: <other-pod-image> # 다른 Pod 이미지
Taints & Tolerations와
operator: Equal
로만 특정 파드가 적합한 노드에 배치되지 않는 이유먼저 Kubernetes 스케줄러는 Taints & Tolerations, Node Affinity, Pod Affinity 등 다양한 요소를 고려하여 파드를 Node에 스케줄링합니다. Taints & Tolerations는 스케줄링 가능 여부를 결정하는 요소 중 하나일 뿐이며 다른 요소들의 영향으로 인해 파드가 다른 노드에 스케줄링될 수도 있습니다.
operator: Equal
을 사용하여 Toleration 조건을 엄격하게 설정해도 파드가 반드시 해당 Taint를 가진 노드에 스케줄링된다는 보장은 없습니다. 왜냐하면 Node Affinity, Pod Affinity, Resource limits 등 다른 제약 조건들이 파드 스케줄링에 영향을 미칠 수 있습니다. 또한 Kubernetes 스케줄러는 다양한 요소를 고려하여 최적의 Node를 선택합니다. Toleration 조건 외에도 Node의 자원 상황, Pod의 우선순위 등을 고려하여 최종 스케줄링 결정을 내립니다.레퍼런스
https://blog.devgenius.io/taints-tolerations-and-node-affinity-in-kubernetes-41d063157852
https://cloud.google.com/kubernetes-engine/docs/concepts/spot-vms