728x90
1. Docker (도커)
"애플리케이션을 실행하기 위한 패키징 툴 (단일 컨테이너 관리)"
주요 특징
- 컨테이너화 (Containerization): OS, 라이브러리, 소스 코드를 하나의 '이미지'로 묶습니다.
- 이식성 (Portability): "내 컴퓨터에선 되는데 서버에선 안 돼요"가 불가능합니다. 어디서든 똑같이 돌아갑니다.
- 이미지 불변성: 한 번 빌드된 이미지는 변하지 않습니다. (Immutable Infrastructure)
장단점 비교
| 구분 | 내용 |
| 장점 | - 가볍고 빠름: VM(가상머신)보다 부팅 속도가 압도적으로 빠름. - 환경 일치: 개발/운영 환경의 차이를 없앰. - 배포 용이: docker run 명령어 하나로 실행 끝. |
| 단점 | - 단일 호스트 한계: 서버가 여러 대일 때 관리하기 힘듦. - 데이터 휘발성: 컨테이너를 삭제하면 데이터도 날아감 (Volume 설정 필요). |
코드 예시
1) Dockerfile (이미지 생성 명세서)
자바 애플리케이션을 도커 이미지로 만드는 파일입니다.
# 1. Base Image: 자바 17이 설치된 리눅스 환경을 가져옴
FROM openjdk:17-jdk-slim
# 2. 작업 디렉토리 생성
WORKDIR /app
# 3. 빌드된 JAR 파일을 컨테이너 내부로 복사
COPY build/libs/myapp.jar app.jar
# 4. 컨테이너 실행 시 작동할 명령어
ENTRYPOINT ["java", "-jar", "app.jar"]
2) docker-compose.yml (여러 컨테이너 실행)
로컬 개발 환경에서 DB와 서버를 같이 띄울 때 씁니다.
version: '3'
services:
# 스프링 부트 서버
backend:
build: .
ports:
- "8080:8080"
depends_on:
- db
# MySQL 데이터베이스
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: 1234
ports:
- "3306:3306"
2. Kubernetes (쿠버네티스, k8s)
도커 컨테이너를 관리하는 관리자
1. 쿠버네티스 핵심 용어 (Object) 정리
① 파드 (Pod) - "배포의 최소 단위"
- 개념: 쿠버네티스는 컨테이너를 직접 다루지 않습니다. 컨테이너를 감싸고 있는 'Pod(콩깍지)'를 다룹니다.
- 특징:
- 보통 1개의 Pod 안에 1개의 컨테이너(스프링 부트 등)가 들어갑니다.
- 일회용(Ephemeral)입니다. 언제든 죽을 수 있고, 죽으면 IP가 바뀝니다..
② 디플로이먼트 (Deployment)
개념: Pod를 몇 개 유지할지 관리하는 관리자입니다.
- 역할:
- ReplicaSet 관리: "항상 Pod 3개를 유지해!"라고 명령해 두면, 하나가 죽는 즉시 새것을 만듭니다.
- 버전 관리: 앱을 v1에서 v2로 업데이트할 때, 기존 Pod를 하나씩 죽이고 새 Pod를 띄우는(Rolling Update) 전략을 수행합니다.
③ 서비스 (Service) - "고정된 주소(전화번호)"
- 개념: Pod는 죽었다 살아나면 IP가 바뀝니다. 그래서 Pod에게 직접 연락하면 안 됩니다. Service는 변하지 않는 고정 IP를 제공합니다.
- 역할: 들어온 요청을 여러 Pod에게 골고루 나눠주는 로드 밸런서 역할을 합니다.
④ 인그레스 (Ingress) - "교통 정리(관문)"
- 개념: 클러스터 외부에서 내부로 들어오는 요청을 처리하는 규칙입니다.
- 역할: www.naver.com/blog는 A 서비스로, www.naver.com/news는 B 서비스로 보내주는 라우팅을 담당합니다.
2. 실제 통신 흐름 (Architecture Flow)
사용자가 웹사이트에 접속했을 때 어떤 과정을 거쳐 컨테이너까지 도달하는지 알아야 합니다.
- User Request: 사용자가 도메인(my-app.com)으로 접속.
- Ingress: 요청을 받아서 "아, 이건 백엔드 서비스로 갈 요청이구나" 판단하고 넘김.
- Service: 백엔드 서비스는 연결된 Pod 리스트를 확인하고 그중 하나로 트래픽을 전달 (Load Balancing).
- Pod: 실제 애플리케이션(Spring Boot)이 요청을 처리하고 응답.
3. 실무 코드 완전 분석 (YAML)
쿠버네티스는 Deployment와 Service가 한 세트로 움직입니다. 아래 코드는 "서버 3대를 띄우고, 로드밸런서로 연결하는" 완벽한 세트입니다.
# 1. Deployment (실제 서버 띄우기)
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-spring-app
spec:
replicas: 3 # "서버 3대(Pod) 유지해라" (핵심)
selector:
matchLabels:
app: spring-backend # "이 라벨 붙은 놈들 내가 관리한다"
template:
metadata:
labels:
app: spring-backend # Pod에 이름표(Label) 붙이기
spec:
containers:
- name: spring-container
image: my-docker-id/spring-app:v1
ports:
- containerPort: 8080
---
# 2. Service (고정 주소 만들기 & 로드밸런싱)
apiVersion: v1
kind: Service
metadata:
name: my-spring-service
spec:
type: ClusterIP # 내부 전용 IP 할당
selector:
app: spring-backend # "이 이름표 붙은 Pod들한테 트래픽 보내라" (연결고리)
ports:
- port: 80 # 서비스의 포트 (들어오는 문)
targetPort: 8080 # Pod의 포트 (실제 문)
코드 해석 (핵심 포인트)
- Labels & Selector: 이게 제일 중요합니다.
- Deployment가 만든 Pod에 app: spring-backend라는 스티커(Label)를 붙입니다.
- Service는 app: spring-backend 스티커가 붙은 Pod만 찾아서(Selector) 트래픽을 보냅니다.
- 이 이름표(Label)가 맞아야 서로 연결됩니다.
4. 자주 쓰는 명령어 (Cheat Sheet)
개발자가 매일 치게 될 명령어입니다.
- 상태 확인:
- kubectl get pods : 현재 실행 중인 파드 목록 조회
- kubectl get svc : 서비스(IP) 목록 조회
- kubectl get all : 모든 리소스 조회
- 로그 확인 (디버깅):
- kubectl logs -f [파드이름] : 실시간 로그 확인 (제일 많이 씀)
- 배포 및 수정:
- kubectl apply -f my-app.yaml : 작성한 YAML 파일로 실행(배포)
- kubectl delete -f my-app.yaml : 배포한 것 삭제
5. 결론: 쿠버네티스의 철학
쿠버네티스의 핵심 철학은 "Desired State (원하는 상태)"입니다.
개발자는 "나는 서버 3개가 필요해"라고 YAML 파일에 적어서(Desired State) 제출하기만 하면 됩니다. 그러면 쿠버네티스는 현재 서버가 2개라면 1개를 더 만들고, 4개라면 1개를 죽여서 어떻게든 그 상태를 유지(Current State)합니다.
주요 특징
- 오토 스케일링 (Auto-Scaling): 트래픽이 많으면 파드(Pod) 개수를 늘리고, 적으면 줄입니다.
- 자가 치유 (Self-Healing): 컨테이너가 죽으면 자동으로 감지해서 재시작합니다.
- 로드 밸런싱 (Load Balancing): 여러 개의 파드에 트래픽을 골고루 분산합니다.
- 무중단 배포 (Rolling Update): 서비스 중단 없이 버전을 업데이트합니다.
장단점 비교
| 구분 | 내용 |
| 장점 | - 고가용성 (HA): 서버가 죽어도 서비스는 죽지 않음. - 자동화: 운영자가 잘 때도 알아서 장애를 복구함. - 효율성: 서버 자원을 빈틈없이 꽉 채워서 사용함. |
| 단점 | - 높은 러닝 커브: 배우기가 매우 어렵고 설정이 복잡함. - 리소스 오버헤드: 쿠버네티스 자체를 돌리는 데에도 서버 자원이 꽤 필요함. |
3. 한눈에 보는 비교 (Docker vs Kubernetes)
| 주 역할 | 컨테이너 만들기 & 실행 | 컨테이너 관리 & 조율 |
| 관리 범위 | 서버 1대 (Single Host) | 서버 여러 대 (Cluster) |
| 스케일링 | 수동 (명령어 입력 필요) | 자동 (Auto-scaling) |
| 장애 대응 | 컨테이너 죽으면 끝 (수동 복구) | 자동 복구 (죽으면 다시 띄움) |
| 추천 상황 | 로컬 개발, 소규모 프로젝트 | 대규모 트래픽, MSA 환경, 운영 서버 |
4. 결론
"개발할 땐 Docker로 환경을 맞추고, 서비스가 커져서 운영이 힘들어지면 그때 Kubernetes를 도입하세요."
728x90
'Spring' 카테고리의 다른 글
| 댓글 알림 기능을 비동기(Event)로 전환 (0) | 2026.01.15 |
|---|---|
| AOP와 Redisson (0) | 2025.11.24 |
| [JPA] Entity Graph vs Fetch Join 차이점 및 N+1, 페이징 성능 최적화 (0) | 2025.11.20 |
| 락 선택 기준표와 실무 트러블슈팅 (Deadlock, Timeout) (1) | 2025.10.27 |
| 게시글 동시성 처리 - 비관적 락은 언제 써야 할까? (0) | 2025.10.27 |