Docker & Kubernetes 완전 정복 8편: Pod, Deployment, Service 완전 이해
Docker & Kubernetes Complete Guide Part 8: Understanding Pod, Deployment, and Service
서론: Kubernetes 핵심 리소스 마스터하기
Kubernetes를 효과적으로 활용하려면 세 가지 핵심 리소스를 완벽히 이해해야 합니다: Pod, Deployment, Service. 이 세 가지는 Kubernetes에서 애플리케이션을 배포하고 운영하는 데 가장 기본이 되는 빌딩 블록입니다. 이번 8편에서는 각 리소스의 개념, YAML 작성법, 그리고 실제 사용 패턴까지 상세히 알아보겠습니다.
1. Pod 상세 이해
Pod는 Kubernetes에서 배포 가능한 가장 작은 단위입니다. 하나 이상의 컨테이너를 포함하며, 같은 Pod 내의 컨테이너들은 네트워크와 스토리지를 공유합니다.
1.1 Pod의 특징
- 컨테이너 그룹: 하나의 Pod에 여러 컨테이너를 배치할 수 있음
- 공유 네트워크: 같은 Pod 내 컨테이너는 localhost로 통신
- 공유 스토리지: 볼륨을 통해 데이터 공유 가능
- 일시적 존재: Pod는 언제든 삭제되고 재생성될 수 있음
- 고유 IP: 각 Pod는 클러스터 내에서 고유한 IP 주소를 가짐
1.2 사이드카 패턴 (Sidecar Pattern)
사이드카 패턴은 메인 컨테이너를 보조하는 컨테이너를 함께 배치하는 패턴입니다. 로그 수집, 프록시, 설정 관리 등에 활용됩니다.
# sidecar-example.yaml
apiVersion: v1
kind: Pod
metadata:
name: web-with-sidecar
spec:
containers:
# 메인 애플리케이션 컨테이너
- name: web-app
image: nginx:1.25
ports:
- containerPort: 80
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
# 사이드카: 로그 수집
- name: log-collector
image: busybox
command: ['sh', '-c', 'tail -F /var/log/nginx/access.log']
volumeMounts:
- name: shared-logs
mountPath: /var/log/nginx
volumes:
- name: shared-logs
emptyDir: {}
1.3 Init Container
Init Container는 메인 컨테이너가 시작되기 전에 실행되는 초기화 컨테이너입니다. 데이터베이스 대기, 설정 파일 생성, 권한 설정 등에 사용됩니다.
# init-container-example.yaml
apiVersion: v1
kind: Pod
metadata:
name: app-with-init
spec:
initContainers:
# 첫 번째 Init Container: DB 대기
- name: wait-for-db
image: busybox
command: ['sh', '-c', 'until nc -z mysql-service 3306; do echo waiting for db; sleep 2; done']
# 두 번째 Init Container: 설정 파일 준비
- name: prepare-config
image: busybox
command: ['sh', '-c', 'cp /config-source/app.conf /config/app.conf']
volumeMounts:
- name: config-volume
mountPath: /config
- name: config-source
mountPath: /config-source
containers:
- name: main-app
image: my-app:latest
volumeMounts:
- name: config-volume
mountPath: /app/config
volumes:
- name: config-volume
emptyDir: {}
- name: config-source
configMap:
name: app-config
1.4 Pod YAML 작성
완전한 Pod YAML 예제를 살펴보겠습니다.
# complete-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-pod
labels:
app: web
environment: production
annotations:
description: "프로덕션 웹 서버"
spec:
# 재시작 정책
restartPolicy: Always # Always, OnFailure, Never
# 노드 선택
nodeSelector:
disktype: ssd
# 컨테이너 정의
containers:
- name: web
image: nginx:1.25
# 포트 설정
ports:
- name: http
containerPort: 80
protocol: TCP
# 리소스 제한
resources:
requests:
memory: "128Mi"
cpu: "250m"
limits:
memory: "256Mi"
cpu: "500m"
# 환경 변수
env:
- name: ENV_NAME
value: "production"
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secrets
key: password
# 헬스 체크
livenessProbe:
httpGet:
path: /healthz
port: 80
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: 80
initialDelaySeconds: 5
periodSeconds: 5
# 볼륨 마운트
volumeMounts:
- name: data-volume
mountPath: /data
volumes:
- name: data-volume
persistentVolumeClaim:
claimName: my-pvc
2. Deployment 완전 이해
Deployment는 Pod의 선언적 업데이트를 관리합니다. ReplicaSet을 통해 원하는 수의 Pod를 유지하고, 롤링 업데이트와 롤백 기능을 제공합니다.
2.1 Deployment와 ReplicaSet의 관계
Deployment는 ReplicaSet을 생성하고 관리합니다. ReplicaSet은 지정된 수의 Pod 복제본을 유지합니다.
- Deployment: 상위 레벨 추상화, 업데이트 전략 관리
- ReplicaSet: Pod 복제본 수 유지
- Pod: 실제 애플리케이션 실행
2.2 Deployment YAML 작성
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
spec:
# 복제본 수
replicas: 3
# 셀렉터 (어떤 Pod를 관리할지)
selector:
matchLabels:
app: web
# 업데이트 전략
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1 # 추가로 생성할 수 있는 Pod 수
maxUnavailable: 0 # 사용 불가능한 Pod 최대 수
# Pod 템플릿
template:
metadata:
labels:
app: web
version: v1
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "200m"
memory: "256Mi"
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 5
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 3
2.3 롤링 업데이트
롤링 업데이트는 점진적으로 새 버전의 Pod를 배포하면서 기존 Pod를 교체합니다.
# 이미지 업데이트 (롤링 업데이트 트리거)
kubectl set image deployment/web-deployment web=nginx:1.26
# 업데이트 상태 확인
kubectl rollout status deployment/web-deployment
# 업데이트 히스토리 확인
kubectl rollout history deployment/web-deployment
# 특정 리비전 상세 확인
kubectl rollout history deployment/web-deployment --revision=2
2.4 롤백
문제가 발생하면 이전 버전으로 쉽게 롤백할 수 있습니다.
# 이전 버전으로 롤백
kubectl rollout undo deployment/web-deployment
# 특정 리비전으로 롤백
kubectl rollout undo deployment/web-deployment --to-revision=2
# 롤백 후 상태 확인
kubectl rollout status deployment/web-deployment
3. 스케일링
Kubernetes는 수동 스케일링과 자동 스케일링(HPA)을 모두 지원합니다.
3.1 수동 스케일링
# 복제본 수 조정
kubectl scale deployment/web-deployment --replicas=5
# 현재 상태 확인
kubectl get deployment web-deployment
# YAML 수정을 통한 스케일링
kubectl edit deployment web-deployment
3.2 HPA (Horizontal Pod Autoscaler)
HPA는 CPU, 메모리 사용량 또는 커스텀 메트릭을 기반으로 자동으로 Pod 수를 조절합니다.
# hpa.yaml
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-deployment
minReplicas: 2
maxReplicas: 10
metrics:
# CPU 기반 스케일링
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
# 메모리 기반 스케일링
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80
# 스케일링 동작 세부 설정
behavior:
scaleDown:
stabilizationWindowSeconds: 300 # 스케일 다운 전 대기 시간
policies:
- type: Percent
value: 10
periodSeconds: 60
scaleUp:
stabilizationWindowSeconds: 0
policies:
- type: Percent
value: 100
periodSeconds: 15
- type: Pods
value: 4
periodSeconds: 15
selectPolicy: Max
# HPA 생성 (명령어)
kubectl autoscale deployment web-deployment --min=2 --max=10 --cpu-percent=70
# HPA 상태 확인
kubectl get hpa
# HPA 상세 정보
kubectl describe hpa web-hpa
4. Service 종류
Service는 Pod 집합에 대한 안정적인 네트워크 엔드포인트를 제공합니다. Pod의 IP는 변경될 수 있지만, Service의 IP는 고정됩니다.
4.1 ClusterIP (기본값)
클러스터 내부에서만 접근 가능한 가상 IP를 제공합니다.
# clusterip-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
type: ClusterIP # 기본값이므로 생략 가능
selector:
app: web
ports:
- name: http
protocol: TCP
port: 80 # 서비스 포트
targetPort: 80 # Pod 포트
사용 사례: 내부 마이크로서비스 간 통신, 데이터베이스 연결
4.2 NodePort
각 노드의 특정 포트를 통해 외부에서 접근할 수 있습니다.
# nodeport-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
selector:
app: web
ports:
- name: http
protocol: TCP
port: 80 # 서비스 포트
targetPort: 80 # Pod 포트
nodePort: 30080 # 노드 포트 (30000-32767)
사용 사례: 개발/테스트 환경, 로드밸런서 없이 외부 접근 필요 시
4.3 LoadBalancer
클라우드 제공업체의 로드밸런서를 통해 외부 IP를 할당받습니다.
# loadbalancer-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-loadbalancer
annotations:
# AWS 예시
service.beta.kubernetes.io/aws-load-balancer-type: nlb
spec:
type: LoadBalancer
selector:
app: web
ports:
- name: http
protocol: TCP
port: 80
targetPort: 80
- name: https
protocol: TCP
port: 443
targetPort: 443
사용 사례: 프로덕션 환경의 외부 서비스 노출
4.4 ExternalName
외부 서비스에 대한 DNS CNAME을 제공합니다.
# externalname-service.yaml
apiVersion: v1
kind: Service
metadata:
name: external-db
spec:
type: ExternalName
externalName: db.example.com
사용 사례: 외부 데이터베이스, 외부 API 서비스 연결
4.5 Service YAML 종합 예제
# complete-service.yaml
apiVersion: v1
kind: Service
metadata:
name: web-service
labels:
app: web
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "80"
spec:
type: ClusterIP
selector:
app: web
environment: production
ports:
- name: http
protocol: TCP
port: 80
targetPort: http # Pod의 포트 이름 참조
- name: https
protocol: TCP
port: 443
targetPort: https
# 세션 어피니티 (같은 클라이언트는 같은 Pod로)
sessionAffinity: ClientIP
sessionAffinityConfig:
clientIP:
timeoutSeconds: 3600
5. 레이블과 셀렉터
레이블과 셀렉터는 Kubernetes 리소스를 조직화하고 연결하는 핵심 메커니즘입니다.
5.1 레이블 (Labels)
레이블은 리소스에 부착하는 키-값 쌍입니다.
# 레이블 예시
metadata:
labels:
app: web
environment: production
version: v1.0.0
team: backend
tier: frontend
# 레이블로 리소스 조회
kubectl get pods -l app=web
kubectl get pods -l 'environment in (production, staging)'
kubectl get pods -l app=web,environment=production
# 레이블 추가/수정
kubectl label pods my-pod new-label=new-value
# 레이블 삭제
kubectl label pods my-pod new-label-
# 모든 레이블 표시
kubectl get pods --show-labels
5.2 셀렉터 (Selectors)
셀렉터는 레이블을 기반으로 리소스를 선택합니다.
# 등호 기반 셀렉터 (Equality-based)
selector:
matchLabels:
app: web
environment: production
# 집합 기반 셀렉터 (Set-based)
selector:
matchLabels:
app: web
matchExpressions:
- key: environment
operator: In
values:
- production
- staging
- key: version
operator: NotIn
values:
- v1.0.0
- key: team
operator: Exists
5.3 레이블과 셀렉터 활용 예제
# 완전한 배포 예제
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
labels:
app: web
environment: production
spec:
replicas: 3
selector:
matchLabels:
app: web
environment: production
template:
metadata:
labels:
app: web
environment: production
version: v2.0.0
spec:
containers:
- name: web
image: nginx:1.25
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app: web
environment: production
ports:
- port: 80
targetPort: 80
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: web-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: web-deployment
minReplicas: 2
maxReplicas: 10
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
6. 실전 명령어 정리
6.1 Pod 관련
# Pod 조회
kubectl get pods
kubectl get pods -o wide
kubectl get pods -w # 실시간 감시
# Pod 상세 정보
kubectl describe pod my-pod
# Pod 로그 확인
kubectl logs my-pod
kubectl logs my-pod -c container-name # 특정 컨테이너
kubectl logs my-pod -f # 실시간 로그
kubectl logs my-pod --previous # 이전 컨테이너 로그
# Pod 내부 접속
kubectl exec -it my-pod -- /bin/bash
kubectl exec -it my-pod -c container-name -- /bin/sh
# Pod 삭제
kubectl delete pod my-pod
kubectl delete pod my-pod --grace-period=0 --force # 강제 삭제
6.2 Deployment 관련
# Deployment 관리
kubectl create deployment nginx --image=nginx
kubectl get deployments
kubectl describe deployment my-deployment
# 업데이트 및 롤백
kubectl set image deployment/my-deployment container=image:tag
kubectl rollout status deployment/my-deployment
kubectl rollout history deployment/my-deployment
kubectl rollout undo deployment/my-deployment
# 스케일링
kubectl scale deployment/my-deployment --replicas=5
# 일시 중지/재개
kubectl rollout pause deployment/my-deployment
kubectl rollout resume deployment/my-deployment
6.3 Service 관련
# Service 관리
kubectl expose deployment my-deployment --port=80 --type=ClusterIP
kubectl get services
kubectl describe service my-service
# 서비스 엔드포인트 확인
kubectl get endpoints my-service
# 포트 포워딩 (로컬 테스트용)
kubectl port-forward service/my-service 8080:80
결론
이번 8편에서는 Kubernetes의 핵심 리소스인 Pod, Deployment, Service에 대해 깊이 있게 살펴보았습니다. Pod는 컨테이너 그룹의 기본 단위이며 사이드카 패턴과 Init Container를 통해 다양한 패턴을 구현할 수 있습니다. Deployment는 Pod의 선언적 관리와 롤링 업데이트, 롤백 기능을 제공하며, HPA를 통해 자동 스케일링도 가능합니다. Service는 Pod에 대한 안정적인 네트워크 접근을 제공하며, 용도에 따라 ClusterIP, NodePort, LoadBalancer 등을 선택할 수 있습니다.
레이블과 셀렉터를 활용하면 이러한 리소스들을 유연하게 연결하고 관리할 수 있습니다. 다음 편에서는 ConfigMap, Secret, Volume 등 데이터와 설정 관리에 대해 알아보겠습니다.