절약왕국 프로젝트에서 기존에 Docker Compose로 돌아가던 bb-server
애플리케이션을 MSA 환경으로 구축하기 위해 Kubernetes로 이전하는 과정을 정리해보겠습니다.
현재 프로젝트 상황
bb-server
가 실행 중 주제: Docker Compose 환경을 Kubernetes를 활용한 Cluster 환경으로 마이그레이션 하기
이제 Docker Compose로 운영되던 bb-server
를 Kubernetes 리소스(Secret
, ConfigMap
, PersistentVolume
, PersistentVolumeClaim
, Deployment
, Service
, HPA
)로 마이그레이션 해보겠습니다.
bb-server
가 어떤 환경 변수를 쓰고 있고, 어떤 포트가 노출되어 있는지 확인합니다. volumes
설정을 사용하고 있다면, Kubernetes에서는 PersistentVolume
, PersistentVolumeClaim
으로 매핑해야 합니다.이 과정을 통해 이전에 쓰였던 환경 변수, 포트, 볼륨 등을 모두 파악해두면, K8s 마이그레이션 시 놓치지 않고 반영할 수 있습니다.
apiVersion: v1
kind: Secret
metadata:
name: bb-mariadb-secret
type: Opaque
data:
mysql-root-password: cm9vdA==
mysql-database: Ym9hcmQ=
apiVersion: v1
kind: ConfigMap
metadata:
name: bb-mariadb-config
data:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: board
문제 발생 & 해결
문제: 모든 설정값을 ConfigMap에 넣었다가, 실제로는 민감정보(비밀번호 등)도 섞여있어서 보안 이슈 제기.
해결: 민감정보만 Secret으로 분리하여 관리함.
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-bb-mariadb
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data/bb-mariadb"
문제 발생 & 해결
문제: 실제 Worker Node의 /mnt/data/bb-mariadb 디렉토리가 없어서 마운트 실패 발생.
해결: 노드에 들어가 sudo mkdir -p /mnt/data/bb-mariadb && sudo chmod 777 /mnt/data/bb-mariadb 로 디렉토리 생성 후 권한 설정.
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-bb-mariadb
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
apiVersion: apps/v1
kind: Deployment
metadata:
name: bb-mariadb
spec:
replicas: 1
selector:
matchLabels:
app: bb-mariadb
template:
metadata:
labels:
app: bb-mariadb
spec:
containers:
- name: bb-mariadb
image: mariadb:latest
envFrom:
- configMapRef:
name: bb-mariadb-config
ports:
- containerPort: 3306
volumeMounts:
- mountPath: "/var/lib/mysql"
name: bb-mariadb-storage
volumes:
- name: bb-mariadb-storage
persistentVolumeClaim:
claimName: pvc-bb-mariadb
apiVersion: v1
kind: Service
metadata:
name: bb-mariadb
spec:
ports:
- port: 3306
selector:
app: bb-mariadb
Compose에서 container_name: mariadb 로 연결하던 것을, K8s에서는 Service 이름(bb-mariadb)으로 접근합니다: bb-mariadb:3306.
apiVersion: apps/v1
kind: Deployment
metadata:
name: bb-server
spec:
replicas: 1
selector:
matchLabels:
app: bb-server
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: bb-server
spec:
containers:
- name: bb-server
image: 99koo/bb-server:1617
env:
- name: SPRING_DATASOURCE_URL
value: jdbc:mariadb://bb-mariadb:3306/board?useUnicode=true&characterEncoding=UTF-8
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: bb-mariadb-secret
key: mysql-root-password
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: bb-mariadb-secret
key: mysql-root-password
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
문제 발생 & 해결
문제: Docker Compose에서는 depends_on: mariadb로 DB를 먼저 띄웠는데, K8s에선 DB 준비가 늦어 bb-server가 DB 연결 실패.
해결: livenessProbe와 readinessProbe를 설정해, DB 연결 전까지는 Pod을 준비 중(Ready=false) 상태로 두도록 조정.
apiVersion: v1
kind: Service
metadata:
name: bb-server
spec:
type: LoadBalancer
ports:
- port: 8080
targetPort: 8080
selector:
app: bb-server
문제 발생 & 해결
문제: On-premise 환경에서 LoadBalancer 타입이 동작하지 않아 접속이 불가.
해결: Service를 NodePort 타입으로 변경해 :로 직접 접근하도록 설정함.
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: bb-server-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: bb-server
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50
이렇게 Docker Compose로 운영되던 bb-server를 Kubernetes 환경으로 이전해보았습니다.
Docker Compose에서 정의했던 볼륨, 환경 변수, 포트 노출을 Kubernetes의 PV/PVC, Secret/ConfigMap, Service로 대체 오토스케일링(HPA) 기능 추가로 부하에 대응할 수 있는 구조로 업그레이드하였습니다.
절약왕국 프로젝트에는 총 5개의 서버(front-server, auth-server, bb-server, sb-server, cm-server)가 있습니다. 서버별로 필요한 Kubernetes 오브젝트를 각각 따로 관리하면 너무 복잡해질 수 있어, 각 서버별로 필요한 오브젝트를 하나의 YAML 파일에 모아 서버 5개에 대한 파일 5개로 구성하였습니다.
apiVersion: v1
kind: Secret
metadata:
name: bb-mariadb-secret
type: Opaque
data:
mysql-root-password: cm9vdA==
mysql-database: Ym9hcmQ=
---
apiVersion: v1
kind: ConfigMap
metadata:
name: bb-mariadb-config
data:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: board
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-bb-mariadb
spec:
capacity:
storage: 1Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/mnt/data/bb-mariadb"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-bb-mariadb
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: bb-mariadb
spec:
replicas: 1
selector:
matchLabels:
app: bb-mariadb
template:
metadata:
labels:
app: bb-mariadb
spec:
containers:
- name: bb-mariadb
image: mariadb:latest
envFrom:
- configMapRef:
name: bb-mariadb-config
ports:
- containerPort: 3306
volumeMounts:
- mountPath: "/var/lib/mysql"
name: bb-mariadb-storage
volumes:
- name: bb-mariadb-storage
persistentVolumeClaim:
claimName: pvc-bb-mariadb
---
apiVersion: v1
kind: Service
metadata:
name: bb-mariadb
spec:
ports:
- port: 3306
selector:
app: bb-mariadb
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: bb-server
spec:
replicas: 1
selector:
matchLabels:
app: bb-server
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1
template:
metadata:
labels:
app: bb-server
spec:
containers:
- name: bb-server
image: 99koo/bb-server:1617
env:
- name: SPRING_DATASOURCE_URL
value: jdbc:mariadb://bb-mariadb:3306/board?useUnicode=true&characterEncoding=UTF-8
- name: SPRING_DATASOURCE_USERNAME
valueFrom:
secretKeyRef:
name: bb-mariadb-secret
key: mysql-root-password
- name: SPRING_DATASOURCE_PASSWORD
valueFrom:
secretKeyRef:
name: bb-mariadb-secret
key: mysql-root-password
ports:
- containerPort: 8080
livenessProbe:
httpGet:
path: /actuator/health
port: 8080
initialDelaySeconds: 60
periodSeconds: 30
---
apiVersion: v1
kind: Service
metadata:
name: bb-server
spec:
type: LoadBalancer
ports:
- port: 8080
targetPort: 8080
selector:
app: bb-server
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: bb-server-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: bb-server
minReplicas: 3
maxReplicas: 50
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 50