오늘도 한 걸음씩 GitHub

Kubenetes

Kubernetes (5)

YongE 2025. 4. 15. 14:31

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).
  • requiredDuringSchedulingRequiredDuringExecution: 규칙에 부합하지 않는 노드에서 실행 중인 파드를 퇴출 혹은 종료시킬 수 있다.

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(용인)은 노드가 특정 파드를 거부하도록 하는 메커니즘이다.

  1. Taints: 노드에 설정되어 특정 파드가 스케줄링되지 않도록 한다.
kubectl taint nodes node1 key=value:NoSchedule
  1. 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은 파드가 노드를 피하게 하는 역할을 한다.

노드와 파드에 완전한 조건을 추가하고 싶다면, 다시 말해 특정 노드에 특정 파드만 배치하고 타 파드는 절대 접근하지 못하도록 하고 싶다면 Node Affinity와 Tains And Tolerations를 병용하는 방식을 채택할 수 있다.

반응형

'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