쿠버네티스 (Kubernetes) 주요 용어 파드(Pod)
Kubernetes(K8s)는 컨테이너 오케스트레이션의 표준으로 자리 잡았으며, 그 중심에는 Pod라는 개념이 있습니다. Pod는 K8s의 최소 배포 단위이자 핵심 구성 요소로, 컨테이너 기반 애플리케이션의 배포 및 관리를 효율적으로 수행하는 데 중요한 역할을 합니다. 이번 글에서는 Pod의 구조, 동작 방식, 최적화 및 실무적 활용 방안에 대해 설명하도록 하겠습니다.
1. Pod의 구조와 동작 원리
1.1 Pod의 정의
Pod는 하나 이상의 컨테이너와 이를 지원하는 네트워크 및 스토리지 리소스를 포함하는 논리적 호스트입니다. 동일한 Pod 내 컨테이너는 다음과 같은 특징을 공유합니다:
- 네트워크 네임스페이스: 모든 컨테이너가 동일한 IP 주소와 포트를 공유합니다.
- 스토리지 볼륨: Pod 수준에서 정의된 볼륨을 모든 컨테이너가 함께 사용합니다.
- 라이프사이클: Pod 내 모든 컨테이너는 동일한 라이프사이클을 가집니다.
1.2 Pod 생성과 관리
Pod는 YAML 또는 JSON 파일을 통해 정의되며, K8s API 서버에 의해 관리됩니다. 기본 구조는 다음과 같습니다:
apiVersion: v1
kind: Pod
metadata:
name: example-pod
labels:
app: example
spec:
containers:
- name: example-container
image: nginx:latest
ports:
- containerPort: 80
K8s 스케줄러는 Pod를 클러스터 내 적합한 노드에 배치하며, kubelet은 해당 노드에서 Pod를 실행하고 상태를 지속적으로 모니터링합니다.
2. Pod 설계의 모범 사례
2.1 단일 책임 원칙(Single Responsibility Principle)
Pod는 일반적으로 하나의 주요 기능을 수행하는 컨테이너를 포함해야 합니다. 그러나 간단한 사이드카 패턴(Sidecar Pattern)을 통해 로그 수집, 데이터 동기화 등의 보조 작업을 수행할 수 있습니다.
2.2 리소스 요청과 제한 설정
Pod는 CPU와 메모리 리소스에 대한 요청(request)과 제한(limit)을 정의하여 안정성과 공정성을 보장해야 합니다. 이를 설정하지 않으면 노드 과부하로 인해 서비스 장애가 발생할 수 있습니다.
resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "512Mi"
cpu: "1"
2.3 Liveness 및 Readiness Probe 활용
Pod의 상태를 지속적으로 확인하여 장애를 조기에 탐지하고, 서비스 트래픽을 관리할 수 있습니다.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 3
periodSeconds: 5
readinessProbe:
httpGet:
path: /readiness
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
3. 고급 Pod 관리 기법
3.1 Auto-scaling
Pod를 효율적으로 확장하려면 Horizontal Pod Autoscaler(HPA)를 사용해야 합니다. HPA는 CPU 및 메모리 사용량을 기준으로 자동으로 Pod 수를 조정합니다.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: example-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: example-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 80
3.2 Pod Disruption Budget(PDB)
Pod의 가용성을 보장하면서도 업그레이드와 같은 작업이 가능하도록 Pod Disruption Budget을 설정할 수 있습니다.
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: example-pdb
spec:
minAvailable: 2
selector:
matchLabels:
app: example
4. 실무에서의 Pod 문제 해결
4.1 CrashLoopBackOff 디버깅
Pod가 지속적으로 재시작된다면 다음 명령을 통해 원인을 분석할 수 있습니다:
kubectl describe pod <pod-name>
kubectl logs <pod-name> -c <container-name>
4.2 네트워크 문제 확인
Pod 간 네트워크 통신 문제는 다음 명령으로 확인 가능합니다:
kubectl exec -it <pod-name> -- ping <target-pod-ip>
4.3 리소스 부족 문제 해결
노드 리소스가 부족하다면 Node Autoscaler를 사용하거나, Pod 우선순위(Priority)를 설정할 수 있습니다.
결론
Kubernetes에서 Pod는 단순한 컨테이너 집합 이상의 의미를 지닙니다. 이를 이해하고 최적화함으로써 클러스터의 안정성과 확장성을 극대화할 수 있습니다. 전문가로서 Pod의 동작 원리와 다양한 설정을 깊이 이해하고 활용하면, 효율적이고 신뢰성 높은 컨테이너 기반 애플리케이션을 운영할 수 있을 것입니다.
5. Init Container
Init Container는 메인 컨테이너 실행 전에 순서대로 완료되어야 하는 초기화 전용 컨테이너입니다.
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
- name: wait-for-config
image: busybox:1.35
command: ['sh', '-c', 'until wget -qO- http://config-server/health; do sleep 2; done']
- name: db-migrate
image: my-app:latest
command: ['python', 'manage.py', 'migrate']
envFrom:
- secretRef:
name: db-secret
containers:
- name: app
image: my-app:latest
ports:
- containerPort: 8080
| 특성 | Init Container | 메인 Container |
|---|---|---|
| 실행 순서 | 순차 실행 | 병렬 실행 |
| 성공 조건 | 0으로 종료 필수 | 지속 실행 |
| Probe 지원 | 없음 | Liveness/Readiness 지원 |
| 목적 | 초기화, 준비 대기 | 애플리케이션 실행 |
6. QoS 클래스 (Quality of Service)
쿠버네티스는 메모리 부족 시 어떤 파드를 먼저 종료할지 결정하기 위해 QoS 클래스를 부여합니다.
| QoS 클래스 | 조건 | OOM Kill 우선순위 |
|---|---|---|
| Guaranteed | requests = limits (모든 컨테이너) | 최하 (마지막 종료) |
| Burstable | requests < limits | 중간 |
| BestEffort | requests/limits 미설정 | 최우선 종료 |
# Guaranteed QoS 예시 (requests == limits)
apiVersion: v1
kind: Pod
metadata:
name: guaranteed-pod
spec:
containers:
- name: app
image: nginx
resources:
requests:
memory: "256Mi"
cpu: "500m"
limits:
memory: "256Mi" # requests와 동일
cpu: "500m" # requests와 동일
# 파드의 QoS 클래스 확인
kubectl get pod my-pod -o jsonpath='{.status.qosClass}'
7. Security Context
Security Context는 파드 또는 컨테이너의 보안 설정을 정의합니다. 최소 권한 원칙(Principle of Least Privilege)을 적용하여 컨테이너 보안을 강화합니다.
apiVersion: v1
kind: Pod
metadata:
name: secure-pod
spec:
securityContext: # Pod 수준 보안 설정
runAsNonRoot: true # root 실행 금지
runAsUser: 1000 # UID 1000으로 실행
runAsGroup: 3000 # GID 3000으로 실행
fsGroup: 2000 # 볼륨 파일 그룹 ID
seccompProfile:
type: RuntimeDefault # 기본 Seccomp 프로파일 적용
containers:
- name: app
image: nginx:alpine
securityContext: # 컨테이너 수준 보안 설정
allowPrivilegeEscalation: false # 권한 상승 금지
readOnlyRootFilesystem: true # 루트 파일시스템 읽기 전용
capabilities:
drop:
- ALL # 모든 Linux Capability 제거
add:
- NET_BIND_SERVICE # 필요한 것만 추가 (80 포트 바인딩)
volumeMounts:
- name: tmp-dir
mountPath: /tmp # 쓰기 필요한 경로는 별도 볼륨으로
volumes:
- name: tmp-dir
emptyDir: {}
주요 Security Context 옵션
| 옵션 | 설명 | 권장값 |
|---|---|---|
runAsNonRoot |
root 실행 금지 | true |
readOnlyRootFilesystem |
파일시스템 읽기 전용 | true |
allowPrivilegeEscalation |
권한 상승 금지 | false |
capabilities.drop: ALL |
모든 Capability 제거 | 적용 권장 |
seccompProfile |
시스템 콜 제한 | RuntimeDefault |
댓글남기기