EKS 기반 spring, vuejs 웹 어플리케이션 배포 및 CI/CD 구축하기 #2

2024. 11. 12. 00:33개발 플랫폼/AWS

이전 글에서 EKS의 환경 세팅을 끝냈고 이젠 EKS로 로컬환경의 쿠버네티스에서 운영중인 어플리케이션을 배포 해보자.

시스템 아키텍처

 

우선 배포하려는 어플리 케이션의 시스템 아키텍처이다

 

시스템 아키텍처 구성

  • 리전: ap-northeast-2 (서울)
  • 네트워크 구성: eks-vpc라는 VPC 내에 두 개의 private 서브넷과 두 개의 public 서브넷을 설정해, EKS가 외부와 내부 트래픽을 모두 처리할 수 있도록 환경을 구성.
  • ALB: Spring Boot 백엔드 애플리케이션과 Vue.js 프론트엔드 애플리케이션을 배포하고, 외부 도메인은 Route 53을 통해 설정. SSL 인증서는 AWS Certificate Manager를 사용하여 HTTPS로 접근하도록 설정.

1. RDS 생성

로컬에서 생성한 데이터베이스를 AWS의 RDS로 옮기는 작업을 먼저 하였다.

RDS를 검색후 서비스 사용

데이터베이스 생성을 통해 사용하려는 스펙에 맞게 정보를 입력 한 후 데이터 베이스 생성

나는 MariaDB를 사용하였다.

 

⚠️MariaDB를 생성하였을 떄 한글 인코딩 문제로 데이터가 Insert가 안되는 문제를 발견하였고 아래의 설정을 통해 해결

 

MariaDB 설정: 한글 인코딩 문제 해결을 위해 아래의 파라미터를 utf8mb4로 수정.

  • character_set_client
  • character_set_connection
  • character_set_database
  • character_set_filesystem
  • character_set_results
  • character_set_server
  • collation_connection
  • collation_server

2. AWS CLI 설치

https://docs.aws.amazon.com/ko_kr/cli/latest/userguide/getting-started-install.html

 

의 최신 버전으로 설치 또는 업데이트 AWS CLI - AWS Command Line Interface

이전 버전에서 업데이트하는 경우 unzip 명령을 실행하면 기존 파일을 덮어쓸지 묻는 메시지가 표시됩니다. 스크립트 자동화와 같은 경우에 이러한 프롬프트를 건너뛰려면 unzip에 대한 -u 업데이

docs.aws.amazon.com

위 링크를 통해 최신 버전을 설치한 후, aws configure 명령어로 접속 정보를 입력

 

EKS 클러스터 설정: aws eks --region <리전> update-kubeconfig --name <클러스터명> 명령어를 통해 EKS 클러스터에 연결하고, kubectl을 통해 접속을 확인

 

3. 애플리케이션 및 Redis 배포

클라이언트 및 서버 애플리케이션, Redis를 EKS에 배포

 

heroes-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: heroes-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: heroes
  template:
    metadata:
      labels:
        app: heroes
    spec:
      containers:
        - name: heroes
          image: <도커 이미지>
          ports:
            - containerPort: 8080
          env:
            - name: DB_URL
              valueFrom:
                configMapKeyRef:
                  name: heroes-config
                  key: DB_URL
            - name: BATCH_DB_URL
              valueFrom:
                configMapKeyRef:
                  name: heroes-config
                  key: BATCH_DB_URL
            - name: FIREBASE_JSON_NAME
              value: /secrets/heroes-firebase-secret.json
            - name: FIREBASE_BUCKET_NAME
              valueFrom:
                configMapKeyRef:
                  name: heroes-config
                  key: FIREBASE_BUCKET_NAME
            - name: JWT_SECRET
              valueFrom:
                configMapKeyRef:
                  name: heroes-config
                  key: JWT_SECRET
            - name: DB_USERNAME
              valueFrom:
                secretKeyRef:
                  name: heroes-secrets
                  key: DB_USERNAME
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: heroes-secrets
                  key: DB_PASSWORD
            - name: BATCH_DB_USERNAME
              valueFrom:
                secretKeyRef:
                  name: heroes-secrets
                  key: BATCH_DB_USERNAME
            - name: BATCH_DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: heroes-secrets
                  key: BATCH_DB_PASSWORD
            - name: MAIL_USERNAME
              valueFrom:
                secretKeyRef:
                  name: heroes-secrets
                  key: MAIL_USERNAME
            - name: MAIL_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: heroes-secrets
                  key: MAIL_PASSWORD
          volumeMounts:
            - name: firebase-secret
              mountPath: /secrets
              readOnly: true
      volumes:
        - name: firebase-secret
          secret:
            secretName: heroes-firebase-secret

 

heroes-frontend-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: heroes-frontend-deploy
spec:
  replicas: 3
  selector:
    matchLabels:
      app: heroes-frontend
  template:
    metadata:
      labels:
        app: heroes-frontend
    spec:
      containers:
        - name: heroes-frontend
          image: <도커 이미지>
          ports:
            - containerPort: 80

 

heroes-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: heroes-service
spec:
  type: ClusterIP
  selector:
    app: heroes
  ports:
    - port: 8080           # 서비스에서 사용하는 포트
      targetPort: 8080      # 컨테이너에서 사용하는 포트
      protocol: TCP

 

heroes-frontend-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: heroes-frontend-service
spec:
  type: ClusterIP
  selector:
    app: heroes-frontend
  ports:
    - port: 80              # 서비스에서 사용하는 포트
      targetPort: 80        # 컨테이너에서 사용하는 포트
      protocol: TCP

 

redis-deploy.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:latest
          ports:
            - containerPort: 6379

 

redis-service.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deploy
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:latest
          ports:
            - containerPort: 6379

 

위 YAML 파일을 모두 준비한 후, kubectl apply -f ./ 명령어로 모든 파일을 배포.

 

이렇게 EKS에 사용하려는 리소스를 배포

 

다음 단계는 ALB 및 Ingress 설정을 통해 외부 트래픽을 안정적으로 처리하도록 구성하는 작업이 필요하다.