Kubernetes 입문: Pod, Service, Deployment 핵심 이해
Kubernetes의 기본 구성 요소인 Pod, Service, Deployment를 심층 분석합니다. 컨테이너 오케스트레이션의 필요성부터 각 컴포넌트의 역할, YAML 설정 예시, CLI 명령어까지 DevOps 엔지니어링 관점에서 자세히 설명합니다.
Kubernetes 입문: Pod, Service, Deployment 핵심 이해
현대 소프트웨어 개발에서 애플리케이션은 점점 더 복잡해지고 있으며, 이를 안정적이고 효율적으로 배포하고 관리하는 것은 매우 중요한 과제가 되었습니다. 특히 마이크로서비스 아키텍처와 컨테이너 기술의 확산은 이러한 복잡성을 더욱 가중시켰고, 이를 해결하기 위한 강력한 도구가 바로 Kubernetes입니다. 이 글에서는 Kubernetes의 핵심 구성 요소인 Pod, Service, Deployment에 대해 DevOps 엔지니어링 관점에서 깊이 있게 다루며, 실제 CLI 명령어와 설정 파일 예시를 통해 그 작동 원리를 명확하게 이해할 수 있도록 돕겠습니다.
왜 Kubernetes인가? 컨테이너 오케스트레이션의 필요성
Docker와 같은 컨테이너 기술은 애플리케이션과 그 종속성을 격리하여 어떤 환경에서든 일관된 실행을 보장하는 혁신적인 방법을 제공했습니다. 개발자는 더 이상 운영체제나 라이브러리 버전에 대한 걱정 없이 애플리케이션을 패키징하고 배포할 수 있게 되었습니다. 하지만 수십, 수백 개의 컨테이너를 수동으로 관리하는 것은 비효율적이며 오류 발생 가능성이 높습니다.
여기서 컨테이너 오케스트레이션 도구인 Kubernetes의 필요성이 대두됩니다. Kubernetes는 컨테이너화된 워크로드를 자동으로 배포, 스케일링, 관리하는 플랫폼입니다. 이는 다음과 같은 이점을 제공합니다.
- 자동화된 배포 및 롤백: 애플리케이션의 새로운 버전을 배포하고 문제가 발생하면 이전 버전으로 되돌리는 과정을 자동화합니다.
- 자가 치유 (Self-healing): 컨테이너가 실패하거나 노드가 다운되면 자동으로 새로운 컨테이너를 시작하거나 다른 노드로 이동시킵니다.
- 로드 밸런싱 및 서비스 디스커버리: 여러 컨테이너 인스턴스 간에 트래픽을 분산하고, 애플리케이션이 서로를 쉽게 찾을 수 있도록 돕습니다.
- 자원 관리: 클러스터의 자원을 효율적으로 사용하여 비용을 절감하고 성능을 최적화합니다.
- 수평적 확장 (Horizontal Scaling): 트래픽 증가에 따라 애플리케이션 인스턴스를 자동으로 늘리고, 트래픽 감소 시 자동으로 줄입니다.
이러한 기능들은 현대 인프라 환경에서 CI/CD 파이프라인과 통합되어 개발 및 운영의 효율성을 극대화하는 데 필수적입니다.
Kubernetes의 최소 배포 단위: Pod
Kubernetes에서 애플리케이션을 배포하는 가장 작은 단위는 바로 Pod입니다. 많은 초보자가 Pod를 Docker 컨테이너와 동일하게 생각하지만, 이는 정확하지 않습니다. Pod는 하나 이상의 컨테이너 그룹으로, 이 컨테이너들은 네트워크, 스토리지 볼륨과 같은 자원을 공유합니다.
Pod의 특징
- 공유 네트워크 및 스토리지: Pod 내의 모든 컨테이너는 동일한 IP 주소와 포트 공간을 공유하며, 함께 마운트된 볼륨에 접근할 수 있습니다. 이는 컨테이너 간의 효율적인 통신과 데이터 공유를 가능하게 합니다.
- 임시적 (Ephemeral): Pod는 언제든지 생성되고 삭제될 수 있는 임시적인 존재입니다. Pod의 생명 주기는 짧으며, Pod가 죽으면 새 Pod가 생성됩니다. 따라서 Pod 내부에 중요한 데이터를 영구적으로 저장하는 것은 권장되지 않습니다.
- 단일 책임 원칙: 일반적으로 각 Pod는 단일 애플리케이션 인스턴스를 실행하는 것을 목표로 합니다. 하지만, 메인 애플리케이션 컨테이너를 보조하는 사이드카(Sidecar) 컨테이너(예: 로깅 에이전트, 프록시)는 같은 Pod 내에 함께 배포될 수 있습니다.
Pod YAML 설정 예시
간단한 Nginx 웹 서버를 실행하는 Pod를 생성하는 YAML 파일입니다.
# nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: my-nginx-pod
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:latest
ports:
- containerPort: 80
Pod 관리 CLI 명령어
Pod를 생성하고 상태를 확인하는 기본적인 kubectl 명령어입니다.
# Pod 생성
kubectl apply -f nginx-pod.yaml
# Pod 목록 확인
kubectl get pods
# 특정 Pod의 상세 정보 확인
kubectl describe pod my-nginx-pod
# Pod 삭제
kubectl delete pod my-nginx-pod
kubectl get pods -o wide 명령어를 사용하면 Pod의 IP 주소와 실행 중인 노드 정보도 확인할 수 있습니다.
외부와 연결하는 방법: Service
Pod는 임시적이고 동적인 IP 주소를 가집니다. 이는 외부 클라이언트나 다른 Pod가 특정 Pod에 안정적으로 접근하기 어렵게 만듭니다. Service는 이러한 문제를 해결하기 위해 고안된 추상화 계층입니다. Service는 Pod 집합에 대한 안정적인 네트워크 엔드포인트를 제공하며, 로드 밸런싱 기능을 내장하고 있습니다.
Service의 역할
- 안정적인 IP 주소 및 DNS 이름: Service는 고유하고 안정적인 IP 주소와 DNS 이름을 가집니다. 클라이언트는 이 IP 주소나 DNS 이름을 통해 애플리케이션에 접근할 수 있습니다.
- 로드 밸런싱: Service는 레이블 셀렉터(Label Selector)를 사용하여 자신과 연결된 Pod들을 식별하고, 들어오는 트래픽을 이 Pod들 간에 분산시킵니다. Pod가 추가되거나 삭제되어도 Service는 자동으로 엔드포인트를 업데이트합니다.
- 서비스 디스커버리: 다른 Pod나 외부 애플리케이션은 Service의 이름으로 애플리케이션을 찾을 수 있습니다.
Service의 종류
Kubernetes는 다양한 사용 시나리오에 맞춰 여러 종류의 Service를 제공합니다.
- ClusterIP (기본값): 클러스터 내부에서만 접근 가능한 가상 IP를 할당합니다. 클러스터 내의 다른 Pod들이 이 Service를 통해 통신할 때 사용됩니다.
- NodePort: 모든 워커 노드의 특정 포트(NodePort)를 통해 Service를 외부에 노출합니다.
NodeIP:NodePort형식으로 접근할 수 있습니다. 개발 및 테스트 환경에서 주로 사용됩니다. - LoadBalancer: 클라우드 프로바이더(AWS, GCP, Azure 등)의 로드 밸런서를 프로비저닝하여 Service를 외부에 노출합니다. 외부 IP 주소를 할당받아 직접 접근할 수 있으며, 프로덕션 환경에서 가장 일반적으로 사용됩니다.
- ExternalName: CNAME 레코드를 통해 Service를 외부 서비스(예: 외부 데이터베이스)에 매핑합니다. 프록시 기능은 없으며, DNS 수준의 별칭 역할을 합니다.
Service YAML 설정 예시
이전에 생성한 Nginx Pod에 접근할 수 있는 ClusterIP Service를 생성하는 YAML입니다. selector 필드가 app: nginx 레이블을 가진 Pod를 찾아 연결합니다.
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-nginx-service
spec:
selector:
app: nginx # 이 레이블을 가진 Pod와 연결됩니다.
ports:
- protocol: TCP
port: 80 # Service 포트 (Service의 IP:Port로 접근)
targetPort: 80 # Pod 컨테이너 포트 (Pod 내부의 80번 포트로 트래픽 전달)
type: ClusterIP # 기본값은 ClusterIP입니다. NodePort, LoadBalancer 등으로 변경 가능.
Service 관리 CLI 명령어
Service를 생성하고 상태를 확인하는 kubectl 명령어입니다.
# Service 생성
kubectl apply -f nginx-service.yaml
# Service 목록 확인
kubectl get services
# 특정 Service의 상세 정보 확인
kubectl describe service my-nginx-service
# Service 삭제
kubectl delete service my-nginx-service
애플리케이션 배포와 관리: Deployment
Pod와 Service만으로는 애플리케이션의 복잡한 배포, 스케일링, 업데이트, 롤백을 효율적으로 처리하기 어렵습니다. Deployment는 이러한 작업을 선언적으로 정의하고 관리하기 위한 상위 레벨의 리소스입니다. Deployment는 ReplicaSet을 사용하여 Pod의 수를 관리하고, 애플리케이션의 무중단 업데이트와 롤백 기능을 제공합니다.
Deployment의 역할
- Pod 스케일링: 원하는 Pod의 개수를
replicas필드에 지정하여 유지합니다. ReplicaSet이 이 역할을 담당합니다. - 무중단 업데이트 (Rolling Update): 애플리케이션의 새 버전을 배포할 때, 기존 Pod를 점진적으로 새 Pod로 교체하여 서비스 중단 없이 업데이트를 수행합니다.
- 롤백 (Rollback): 업데이트 중 문제가 발생하면, 이전 버전의 애플리케이션으로 쉽게 되돌릴 수 있습니다.
- 상태 관리: Deployment는 Pod의 현재 상태를 모니터링하고, 선언된 목표 상태와 일치하도록 자동으로 Pod를 생성하거나 삭제합니다.
Deployment YAML 설정 예시
Nginx Pod 3개를 관리하는 Deployment를 생성하는 YAML 파일입니다. template 섹션은 Deployment가 생성할 Pod의 명세를 정의합니다.
# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment
labels:
app: nginx
spec:
replicas: 3 # Nginx Pod를 3개 유지합니다.
selector:
matchLabels:
app: nginx # 이 레이블을 가진 Pod를 관리합니다.
template: # Deployment가 생성할 Pod의 템플릿입니다.
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-container
image: nginx:1.21.6 # 특정 버전의 Nginx 이미지를 사용합니다.
ports:
- containerPort: 80
Deployment 관리 CLI 명령어
Deployment를 생성하고 관리하는 kubectl 명령어입니다.
# Deployment 생성
kubectl apply -f nginx-deployment.yaml
# Deployment 목록 확인
kubectl get deployments
# Deployment의 상태 확인 (Pod, ReplicaSet 정보 포함)
kubectl describe deployment my-nginx-deployment
# Deployment가 관리하는 Pods 목록 확인
kubectl get pods -l app=nginx
# Deployment 스케일링 (Pod 개수 변경)
kubectl scale deployment my-nginx-deployment --replicas=5
# 이미지 업데이트 (롤링 업데이트 시작)
kubectl set image deployment/my-nginx-deployment nginx-container=nginx:1.22.0
# 업데이트 히스토리 확인
kubectl rollout history deployment/my-nginx-deployment
# 이전 버전으로 롤백 (Undo)
kubectl rollout undo deployment/my-nginx-deployment
# Deployment 삭제
kubectl delete deployment my-nginx-deployment
kubectl set image 명령어를 사용하면 nginx:1.21.6에서 nginx:1.22.0으로 이미지를 변경하면서 롤링 업데이트가 진행되는 것을 확인할 수 있습니다.
Pod, Service, Deployment 관계 및 워크플로우
이제 Pod, Service, Deployment가 어떻게 서로 연관되어 작동하는지 전체적인 그림을 살펴보겠습니다.
- Deployment 생성: 사용자는
Deployment를 정의하여 원하는 애플리케이션의 상태(어떤 Pod를 몇 개 실행할지)를 선언합니다. - ReplicaSet 관리:
Deployment는 내부적으로ReplicaSet을 생성하고 관리합니다.ReplicaSet은Deployment가 정의한replicas수만큼Pod가 항상 실행되도록 보장합니다. - Pod 생성:
ReplicaSet은Deployment의template에 따라Pod를 생성합니다. 각Pod는 고유한 IP 주소를 가지며, 정의된 컨테이너를 실행합니다. - Service 연결:
Service는selector필드를 사용하여 특정 레이블을 가진Pod들을 찾습니다. 이Pod들은Service의 엔드포인트로 등록되고,Service는 이Pod들 간에 트래픽을 로드 밸런싱합니다.
이러한 구조를 통해 개발자는 Deployment만 관리하면 되며, Pod의 생성, 삭제, 스케일링, Service를 통한 접근 등 복잡한 인프라 관리 작업은 Kubernetes가 자동으로 처리합니다. 이는 CI/CD 파이프라인에서 애플리케이션 배포 자동화를 구현하는 핵심 기반이 됩니다.
| 구성 요소 | 역할 | 주요 특징 |
|---|---|---|
| Pod | Kubernetes의 최소 배포 단위. 하나 이상의 컨테이너 그룹. | 임시적, 동적 IP, 공유 네트워크/스토리지 |
| Service | Pod 집합에 대한 안정적인 네트워크 엔드포인트 제공. 로드 밸런싱. | 안정적인 IP/DNS, 서비스 디스커버리, Pod의 동적인 변화에 대응 |
| Deployment | Pod 및 ReplicaSet의 선언적 관리. 애플리케이션 배포, 스케일링, 업데이트, 롤백. | 무중단 업데이트, 롤백, 원하는 Pod 상태 유지, ReplicaSet 자동 관리 |
마무리
이 글을 통해 Kubernetes의 핵심 구성 요소인 Pod, Service, Deployment에 대한 기본적인 이해를 높일 수 있었기를 바랍니다. 이 세 가지 리소스는 Kubernetes 클러스터에서 애플리케이션을 배포하고 관리하는 데 있어 가장 기본적이면서도 중요한 역할을 수행합니다.
Pod는 컨테이너를 감싸는 최소 단위, Service는 Pod에 안정적인 접근을 제공하는 방법, 그리고 Deployment는 이러한 Pod들을 효율적으로 배포하고 관리하는 전략을 정의합니다. 이러한 개념들을 숙지하는 것은 Kubernetes를 활용한 DevOps 환경을 구축하고, 안정적인 인프라를 운영하는 데 있어 첫걸음입니다. 다음 단계로는 Ingress, Persistent Volume, ConfigMap, Secrets와 같은 다른 중요한 Kubernetes 리소스들을 학습하며 지식을 확장해 나가시길 추천합니다.
관련 게시글
GitOps Workflow 설계 가이드: Kubernetes와 CI/CD를 활용한 자동화
GitOps는 선언적 인프라 및 애플리케이션 관리를 위한 강력한 패러다임입니다. 이 가이드에서는 Git을 Single Source of Truth로 활용하여 Kubernetes 환경에서 안정적이고 효율적인 GitOps 워크플로우를 설계하는 방법을 Docker, CI/CD 자동화 예시와 함께 상세히 설명합니다.
GitHub Actions Advanced Workflows: Docker, Kubernetes CI/CD
GitHub Actions를 활용한 Docker, Kubernetes 기반 CI/CD 파이프라인 구축 심화 가이드. DevOps 엔지니어링 관점에서 자동화 전략을 탐구합니다.
Terraform Infrastructure Automation: DevOps 엔지니어링 가이드
Terraform을 활용한 인프라 자동화의 핵심 개념부터 실제 AWS 환경에서의 배포 예시까지, DevOps 엔지니어링 관점에서 자세히 알아봅니다. IaC, Docker, Kubernetes, CI/CD 파이프라인 통합 전략을 다룹니다.