ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [AWS] Spring Boot, S3, Travis CI, Auto-Scaling, Load-Balacner, CodeDeploy로 자동화 배포하기
    Cloud/AWS 2021. 4. 14. 11:04
    728x90
    반응형

    AWS Auto-Scaling, CodeDeploy로 배포 자동화 하기

    CodeDeploy를 사용하기 위해서는 역할, 정책, 사용자 개념에 대해서 알아야 합니다. 아래의 글을 읽기 전에 여기 에서 간단하게 IAM 개념에 대해 학습하고 오시는 걸 추천합니다.

     

     

    역할 생성

    스크린샷 2021-04-13 오후 3 23 04스크린샷 2021-04-13 오후 3 24 11스크린샷 2021-04-13 오후 3 24 58

     

    위와 같이 기본으로 [AWSCodeDeployRole]이 존재하는 것을 볼 수 있습니다.

     

     

    스크린샷 2021-04-13 오후 3 26 52

     

    즉, 해당 역할은 CodeDeploy에 접근할 수 있도록 하기 위해서 만드는 것입니다.

     

     

     

    정책 생성

    스크린샷 2021-04-13 오후 3 29 07

    {
        "Version": "2012-10-17",
        "Statement": [
            {
                "Action": [
                    "s3:Get*",
                    "s3:List*"
                ],
                "Effect": "Allow",
                "Resource": "*"
            }
        ]
    }

     

     

    스크린샷 2021-04-13 오후 3 29 53

     

    S3에 접근할 수 있도록 정책을 하나 만들겠습니다. 기존에 존재하는 역할을 사용해도 되지만 본인이 원하는 정책으로 커스텀해서 역할을 만들고 싶을 때 위와 같이 할 수 있습니다.

     

     

     

    역할 만들기

    스크린샷 2021-04-13 오후 3 31 39스크린샷 2021-04-13 오후 3 32 44

     

    사용자나 그룹들에 권한을 직접 적용할 수는 없고 권한들로 만든 정책을 적용해야 하기 때문에 방금 만든 정책을 추가하겠습니다.

     

     

    스크린샷 2021-04-13 오후 3 33 52스크린샷 2021-04-13 오후 3 35 42

     

    즉 해당 역할은 Auto-Scaling과 CodeDeploy로 배포하는 과정에서 통해 각 EC2가 S3 버켓에 파일들을 읽어올 수 있도록 부여하는 역할입니다.

     

     

     

     

    시작 템플릿 만들기

    스크린샷 2021-04-13 오후 2 14 56스크린샷 2021-04-13 오후 2 15 31스크린샷 2021-04-13 오후 2 36 09스크린샷 2021-04-13 오후 3 39 31

     

    위와 같이 시작 템플릿에서 인스턴스 프로파일을 설정해주어야 템플릿으로 생성된 인스턴스들은 [Auto-Scaling-Gyunny-Role] 역할을 갖고 시작될 것입니다. (그래야 배포에 성공할 수 있기 때문에 꼭 잘 설정을 해주어야 합니다.) 즉 해당 역할은 EC2에 설치되어 있는 CodeAgent가 S3 버켓을 잘 읽어올 수 있도록 하기 위해서 설정하는 것입니다.



    Auto Scaling Group 만들기

    스크린샷 2021-04-13 오후 5 15 39

    Auto Scaling Group 만들기 를 참고해서 만들고 오시면 됩니다.

    • 최소 인스턴스, 적정 인스턴스, 최대 인스턴스 모두 2로 만들었습니다.
    • 기존 로드 밸런서에 연결을 했습니다.

     

     

     

    스크린샷 2021-04-13 오후 5 19 54

     

    그렇게 Auto Scaling Group을 만들고 설정할 때 희망 인스턴스 수를 2로 했다면 위와 같이 인스턴스 2개가 새로 만들어졌을 것입니다.

     

     

    스크린샷 2021-04-13 오후 5 22 02

     

    그리고 로드 밸런서 대상 그룹에 가보면 위와 같이 정상적으로 로드밸런서에 연결이 되어 있는 것을 볼 수 있습니다.

     

    CodeDeploy 생성하기

    스크린샷 2021-04-13 오후 5 23 56스크린샷 2021-04-13 오후 5 25 55

     

    이번에 지정하는 역할은 어떤 것일까요? 저 해당 역할의 내용들을 보면 Auto-Scaling, Load-Balancer 등등에 관련된 설정이 되어 있는 정책이 있는 것을 볼 수 있습니다.
    즉, CodeDeploy에게 해당 역할을 부여해야 CodeDeploy를 통해 Load-Balancer에 연결된 Auto-Scaling 그룹에 배포를 할 수 있는 것입니다.

     

     

    스크린샷 2021-04-13 오후 5 29 00스크린샷 2021-04-13 오후 5 30 24

     

    배포 설정의 종류는 3가지가 존재합니다. 각각의 특징은 아래와 같습니다.

    • CodeDeployDefault.OneAtTime: 한 번에 하나씩 배포
    • CodeDeployDefault.HalfAtTime: 절반씩 배포
    • CodeDeployDefault.AllAtOnce: 한꺼번에 배포

     

     

    여기서는 그냥 CodeDeployDefault.AllAtOnce로 진행하겠습니다. (나중에 좀 더 커스텀하게 해서 사용해보겠습니다.)



     

     

    Spring Boot로 자동화 배포 테스트

    1

    현재 진행하고자 하는 아키텍쳐는 위와 같습니다.

    • CI 도구는 Travis CI를 사용하였습니다.
    • CD는 CodeDeploy 를 사용하여 Auto-Scaling Group에 배포를 진행하고 있습니다.

     

    참고로 이번 글에서는 Travis CI에서 IAM 사옹자 엑세스 키 설정에 대해서는 다루지 않습니다.

     

    스크린샷 2021-04-13 오후 5 35 50

     

    전체 프로젝트 구조는 위와 같습니다.

    • travis.yml: Travis CI가 어떻게 작동해야 하는지에 대해 작성합니다.
    • appspec.yml: CodeDeploy가 배포할 때 각 과정마다 어떻게 동작해야 하는지에 대해 작성합니다.
    • deploy.sh: 배포가 된 후에 EC2 내부에서 작동해야 할 명령어들에 대해서 적습니다.

     

    각각 하나씩 어떤 것인지 알아보겠습니다.

     

     

     

    travis.yml

    language: java
    jdk:
      - openjdk11
    
    brances:
      only:
        - master
    
    cache:
      directories:
        - '$HOME/.m2/repository'
        - '$HOME/.gradle'
    
    script:
      - "./gradlew clean build"
    
    # before_deploy 과정에서 S3에 파일을 저장하고 EC2에 배포할 것들에 대해서 작성합니다. 
    before_deploy:
      - mkdir -p before-deploy # zip에 포함시킬 파일들을 담을 디렉토리 생성
      - cp scripts/*.sh before-deploy/
      - cp Dockerfile before-deploy/    # Dockerfile 디렉토리로 이동
      - cp appspec.yml before-deploy/   # appspec.yml  디렉토리로 이동
      - cp build/libs/*.jar before-deploy/  # jar 파일도 디렉토리로 이동
      - cd before-deploy && zip -r before-deploy * # before-deploy로 이동후 전체 압축
      - cd ../ && mkdir -p deploy # 상위 디렉토리로 이동후 deploy 디렉토리 생성
      - mv before-deploy/before-deploy.zip deploy/SpringBoot_CI-CD.zip # deploy로 zip파일 이동
    
    deploy:
      - provider: s3
        access_key_id: $AWS_ACCESS_KEY         # Travis CI 에서 IAM 사용자 엑세스 키
    
        secret_access_key: $AWS_SECRET_KEY     # Travis CI 에서 IAM 사용자 비밀 엑세스 키
    
        bucket: aws-gyun-s3        # S3 Bucket 이름
        region: ap-northeast-2
        skip_cleanup: true
        acl: private
        local_dir: deploy
        wait-until-deployed: true
    
      - provider: codedeploy
        access_key_id: $AWS_ACCESS_KEY        # Travis CI 에서 IAM 사용자 엑세스 키
    
        secret_access_key: $AWS_SECRET_KEY    # Travis CI 에서 IAM 사용자 비밀 엑세스 키
    
        bucket: aws-gyun-s3         # S3 Bucket 이름
        key: SpringBoot_CI-CD.zip
        bundle_type: zip                 # zip 형태라는 걸 명시
        application: Gyunny              # CodeDeploy 애플리케이션 이름
    
        deployment_group: Gyunny-Group   # CodeDeploy 배포 그룹 이름
    
        region: ap-northeast-2
        wait-until-deployed: true
    
    notification:
      email:
        recipients:
          - wjdrbs966@naver.com    # 해당 메일로 알림이 옴

    각각 어떤 뜻인지는 주석으로 적어놓았습니다. CodeDeploy 애플리케이션 이름, 애플리케이션 그룹, S3 버켓 이름들 잘 맞게 썼는지 확인을 해야 합니다. 또한 before_deploy 과정에서 배포에 필요한 파일들을 zip으로 압축하기 때문에 어떤 파일을 옮겨야 하는지 잘 보아야 합니다.

     

     

    appspec.yml

    version: 0.0
    os: linux         # 현재 EC2 Linux2를 사용하고 있습니다.
    files:
      - source:  /   # 프로젝트 전체를 의미
        destination: /home/ec2-user/app/step2/zip/   # EC2 내부에 해당 위치에 파일을 옮기겠다는 뜻 (본인이 원하는 곳을 지정하면 됩니다.)
        overwrite: yes
    
    permissions:
      - object: /
        pattern: "**"
        owner: ec2-user
        group: ec2-user
    
    hooks:
      ApplicationStart:
        - location: deploy.sh  # ApplicationStart 에서 deploy.sh를 실행합니다. 
          timeout: 60
          runas: ec2-user

     

     

    deploy.sh

    echo "> 현재 실행 중인 Docker 컨테이너 pid 확인" >> /home/ec2-user/deploy.log
    CURRENT_PID=$(sudo docker container ls -q)
    
    if [ -z $CURRENT_PID ]
    then
      echo "> 현재 구동중인 Docker 컨테이너가 없으므로 종료하지 않습니다." >> /home/ec2-user/deploy.log
    else
      echo "> sudo docker stop $CURRENT_PID"
      sudo docker stop $CURRENT_PID
      sleep 5
    fi
    
    cd /home/ec2-user/app/step2/zip/     # 해당 디렉터리로 이동
    sudo docker build -t gyunny ./       # 이미지 만들기
    sudo docker run -d -p 8080:8080 gyunny  # Docker Container 생성
    sudo docker run -d -p 8081:8080 gyunny  # Docker Container 생성

    쉘 스크립트도 위에 적혀있는 거 같이 현재 실행 중인 것이 있다면 죽이고 새로 컨테이너를 띄우는 식으로 스크립트 파일을 작성하였습니다. (도커를 좀 더 깔끔하게 커스텀 할 수 있을 거 같긴 하지만..)

     

     

     

    자동화 배포 시작해보기

    스크린샷 2021-04-13 오후 5 44 47

     

    위와 같이 간단한 Controller를 만든 후에 Github에 push를 해보겠습니다.

     

     

    스크린샷 2021-04-13 오후 5 46 10

     

    그러면 Travis CI에서 위와 같이 자동으로 해당 커밋에 대해서 CI를 수행합니다. (travis.yml에 적은 대로)

     

     

    스크린샷 2021-04-13 오후 5 47 21스크린샷 2021-04-13 오후 5 48 02

     

    그리고 CodeDeploy에 보면 위와 같이 배포가 성공적으로 잘 된 것을 볼 수 있습니다. 이제 Auto Scaling으로 만들어졌던 EC2에 각각 접속해서 확인해보겠습니다.

     

     

    스크린샷 2021-04-13 오후 5 49 20스크린샷 2021-04-13 오후 5 48 59

     

    그러면 위와 같이 EC2 각각에 Docker Container가 실행되고 있는 것도 확인할 수 있습니다.

     

     

    스크린샷 2021-04-13 오후 5 53 37스크린샷 2021-04-13 오후 5 53 42

     

    그리고 실제 EC2 주소로 접속했을 때 위와 같이 잘 뜨는 것을 볼 수 있습니다.

    반응형

    댓글

Designed by Tistory.