CodeDeploy를 이용해서 S3에 복사된 파일을 EC2에 Deploy되도록 Github action을 설정해 본다.
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 에 그룹 생성이 완료되었다.
프로젝트의 루트 디렉토리에 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를 실행한다.
이제 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
이제 커밋하고 github action 진행사항을 살펴보자
모두 정상으로 동작했다면 이제 CodeDeploy에서 appspec.yml을 기준으로 install 과정이 진행된다.
CodeDeploy에 Developments에 보면 모든 Deployment 상황을 확인할 수 있다.
Deployment Id를 선택해서 자세한 상황도 알 수 있다.
오류난 경우를 살펴보면, ApplicationStart
이벤트중에 오류가 발생한걸 알 수 있다.
당연히 오류가 없으면 정상적인 deploy 과정이 완료된것이다. 수고하셨습니다 👍
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들이 모두 필요하다.
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파일을 포함시켜준다.
lifecycle event에서 실행되는 스크립트의 로그는 UI로 확인할 수 있다. 필요한 경우가 아니면 로그로 남길 필요는 없다.
Script at specified location: scripts/run-deploy.sh failed to close STDOUT
run-deploy.sh에서 jar를 실행시 STDERR을 STDOUT로 redirect하고 있다.
STDOUT대신에 실제 파일로 로깅하도록 변경한다.