1. Pod를 수동으로 특정 Node에 배치하는 방법
이 강의는 스케줄러 없이 Pod를 Node에 배치하는 방법을 설명함.
보통 Kubernetes에서는 Scheduler가 어떤 Pod를 어떤 Node에 올릴지 결정함.
그런데 다음과 같은 상황이 있을 수 있음.
- 클러스터에 Scheduler가 없음
- 기본 Scheduler를 쓰지 않고
- 직접 Pod를 원하는 Node에 배치하고 싶음
이럴 때 사용할 수 있는 방법을 이해하는 것이 이 강의의 핵심임.
1. Scheduler는 원래 어떻게 동작하는가
먼저 기본 동작부터 보면 이해가 쉬움.
Pod 정의 파일에는 nodeName 이라는 필드가 있음.
nodeName: ...
그런데 일반적으로는 이 값을 직접 적지 않음.
Pod를 생성할 때 보통 비워두고 생성함.
왜냐하면 원래는 Scheduler가 이 값을 채우기 때문임.
Scheduler의 동작 흐름은 대략 다음과 같음.
- 클러스터 안의 Pod들을 확인함
- 그중에서 nodeName이 아직 설정되지 않은 Pod를 찾음
- 그런 Pod들을 스케줄링 대상(candidate) 으로 봄
- 스케줄링 알고리즘으로 어떤 Node가 적절한지 결정함
- 적절한 Node를 찾으면 Pod를 그 Node에 배치함
- 이 과정에서 내부적으로 Binding Object를 만들어 연결함
즉, 핵심은 다음임.
- nodeName이 없는 Pod = 아직 어느 Node에도 배치되지 않음
- Scheduler가 적절한 Node를 골라서 nodeName을 설정해 줌
2. Scheduler가 없으면 무슨 일이 생기는가
클러스터에 Scheduler가 없으면,
nodeName이 비어 있는 Pod를 아무도 처리하지 못함.
그 결과 Pod는 계속 다음 상태로 남음.
- Pending
즉, Pod는 생성되었지만
어느 Node에서 실행되어야 하는지 정해지지 않았기 때문에 실제로 올라가지 못하는 상태임.
3. Scheduler 없이 Pod를 수동으로 배치하는 가장 쉬운 방법
가장 쉬운 방법은 Pod 생성 시점에 nodeName을 직접 지정하는 것임.
예를 들어 Pod manifest에 이렇게 적을 수 있음.
kind: Pod
metadata:
name: my-pod
spec:
nodeName: node01
containers:
- name: nginx
image: nginx
이렇게 하면 Scheduler가 없어도
Pod는 바로 node01에 배치됨.
즉,
- Pod를 처음 만들 때
- spec.nodeName에 원하는 Node 이름을 적으면
- 해당 Node에 직접 할당 가능함
4. 이미 생성된 Pod에는 nodeName을 바꿀 수 없음
여기서 중요한 제약이 있음.
Pod가 이미 생성된 뒤에는 nodeName을 수정할 수 없음.
즉 이런 식은 안 됨.
- Pod를 먼저 만들고
- 나중에 nodeName만 수정해서 다른 Node에 붙이기
Kubernetes는 기존 Pod의 nodeName 변경을 허용하지 않음.
5. 이미 만들어진 Pod를 Node에 붙이고 싶다면
이미 생성된 Pod를 특정 Node에 연결하려면
실제 Scheduler가 하는 것처럼 Binding Object를 만들어서 API 요청을 보내야 함.
즉, 직접 Scheduler처럼 동작을 흉내 내는 방식임.
흐름은 다음과 같음.
- Binding Object를 만듦
- 그 안에 목표 Node 이름을 적음
- Pod의 Binding API로 POST 요청을 보냄
- 그러면 해당 Pod가 그 Node에 바인딩됨
Binding Object에는 어떤 Node에 붙일지에 대한 정보가 들어감.
예를 들어 개념적으로는 다음과 비슷함.
kind: Binding
metadata:
name: my-pod
target:
apiVersion: v1
kind: Node
name: node01
그런데 API로 보낼 때는 보통 JSON 형식으로 보내야 하므로,
YAML을 그대로 보내는 것이 아니라 JSON으로 변환해서 POST 요청해야 함.
2. Labels and Selectors
1. Labels와 Selectors의 기본 개념
Labels와 Selectors는 대상을 분류하고 필터링하기 위한 방법임.
예를 들어 여러 동물이 있다고 하면, 다음과 같은 기준으로 나눌 수 있음.
- class
- kind
- domestic / wild
- color
이렇게 각 대상에 여러 속성을 붙여두면, 원하는 조건으로 쉽게 묶어서 볼 수 있음.
예를 들면 다음과 같음.
- class = mammal → 포유류만 조회
- color = green → 초록색 동물만 조회
- class = bird, color = green → 초록색 새만 조회
즉, Labels는 속성을 붙이는 역할, Selectors는 그 속성을 기준으로 원하는 대상을 찾는 역할을 함.
2. Labels는 무엇인가
Labels는 각 객체에 붙이는 key-value 형태의 속성 정보임.
예를 들어 어떤 대상에 다음과 같은 label을 붙일 수 있음.
- class: mammal
- kind: dog
- color: green
이런 식으로 label을 붙여두면, 나중에 여러 기준으로 객체를 구분할 수 있음.
핵심은 다음과 같음.
- Labels는 객체를 설명하는 속성임
- 필요한 만큼 여러 개를 붙일 수 있음
- 객체를 그룹화할 때 기준이 됨
3. Selectors는 무엇인가
Selectors는 Labels를 기준으로 원하는 객체를 골라내는 조건임.
즉, Labels가 붙어 있어야 Selectors가 동작할 수 있음.
예를 들어 다음과 같이 사용할 수 있음.
- class = mammal
- app = app1
- color = green
또는 여러 조건을 함께 사용할 수도 있음.
즉, Selectors는 단순히 객체를 보는 것이 아니라,
특정 조건에 맞는 객체만 선택하는 역할을 함.
4. 왜 Labels와 Selectors가 필요한가
Kubernetes에서는 다양한 객체를 생성하게 됨.
예를 들면 다음과 같음.
- Pod
- Service
- ReplicaSet
- Deployment
처음에는 객체 수가 적어서 직접 확인할 수 있지만, 시간이 지나면 클러스터 안에 수백 개, 수천 개의 객체가 생길 수 있음.
이때는 객체를 다음과 같은 기준으로 나눠서 봐야 함.
- 어떤 애플리케이션에 속하는지
- 어떤 기능을 담당하는지
- 어떤 종류의 객체인지
이런 구분을 위해 Labels와 Selectors를 사용함.
즉, Kubernetes에서 Labels와 Selectors는
객체를 체계적으로 관리하기 위한 핵심 수단임.
5. Kubernetes에서 Labels를 지정하는 위치
Kubernetes에서 Labels는 객체 정의 파일의 metadata 아래에 작성함.
예를 들어 Pod 정의 파일에서는 metadata.labels 아래에 label을 추가함.
형식은 key-value 방식임.
apiVersion: v1
kind: Pod
metadata:
name: simple-webapp
labels:
app: App1
function: Front-end
spec:
containers:
- name: simple-webapp
image: simple-webapp
ports:
- containerPort: 8080

여기에 원하는 만큼 label을 추가할 수 있음.
즉, Pod를 만들 때부터 어떤 그룹에 속하는지 미리 표시해두는 것임.
6. Labels로 Pod를 조회하는 방법
Pod가 생성된 후에는 label을 기준으로 Pod를 조회할 수 있음.
이때 kubectl get pods 명령어와 --selector 옵션을 함께 사용함.
예를 들어 다음과 같은 조건으로 조회할 수 있음.
$ kubectl get pods --selector app=App1
이렇게 하면 해당 label을 가진 Pod만 확인할 수 있음.
즉, label은 단순한 메모가 아니라
실제로 원하는 객체를 찾는 기준으로 사용됨.
7. ReplicaSet에서 Labels와 Selectors가 어떻게 연결되는가

7. 1 metadata.labels → ReplicaSet 객체 자신에게 붙는 라벨
metadata:
labels:
app: myapp
-> 즉 ReplicaSet 리소스를 분류할 때 의미가 있음.
kubectl get rs --selector app=myapp
7.2 spec.template.metadata.labels → ReplicaSet이 생성할 Pod들에 붙는 라벨
selector:
matchLabels:
app: myapp
"label이 app=myapp인 Pod를 내가 관리하겠다."
7.3 spec.selector → ReplicaSet이 어떤 Pod를 자기 관리 대상으로 볼지 고르는 조건
template:
metadata:
labels:
app: myapp
-> ReplicaSet이 Pod를 만들면, 그 Pod는 app=myapp label을 가지고 생성됨.
spec.selector.matchLabels와 spec.template.metadata.labels는 반드시 맞춰야 함
selector가 app=myapp인데,
template에서 생성되는 Pod label이 app=nginx라면 어떻게 되느냐?
ReplicaSet은 자기가 만든 Pod조차 자기 Pod로 인식하지 못할 수 있음!
metadata.labels는 달라도 ReplicaSet 동작에는 직접 문제 없음.
8. Service에서도 같은 방식이 사용됨
Service도 Labels와 Selectors를 이용해 Pod를 찾음.
동작 방식은 ReplicaSet과 거의 같음.
- Pod에 labels가 붙어 있음
- Service에 selector가 정의되어 있음
- Service가 selector와 일치하는 Pod를 찾음
- 그 Pod들로 트래픽을 전달함
즉, Service도 Pod 이름이나 IP를 직접 기준으로 연결하는 것이 아니라
label 기준으로 연결 대상 Pod를 선택함

9. Labels와 Selectors의 핵심 역할 정리
Kubernetes에서 Labels와 Selectors는 다음 두 가지 목적으로 사용됨.
9-1. 객체를 조회하고 필터링하기 위해
예를 들어 특정 앱에 속한 Pod만 보고 싶을 때 사용함.
9-2. Kubernetes 객체끼리 연결하기 위해
예를 들어 다음과 같은 연결에 사용됨.
- ReplicaSet → Pod 연결
- Service → Pod 연결
즉, Kubernetes에서 Labels와 Selectors는
관리용 기능이면서 동시에 객체 연결의 기준이기도 함.
10. Annotations는 Labels와 어떻게 다른가
Annotations는 Labels와 목적이 다름.
Labels와 Selectors는 객체를 그룹화하고 선택하기 위한 것임.
반면 Annotations는 객체에 부가 정보를 기록하기 위한 것임.
예를 들면 다음과 같은 정보를 넣을 수 있음.
- tool name
- version
- build information
- contact details
- phone numbers
- email IDs
즉, Annotations는 객체를 선택하는 기준이 아니라
참고용 정보나 통합용 정보를 저장하는 용도임.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: simple-webapp
labels:
app: App1
function: Front-end
annotations:
buildversion: 1.34
spec:
replicas: 3
selector:
matchLabels:
app: App1
template:
metadata:
labels:
app: App1
function: Front-end
spec:
containers:
- name: simple-webapp
image: simple-webapp
3. Taints and Tolerations
1. 목적
Taints와 Tolerations는 어떤 Pod가 어떤 Node에 스케줄될 수 있는지를 제한하는 기능임.
즉, 특정 Node에 아무 Pod나 올라가지 못하게 하고,
조건을 만족하는 Pod만 올라가게 할 때 사용함.
2. 어디에 설정하는가
2-1. Taint
Node에 설정함
2-2. Toleration
Pod에 설정함
즉, Node 쪽에는 “이런 Pod만 받을 수 있다”는 제한을 걸고,
Pod 쪽에는 “이 taint를 견딜 수 있다”는 설정을 넣는 구조임.
3. 핵심 동작
Node에 taint가 있으면,
그 taint를 toleration하지 못하는 Pod는 해당 Node에 스케줄되지 않음.
반대로 Pod에 해당 taint에 대한 toleration이 있으면,
그 Node에 스케줄될 수 있음.
중요한 점은 다음과 같음.
- Taint는 Node가 Pod를 거부하는 기준
- Toleration은 Pod가 그 거부 조건을 예외적으로 통과할 수 있게 하는 설정
4. Taint Effect 3가지
4-1. NoSchedule
해당 taint를 toleration하지 않는 Pod는
그 Node에 새로 스케줄되지 않음
4-2. PreferNoSchedule
가능하면 그 Node에 스케줄하지 않으려 하지만
강제는 아님
4-3. NoExecute
해당 taint를 toleration하지 않는 Pod는
- 새로 스케줄되지 않고
- 이미 그 Node에서 실행 중이던 Pod도 evict(제거) 됨

apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: nginx-container
image: nginx
tolerations:
- key: "app"
operator: "Equal"
value: "blue"
effect: "NoSchedule"

5. 반드시 기억할 핵심
Taints와 Tolerations는
Pod를 특정 Node로 보내는 기능이 아님
즉, 이것은
“이 Pod는 반드시 이 Node로 가야 한다”를 의미하지 않음.
정확히는 다음 의미임.
해당 Node는 특정 toleration이 있는 Pod만 받을 수 있다
따라서 특정 Pod를 특정 Node에 반드시 배치하고 싶다면
그건 Node Affinity로 해결해야 함.
6. Master Node 관련
Kubernetes 클러스터에서는 보통 Master Node에 기본 taint가 설정되어 있음.
그래서 일반 Pod는 Master Node에 스케줄되지 않음.
즉, Master Node에 워크로드가 올라가지 않는 이유 중 하나가
바로 이 taint 설정 때문임.
4. Node Selectors
1. 목적
Node Selector는 특정 Pod가 특정 Node에서만 실행되도록 제한하는 기능임.
예를 들어 클러스터에 3개의 Node가 있고,
- 2개는 리소스가 적은 작은 Node
- 1개는 리소스가 많은 큰 Node
라고 할 때,
리소스를 많이 사용하는 데이터 처리 workload는 큰 Node에서만 실행되게 하고 싶을 수 있음.
기본 설정에서는 어떤 Pod든 어떤 Node에나 배치될 수 있기 때문에,
원하는 Pod가 작은 Node에 배치될 수도 있음.
이 문제를 해결하기 위해 Pod가 특정 Node에서만 실행되도록 제한하는 방법이 필요함.
2. Pod를 특정 Node에 배치하는 방법
그 방법 중 하나로 Node Selector가 있음
Pod를 특정 Node에서만 실행되게 하려면,
Pod 정의 파일의 spec 아래에 nodeSelector를 추가하면 됨.
예를 들어 다음과 같이 설정할 수 있음.
- size: large
-> size=large 라는 label이 붙은 Node에만 이 Pod를 배치하라
3. Node Selector의 동작 방식
동작 흐름은 아래와 같음.
3-1. Node에 label을 붙임

$ kubectl label nodes <node-name> <label-key>=<label-value>
$ kubectl label nodes node-1 size=Large
3-2. Pod에 nodeSelector를 설정함

apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: data-processor
image: data-processor
nodeSelector:
size: Large
$ kubectl create -f pod-definition.yml
3-3. Scheduler가 label과 selector를 비교함
3-4. 일치하는 Node에 Pod를 배치함
즉 핵심은:
Pod의 nodeSelector와 Node의 label이 일치해야 한다는 것임.
4. Node Selector의 한계
Node Selector는 단순하고 쉬운 방법이지만,
복잡한 조건을 표현하는 데는 한계가 있음.
예를 들어 아래와 같은 조건은 Node Selector로 처리하기 어려움.
- large 또는 medium Node에 배치
- small이 아닌 모든 Node에 배치
즉 Node Selector는
단순한 key-value 일치 조건만 사용할 수 있음.
더 복잡한 조건이 필요하면 Node Selector만으로는 부족함.
이런 경우에는 Node Affinity / Anti-Affinity 기능을 사용해야 함.
즉:
- 간단한 조건 → Node Selector
- 복잡한 조건 → Node Affinity / Anti-Affinity
5. Node Affinity
1. 목적
Kubernetes에서는 기본적으로 Scheduler가 Pod를 적절한 Node에 알아서 배치함.
그런데 어떤 Pod는 아무 Node에나 가면 안 되는 경우가 있음.
예를 들어:
- Node 3개가 있음
- 그중 2개는 작은 Node
- 1개는 큰 Node
- 어떤 Pod는 리소스를 많이 쓰는 데이터 처리 Pod임
이 경우에는 그 Pod가 큰 Node에 가야 함.
작은 Node에 가면 성능이 부족하거나 리소스가 모자랄 수 있기 때문임.
이렇게 특정 Pod를 특정 조건의 Node에 배치하고 싶을 때 사용하는 기능이 Node Affinity임.
2. Node Selector와의 다른 점
- Node Selector = 단순한 조건
- Node Affinity = 더 복잡한 조건
Node Affinity는
Pod를 특정 label 조건을 만족하는 Node에 배치하도록 제어하는 기능임.
3. Node Affinity 동작 방식
Node Affinity는 Node 이름을 직접 보는 게 아니라,
Node에 붙어 있는 label을 기준으로 판단함.
예를 들어 Node에 이런 label이 있다고 하자.
- node1 → size=large
- node2 → size=medium
- node3 → label 없음
그럼 Pod는 Node Affinity 조건을 통해:
- large에만 가게 하거나
- large 또는 medium에 가게 하거나
- size label이 있는 Node에만 가게 할 수 있음
Pod의 affinity 조건과 Node의 label이 매칭되는가
4. Yaml 구조
apiVersion: v1
kind: Pod
metadata:
name: myapp-pod
spec:
containers:
- name: data-processor
image: data-processor
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values:
- Large
- Medium
어떤 Node를 원하는가 / 그 조건을 얼마나 강하게 적용할 것인가
| spec.affinity.nodeAffinity | Node Affinity 설정 위치 |
| requiredDuringSchedulingIgnoredDuringExecution | 조건 적용 방식 |
| nodeSelectorTerms / matchExpressions | Node 조건식 |
5. Node 조건 적용 방식
| 조건 | 의미 |
| required | 반드시 조건 만족, 조건 맞는 Node가 없으면 스케줄하지 않음 |
| prefered | 조건 맞는 Node가 있으면 우선 사용, 없으면 다른 Node 허용 |
| Ignored | 변경 무시 |
| 시점 | 의미 |
| DuringScheduling | Pod가 처음 생성되어 아직 어디에도 배치되지 않은 상태 |
| DuringExecution | Pod가 이미 Node에 배치되어 실행 중인 상태 |
| During Scheduling |
During Execution |
실제/계획 이름 | 의미 |
| Required | Ignored | requiredDuringScheduling IgnoredDuringExecution |
처음 배치할 때는 반드시 조건 만족, 배치 후에는 label 변경 무시 |
| Preferred | Ignored | preferredDuringScheduling IgnoredDuringExecution |
처음 배치할 때는 가능하면 조건 만족, 안 되면 다른 Node 허용, 배치 후에는 label 변경 무시 |
| Required | Required | requiredDuringScheduling RequiredDuringExecution |
처음 배치할 때는 반드시 조건 만족, 실행 중에도 계속 조건 유지 필요 |
| Preferred | Required | preferredDuringScheduling RequiredDuringExecution |
처음 배치할 때는 가능하면 조건 만족, 안 되면 다른 Node 허용, 실행 중에도 조건 유지 필요 |
IgnoredDuringExecution -> 배치 후 Node label이 바뀌어도 기존 Pod는 계속 실행됨
RequiredDuringExecution 은 현재 지원중이 아니고, K8s의 Plan임
6. Node 조건 구조
6-1 requiredDuringSecheduling
- nodeSelectorTerms : 어떤 Node를 선택할지 적는 조건들의 집합
- matchExpressions : matchExpressions 안에 들어 있는 조건들을 만족해야 함
단, 하나의 nodeSelectorTerm 안의 matchExpressions는 모두 만족해야 하고, 여러 nodeSelectorTerms 사이에서는 하나만 만족해도 됨
- 같은 matchExpressions 안 = AND
- 여러 nodeSelectorTerms 사이 = OR
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values:
- large
- matchExpressions:
- key: disk
operator: In
values:
- ssd
ㄴ> 이 경우는 같은 matchExpressions 안이므로, size=large, disk=ssd 를 둘 다 만족하는 Node여야 함.
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values: [large]
- matchExpressions:
- key: disk
operator: In
values: [ssd]
ㄴ> 이 경우는, size=large 이거나 disk=ssd 둘 중 하나만 만족해도 됨.
6-2 preferredDuringScheduling
- weight : 선호도 점수, 값이 클수록 그 조건을 더 선호하게 됨
- preference: 어떤 조건의 Node를 선호하는지
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: size
operator: In
values: [large]
- key: disk
operator: In
values: [ssd]
ㄴ> size=large / 그리고 disk=ssd를 둘 다 만족해야 이 preference를 만족한 것임.
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: size
operator: In
values: [large]
- weight: 1
preference:
matchExpressions:
- key: disk
operator: In
values: [ssd]
ㄴ> size=large 만족하면 1점 / disk=ssd 만족하면 1점
즉 Node는 둘 중 하나만 만족해도 점수를 얻음.
둘 다 만족하면 더 높은 점수를 얻음.
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
nodeSelectorTerms:
- matchExpressions:
- key: size
operator: In
values: [large]
- matchExpressions:
- key: disk
operator: In
values: [ssd]
ㄴ> nodeSelectorTerms 사이는 OR이므로, size=large 또는 disk=ssd 를 만족하면 이 preference를 만족함.
조건식은 보통 아래 3개로 구성됨.
| 요소 | 의미 |
| key | 어떤 Node label을 볼지 |
| operator | 어떻게 비교할지 |
| values | 어떤 값을 허용/제외할지 |
- key: size
operator: In
values:
- large
size=large 인 Node에 배치하라
자주 나오는 operator
| Operator | 의미 | 예시 |
| In | values 목록 안에 포함되면 허용 | - key: size operator: In values: - large - medimum -> size가 large 또는 medium인 Node 허용 |
| NotIn | values 목록 안에 포함되지 않아야 허용 | - key: size operator: NotIn values: - small -> size가 small이 아닌 Node 허용 |
| Exists | values 필요 없음 key에 해당하는 label이 존재하면 허용 |
- key: size operator: Exists -> size라는 label key가 존재하는 Node 허용 |
6. Taints and Tolerations vs Node Affinity
개념핵심 의미보장하는 것보장하지 못하는 것시험용 핵심 포인트
| 개념 | 핵심 의미 | 막는 대상 | 보장하는 것 | 보장하지 못하는 것 | 핵심 정리 |
| Taints / Tolerations | Node가 특정 Pod를 거부하도록 설정 | 다른 Pod가 우리 Node에 오는 것 | 특정 Pod만 Node에 들어오게 제한 | 우리 Pod가 반드시 그 Node에 가는 것 (다른 제한 없는 Node로 갈 수 있으므로) | |
| Node Affinity | Pod가 특정 Node를 선택하도록 설정 | 우리 Pod가 다른 Node로 가는 것 | 우리 Pod를 원하는 Node에 배치 | 다른 Pod가 우리 Node에 오는 것 | |
| Taints/Tolerations + Node Affinity |
둘을 함께 사용 | 다른 Pod 차단 + 우리 Pod를 원하는 Node에 배치 | 단독 사용 시 생기는 각 한계 보완 | 전용 Node 구성 시 같이 사용 |
| 기능 | 요약 |
| Taints / Tolerations | 남의 Pod를 내 Node에서 막는 기능 |
| Node Affinity | 내 Pod를 원하는 Node로 보내는 기능 |
| 같이 사용 | 특정 Pod 전용 Node를 만들 때 사용 |
7. Resource Requirements
1. 전체 구조
apiVersion: v1
kind: Pod
metadata:
name: resource-demo
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
- requests
- 최소 보장 자원
- Scheduler가 Pod를 Node에 배치할 때 참고하는 값
- limits
- 최대 사용 가능 자원
- 이 이상은 못 쓰게 제한하는 값
2. requests
resources:
requests:
cpu: "250m"
memory: "256Mi"
- requests = 최소 보장 + 스케줄링 기준
- CPU 250m, Memory 256Mi를 최소로 필요로 한다는 뜻
- 이 정도 자원이 남아 있는 Node에만 Pod가 배치됨
3. limits
resources:
limits:
cpu: "500m"
memory: "512Mi"
- limits = 최대 제한
- CPU는 최대 500m
- Memory는 최대 512Mi
4. CPU와 Memory limit 초과 시 차이
CPU
- limit를 넘으려고 하면 throttle
- 즉 더 못 쓰게 속도를 제한함
Memory
- limit를 계속 넘으려고 하면 OOMKilled
- 즉 Pod가 죽을 수 있음
5. requests만 쓰는 경우
apiVersion: v1
kind: Pod
metadata:
name: request-only-demo
spec:
containers:
- name: nginx
image: nginx
resources:
requests:
cpu: "250m"
memory: "256Mi"
- 최소 자원은 보장
- limit는 없으므로 남는 자원이 있으면 더 사용할 수 있음
- CPU 관점에서는 이런 구성이 유연할 수 있음
- 대신 모든 Pod에 request는 잡아두는 게 중요함
6. 아무것도 안 쓰는 경우
apiVersion: v1
kind: Pod
metadata:
name: no-resource-demo
spec:
containers:
- name: nginx
image: nginx
- request 없음
- limit 없음
- Kubernetes는 기본적으로 request/limit를 자동으로 넣어주지 않음
문제
- 특정 Pod가 Node 자원을 많이 먹을 수 있음
- 다른 Pod가 자원을 못 받을 수 있음
7. LimitRange
LimitRange는 Namespace 안에서 Pod/Container의 기본 request/limit, 최소값, 최대값을 정하는 객체임.
apiVersion: v1
kind: LimitRange
metadata:
name: cpu-resource-constraint
spec:
limits:
- type: Container
default:
cpu: "500m"
memory: "512Mi"
defaultRequest:
cpu: "250m"
memory: "256Mi"
max:
cpu: "1"
memory: "1Gi"
min:
cpu: "100m"
memory: "128Mi"
7.1 default
default:
cpu: "500m"
memory: "512Mi"
- Pod가 limit를 안 쓰면 자동으로 들어가는 기본 limit 값
7.2 defaultRequest
defaultRequest:
cpu: "250m"
memory: "256Mi"
- Pod가 request를 안 쓰면 자동으로 들어가는 기본 request 값
7.3 max
max:
cpu: "1"
memory: "1Gi"
- 컨테이너가 설정할 수 있는 최대 허용치
7.4 min
min:
cpu: "100m"
memory: "128Mi"
- 컨테이너가 요청할 수 있는 최소 허용치
요약
- default = 기본 limit
- defaultRequest = 기본 request
- max = 최대 허용치
- min = 최소 허용치
8. ResourceQuota
ResourceQuota는 Namespace 전체가 사용할 수 있는 총 자원량 제한임.
개별 Pod가 아니라 Namespace 전체 합계를 제한함.
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
spec:
hard:
requests.cpu: "4"
requests.memory: "4Gi"
limits.cpu: "10"
limits.memory: "10Gi"
이 Namespace 전체에서:
- 모든 Pod의 request CPU 합계는 4 이하
- 모든 Pod의 request Memory 합계는 4Gi 이하
- 모든 Pod의 limit CPU 합계는 10 이하
- 모든 Pod의 limit Memory 합계는 10Gi 이하
8. Daemonset
1. DaemonSet의 핵심 개념
DaemonSet은 클러스터의 각 Node마다 Pod 1개씩 자동으로 배포하는 객체임.
즉:
- Node가 3개면 Pod도 3개
- Node가 새로 추가되면 그 Node에도 Pod가 자동 생성됨
- Node가 삭제되면 그 Node의 Pod도 자동 제거됨
모든 Node에 반드시 하나씩 있어야 하는 Pod를 배포할 때 사용함
2. ReplicaSet / Deployment와 차이
ReplicaSet이나 Deployment는 원하는 개수만큼 Pod를 유지하는 개념임.
반면 DaemonSet은 Node 수에 맞춰 각 Node마다 1개씩 유지하는 개념임.
| 객체 | 기준 |
| ReplicaSet / Deployment | Pod 개수 기준 |
| DaemonSet | Node 개수 기준 |
3. 대표 사용 사례
DaemonSet은 모든 Node에 공통적으로 꼭 필요한 Pod를 배포할 때 사용함.
대표 예시는 아래 정도만 기억하면 됨.
3-1. Monitoring Agent : 각 Node의 상태를 수집하는 모니터링 에이전트
3-2. Log Collector : 각 Node의 로그를 수집하는 로그 수집기
3-3. kube-proxy: 각 Node에서 동작해야 하는 Kubernetes 네트워크 관련 컴포넌트
3-4. Networking Agent : 예: Calico 같은 CNI 에이전트
“모든 Node에 하나씩 떠야 하는 시스템성 Pod” = DaemonSet
4. DaemonSet YAML 구조
구조는 ReplicaSet과 매우 비슷함.
- apiVersion: apps/v1
- kind: DaemonSet
- metadata
- spec
- selector
- template
중요!!
- kind가 DaemonSet
- selector와 template.metadata.labels가 맞아야 함
기본 예시
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: monitoring-daemon
spec:
selector:
matchLabels:
app: monitoring-agent
template:
metadata:
labels:
app: monitoring-agent
spec:
containers:
- name: monitoring-agent
image: nginx
5. YAML에서 꼭 볼 부분
5-1. kind: DaemonSet
이 리소스가 DaemonSet이라는 뜻
5-2. selector.matchLabels
DaemonSet이 어떤 Pod를 자기 대상으로 볼지 결정
5-3. template.metadata.labels
실제로 생성될 Pod의 label
중요: selector.matchLabels와 template.metadata.labels는 일치해야 함
6. 생성 / 조회 명령어
생성
kubectl create -f daemonset.yaml
조회
kubectl get daemonset
또는 축약형으로:
kubectl get ds
상세 확인
kubectl describe daemonset <daemonset-name>
예:
kubectl describe daemonset monitoring-daemon
7. DaemonSet이 Pod를 각 Node에 배치하는 방식
예전 방식에서는 Pod spec에 nodeName을 직접 지정해서 Scheduler를 우회하는 방식이 사용되었음.
즉 Node마다 직접 Pod를 만들어서 해당 Node로 보내는 방식이었다고 볼 수 있음. (Kubernetes 1.12까지 사용되던 방식)
그 이후에는 기본 Scheduler와 이전 강의에서 배운 Node Affinity 규칙을 사용해서 DaemonSet Pod를 각 Node에 배치함.
- DaemonSet은 각 Node에 Pod 1개씩 배치함
- 새 Node가 생기면 자동으로 추가 배치됨
- Node가 사라지면 해당 Pod도 정리됨
'Infra > K8S' 카테고리의 다른 글
| [CKA 준비] Pod & Deployment 명령어 정리 (0) | 2026.04.18 |
|---|---|
| [CKA 준비] Core Concepts - 3 (0) | 2026.03.15 |
| [CKA 준비] - Core Concepts - 2 (0) | 2026.03.15 |
| [CKA 준비] Core Conecepts - 1 (4) | 2026.03.04 |
| KEDA 필요성, HPA 와의 차이점 (0) | 2026.01.18 |