Spring

Docker와 Kubernetes

으엉어엉 2025. 11. 24. 15:29
728x90

1. Docker (도커)

"애플리케이션을 실행하기 위한 패키징 툴 (단일 컨테이너 관리)"

주요 특징

  1. 컨테이너화 (Containerization): OS, 라이브러리, 소스 코드를 하나의 '이미지'로 묶습니다.
  2. 이식성 (Portability): "내 컴퓨터에선 되는데 서버에선 안 돼요"가 불가능합니다. 어디서든 똑같이 돌아갑니다.
  3. 이미지 불변성: 한 번 빌드된 이미지는 변하지 않습니다. (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)

사용자가 웹사이트에 접속했을 때 어떤 과정을 거쳐 컨테이너까지 도달하는지 알아야 합니다.

  1. User Request: 사용자가 도메인(my-app.com)으로 접속.
  2. Ingress: 요청을 받아서 "아, 이건 백엔드 서비스로 갈 요청이구나" 판단하고 넘김.
  3. Service: 백엔드 서비스는 연결된 Pod 리스트를 확인하고 그중 하나로 트래픽을 전달 (Load Balancing).
  4. 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)합니다.

 

주요 특징

  1. 오토 스케일링 (Auto-Scaling): 트래픽이 많으면 파드(Pod) 개수를 늘리고, 적으면 줄입니다.
  2. 자가 치유 (Self-Healing): 컨테이너가 죽으면 자동으로 감지해서 재시작합니다.
  3. 로드 밸런싱 (Load Balancing): 여러 개의 파드에 트래픽을 골고루 분산합니다.
  4. 무중단 배포 (Rolling Update): 서비스 중단 없이 버전을 업데이트합니다.

장단점 비교

구분 내용
장점 - 고가용성 (HA): 서버가 죽어도 서비스는 죽지 않음.

- 자동화: 운영자가 잘 때도 알아서 장애를 복구함.

- 효율성: 서버 자원을 빈틈없이 꽉 채워서 사용함.
단점 - 높은 러닝 커브: 배우기가 매우 어렵고 설정이 복잡함.

- 리소스 오버헤드: 쿠버네티스 자체를 돌리는 데에도 서버 자원이 꽤 필요함.

 

 

3. 한눈에 보는 비교 (Docker vs Kubernetes)

주 역할 컨테이너 만들기 & 실행 컨테이너 관리 & 조율
관리 범위 서버 1대 (Single Host) 서버 여러 대 (Cluster)
스케일링 수동 (명령어 입력 필요) 자동 (Auto-scaling)
장애 대응 컨테이너 죽으면 끝 (수동 복구) 자동 복구 (죽으면 다시 띄움)
추천 상황 로컬 개발, 소규모 프로젝트 대규모 트래픽, MSA 환경, 운영 서버
     

 

4. 결론

"개발할 땐 Docker로 환경을 맞추고, 서비스가 커져서 운영이 힘들어지면 그때 Kubernetes를 도입하세요."

 

 

 

728x90