Pod
파드 라이프사이클
쿠버네티스에서 파드(Pod)는 애플리케이션의 기본 실행 단위로, 생성부터 종료까지 정의된 라이프사이클을 따른다. 파드는 컨테이너 그룹을 표현하는 추상적인 개념이며, 쿠버네티스 클러스터에서 실행되는 프로세스를 나타낸다.
파드의 상태와 단계
+----------+
| Pending |
+----------+
|
v
+----------+
| Running |
+----------+
/ \
v v
+----------+ +----------+
|Succeeded| | Failed |
+----------+ +----------+
|
v
+----------+
| Unknown |
+----------+
파드는 생명주기 동안 다양한 단계(Phase)를 거치며, 이는 파드의 전체 상태를 대표하는 속성이다.
- Pending: 파드가 쿠버네티스 클러스터에서 승인되었지만, 하나 이상의 컨테이너가 실행 준비가 되지 않은 상태이다. 이 단계에서는 다음과 같은 작업이 진행된다.
- 노드 스케줄링 대기
- 컨테이너 이미지 다운로드
- InitContainers 실행: 메인 컨테이너 시작 전에 초기화 작업 수행
apiVersion: v1
kind: Pod
metadata:
name: init-pod-example
spec:
initContainers:
- name: init-myservice
image: busybox:1.28
command: ['sh', '-c', 'until nslookup myservice; do echo waiting for myservice; sleep 2; done;']
containers:
- name: myapp-container
image: nginx
- Running: 파드가 노드에 바인딩되고, 모든 컨테이너가 생성된 상태이다. 적어도 하나의 컨테이너가 실행 중이거나 시작/재시작 중인 상태이다. 이 단계에서 확인할 수 있는 부가 속성은 다음과 같다.
- containerReady: 컨테이너가 준비된 상태인지 여부
- ready: 파드가 서비스 요청을 처리할 준비가 되었는지 여부
- Succeeded: 파드 내 모든 컨테이너가 성공적으로 종료된 상태이며, 재시작되지 않는다. 주로 Job이나 CronJob과 같은 일회성 작업에서 볼 수 있다.
- Failed: 파드 내 하나 이상의 컨테이너가 실패로 종료된 상태이다. 컨테이너가 비정상 종료 코드로 종료되거나 시스템에 의해 종료된 경우이다.
- Unknown: 파드의 상태를 확인할 수 없는 상태이다. 일반적으로 파드가 위치한 노드와의 통신 문제로 발생한다.
Phase | 주요 조건(Conditions) | 컨테이너 상태(ContainerStatus) | 주요 Reason | 설명 |
---|---|---|---|---|
Pending | Initialized | Waiting | ContainersNotReady | 이미지 다운로드, 초기화 등 |
Running | Ready, ContainersReady | Running | - | 서비스 중 |
Succeeded | - | Terminated | PodCompleted | 작업 완료 |
Failed | - | Terminated | Error | 에러 발생 |
Unknown | - | - | NodeLost | 통신 장애 |
파드 상태 세부 속성
파드 상태는 여러 세부 속성을 통해 더 자세히 파악할 수 있다.
- Conditions: 파드가 현재 어떤 상태에 있는지 보여주는 속성이다. 다음과 같은 조건들이 있다.
- Initialized: 모든 초기화 컨테이너가 성공적으로 완료되었는지 여부
- ContainersReady: 파드 내 모든 컨테이너가 준비 상태인지 여부
- PodScheduled: 파드가 노드에 스케줄되었는지 여부
- Ready: 파드가 요청을 처리할 수 있고 서비스의 로드밸런싱 풀에 추가될 수 있는지 여부
kubectl describe pod my-pod | grep Conditions -A5
- containerStatuses: 파드 내 각 컨테이너의 상세 상태 정보를 제공한다.
- Waiting: 컨테이너가 아직 실행되지 않은 상태 (이미지 다운로드, 초기화 등)
- Running: 컨테이너가 문제없이 실행 중인 상태
- Terminated: 컨테이너가 실행을 완료했거나 실패한 상태
kubectl get pod my-pod -o jsonpath='{.status.containerStatuses[*].state}'
컨테이너 프로브(Probe)
+------------------+
| Startup Probe |
+------------------+
|
v
+------------------+
| Liveness Probe |
+------------------+
|
v
+------------------+
| Readiness Probe |
+------------------+
쿠버네티스에서는 컨테이너의 상태를 주기적으로 진단하기 위해 프로브(Probe)라는 메커니즘을 제공한다. 프로브는 kubelet이 컨테이너에 대해 주기적으로 수행하는 진단으로, 애플리케이션의 안정성을 보장하는 데 중요한 역할을 한다.
Liveness Probe
LivenessProbe는 컨테이너가 살아있는지(동작 중인지) 확인한다. 만약 이 프로브가 실패하면, kubelet은 컨테이너를 종료하고 재시작 정책에 따라 재시작한다.
apiVersion: v1
kind: Pod
metadata:
name: liveness-example
spec:
containers:
- name: liveness-container
image: busybox
args:
- /bin/sh
- -c
- touch /tmp/healthy; sleep 30; rm -f /tmp/healthy; sleep 600
livenessProbe:
exec:
command:
- cat
- /tmp/healthy
initialDelaySeconds: 5
periodSeconds: 5
Liveness Probe는 다음과 같은 상황에서 유용하다:
- 애플리케이션이 실행 중이지만 프로세스가 교착 상태(deadlock)에 빠진 경우
- 메모리 누수나 기타 버그로 인해 애플리케이션이 응답하지 않는 경우
Readiness Probe
ReadinessProbe는 컨테이너가 요청을 처리할 준비가 되었는지 확인한다. 이 프로브가 성공하면 서비스는 해당 파드로 트래픽을 전송할 수 있다. 실패하면 엔드포인트 컨트롤러는 서비스의 엔드포인트에서 파드의 IP 주소를 제거한다.
apiVersion: v1
kind: Pod
metadata:
name: readiness-example
spec:
containers:
- name: readiness-container
image: nginx
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
Readiness Probe는 다음과 같은 상황에서 유용하다:
- 외부 서비스에 의존하는 애플리케이션이 시작 시 연결을 준비하는 경우
- 대용량 데이터를 로드해야 하는 애플리케이션의 초기화 시간이 필요한 경우
Startup Probe
StartupProbe는 컨테이너 내의 애플리케이션이 시작되었는지 확인한다. Startup Probe가 제공되면, 이 프로브가 성공할 때까지 다른 프로브는 활성화되지 않는다.
apiVersion: v1
kind: Pod
metadata:
name: startup-example
spec:
containers:
- name: startup-container
image: myapp
startupProbe:
httpGet:
path: /healthz
port: 8080
failureThreshold: 30
periodSeconds: 10
Startup Probe는 다음과 같은 상황에서 유용하다:
- 시작 시간이 긴 애플리케이션(예: 자바 애플리케이션)
- 가변적인 초기화 시간을 가진 레거시 애플리케이션
Probe 종류 | 목적 | 동작 시점 | 실패 시 동작 |
---|---|---|---|
Startup Probe | 앱이 완전히 시작됐는지 확인 | 컨테이너 시작 직후 | Liveness/Readiness 대기 |
Liveness Probe | 앱이 살아있는지(죽었는지) 확인 | 주기적으로 | 컨테이너 재시작 |
Readiness Probe | 앱이 서비스 요청 받을 준비 됐는지 확인 | 주기적으로 | 트래픽 전달 중단 |
QoS(Quality of Service) 클래스
+-------------+ +-------------+ +-------------+
| Guaranteed | --> | Burstable | --> | BestEffort |
+-------------+ +-------------+ +-------------+
(가장 늦게 종료) (중간) (가장 먼저 종료)
쿠버네티스는 노드의 자원이 부족할 때 어떤 파드가 먼저 종료될지 결정하기 위해 QoS 클래스를 사용한다. 이는 자원 경합 상황에서 중요한 서비스의 안정성을 보장하는 데 도움이 된다.
Guaranteed
Guaranteed 클래스는 가장 높은 우선순위를 가지며, 노드 자원이 부족할 때 마지막으로 종료된다.
할당 조건:
- 파드 내 모든 컨테이너가 CPU와 메모리에 대한 requests와 limits를 지정해야 한다.
- 각 컨테이너의 CPU requests와 limits가 동일해야 한다.
- 각 컨테이너의 메모리 requests와 limits가 동일해야 한다.
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: guaranteed-container
image: nginx
resources:
limits:
memory: "200Mi"
cpu: "700m"
requests:
memory: "200Mi"
cpu: "700m"
Burstable
Burstable 클래스는 중간 우선순위를 가지며, BestEffort 클래스의 파드가 모두 종료된 후에 종료된다.
할당 조건:
- Guaranteed 클래스의 조건을 충족하지 않는다.
- 파드 내 적어도 하나의 컨테이너가 CPU 또는 메모리에 대한 requests나 limits를 지정해야 한다.
apiVersion: v1
kind: Pod
metadata:
name: burstable-pod
spec:
containers:
- name: burstable-container
image: nginx
resources:
limits:
memory: "200Mi"
requests:
memory: "100Mi"
BestEffort
BestEffort 클래스는 가장 낮은 우선순위를 가지며, 노드 자원이 부족할 때 가장 먼저 종료된다.
할당 조건:
- 파드 내 모든 컨테이너가 CPU와 메모리에 대한 requests나 limits를 지정하지 않아야 한다.
apiVersion: v1
kind: Pod
metadata:
name: besteffort-pod
spec:
containers:
- name: besteffort-container
image: nginx
# 자원 요청/제한이 지정되지 않음
OOM 스코어와 QoS
쿠버네티스는 리눅스 커널의 OOM(Out Of Memory) 킬러 메커니즘을 활용하여 자원 부족 시 어떤 프로세스를 종료할지 결정한다. 각 QoS 클래스는 다음과 같은 OOM 스코어를 가진다:
QoS | 설명 | 종료 우선순위 | OOM Score |
---|---|---|---|
Guaranteed | 모든 컨테이너가 동일한 requests/limits 지정 | 가장 늦게 종료 | -998 |
Burstable | 일부 컨테이너만 requests/limits 지정 | 중간 | 2~999 |
BestEffort | 자원 요청/제한 없음 | 가장 먼저 종료 | 1000 |
파드 스케줄링
쿠버네티스에서는 파드를 특정 노드에 배치하기 위한 다양한 스케줄링 메커니즘을 제공한다. 이를 통해 워크로드를 클러스터 내에서 효율적으로 분배할 수 있다.
정책 유형 | 설명 | 예시/용도 |
---|---|---|
Node Affinity | 특정 노드(라벨)에만 파드 배치 | SSD 노드, 특정 리전 등 |
Pod Affinity | 특정 파드와 같은 노드에 배치 | 웹-캐시 서버 등 지연 최소화 |
Pod Anti-Affinity | 특정 파드와 다른 노드에 배치 | 고가용성, 복제본 분산 |
Taints | 노드에 얼룩 부여(파드 거부) | GPU 노드, 마스터 노드 보호 |
Tolerations | 파드가 얼룩 허용(특정 노드에만 배치 가능) | GPU 워크로드, 유지보수 노드 등 |
Node Affinity
Node Affinity는 파드가 특정 노드 집합에서 실행되도록 제한하는 규칙을 제공한다. 노드 셀렉터보다 더 표현적인 구문을 사용한다.
apiVersion: v1
kind: Pod
metadata:
name: node-affinity-pod
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/e2e-az-name
operator: In
values:
- e2e-az1
- e2e-az2
Node Affinity 유형:
- requiredDuringSchedulingIgnoredDuringExecution: 반드시 규칙을 충족해야만 스케줄링된다(Hard).
- preferredDuringSchedulingIgnoredDuringExecution: 가능하면 규칙을 충족하는 노드에 스케줄링하지만, 없으면 다른 노드에도 스케줄링된다(Soft).
Pod Affinity 및 Anti-Affinity
Pod Affinity는 파드가 다른 파드와의 관계를 기반으로 스케줄링되도록 한다.
apiVersion: v1
kind: Pod
metadata:
name: pod-affinity-example
spec:
affinity:
podAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- web-store
topologyKey: "kubernetes.io/hostname"
- Pod Affinity: 특정 라벨을 가진 파드와 같은 노드 또는 토폴로지 도메인에 스케줄링되도록 한다.
- Pod Anti-Affinity: 특정 라벨을 가진 파드와 다른 노드 또는 토폴로지 도메인에 스케줄링되도록 한다.
apiVersion: v1
kind: Pod
metadata:
name: pod-anti-affinity-example
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- database
topologyKey: "kubernetes.io/hostname"
Pod Affinity와 Anti-Affinity의 사용 사례:
- 웹 서버와 캐시 서버를 같은 노드에 배치하여 지연 시간 감소 (Affinity)
- 고가용성을 위해 동일한 서비스의 복제본을 다른 노드에 분산 (Anti-Affinity)
- 동일한 서비스 인스턴스를 동일한 가용성 영역 또는 랙에 배치 (Affinity)
Taints와 Tolerations
Taints(얼룩)와 Tolerations(용인)은 노드가 특정 파드를 거부하도록 하는 메커니즘이다.
- Taints: 노드에 설정되어 특정 파드가 스케줄링되지 않도록 한다.
kubectl taint nodes node1 key=value:NoSchedule
- Tolerations: 파드에 설정되어 특정 Taints를 가진 노드에도 스케줄링될 수 있도록 한다.
apiVersion: v1
kind: Pod
metadata:
name: toleration-pod
spec:
tolerations:
- key: "key"
operator: "Equal"
value: "value"
effect: "NoSchedule"
containers:
- name: main-container
image: nginx
Taint 효과:
- NoSchedule: 해당 Taint를 용인하지 않는 파드는 노드에 스케줄링되지 않는다.
- PreferNoSchedule: 가능하면 해당 Taint를 용인하지 않는 파드를 스케줄링하지 않지만, 필요하면 스케줄링할 수 있다.
- NoExecute: 해당 Taint를 용인하지 않는 파드는 노드에 스케줄링되지 않으며, 이미 실행 중인 파드도 제거된다.
Taints와 Tolerations의 주요 사용 사례:
- 특정 하드웨어에만 실행되어야 하는 워크로드 분리 (예: GPU 노드)
- 마스터 노드에 일반 워크로드가 스케줄링되지 않도록 제한
- 노드 유지보수 작업 중 파드 퇴거 제어
- 특정 사용자 또는 팀에 전용 노드 제공
# 노드 유지보수를 위한 Taint 설정
kubectl taint nodes node1 node-role.kubernetes.io/maintenance:NoSchedule
# 특정 워크로드만 실행할 수 있는 Taint 설정
kubectl taint nodes node2 dedicated=special-workload:NoSchedule
Taints와 Tolerations은 Node Affinity와 함께 사용하면 더 세밀한 스케줄링 제어가 가능하다. Node Affinity는 파드가 특정 노드에 끌리게 하는 반면, Taints와 Tolerations은 파드가 노드를 피하게 하는 역할을 한다.
'Tech > Kubenetes' 카테고리의 다른 글
Kubernetes (7) (0) | 2025.04.17 |
---|---|
Kubernetes (6) (0) | 2025.04.16 |
Kubernetes (4) (0) | 2025.04.14 |
Kubernetes (3) (0) | 2025.04.11 |
Kubernetes (2) (0) | 2025.04.10 |