AWS 클라우드 실습 (TIL 24)

석형원·2024년 5월 2일

TIL

목록 보기
24/52
post-thumbnail

✏️ 오늘 학습한 내용

AWS 클라우드 실습

  • SpringBoot 구성
  • VPC 구성
  • EC2 구성
  • Elastic Beanstalk 구성
  • 콘솔 접속
  • RDS 구성
  • S3 구성
  • CI/CD 구성

🔎 AWS 클라우드 실습

  • 구성도

시나리오 :
내부적으로 Public / Private subnet을 나누어 서비스를 진행,

제공 할 서비스(Elastic Beanstalk)는 private 영역에 instance을 띄움, 또한 DBMS(RDS)도 private 영역에 설치

public은 baston host라는 터널링을 통해서 인터넷 게이트웨이에 접속할 수 있도록 구성 ( 외부 통신 )

서비스 명을 정하고 도메인을 만들었으면,
route53에 등록해서 SSL 인증서를 적용하고,
CloudFront를 구성해서 S3에 정적 웹 호스팅 기능으로 간단한 React 소스를 올려놓고 배포를 진행

마지막으로, local의 소스코드를 git repository에 업로드하면 codepipeline을 통해 자동적으로 서버에 배포까지 될 수 있도록 진행.


SpringBoot 구성

SpringBoot로 백엔드 역할을 해줄 형식적인 프로젝트를 간단하게 구현하겠습니다.

Spring 프로젝트를 생성하는 툴은 Gradle을 사용할 것입니다.

Gradle이란

  • 거의 모든 유형의 소프트웨어를 빌드할 수 있을 만큼 유연한 오픈 소스 빌드 자동화 도구

SpringBoot 프로젝트 with gradle

Intellij를 사용해 Gradle로 프로젝트를 생성하겠습니다.


빌드는 Gradle로 진행하고 JDK는 Amazon Coretto 17버전으로 지정하여 프로젝트를 생성합니다.

AWS CodeCommit 대신 Github를 이용할 것이기에 방금 만든 프로젝트를 Github에 업로드 하겠습니다.

https://github.com/lv1turtle/citron

필요하신 분은 fork 혹은 clone하셔서 사용하시면 됩니다.


VPC 구성

  • VPC 생성

    • VPC 명 : citron-vpc
    • 가용 영역(AZ) 수 : 2
    • 서브넷 : public 2개, private 2개
    • NAT 게이트웨이 : 1개의 AZ에서만 나갈 수 있도록 설정
    • 그 외는 default
  • 완료


EC2 구성

시나리오의 baston host 역할을 해줄 EC2를 생성

  • EC2 생성

    • 대부분 default 옵션을 사용
  • 키 페어 생성

    • 필자는 윈도우 환경이므로 .ppk를 선택
  • 네트워크 설정

    • VPC : 위에서 설정한 Citron-vpc를 선택
    • 서브넷 : baston host는 Public subnet에 위치해야하므로 public-2a를 선택
    • 퍼블릭 IP 자동 할당 ✅
    • 그 외 default

Elastic Beanstalk 구성

  • Elastic Beanstalk 생성 - 환경 구성

    • 애플리케이션 이름 : citron-app
    • 환경이름 : Citronapp-env
    • 도메인 : 임시로 citron12로 지정
    • 플랫폼 : Java, Corretoo 11 Linux 2
  • 서비스 액세스 구성

    EC2 인스턴스 프로파일은 처음 앱을 만들기에 아무 것도 없을 것이다.
    이때, 없다고 그냥 넘어가게 되면 배포시 오류가 발생한다.
    아래처럼 생성을 하고 진행하자.

    • EC2 인스턴스 프로파일 생성

      IAM에서 EC2, RDS, S3의 FullAccess 권한 부여한 역할을 생성

  • 네트워크 구성(VPC)

    • 퍼블릭 IP 주소 활성화 ✅
    • 인스턴스 서브넷 : Private subnet 2개
    • 데이터베이스 : Private subnet 2개

    ( Elastic Beanstalk을 Public에 두어 간단하게 할 수 있지만 시나리오에 따라 Private subnet에 집어넣는다. )

  • 완료

    EC2에 Elastic Beanstalk이 생성된 것을 확인할 수 있다.


콘솔 접속

윈도우 환경이므로 EC2 접속을 위해 PuTTY를 사용하겠습니다.

  • Public Subnet 안의 baston host에 접속

    1. PuTTY 설치 및 실행
    2. baston host의 퍼블릭 IPv4 주소를 복사
    3. Putty의 Host Name에 복사해둔 주소 입력
    4. Putty의 Saved Sessions에 원하는 이름 작성
    5. Putty에 생성한 키 .ppk를 입력
    6. Session으로 돌아와 Save로 저장하고 Open으로 실행
    7. 위에서 Linux 환경으로 만들었으므로 계정은 "ec2-user"로 로그인
  • Private Subnet 안의 Elastic Beanstalk에 접속

    private subnet에 다이렉트로 접근할 수 없기에, baston host에 들어가서 접근해보자

    1. puttygen으로 키의 형식을 .pek에서 .pem으로 변환시켜준다.
      ( 참고 : https://iamrealizer.tistory.com/52 )
    2. .pem의 내용을 복사한다.
    3. putty로 baston host에 접속한다.
    4. sudo su - 명령어를 통해 root계정으로 shell을 실행시킨다.
    5. /home/ec2-user/.ssh 경로에서 복사한 내용으로 키.pem를 생성한다.
    6. chmod 400을 통해 사용자에게만 읽기 권한을 부여한다.
    7. 생성한 키를 통해 Citronapp-env의 프라이빗 Ipv4 주소로 접근한다.
      ssh -i 키파일 계정명@ip주소
  • Elastic Beanstalk 살펴보기

    • Elastic Beanstalk은 기본적으로 5000번 포트 안쪽에 있다.

      앞단에 nginx의 80포트가 5000번 포트로 리버스 프록시를 통해 연결을 해주기 때문.

      Reverse Proxy : 클라이언트 요청을 대신 받아 내부 서버로 전달해주는 것

    • Log 파일
      cd /var/log에 위치

      • nginx : nginx의 로그
      • web.stdout.log : Elastic Beanstalk의 WAS(웹 앱 서버)의 로그

      -> 로그들은 AWS 웹 콘솔으로도 확인할 수 있다. (동일한 로그 파일)


RDS 구성

RDS는 VPC의 Private subnet 내부에 구성하겠습니다.

  • RDS - DB 서브넷 그룹 생성

    • VPC : citron-vpc
    • 가용 영역 : citron-vpc에서 만든 AZ 2개 모두 선택
    • 서브넷 : 각 AZ의 Private subnet을 선택
  • 데이터베이스 생성

    • 엔진 옵션 : MySQL
    • 템플릿 : 프리 티어
    • 연결 : EC2 컴퓨팅 리소스에 연결 안함

      연결 시 EC2와 다이렉트로 연결할 수 있지만,
      Client 툴과도 연결해야하기 때문에 여기선 연결하지 않겠습니다.

    • VPC : citron-vpc
    • DB 서브넷 : 위에서 생성한 서브넷
    • 퍼블릭 액세스 ✅
    • VPC 보안 그룹 : launch-wizard
    • 가용영역 : 2a
  • 데이터베이스 접근

    • VPC 보안 그룹 (launch-wizard)

      위에서 설정한 VPC 보안 그룹의 인바운드 규칙에 mysql의 포트 번호가 3306이 설정되있는 지를 확인합니다. 없을 경우, 설정을 해야 접근이 가능합니다.

    • MySQL workbench로 접근

      Workbench를 열고 new Connection을 생성하겠습니다.
      DB를 private subnet에 구성했기에 직접 접근은 불가능하므로,
      ssh 터널링을 사용해 baston host을 거쳐 접근할 것입니다.
      이때, Connection MethodStandard TCP/IP over SSH로 꼭 변경해주시
      길 바랍니다.

      • MySQL Hostname : 생성한 RDS의 엔드포인트를 입력
      • Username : RDS DB에서 생성한 계정
      • SSH Hostname: baston host의 퍼블릭 ip주소
      • SSH Username : ec2-user
      • SSH Key File : .pem 형식의 키파일

      Test Connection을 눌러보면 처음 연결시 경고 문구가 나올 수 있습니다.
      그대로 실행을 해주고 pw를 입력해주면 Success가 나올 것입니다.

    • DB 내에 테이블 생성

      Workbench로 접속한 DB에 citron이란 이름의 schema를 생성하고,
      하위 테이블로 member_mst를 생성해보겠습니다.


S3 구성

웹 프론트 개발에 관련된 소스를 올려서 서비스할 수 있도록 S3의 정적 웹 호스팅 기능을 사용해보겠습니다.

  • 버킷 생성

    • 버킷 이름 : citron12.com
      ( Elastic Beanstalk을 구성할 때, 도메인을 citron12라 했으므로 버킷 이름도 동일하게 따라가겠습니다. )
    • 그 외 값은 default
  • 정적 웹 호스팅 기능 활성화

React 프로젝트 제작

S3 테스트를 위해 템플릿을 그대로 사용한 간단한 React 프로젝트를 만들어보겠습니다.
(Front)

  • 설치

    1. Node.js 설치
      https://nodejs.org/en/ 접속하여 LTS 버전 설치
    2. Npx 설치
      npm install npx -g
  • 템플릿 생성

    npx create-react-app citron-app

  • 실행

    cd citron-app
    npm start

React 프로젝트를 S3에 업로드

프로젝트를 빌드하여 생긴 build 폴더 내 파일들을 S3에 업로드하겠습니다.

  • 빌드
    npm run build

  • S3에 업로드

    build 내부 파일을 웹 콘솔을 통해 전부 업로드

  • 퍼블릭 액세스 차단 해제

  • 버킷 정책 생성 및 부여

    • 버킷 생성기를 사용
      • Type : S3 Bucket Polciy
      • Principal : *
      • Actions : ✅ All Actions
      • ARN : 버킷 정책 편집에 있던 url에 /*을 붙이겠습니다.
        ex) arn:aws:s3:::citron12.com/*

    .

    • 생성한 정책 붙여넣기
  • 서버 접속

    정적 웹 사이트 호스팅에 엔드포인트가 생성되었습니다.

    이 엔드포인트로 접속


CI/CD 구성

깃허브에 업로드한 Springboot로 만든 소스를 CI/CD 연동하겠습니다.

CodePipeline 생성

파이프라인 설정

소스 스테이지

  • 소스공급자 : Github(버전 2)
  • 트리거 : 트리거 필터 없음
  • 그 외는 개별 설정

빌드 스테이지

  • 빌드 공급자 : AWS CodeBuild
  • 프로젝트 이름 : 프로젝트 생성
  • 빌드 프로젝트 생성

    • Buildspec : 빌드 명령 삽입
    version: 0.2
     phases:
       build:
         commands:
           - ./gradlew build
     artifacts:
       files:
         - '**/*'

배포 스테이지

만약, public에서 배포를 진행하는 것이라면 Elastic Beanstalk으로 선택을 하면 쉽게 배포가 가능합니다.

하지만 private 내부에서 배포를 해야하기에 CodeDeploy를 만들때 ELB(로드밸런싱)를 통해 배포를 하도록 진행하겠습니다.

  • CodeDeploy 애플리케이션 생성

    CodeDeploy 세션으로 가서 애플리케이션을 생성해줍니다.

  • IAM 역할 생성

    배포 그룹에 서비스 역할을 넣기 위해 IAM 세션으로 가서 CodeDeployFullAccess 정책이 들어간 역할을 생성하겠습니다.

  • ELB(로드밸런싱) 대상 그룹 생성

    마찬가지로 CodeDeploy 배포 그룹에 넣어줄 ELB 대상 그룹을 생성해주겠습니다.
    ELB 세션으로 가서 대상 그룹을 생성해줍니다.

    • VPC : citron-vpc
    • 대상 등록 : citron-app
  • Application Load Balancer 생성

    • 체계 : 내부 (private ip 사용)
    • VPC : citron-vpc
    • 매핑 : private subnet 2개
    • 보안그룹 : 80포트로 통신할 것이므로 인바운드 규칙에 80포트가 허용된 보안그룹을 생성하거나 선택
    • 리스너 : HTTP:80, 위의 대상 그룹 선택
  • CodeDeploy 배포 그룹 생성

    준비가 되었으니 이제 CodeDeploy세션으로 돌아와 배포 그룹을 완성해주겠습니다.

    • 서비스 역할: 위에서 만든 역할
    • 환경 구성 : Amazon EC2 Auto Scaling 그룹
    • 로드밸런서 : ✅로드 밸런싱 활성화
    • ✅Application Load Balancer : 위에서 만든 대상 그룹 (citron-service-target)
    • 그 외 default
  • 배포 스테이지 작성

    다시 배포 스테이지로 돌아와 위에서 작성한 Deploy 애플리케이션과 그룹을 선택하면 종료!

파이프라인 완료?

인줄 알았으나 문제가 발생하였습니다.
자.. 하나씩 해결해보겠습니다..

  • 첫 시도

    에러 로그가 날라가 올리지 못했지만,
    java가 없거나 버젼이 맞지 않아 생긴 문제일 것이라 추측했습니다.
    CodeBulid의 Buildspec에서 java11를 설치하도록 변경!

  • 두 번째 시도

    에러 로그./gradlew: Permission denied를 보아 접근권한에 문제라고 생각해 실행할 때 접근 권한을 줘보도록 수정하겠습니다.

  • ㅅ..세 번째 시도


    Gradle 명령어가 실행됬지만 설치에 실패했습니다.
    Java 버젼의 문제로 보이기에 17로 올려보겠습니다.

  • 네 번째 시도

    Build는 성공했지만 Deploy에서 문제가 발생했습니다.

    오류를 타고 타고 들어가보니 BeforeBlockTraffic이란 이벤트에서 UnknownError가 발생한 것을 확인했습니다.

    초기부터 발생한 에러를 보아 인스턴스(Elastic Beanstalk)에 Code Deploy의 역할이 부여되지 않았다고 생각했고,

    검색 끝에 Elastic Beanstalk에 부여한 EC2 인스턴스 프로파일(역할)에 AmazonEC2RoleforAWSCodeDeploy 정책을 한번 추가해보았습니다.

  • 다섯 번째 시도

    여전히 오류는 남아있었고.. 서버에 CodeDeploy agent가 설치가 안되어있다는 것을 확인했습니다. 설치 후 재시도해보겠습니다.

    CodeDeploy agent 설치 : https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-cli.html

    putty를 사용해 Elastic Beanstalk에 접근하였고 위 가이드를 참고하여 agent를 설치해줬습니다.

    # Elastic Beanstalk : citron-app
    sudo yum update
    sudo yum install ruby
    sudo yum install wget
    
    cd /home/ec2-user
    # Seoul region
    wget https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install
    
    # 권한 부여
    chmod +x ./install
    # 최신 agent 설치
    sudo ./install auto
    
    # codedeploy-agent 상태 확인
    sudo service codedeploy-agent status
    
    # codedeploy-agent 서비스 시작
    sudo service codedeploy-agent start
    
    # 로그 보는 명령어
    tail -f /var/log/aws/codedeploy-agent/codedeploy-agent.log

  • 여섯 번째 시도

    BeforeBlockTraffic은 해결됐지만 BeforeInstall에서 동일한 에러가 발생했습니다. 로그를 확인해보니 AppSpec.yml 파일이 없기에 발생한 일이라고 합니다. 위에서 SpringBoot 프로젝트에 appspec.yml과 관련 스크립트 파일을 추가 후 Github에 재업로드를 진행하겠습니다.

    #appspec.yml
    version: 0.0
    os: linux
    
    files:
      - source:  / # Github에 업로드한 모든 파일이
        destination: /home/ec2-user/build/ # 이 위치로 복사된다.
  • 성공!


📒 참고

Gradle : https://velog.io/@tjseocld/Gradle-%EC%9D%B4%EB%9E%80
Putty : https://velog.io/@heejung/AWS-EC2%EC%97%90-PuTTY%EB%A1%9C-%EC%A0%91%EC%86%8D%ED%95%98%EA%B8%B0
Puttygen : https://iamrealizer.tistory.com/52
CodeDeploy agent : https://docs.aws.amazon.com/ko_kr/codedeploy/latest/userguide/codedeploy-agent-operations-install-cli.html
AppSpec.yml : https://velog.io/@juhyeon1114/%EC%8B%A4%EC%A0%84-Github-actions-AWS-Code-deploy%EB%A1%9C-Spring-boot-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0

profile
데이터 엔지니어를 꿈꾸는 거북이, 한걸음 한걸음

0개의 댓글