본문 바로가기
개발이야기

AWS Elastic Beanstalk으로 개발서버를 구축해본 이야기

by janiiiiie 2021. 10. 13.
반응형

안녕하세요 :) 제인입니다.

 

현재 디자이너, 프론트엔드 분들과 함께 사이드 프로젝트를 진행하고 있는데요, 백엔드 포지션이다 보니 아무래도 같은 개발자인 프론트엔드 분들과 이야기할 시간이 많습니다. 프론트엔드 분들이 좀 더 원활하게 백엔드와 협업하기 위해서 Swagger는 거의 필수로 가져가고 있는 기능인데요, 얼마 남지 않은 개발시간과 문서정리 시간이 살짝 부족할 것 같아 우선적으로 개발서버를 띄워 보다 편하게 스웨거에 접근할 수 있도록 구축하기로 결정했습니다. 

 

 

Elastic Beanstalk & Github Actions CD

저희는 최종적으로 AWS EC2가 아닌 Beanstalk을 이용하기로 했는데요, EC2/RDS/S3를 한꺼번에 같이 운영할 수 있고, 트래픽 5만 미만은 추가적인 요금을 물지 않기 때문에 크레딧이 부족한 상황에 제격이라고 판단했습니다.

 

어플리케이션 만들기

먼저, AWS 콘솔에 접속에 Elastic Beanstalk에 들어가 새로운 어플리케이션을 생성합니다. (현재 IAM 계정이 생성되어있다는 가정입니다.)

 

웹 앱 생성에 어플리케이션 이름(변경 불가능입니다)과 플랫폼을 설정합니다. 저는 자바/스프링부트 기반이기 때문에 이에 맞춰서 셋팅해주었습니다. 애플리케이션은 샘플 어플리케이션을 선택 후, "어플리케이션 생성"을 클릭합니다.

 

 

환경 생성하기

위의 블로그 가이드를 따라 애플리케이션을 생성했다면 이제 내부에 환경을 생성할 차례 입니다. 오른쪽 위에 새 환경 생성을 눌러줍니다.

 

 

 

환경 이름을 입력해주고(수정불가능) 추가옵션 구성을 클릭합니다. 추가 옵션에서는 여러 설정을 할 수 있는데요, 저는 jojoldu님의 블로그 글을 참고해 설정하였습니다. 운영서버가 아닌 개발서버이기 때문에 해당 블로그와 같이 간단하게 적용해도 되겠다고 판단하였고, 로드밸런싱(ALB) 또한 개발서버의 경우 불필요하게 늘릴 필요가 없을 것 같아 우선 1개로 해두었습니다.

 

위의 인스턴스 보안 그룹의 경우 저는 이미 기존의 elastic beanstalk 보안그룹이 구성이 되어 있어 이렇게 뜨게 되는데요, 아마 설정을 해주지 않는다면 자동으로 EC2에 default 보안그룹 제외 나머지 3개를 생성해주는 것으로 알고있습니다. 따로 설정한 보안그룹을 사용하고 싶다면 EC2 메뉴에 가서 보안그룹을 생성을 하시면 됩니다. 

 

pem key 설정하기

보안 이라는 탭에 들어가면 수정을 할 수 있는데, 이 때 pem key가 필요합니다. pem key를 한번도 생성해보지 않았다면, EC2 메뉴에 가서 생성을 해야합니다. 

왼쪽은 Elastic Beanstalk - 환경생성 - 보안        오른쪽은 EC2 - 왼쪽 메뉴바 아래

 

 

 

키 페어의 이름을 설정하고 아래와 같이 설정합니다. 키 페어 생성을 클릭하면 .pem 확장자로 키가 다운로드 되는데 이 때, 이 키를 잃어버리시면 안됩니다. 원래는 ssh 접속을 위해 따로 설정해줄 게 있긴 하지만 EB 환경을 셋팅하는데는 키 페어 생성까지만 해도 무방하여 여기까지만 하도록 하고, Elastic Beanstalk 환경으로 넘어가 방금 보안수정에서 생성한 키 페어를 선택해주도록 합니다. 

 

 

RDS 설정하기

EB 환경에서는 RDS 환경을 쉽게 구축할 수 있습니다. 저희는 postgres 를 사용하고 있고, 사용자 이름/암호 또한 커스텀으로 넣어주도록 합니다.(잊어버리지만 맙시다) 

 

아래에 보시면 데이터 베이스 삭제 정책이라는 설정창이 있는데요, EB환경을 지울 때 RDS도 같이 지워지도록 하는 정책입니다. 저는 안전을 위해서 EB 환경이 지워지면 같이 삭제되도록 선택해주었습니다. 

 

여기까지 설정이 되었다면, 이제 환경생성을 클릭해 환경을 생성하도록 합니다. 이 과정은 조금 오래 걸릴 수 있으니 인내심을 가지고 기다립니다. 😭

 

 

Github Actions 에서 AWS 접근을 위한 Access key 발급하기

깃허브 액션을 사용할 때, 저희의 소스코드를 EB 환경에 접근하여 업로드를 해줘야하는데, 이 때 Access Key가 필요합니다. 먼저 IAM 메뉴에 접속합니다.

 

사용자이름은 원하는 명을 입력해주고, 자격증명 유형은 액세스 키(Access Key)를 선택해줍니다. 다음으로 넘어가면 권한 설정이 있는데, 저는 Elastic Beanstalk Administrator 접근 권한을 설정했습니다. 

 

이 후, 태그 같은 건 옵션이기 때문에 넘어가도록 하고, 마지막으로 가면 액세스 키가 csv 파일로 발급이 됩니다. 이 키값은 잊어버리지 않도록 주의하도록 하며, 연결을 원하는 깃허브 레파지토리를 갑니다.

 

 

깃허브 액션에 주입할 비밀키 이기 때문에 Settings -> Secrets -> New respository secret으로 가서 Access key ID 와 Secret Access Key 값을 입력해 저장합니다. 

 

 

Github Actions 스크립트 작성하기

이제 EB 환경으로 업로드 하고 배포할 수 있게 CD 스크립트를 작성해주도록 합니다. 저는 아래와 같이 작성해주었습니다.

# 개발서버 Deploy workflow - develop 브랜치
name: DaeDong-BreadMap dev server CD

on:
  push:
    branches:
      - 'develop'   # develop 브랜치에 푸시 된 코드들만 개발서버 배포

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v2

      - name: Set up JDK 1.8
        uses: actions/setup-java@v1
        with:
          java-version: 1.8

      - name: Grant execute permission for gradlew
        run: chmod +x gradlew

      - name: Build with Gradle
        run: ./gradlew build -x test

      - name: Test with Gradle
        run: ./gradlew test

      - name: Get current time    # 빌드 될 때마다 해당 타임스탬프로 태그가 붙은 파일 배포
        uses: 1466587594/get-current-time@v2
        id: current-time
        with:
          format: YYYY-MM-DDTHH-mm-ss
          utcOffset: "+09:00"

      - name: Generate deployment package
        run: |
          mkdir -p deploy-dev
          cp build/libs/*.jar deploy-dev/application.jar
          cp Procfile deploy-dev/Procfile
          cp -r .ebextensions deploy-dev/.ebextensions
          cp -r .platform deploy-dev/.platform
          cd deploy-dev && zip -r deploy-dev.zip .
          
      - name: Deploy to Elastic Beanstalk dev-server
        uses: einaregilsson/beanstalk-deploy@v14
        with:
          aws_access_key: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws_secret_key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          application_name: daedong-breadmap
          environment_name: Daedongbreadmap-env
          version_label: Daedong Bread Map-${{steps.current-time.outputs.formattedTime}}
          region: ap-northeast-2
          deployment_package: deploy-dev/deploy-dev.zip
          wait_for_environment_recovery: 180

방금 Secrets에 넣은 AWS access key 정보에 여기에 쓰이게 됩니다.

 

 

배포에 필요한 파일 Procfile, .ebextensions, .platform

Procfile

web: appstart

리버스 프록시를 담당할 nginx 설정파일 입니다.

 

.ebextensions/00-makeFiles.config

files:
    "/sbin/appstart" :
        mode: "000755"
        owner: webapp
        group: webapp
        content: |
            #!/usr/bin/env bash
            JAR_PATH=/var/app/current/application.jar

            # run app
            killall java   # 현재 실행 중인 자바 어플리케이션 종료
            java -Dfile.encoding=UTF-8 -jar $JAR_PATH   # 새로 배포된 jar 파일 실행

EB는 대부분의 작업이 자동화 되어있는데요, 커스텀하게 지정해주고 싶다면 이 파일을 이용해야합니다. 

 

 

.ebextensions/00-set-timezone.config

commands:
  set_time_zone:
    command: ln -f -s /usr/share/zoneinfo/Asia/Seoul /etc/localtime

EB환경의 시간을 아시아/서울로 설정을 하기 위해서 따로 추가한 파일입니다. 

 

 

.platform/nginx/nginx.conf

user                    nginx;
error_log               /var/log/nginx/error.log warn;
pid                     /var/run/nginx.pid;
worker_processes        auto;
worker_rlimit_nofile    33282;

events {
    use epoll;
    worker_connections  1024;
}

http {
  include       /etc/nginx/mime.types;
  default_type  application/octet-stream;

  log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';

  include       conf.d/*.conf;

  map $http_upgrade $connection_upgrade {
      default     "upgrade";
  }

  upstream springboot {
    server 127.0.0.1:8080;
    keepalive 1024;
  }

  server {
      listen        80 default_server;

      location / {
          proxy_pass          http://springboot;
          proxy_http_version  1.1;
          proxy_set_header    Connection          $connection_upgrade;
          proxy_set_header    Upgrade             $http_upgrade;

          proxy_set_header    Host                $host;
          proxy_set_header    X-Real-IP           $remote_addr;
          proxy_set_header    X-Forwarded-For     $proxy_add_x_forwarded_for;
      }

      access_log    /var/log/nginx/access.log main;

      client_header_timeout 60;
      client_body_timeout   60;
      keepalive_timeout     60;
      gzip                  off;
      gzip_comp_level       4;

      # Include the Elastic Beanstalk generated locations
      include conf.d/elasticbeanstalk/healthd.conf;
  }
}

현재 로드밸런서(ALB)가 앞 단에 있기 때문에 이 후 배포를 위해서 위와 같은 nginx 설정이 필요합니다.

 

 

프로젝트 내 application.yml 및 Profile 정리

깃허브에 올릴 때는 개발서버에 대한 접속정보가 공개가 되어서는 안됩니다. Swagger 또한 위에서 언급한 바와 같이, 보안 문제로 특정 아이피에서만 접속되도록 해야하기 때문에 yml 설정파일의 정리가 필요합니다.

 

application.yml

spring:
  datasource:
    url: jdbc:h2:mem:testdb
    username: sa
    password:
    driver-class-name: org.h2.Driver
  profiles:
      group:
        dev: dev, oauth
        ebdev: ebdev, eboauth

  jpa:
    hibernate:
      ddl-auto: create-drop
    properties:
      hibernate:
        format_sql: true

app:
  auth:
    tokenSecret: secretkeysecretkeysecretkeysecretkeysecretkeysecretkey
    tokenExpiry: 3333333333

현재 디폴트 프로파일로 작동 될 application.yml에는 h2 DB 정보만 적어 주었으며, 해당 디비는 사용되지 않을 것이기 때문에 create-drop을 시켜주었습니다. 저희가 실질적으로 깃허브 상에 올릴 yml 파일은 ebdev/eboauth 파일이라 이 두 설정파일이 "ebdev" 프로파일일 때 같이 동작될 수 있도록 설정하였습니다. 아래 app.auth.token~ 설정은 실제로 사용하는게 아닌, 가짜로 넣어준 값입니다. 주입받는 부분이 있기 때문에 적어주지 않는다면 빈 생성 실패로 에러가 발생합니다. 

 

 

application-ebdev.yml

spring:
  datasource:
    url: jdbc:postgresql://${rds.hostname}:${rds.port}/${rds.dbname}
    username: ${rds.username}
    password: ${rds.password}
    driver-class-name: ${rds.driver}

  jpa:
    hibernate:
      ddl-auto: none
    database: postgresql
    properties:
      hibernate:
        format_sql: true
    generate-ddl: true

swagger-info:
  title: ${swagger.title}
  description: ${swagger.description}
  version: ${swagger.version}

logging:
  level:
    org.hibernate.SQL: debug

이 파일을 이용해 배포 후, 원하는 RDS로 연결될 수 있도록 합니다. ${} 값에 들어갈 정보는 어떻게 설정하는지는 아래에 설명하도록 하겠습니다. 

Swagger 설정 또한, 개발서버에서만 사용할 것이기 때문에 이 설정파일에만 Swagger 관련 값들을 넣어주도록 합니다. 

 

application-eboauth.yml

app:
  auth:
    tokenSecret: ${app.auth.token.secret}
    tokenExpiry: ${app.auth.token.expiry}

실질적으로 소셜로그인에 필요한 tokenSecret값고 토큰 유효기간 설정정보입니다.

 

 

SwaggerConfig Profile 설정하기

스웨거가 ebdev 환경에서만 설정할 수 있도록 swagger configuration 클래스 상단에 아래와 같은 어노테이션을 추가해주도록 합니다.

/*
    dev, ebdev 환경에서만 Swagger 동작하도록 설정
    run configuration의 VM option: -Dspring.profiles.active=dev or ebdev 설정 필요
 */
@Configuration
@Profile({"ebdev", "dev"})  # 프로파일 설정
@EnableSwagger2
public class SwaggerConfig implements WebMvcConfigurer {

 

 

설정파일에 주입할 환경변수 설정하기

 

이 부분은 AWS Elastic Beanstalk 콘솔에서 설정할 수 있습니다.

 

편집을 클릭하여 아래로 내리면 배포할 소스코드 설정 값에 주입할 환경변수를 직접 입력할 수 있습니다.

이 때 이름설정에 주의할 점은 스네이크케이스 + 대문자 입니다. 

예를 들어, RDS_DBNAME 이라고 설정해두었다면 yml 파일에는 ${rds.dbname} 으로 설정해주어야 제대로 맵핑이 됩니다. 

 

이렇게 까지 설정 후, develop 브랜치에 푸시해서 개발서버에 배포를 해보도록 하겠습니다. 

 

이전에 무수한..(^^) 삽질이 있긴 했지만 잘 배포는 완료되었습니다. (감격) 이제 개발서버 URL에 들어가서 아래처럼 스웨거가 잘 뜬다면 모든 배포 프로세스가 잘 마무리 된 것입니다!!!! 👏👏👏👏👏👏

 

 

만세!!!!!!!!! 눈물흘릴 뻔..?

반응형