Github Action에서 CodeDeploy를 이용해서 EC2에 Deploy 해보자

이창주·2023년 5월 29일
0

Backend

목록 보기
4/7

CodeDeploy를 이용해서 S3에 복사된 파일을 EC2에 Deploy되도록 Github action을 설정해 본다.

CodeDeploy Application 생성

AWS > CodeDeploy검색해서 Application을 생성한다.

Application name: springbootcamp-deploy
Compute platform: EC2/On-premises

그룹생성

application이 속하는 그룹을 생성한다.

이름은 springbootcamp-deploy-group를 사용했지만, 향후에는 좀 단순하게 develop 과 같은 형태로 변경이 필요해보인다.

이때 IAM에서 생성했던 CodeDeploy용 role(springbootcamp-codedeploy-role)을 사용한다.

springbootcamp-codedeploy-role
는 다음과 같은 관련된 모든 권한을 가지도록 설정했다.(필요없는건 제거가 필요해 보인다.)

다음은 Deploy type은 in-place를 선택하고,

Environment configuration은 Amazon EC2 instances를 선택한다.

나머지는 기본값을 사용한다.

EC2에서 jar파일을 적용할때 무중단배포 설정을 이용할 것이기 때문에 여기서 load balancer를 사용하지 않는다.(나중에는 ALB로 변경하는게 좋은선택일 것 같다)

이제 application 에 그룹 생성이 완료되었다.

Github action

appspec.yml 생성

프로젝트의 루트 디렉토리에 appspece.yml 이름으로 파일을 생성한다.

S3/Github에서 어떤 것을 EC2로 install할지를 결정하고,
deployment lifecycle 이벤트에 hook을 설정하는데 사용된다.

version: 0.0
os: linux
files:
  - source:  /
    destination: /home/ec2-user/action
    overwrite: yes

permissions:
  - object: /
    pattern: "**"
    owner: ec2-user
    group: ec2-user

hooks:
  ApplicationStart:
    - location: scripts/run-codedeploy.sh
      timeout: 60
      runas: ec2-user

bundle install 이후에 ApplicationStart event에 scripts/deploy.sh를 실행한다.

develop.yml 작성

이제 github action 에 codedeploy step을 추가해 보자.

env:
  S3_BUCKET_NAME: S3 버킷 이름
  AWS_REGION: ap-northeast-2
  CODEDEPLOY_APPNAME: CodeDeploy 앱이름
  CODEDEPLOY_GROUPNAME: CodeDeploy 배포그룹 이름
  
jobs:
  build:
    runs-on: ubuntu-latest

    steps:
    ...

    - name: Make a bundle for CodeDeploy
      run: zip -r ./$GITHUB_SHA.zip appspec.yml ./springbootcamp-$GITHUB_SHA.jar scripts/
      shell: bash
      
    - name: CodeDeploy to deploy the bundle
      run: aws deploy create-deployment --application-name $CODEDEPLOY_APPNAME --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name $CODEDEPLOY_GROUPNAME --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=springbootcamp/$GITHUB_SHA.zip
 

commit

이제 커밋하고 github action 진행사항을 살펴보자

모두 정상으로 동작했다면 이제 CodeDeploy에서 appspec.yml을 기준으로 install 과정이 진행된다.

CodeDeploy

CodeDeploy에 Developments에 보면 모든 Deployment 상황을 확인할 수 있다.

Deployment Id를 선택해서 자세한 상황도 알 수 있다.
오류난 경우를 살펴보면, ApplicationStart 이벤트중에 오류가 발생한걸 알 수 있다.

당연히 오류가 없으면 정상적인 deploy 과정이 완료된것이다. 수고하셨습니다 👍

오류

  1. Github Action은 성공했는데 CodeDeploy에 Deployment 진행사항을 보면 실패가 발생하고 있다.

An error occurred (AccessDeniedException) when calling the CreateDeployment operation: User: arn:aws:iam:::user/github-action-s3 is not authorized to perform: codedeploy:CreateDeployment on resource: arn:aws:codedeploy:ap-northeast-2::deploymentgroup:springbootcamp-deploy/springbootcamp-deploy-group because no identity-based policy allows the codedeploy:CreateDeployment action

CodeDeploy를 위해서는 application을 생성하고 application은 group으로 세분화된다. 각 그룹읜 각자 role을 가지고 있다.
group의 role은 권한을 가지고 있다.
CodeDeploy의 경우 S3에서 bundle을 EC2 Instance에 download하기 때문에 S3,CodeDeploy,EC2 permission들이 모두 필요하다.

  1. BeforeInstall과정에서 실패하는 경우,

codedeploy의 로그를 확인해보면 다음과 같이 확인할 수 있다.
CodeDeploy agent did not find an AppSpec file within the unpacked revision directory

2023-05-29T12:36:20 INFO [codedeploy-agent(2030)]: [Aws::CodeDeployCommand::Client 200 0.022384 0 retries] put_host_command_complete(command_status:"Failed",diagnostics:{format:"JSON",payload:"{\"error_code\":5,\"script_name\":\"\",\"message\":\"The CodeDeploy agent did not find an AppSpec file within the unpacked revision directory at revision-relative path \\"appspec.yml\\". The revision was unpacked to directory \\"/opt/codedeploy-agent/deployment-root/335bc7e3-f704-499b-a274-b4211c5d4570/d-APKE9MVQN/deployment-archive\\", and the AppSpec file was expected but not found at path \\"/opt/codedeploy-agent/deployment-root/335bc7e3-f704-499b-a274-b4211c5d4570/d-APKE9MVQN/deployment-archive/appspec.yml\\". Consult the AWS CodeDeploy Appspec documentation for more information at http://docs.aws.amazon.com/codedeploy/latest/userguide/reference-appspec-file.html\",\"log\":\"\"}"},host_command_identifier:"eyJiYXRjaElkIjoiNmY3NzgxOGMzNGJiYjcwMjk2MTk4MjA2MzA5ZDQ1MmIvcHVibGljMDAzIiwiZGVwbG95bWVudElkIjoiQ29kZURlcGxveS9hcC1ub3J0aGVhc3QtMi9wcm9kL29ycGhldXM6cHVibGljMDAzLzkyNTc0NzM2NzU3MzpkLUFQS0U5TVZRTiIsImhvc3RJZCI6ImFybjphd3M6ZWMyOmFwLW5vcnRoZWFzdC0yOjkyNTc0NzM2NzU3MzppbnN0YW5jZS9pLTAyOWU0ZDc5ZTVjMmU4MThlIiwiY29tbWFuZElkIjoiQXBvbGxvRGVwbG95Q29udHJvbFNlcnZpY2V8YXJuOmF3czplYzI6YXAtbm9ydGhlYXN0LTI6OTI1NzQ3MzY3NTczOmluc3RhbmNlL2ktMDI5ZTRkNzllNWMyZTgxOGV8M3wwIiwiY29tbWFuZE5hbWUiOiJCZWZvcmVJbnN0YWxsIiwiY29tbWFuZEluZGV4IjozLCJhdHRlbXB0SW5kZXgiOjF9")

해결책은 bundle를 만들때 appspec.yml파일을 포함시켜준다.

  1. lifecycle event에서 실행되는 스크립트의 로그는 UI로 확인할 수 있다. 필요한 경우가 아니면 로그로 남길 필요는 없다.

  2. Script at specified location: scripts/run-deploy.sh failed to close STDOUT

    run-deploy.sh에서 jar를 실행시 STDERR을 STDOUT로 redirect하고 있다.

STDOUT대신에 실제 파일로 로깅하도록 변경한다.

마무리

  • Deploy를 위한 CodeDeploy Application 생성 및 그룹을 생성해 보았다.
  • Github Action에서 S3와 CodeDeploy를 통해서 EC2에 deploy를 자동화 하였다.
  • appspec.yml 파일은 CodeDeploy의 동작과 이벤트 처리를 어떻게 해야 하는지 알려주는 작업지시서 같은 것이니 번들 만들때 꼭 포함시키자
  • 마지막 app이 실행되기 전까지 끝난게 아니다. redirect하나가 문제를 만들줄이야.
profile
coder,maker,custom

0개의 댓글