Post

[Kubernetes] 3-tier 웹 어플리케이션 배포(VM)

📌 들어가며

이번 글에서는 VM 기반 쿠버네티스 클러스터에 3-tier 웹 애플리케이션(프론트엔드·백엔드·DB)을 배포한다. kompose로 Docker Compose를 쿠버네티스 YAML로 변환하고, 서비스 타입을 계층별로 다르게 주어 외부 노출과 내부 통신을 구분한다.

3-tier 구성 전략 — 프론트만 외부에 노출(NodePort)하고, 백엔드·DB는 내부 전용(ClusterIP)으로 감춘다. 외부 → 프론트 → 백엔드 → DB로 이어지는 단방향 계층 구조를 서비스 타입으로 구현한다.


1. 프로젝트 시나리오

flowchart LR
    User(("🌐 외부"))
    subgraph K8s["쿠버네티스 (default ns)"]
        FE["🖥️ 프론트<br/>NodePort:30009"]
        BE["⚙️ 백엔드(Spring)<br/>ClusterIP:8080"]
        DB[("🗄️ MySQL<br/>ClusterIP:3306")]
    end
    User --> FE --> BE --> DB
계층서비스 타입노출
프론트엔드NodePort외부 접속
백엔드(Spring Boot)ClusterIP프론트만 접근
데이터베이스(MySQL)ClusterIP백엔드만 접근

2. kompose로 Compose → 쿠버네티스 변환

kompose는 Docker Compose 파일을 쿠버네티스 리소스로 변환하는 도구다.

1
2
3
4
5
6
7
# 설치
curl -L https://github.com/kubernetes/kompose/releases/download/v1.31.2/kompose-linux-amd64 -o kompose
chmod +x kompose && sudo mv ./kompose /usr/local/bin/kompose

# 변환
cd ~/LABs/3tier
kompose convert

변환 결과로 각 계층의 *-service.yaml·*-deployment.yaml이 생성된다(네트워크 폴리시 파일은 삭제).

💡 kompose는 마이그레이션 출발점이다. Compose를 완벽하게 옮겨주진 않으므로, 서비스 타입(NodePort 등)·환경 변수 같은 세부 사항은 변환 후 직접 다듬어야 한다.


3. YAML 수정 — 계층별 서비스

프론트엔드 (NodePort)

1
2
3
4
5
6
7
8
9
10
11
12
13
apiVersion: v1
kind: Service
metadata:
  name: mydiary-front
spec:
  type: NodePort
  ports:
    - name: "3000"
      port: 3000
      targetPort: 3000
      nodePort: 30009
  selector:
    app: mydiary-front

백엔드 (ClusterIP + DB 연결)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydiary-back
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mydiary-back
  template:
    metadata:
      labels:
        app: mydiary-back
    spec:
      containers:
        - name: mydiary-back
          image: dbgurum/mydiary-back:1.0
          env:
            - name: SPRING_DATASOURCE_URL
              value: jdbc:mysql://mydiary-db:3306/paperdb?serverTimezone=Asia/Seoul
            - name: SPRING_DATASOURCE_USERNAME
              value: user
            - name: SPRING_DATASOURCE_PASSWORD
              value: pass123

💡 백엔드의 DB 접속 주소가 jdbc:mysql://mydiary-db:3306인 점이 핵심이다. mydiary-db는 DB 서비스 이름이고, 쿠버네티스 DNS가 이를 ClusterIP로 해석한다. IP가 아니라 서비스 이름으로 연결하므로 파드가 재생성돼도 안전하다.

데이터베이스 (ClusterIP)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydiary-db
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mydiary-db
  template:
    metadata:
      labels:
        app: mydiary-db
    spec:
      containers:
        - name: mydiary-db
          image: mysql:5.7-debian
          env:
            - name: MYSQL_ROOT_PASSWORD
              value: pass123
            - name: MYSQL_DATABASE
              value: paperdb

4. 배포 & 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 전체 적용
kubectl apply -f ~/LABs/3tier/

# 상태 확인 (약 1분 후 모두 Running)
kubectl get deploy,po,svc -o wide | grep mydiary

# 백엔드 로그
kubectl logs -f mydiary-back-xxxxx

# 프론트 접속: http://192.168.56.101:30009/

# DB 데이터 확인
kubectl exec -it mydiary-db-xxxxx -- bash
mysql -uroot -p
1
2
use paperdb;
select * from paper;

⚠️ 백엔드(Spring Boot)는 기동에 시간이 걸린다. 배포 직후 Running이 아니어도 약 1분간 기다린 뒤 상태를 다시 확인하자. DB가 먼저 떠 있어야 백엔드가 정상 연결된다.


📝 정리

1
2
3
4
5
3-tier 배포(VM)
├─ 변환   kompose로 Compose → k8s YAML
├─ 계층   프론트(NodePort) / 백엔드·DB(ClusterIP)
├─ 연결   서비스 이름(mydiary-db)으로 DNS 통신
└─ 배포   kubectl apply -f 디렉터리
개념한 줄 정의
komposeCompose → k8s 변환 도구
NodePort/ClusterIP외부 노출/내부 전용
서비스 이름 통신DNS로 파드 연결

3-tier 배포의 핵심은 서비스 타입으로 노출 범위를 계층화하는 것이다. 프론트만 NodePort로 열고 백엔드·DB는 ClusterIP로 숨기며, 계층 간 연결은 서비스 이름(DNS)으로 잇는다.

This post is licensed under CC BY 4.0 by the author.

Comments powered by Disqus.