Automated Deployment
배포 자동화
- 손쉽게 전체 배포 과정을 자동으로 진행하는 것
- 수동적이고 반복적인 배포 과정을 자동화하여 시간 절약
- 휴먼 에러를 방지
배포 자동화 파이프라인
- source stage
- 원격 저장소에 관리되고 있는 소스 코드에 변경 사항이 일어날 경우 이를 감지하고 다음 단계로 전달
- Build stage
- source stage에서 전달받은 코드를 컴파일, 빌드, 테스트하여 가공하고 생성물을 다음 단계 전달
- Deploy stage
- 전달받은 결과물을 실제 서비스에 반영
AWS 개발자 도구
- 배포 자동화 파이프라인 구축 가능
CodeCommit
- source stage에서 CodeCommit 서비스를 사용
- github와 유사한 버전 관리 도구
- 보안과 관련 기능 강점을 가지고 있으나 과금이 존재
CodeBuild
- Build stage에서 CodeBuild를 사용
- 유닛 테스트, 컴파일, 빌드 같은 단계에서 실행
CodeDeploy
- Deploy stage에서 사용
- 실시간으로 변경 사항을 전달 가능
- S3 버킷을 통해 업로드된 정적 웹 사이트 변경 사항을 실시간으로 전달 및 반영 가능
CodePipeline
- 각 단계를 연결하는 파이프라인을 구축할 때 사용
AWS Pipeline을 통한 배포 자동화
개발 환경 구축
JAVA 설치
- EC2 인스턴스에서 JAVA 설치
- sudo apt update
- sudo apt install openjdk-11-jre-headless
AWS CLI 설치
- EC2 인스턴스에 AWS CLI 설치
- curl "<https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip>" -o "awscliv2.zip"
- sudo apt install unzip
- unzip awscliv2.zip
- sudo ./aws/install
- aws —version을 통해 설치 확인
CodeDeploy Agent 설치
- sudo apt update
- sudo apt install ruby-full
- sudo apt install wget
- cd /home/ubuntu
- sudo wget <https://aws-codedeploy-ap-northeast-2.s3.ap-northeast-2.amazonaws.com/latest/install>
- sudo chmod +x ./install
- sudo ./install auto > /tmp/logfile
- sudo service codedeploy-agent status 를 통해 상태 확인
EC2 인스턴스 역할 부여 튜토리얼
- EC 대시보드에서 인스턴스로 이동
- 인스턴스 선택 후 태그 탭 접속
- 태그는 key-value 값으로 cohort 태그와 개인 소유 리소스를 식별하기 위한 name 태그 존재
- 인스턴스의 보안 → IAM 역할을 확인
- 역할을 클릭하면 역할에 연결되어있는 권한과 역할 등 다양한 정보 확인 가능
- 권한 추가 → 정책 연결하여 검색창을 통해 AmazonS3FullAccess, AmazonEC2RoleforAWSCodeDeploy, AWSCodeDeployRole, AmazonSSMFullAccess를 선택 후 정책 연결
- 권한 정책 항목에 권한 확인
- 신뢰 관계 항목에서 편집
- service 값으로 codedeploy.ap-northeast-2.amazonaws.com를 추가
EC2를 활용한 파이프라인 구축
AWS CodeDeploy
- 로컬 환경에서 적용할 실습 파일에 appspec.yml 파일 추가하고 내용을 추가
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/build
hooks:
BeforeInstall:
- location: server_clear.sh
timeout: 3000
runas: root
AfterInstall:
- location: initialize.sh
timeout: 3000
runas: root
ApplicationStart:
- location: server_start.sh
timeout: 3000
runas: root
ApplicationStop:
- location: server_stop.sh
timeout: 3000
runas: root
- CodeDeploy-agent가 인식하는 파일
- buildspec.yml 파일 추가하고 내용 추가
- CodeBulid-Agent가 인식하는 파일
version: 0.2 phases: install: runtime-versions: java: corretto11 build: commands: - echo Build Starting on `date` - cd DeployServer - chmod +x ./gradlew - ./gradlew build post_build: commands: - echo $(basename ./DeployServer/build/libs/*.jar) artifacts: files: - DeployServer/build/libs/*.jar - DeployServer/scripts/** - DeployServer/appspec.yml discard-paths: yes
- 최상위에 scripts 디렉터리를 생성한 뒤 initialize.sh, server_clear.sh, server_start.sh, server_stop.sh 파일 4개 생성
- initialize.sh(결과물에 실행 권한 부여)
#!/usr/bin/env bash chmod +x /home/ubuntu/build/**
- server_clear.sh(build 디렉터리 제거)
#!/usr/bin/env bash rm -rf /home/ubuntu/build
- server_start.sh(빌드 결과물 실행)
#!/usr/bin/env bash cd /home/ubuntu/build sudo nohup java -jar {빌드된 파일} > /dev/null 2> /dev/null < /dev/null &
- server_stop.sh(실행 중인 Spring Boot 프로젝트 종료)
#!/usr/bin/env bash sudo pkill -f 'java -jar'
- 변경 사항을 저장하고 commit 후 main으로 push
- AWS CodeDeploy 대시보드로 이동 후 애플리케이션 탭으로 이동
- 애플리케이션 생성 버튼을 클릭
- 애플리케이션 이름을 작성하고 컴퓨팅 플랫폼은 EC2/온프레미스 선택 후 생성
- 생성 후 배포 그룹 탭을 선택해서 배포 그룹 생성 클릭
- 배포 그룹의 이름을 지정하여 입력하고 서비스 역할 영역을 클릭하면 연결할 수 있는 IAM 역할 목록 중 본인 소유의 EC2 인스턴스에 연결되어 있는 IAM 역할 선택
- 환경 구성에 Amazon EC2 인스턴스 선택 후 태그 그룹에 name 태그 키와 값을 선택
- 로드 밸런싱 활성화를 체크 해제 후 배포 그룹 생성 버튼 클릭
AWS CodePipeline
- AWS CodePipeline 대시보드로 이동 후 파이프라인 생성 클릭
- 파이프라인 이름 작성
- github(버전2)로 소스 스테이지 공급자로 선택
- github에 연결 버튼 클릭 후 연결을 누른다.
- 새 앱 설치를 클릭 후 자신 github 계정을 선택 후 only select repositories를 통해 해당 repository 선택하고 install 누른 후 연결 완료
- 레퍼지토리 이름은 이전에 선택한 파이프라인 이름값으로 설정하고 브랜치 이름은 main, 출력 아티팩트 형식은 codePipeline 기본값으로 지정 후 다음
- 빌드 공급자를 AWS CodeBuild를 클릭 후 프로젝트 생성 클릭
- 프로젝트 이름을 설정
- 환경에서 운영체제는 Amazon Linux2, 런타임 standard, 이미지는 aws/codebuild/amazonlinux2-x86_64-standart:3.0 선택
- buildspec 이름에 DeployServer/buildspec.yml 입력
- codepipeline으로 계속 클릭
- 다음으로 넘어가 배포 스테이지에서 배포 공급자는 AWS CodeDeploy 선택
- 애플리케이션 이름과 배포 그룹 설정
- 설정 내용 확인 후 파이프라인 생성 버튼 클릭
- 파이프라인 생성과 동시에 소스 코드 배포 자동 실행
- 구축한 파이프라인 중 deploy 스테이지에서 실패가 발생하는 경우
- EC2 인스턴스에 cd /opt/codedeploy-agent/deployment-root/deployment-logs 명령어 입력
- codedeploy-agent-deployments.log를 vi나 nano를 통해 확인
- tail,head, grep 명령어로 확인 가능하고 프로세스 실행 중인지 확인하려면 sudo lsof -i :(실행한 포트번호) 명령어로 확인 가능
- EC2 IP주소와 8080포트를 통해 접속 확인
환경 변수 설정
서버 환경 변수 설정
환경 변수 생성 후 EC2에 전달
- AWS Parameter Store 서비스를 이용하여 EC2 인스턴스에 환경 변수 전달 가능
- Parameter Store 대시보드 이동 후 파라미터 생성
- spring.datasource.url, spring.datasource.username, spring.datasource.password 파라미터 값을 각각 생성
- 이름은 /prefix/name/key 형식을 갖추어야 한다. (예시 /spring-boot-aws/be-0-NAME/key)
- build.gradle에 dependencies에 implementation 'org.springframework.cloud:spring-cloud-starter-aws-parameter-store-config' 추가
- build.gradle에 아래 항목 추가
- dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-starter-parent:Hoxton.SR12" } }
- src/main/resources/bootstrap.yml 파일을 생성 후 아래 작성
- aws: paramstore: enabled: true prefix: /spring-boot-aws name: [리소스 이름] profileSeparator: _
- src/main/resources/application.properties 파일에서 파라미터로 전달하는 변수 값은 #으로 주석 처리한다.
- 수정 사항을 commit 하고 main으로 push하여 파이프라인을 통해 변경 사항 전달
Github Actions를 통한 배포 자동화
사전 준비
프로젝트 준비
- spring boot 프로젝트를 spring web 의존 모듈만 선택해서 간단하게 생성
S3 버킷 비우기
- 버킷 내용물을 삭제
- 버킷 속성에 정적 웹사이트 호스팅 비활성화
이전 리소스 삭제
- CodeBuild, CodeDeploy, CodePipeline 삭제
Github Actions를 통한 배포 Flow
Github Actions
- Github가 공식적으로 제공하는 빌드,테스트, 배포 파이프라인을 자동화할 수 있는 CI/CD 플랫폼이다.
- 레포지터리에서 pull request나 push 같은 이벤트를 트리거로 workflow 구성
- .yml 파일에 의해 workflow가 구성되고 생성된 워크플로우는 .github/workflows 디렉터리에 위치
- 비공개 레포지터리의 경우 용량과 시간제한이 있고 공개 레포지토리는 무료 사용 가능
배포 flow
- github Actions는 설정 파일에 따라 레포지터리의 변동사항을 트리거로 동작
- 빌드를 마친 프로젝트는 S3 버킷에 저장하고 CodeDeploy에 S3에서 EC2로 명령을 내린다.
S3
- Github Actions를 통한 배포 자동화에서 저장소로의 기능으로 사용
Code Deploy
- Github actions에서 배포 명령을 받아 S3에 저장되어 있는 빌드 결과물을 EC2 인스턴스로 이동
- appspec.yml 설정 파일에 의해 쉘 스크립트 단계에 따라 동작
- Ec2 인스턴스에 Code Deploy Agent의 설치가 필요
EC2
- Code Deploy에 의해 빌드가 된 프로젝트를 EC2 인스턴스가 받아서 .yml 설정 파일과 .sh 쉘 스크립트에 의해 배포 결과를 로그로 저장하고 빌드 파일을 실행
리소스 설정
Github Actions 생성
- github에서 Public Repository 생성 및 생성한 spring boot 프로젝트 업로드
- Actions 탭 클릭 후 Java with Gradle의 configure을 접속하여 gradle 빌드가 기본 설정되어있는 추천 구성 사용 가능
- Github Actions 워크플로를 생성하기 위해 start commit 버튼 클릭 후 commit new file 클릭
- gradle.yml 파일이 생성됨과 동시에 워크플로에 작성되어 있는 트리거로 인해 Github Actions 실행
- Actions 탭에서 워크플로 진행 상황 확인 가능
- 워크플로 성공하면 초록색 체크, 실패하면 X 표시
- 레포지토리 최근 커밋 내역과 함께 표시된다.
- gradle is not executable 오류가 발생 시 git update-index —chmod=+x gradlew 와 git commit 후 git push origin +main을 통해 권한을 변경해야 한다.
Github Action 수정
- Github Actions를 실행화는 과정에서 액세스 키가 필요한데 공개되면 보안 이슈가 발생하여 github secret을 이용해 액세스 키 저장 후 사용
- github 레포지터리에서 settings → Secrets → Actions로 이동하고 new repository secret 클릭
- Name에 변수 이름, Value에는 변수 값 저장
- 액세스 키 ID 값과, 비밀 액세스 키 값을 저장
- gradle.yml에 코드를 수정
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
permissions:
contents: read
env:
S3_BUCKET_NAME: #S3 버킷 이름
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Build with Gradle
uses: gradle/gradle-build-action@67421db6bd0bf253fb4bd25b31ebb98943c375e1
with:
arguments: build
- name: Make zip file
run: zip -r ./practice-deploy.zip .
shell: bash
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY }}
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
aws-region: ap-northeast-2
- name: Upload to S3
run: aws s3 cp --region ap-northeast-2 ./practice-deploy.zip s3://$S3_BUCKET_NAME/practice-deploy.zip
- bulid 후 프로젝트 압축하고 압축한 프로젝트를 S3로 전송하는 내용이다.
- push하여 github Actions 동작
- 성공한다면 S3 버킷에 압축파일 전송되었는지 확인
빌드 파일 배포 및 실행
- CodeDeploy 설정
- CodeDeploy로 이동 후 애플리케이션 생성
- 애플리케이션 이름 작성하고 EC2/온프레미스로 플랫폼 선택
- 애플리케이션 내에 배포 그룹 생성
- 배포 그룹 이름 작성 및 서비스 역할을 선택
- EC2 인스턴스 태그를 이용해 배포 그룹 환경 구성
- 환경 구성에 Amazon EC2 인스턴스 선택, 키와 값에 name, 리소스 이름 작성
- 로드 밸런서 활성화를 체크 해제
- 최상위 디렉터리 구조에 appspec.yml 생성
- version: 0.0 os: linux files: - source: / destination: /home/ubuntu/action overwrite: yes permissions: - object: / pattern: "**" owner: ubuntu group: ubuntu hooks: ApplicationStart: - location: scripts/deploy.sh timeout: 60 runas: ubuntu
- Scripts 폴더를 생성하고 내부에 deploy.sh 파일 생성
- #!/bin/bash BUILD_JAR=$(ls /home/ubuntu/action/build/libs/practice-githubAction-deploy-0.0.1-SNAPSHOT.jar) JAR_NAME=$(basename $BUILD_JAR) echo "> 현재 시간: $(date)" >> /home/ubuntu/action/deploy.log echo "> build 파일명: $JAR_NAME" >> /home/ubuntu/action/deploy.log echo "> build 파일 복사" >> /home/ubuntu/action/deploy.log DEPLOY_PATH=/home/ubuntu/action/ cp $BUILD_JAR $DEPLOY_PATH echo "> 현재 실행 중인 애플리케이션 pid 확인" >> /home/ubuntu/action/deploy.log CURRENT_PID=$(pgrep -f $JAR_NAME) if [ -z $CURRENT_PID ] then echo "> 현재 구동 중인 애플리케이션이 없으므로 종료하지 않습니다." >> /home/ubuntu/action/deploy.log else echo "> kill -9 $CURRENT_PID" >> /home/ubuntu/action/deploy.log sudo kill -9 $CURRENT_PID sleep 5 fi DEPLOY_JAR=$DEPLOY_PATH$JAR_NAME echo "> DEPLOY_JAR 배포" >> /home/ubuntu/action/deploy.log sudo nohup java -jar $DEPLOY_JAR >> /home/ubuntu/deploy.log 2>/home/ubuntu/action/deploy_err.log &
- gradle.yml 최하단에 Code Deploy 배포 명령 추가
- - name: Code Deploy run: > aws deploy create-deployment --application-name {애플리케이션 이름} --deployment-config-name CodeDeployDefault.AllAtOnce --deployment-group-name {배포 그룹 이름} --s3-location bucket=$S3_BUCKET_NAME,bundleType=zip,key=practice-deploy.zip
- 수정을 마치고 push하면 Github Actions 실행
배포 결과 확인
- EC2 인스턴스를 클릭하고 퍼블릭 DNS로 접속하여 접근 가능한지 확인
- whitelabel Error page가 정상(화면 구성을 하지 않았기 때문)
- 응답 자체에 에러가 발생하는지 확인
- EC2 인스턴스에서도 배포 및 프로젝트 실행 확인
- appspec.yml과 deploy.sh에 작성한 대로 action 디렉터리 내에 빌드 파일이 이동했고 실행 중인 프로세스를 검색해 확인
- ps -ef | grep java로 확인 가능
- appspec.yml과 deploy.sh에 작성한 대로 action 디렉터리 내에 빌드 파일이 이동했고 실행 중인 프로세스를 검색해 확인
- 배포 로그 확인
- deploy.sh에는 배포 진행될 때마다 상황 기록
- 배포를 마치면 action 디렉토리 내 deploy.log, deploy_err.log 두 개의 파일 생성
- 빌드 과정은 deploy.log에 정상적으로 실행하지 못하면 deploy_err.log에 기록
- cat이나 에디터로 내용 확인 가능
- 스프링 프로젝트를 수정하고 push하여 배포 자동화가 이루어졌는지 로그를 통해 확인 가능
수동 배포와 자동 배포 workflow
수동 배포
자동 배포 - AWS Pipeline
자동배포 - Gitub Actions
'Backend boot camp > Session4' 카테고리의 다른 글
웹 애플리케이션 로컬 배포 (1) | 2022.12.13 |
---|---|
[Cloud] 운영 전략 (0) | 2022.12.09 |
[Cloud]배포 컨테이너 (1) | 2022.12.09 |
[Cloud] 운영 환경 구성 (1) | 2022.12.09 |
[Spring WebFlux] Spring WebFlux (0) | 2022.12.09 |