Kubernetes를 이용해서 Cluster 구축

yeong-min·2025년 1월 15일
0

현재 프로젝트 상황

절약왕국 프로젝트에서 기존에 Docker Compose로 돌아가던 bb-server 애플리케이션을 MSA 환경으로 구축하기 위해 Kubernetes로 이전하는 과정을 정리해보겠습니다.

현재 프로젝트 상황

  • Master Node: 1대
  • Worker Node: 2대
  • Docker Composebb-server가 실행 중

주제: Docker Compose 환경을 Kubernetes를 활용한 Cluster 환경으로 마이그레이션 하기

이제 Docker Compose로 운영되던 bb-server를 Kubernetes 리소스(Secret, ConfigMap, PersistentVolume, PersistentVolumeClaim, Deployment, Service, HPA)로 마이그레이션 해보겠습니다.


1. 기존 Docker Compose 환경 점검

  1. Docker Compose 파일 확인
    • bb-server가 어떤 환경 변수를 쓰고 있고, 어떤 포트가 노출되어 있는지 확인합니다.
    • DB 연결 정보(주소, 계정, 비밀번호)도 파악합니다.
  2. 로컬 볼륨 사용 여부
    • 기존 Compose에서 volumes 설정을 사용하고 있다면, Kubernetes에서는 PersistentVolume, PersistentVolumeClaim으로 매핑해야 합니다.

이 과정을 통해 이전에 쓰였던 환경 변수, 포트, 볼륨 등을 모두 파악해두면, K8s 마이그레이션 시 놓치지 않고 반영할 수 있습니다.


2. Kubernetes 리소스 준비하기

2.1 Secret & ConfigMap

(1) Secret 생성

apiVersion: v1
kind: Secret
metadata:
  name: bb-mariadb-secret
type: Opaque
data:
  mysql-root-password: cm9vdA==
  mysql-database: Ym9hcmQ=
  • 기존 Docker Compose에서 사용하던 DB 비밀번호, DB 이름을 Base64 인코딩 후 넣습니다.
  • cm9vdA== 은 root, Ym9hcmQ= 은 board 값과 동일합니다.

(2) ConfigMap 생성

apiVersion: v1
kind: ConfigMap
metadata:
  name: bb-mariadb-config
data:
  MYSQL_ROOT_PASSWORD: root
  MYSQL_DATABASE: board
  • 민감하지 않은 설정(MYSQL_DATABASE 등)을 여기에 저장합니다.
  • Docker Compose의 환경 변수를 참고하여 분리할 것들을 ConfigMap에 정의합니다.

문제 발생 & 해결
문제: 모든 설정값을 ConfigMap에 넣었다가, 실제로는 민감정보(비밀번호 등)도 섞여있어서 보안 이슈 제기.
해결: 민감정보만 Secret으로 분리하여 관리함.

2.2 PV & PVC 생성 (MariaDB 데이터 영구화)

(1) PersistentVolume (PV)

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 경로를 PV로 만듭니다.
  • Compose에서 volumes: 설정을 사용하던 부분을 이로 대체한다고 생각하면 됩니다.

문제 발생 & 해결
문제: 실제 Worker Node의 /mnt/data/bb-mariadb 디렉토리가 없어서 마운트 실패 발생.
해결: 노드에 들어가 sudo mkdir -p /mnt/data/bb-mariadb && sudo chmod 777 /mnt/data/bb-mariadb 로 디렉토리 생성 후 권한 설정.

(2) PersistentVolumeClaim (PVC)

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: pvc-bb-mariadb
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  • Pod(Deployment)에서 PVC를 통해 스토리지를 사용하도록 요청합니다.
  • PV와 1Gi 용량이 일치해야 정상적으로 바인딩이 이루어집니다.

2.3 MariaDB Deployment & Service

(1) Deployment

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
  • Compose에서 쓰던 mariadb 이미지를 그대로 사용합니다.
  • 환경 변수(MYSQL_ROOT_PASSWORD, MYSQL_DATABASE)는 ConfigMap에서 가져옵니다.
  • DB 데이터 폴더(/var/lib/mysql)를 PVC로 연결해 영구 저장이 가능합니다.

(2) Service

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.

2.4 bb-server Deployment & Service

(1) Deployment

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
  • Compose에서 환경 변수로 주입했던 DB 접속 정보(SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME, SPRING_DATASOURCE_PASSWORD)를 K8s에서는 env로 전달합니다.
  • username과 password는 Secret에서 가져옵니다.
  • livenessProbe를 통해 애플리케이션이 정상 동작하는지 K8s가 주기적으로 체크합니다.

문제 발생 & 해결
문제: Docker Compose에서는 depends_on: mariadb로 DB를 먼저 띄웠는데, K8s에선 DB 준비가 늦어 bb-server가 DB 연결 실패.
해결: livenessProbe와 readinessProbe를 설정해, DB 연결 전까지는 Pod을 준비 중(Ready=false) 상태로 두도록 조정.

(2) Service

apiVersion: v1
kind: Service
metadata:
  name: bb-server
spec:
  type: LoadBalancer
  ports:
    - port: 8080
      targetPort: 8080
  selector:
    app: bb-server
  • type: LoadBalancer를 사용하면 클라우드 환경에서 외부 IP가 할당되어 바로 접근이 가능합니다.
  • On-premise 환경이라면 NodePort를 써서 : 형태로 접속할 수도 있습니다.
  • 기존 Docker Compose에서 ports: "8080:8080"로 노출하던 것을, K8s에서는 Service로 노출합니다.

문제 발생 & 해결
문제: On-premise 환경에서 LoadBalancer 타입이 동작하지 않아 접속이 불가.
해결: Service를 NodePort 타입으로 변경해 :로 직접 접근하도록 설정함.

2.5 HPA(Horizontal Pod Autoscaler)

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
  • bb-server Deployment를 모니터링하여 CPU 사용량이 50%를 넘으면 자동으로 스케일 아웃합니다.
  • Docker Compose에서는 따로 오토스케일링 개념이 없었지만, K8s에서는 HPA로 간편하게 확장 가능합니다.

3. 결과 및 후기

3.1 결과

이렇게 Docker Compose로 운영되던 bb-server를 Kubernetes 환경으로 이전해보았습니다.

Docker Compose에서 정의했던 볼륨, 환경 변수, 포트 노출을 Kubernetes의 PV/PVC, Secret/ConfigMap, Service로 대체 오토스케일링(HPA) 기능 추가로 부하에 대응할 수 있는 구조로 업그레이드하였습니다.

(1) 전체 bb-server.yaml

절약왕국 프로젝트에는 총 5개의 서버(front-server, auth-server, bb-server, sb-server, cm-server)가 있습니다. 서버별로 필요한 Kubernetes 오브젝트를 각각 따로 관리하면 너무 복잡해질 수 있어, 각 서버별로 필요한 오브젝트를 하나의 YAML 파일에 모아 서버 5개에 대한 파일 5개로 구성하였습니다.

  • 아래는 최종 bb-server.yaml파일 입니다.
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

3.2 후기

  • 실제 운영 환경으로 가면 네트워크 설정(ingress, 로드밸런서), 로그/모니터링, CI/CD 파이프라인 등 고려해야 할 사항이 훨씬 많을 것 같습니다.
  • 이번 과정을 통해 백엔드 개발뿐만 아니라 인프라 관점에서도 학습할 수 있었고, 전반적인 아키텍처를 좀 더 깊이 이해하게 되어 좋았습니다.

0개의 댓글